fastapi-fullstack 0.1.7__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fastapi_fullstack-0.1.7.dist-info/METADATA +739 -0
- fastapi_fullstack-0.1.7.dist-info/RECORD +241 -0
- fastapi_fullstack-0.1.7.dist-info/WHEEL +4 -0
- fastapi_fullstack-0.1.7.dist-info/entry_points.txt +2 -0
- fastapi_fullstack-0.1.7.dist-info/licenses/LICENSE +21 -0
- fastapi_gen/__init__.py +3 -0
- fastapi_gen/cli.py +442 -0
- fastapi_gen/config.py +356 -0
- fastapi_gen/generator.py +207 -0
- fastapi_gen/prompts.py +874 -0
- fastapi_gen/template/VARIABLES.md +276 -0
- fastapi_gen/template/cookiecutter.json +93 -0
- fastapi_gen/template/hooks/post_gen_project.py +355 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/.env.prod.example +56 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/.github/workflows/ci.yml +150 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/.gitignore +109 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/AGENTS.md +55 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/CLAUDE.md +99 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/Makefile +315 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/README.md +768 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/.dockerignore +60 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/.env.example +155 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/.pre-commit-config.yaml +32 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/Dockerfile +56 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/alembic/env.py +76 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/alembic/script.py.mako +30 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/alembic/versions/.gitkeep +0 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/alembic.ini +48 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/__init__.py +3 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/admin.py +447 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/agents/__init__.py +23 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/agents/assistant.py +226 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/agents/langchain_assistant.py +226 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/agents/prompts.py +10 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/agents/tools/__init__.py +13 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/agents/tools/datetime_tool.py +17 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/__init__.py +1 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/deps.py +541 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/exception_handlers.py +98 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/router.py +10 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/__init__.py +9 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/__init__.py +87 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/agent.py +902 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/auth.py +395 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/conversations.py +498 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/health.py +227 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/items.py +275 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/oauth.py +205 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/sessions.py +168 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/users.py +333 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/webhooks.py +477 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/ws.py +46 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/versioning.py +221 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/clients/__init__.py +14 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/clients/redis.py +88 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/commands/__init__.py +117 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/commands/cleanup.py +75 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/commands/example.py +28 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/commands/seed.py +266 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/__init__.py +5 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/cache.py +23 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/config.py +267 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/csrf.py +153 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/exceptions.py +122 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/logfire_setup.py +101 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/middleware.py +99 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/oauth.py +23 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/rate_limit.py +58 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/sanitize.py +271 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/security.py +102 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/__init__.py +7 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/base.py +41 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/models/__init__.py +31 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/models/conversation.py +319 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/models/item.py +96 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/models/session.py +126 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/models/user.py +218 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/models/webhook.py +244 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/session.py +130 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/main.py +334 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/pipelines/__init__.py +9 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/pipelines/base.py +73 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/repositories/__init__.py +49 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/repositories/base.py +154 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/repositories/conversation.py +838 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/repositories/item.py +222 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/repositories/session.py +318 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/repositories/user.py +322 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/repositories/webhook.py +358 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/__init__.py +50 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/base.py +57 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/conversation.py +192 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/item.py +52 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/session.py +42 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/token.py +31 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/user.py +64 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/webhook.py +89 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/__init__.py +38 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/conversation.py +850 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/item.py +246 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/session.py +333 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/user.py +432 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/webhook.py +561 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/worker/__init__.py +5 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/worker/celery_app.py +64 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/worker/taskiq_app.py +38 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/worker/tasks/__init__.py +25 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/worker/tasks/examples.py +106 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/worker/tasks/schedules.py +29 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/worker/tasks/taskiq_examples.py +92 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/cli/__init__.py +1 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/cli/commands.py +438 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/pyproject.toml +180 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/scripts/.gitkeep +0 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/__init__.py +1 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/api/__init__.py +1 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/api/test_auth.py +242 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/api/test_exceptions.py +151 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/api/test_health.py +113 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/api/test_items.py +310 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/api/test_users.py +253 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/conftest.py +151 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_admin.py +890 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_agents.py +261 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_clients.py +183 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_commands.py +173 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_core.py +143 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_pipelines.py +118 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_repositories.py +181 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_security.py +124 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_services.py +363 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_worker.py +85 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/docker-compose.dev.yml +242 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/docker-compose.frontend.yml +31 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/docker-compose.prod.yml +435 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/docker-compose.yml +241 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/docs/adding_features.md +132 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/docs/architecture.md +63 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/docs/patterns.md +161 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/docs/testing.md +120 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/.dockerignore +40 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/.env.example +12 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/.gitignore +45 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/.prettierignore +19 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/.prettierrc +11 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/Dockerfile +44 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/README.md +648 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/e2e/auth.setup.ts +49 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/e2e/auth.spec.ts +134 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/e2e/chat.spec.ts +207 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/e2e/home.spec.ts +73 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/instrumentation.ts +14 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/messages/en.json +84 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/messages/pl.json +84 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/next.config.ts +76 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/package.json +69 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/playwright.config.ts +101 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/postcss.config.mjs +7 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/(auth)/layout.tsx +11 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/(auth)/login/page.tsx +5 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/(auth)/register/page.tsx +5 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/(dashboard)/chat/page.tsx +48 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/(dashboard)/dashboard/page.tsx +99 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/(dashboard)/layout.tsx +17 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/(dashboard)/profile/page.tsx +152 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/auth/callback/page.tsx +113 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/layout.tsx +46 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/page.tsx +73 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/auth/login/route.ts +58 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/auth/logout/route.ts +24 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/auth/me/route.ts +39 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/auth/oauth-callback/route.ts +50 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/auth/refresh/route.ts +54 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/auth/register/route.ts +26 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/conversations/[id]/messages/route.ts +41 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/conversations/[id]/route.ts +108 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/conversations/route.ts +73 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/health/route.ts +21 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/globals.css +323 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/layout.tsx +22 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/providers.tsx +29 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/auth/index.ts +2 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/auth/login-form.tsx +120 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/auth/register-form.tsx +153 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/chat-container.tsx +234 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/chat-input.tsx +72 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/conversation-sidebar.tsx +328 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/copy-button.tsx +46 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/index.ts +11 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/local-conversation-sidebar.tsx +295 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/markdown-content.tsx +167 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/message-item.tsx +79 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/message-list.tsx +18 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/tool-call-card.tsx +79 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/icons/google-icon.tsx +32 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/icons/index.ts +3 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/language-switcher.tsx +97 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/layout/header.tsx +65 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/layout/index.ts +2 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/layout/sidebar.tsx +82 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/theme/index.ts +7 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/theme/theme-provider.tsx +53 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/theme/theme-toggle.tsx +105 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/badge.tsx +35 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/button.test.tsx +75 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/button.tsx +56 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/card.tsx +82 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/index.ts +13 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/input.tsx +21 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/label.tsx +21 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/sheet.tsx +109 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/index.ts +7 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-auth.ts +97 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-chat.ts +203 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-conversations.ts +181 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-local-chat.ts +165 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-websocket.ts +105 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/i18n.ts +37 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/lib/api-client.ts +90 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/lib/constants.ts +39 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/lib/server-api.ts +78 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/lib/utils.test.ts +44 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/lib/utils.ts +44 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/middleware.ts +31 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/stores/auth-store.test.ts +72 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/stores/auth-store.ts +64 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/stores/chat-sidebar-store.ts +17 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/stores/chat-store.ts +65 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/stores/conversation-store.ts +76 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/stores/index.ts +9 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/stores/local-chat-store.ts +255 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/stores/sidebar-store.ts +17 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/stores/theme-store.ts +44 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/types/api.ts +27 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/types/auth.ts +52 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/types/chat.ts +83 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/types/conversation.ts +49 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/types/index.ts +10 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/tsconfig.json +28 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/vitest.config.ts +36 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/vitest.setup.ts +56 -0
|
@@ -0,0 +1,498 @@
|
|
|
1
|
+
{%- if cookiecutter.enable_conversation_persistence %}
|
|
2
|
+
"""Conversation API routes for AI chat persistence.
|
|
3
|
+
|
|
4
|
+
Provides CRUD operations for conversations and messages.
|
|
5
|
+
|
|
6
|
+
The endpoints are:
|
|
7
|
+
- GET /conversations - List user's conversations
|
|
8
|
+
- POST /conversations - Create a new conversation
|
|
9
|
+
- GET /conversations/{id} - Get a conversation with messages
|
|
10
|
+
- PATCH /conversations/{id} - Update conversation title/archived status
|
|
11
|
+
- DELETE /conversations/{id} - Delete a conversation
|
|
12
|
+
- POST /conversations/{id}/messages - Add a message to conversation
|
|
13
|
+
- GET /conversations/{id}/messages - List messages in conversation
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
{%- if cookiecutter.use_postgresql %}
|
|
17
|
+
from uuid import UUID
|
|
18
|
+
{%- endif %}
|
|
19
|
+
|
|
20
|
+
from fastapi import APIRouter, Query, status
|
|
21
|
+
|
|
22
|
+
{%- if cookiecutter.use_mongodb %}
|
|
23
|
+
from app.api.deps import ConversationSvc
|
|
24
|
+
{%- else %}
|
|
25
|
+
from app.api.deps import DBSession, ConversationSvc
|
|
26
|
+
{%- endif %}
|
|
27
|
+
{%- if cookiecutter.use_jwt %}
|
|
28
|
+
from app.api.deps import CurrentUser
|
|
29
|
+
{%- endif %}
|
|
30
|
+
from app.schemas.conversation import (
|
|
31
|
+
ConversationCreate,
|
|
32
|
+
ConversationList,
|
|
33
|
+
ConversationRead,
|
|
34
|
+
ConversationReadWithMessages,
|
|
35
|
+
ConversationUpdate,
|
|
36
|
+
MessageCreate,
|
|
37
|
+
MessageList,
|
|
38
|
+
MessageRead,
|
|
39
|
+
MessageReadSimple,
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
router = APIRouter()
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
{%- if cookiecutter.use_postgresql %}
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@router.get("", response_model=ConversationList)
|
|
49
|
+
async def list_conversations(
|
|
50
|
+
conversation_service: ConversationSvc,
|
|
51
|
+
{%- if cookiecutter.use_jwt %}
|
|
52
|
+
current_user: CurrentUser,
|
|
53
|
+
{%- endif %}
|
|
54
|
+
skip: int = Query(0, ge=0, description="Number of conversations to skip"),
|
|
55
|
+
limit: int = Query(50, ge=1, le=100, description="Maximum conversations to return"),
|
|
56
|
+
include_archived: bool = Query(False, description="Include archived conversations"),
|
|
57
|
+
):
|
|
58
|
+
"""List conversations for the current user.
|
|
59
|
+
|
|
60
|
+
Returns conversations ordered by most recently updated.
|
|
61
|
+
"""
|
|
62
|
+
items, total = await conversation_service.list_conversations(
|
|
63
|
+
{%- if cookiecutter.use_jwt %}
|
|
64
|
+
user_id=current_user.id,
|
|
65
|
+
{%- endif %}
|
|
66
|
+
skip=skip,
|
|
67
|
+
limit=limit,
|
|
68
|
+
include_archived=include_archived,
|
|
69
|
+
)
|
|
70
|
+
return ConversationList(items=items, total=total)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
@router.post("", response_model=ConversationRead, status_code=status.HTTP_201_CREATED)
|
|
74
|
+
async def create_conversation(
|
|
75
|
+
conversation_service: ConversationSvc,
|
|
76
|
+
{%- if cookiecutter.use_jwt %}
|
|
77
|
+
current_user: CurrentUser,
|
|
78
|
+
{%- endif %}
|
|
79
|
+
data: ConversationCreate | None = None,
|
|
80
|
+
):
|
|
81
|
+
"""Create a new conversation.
|
|
82
|
+
|
|
83
|
+
The title is optional and can be set later.
|
|
84
|
+
"""
|
|
85
|
+
if data is None:
|
|
86
|
+
data = ConversationCreate()
|
|
87
|
+
{%- if cookiecutter.use_jwt %}
|
|
88
|
+
data.user_id = current_user.id
|
|
89
|
+
{%- endif %}
|
|
90
|
+
return await conversation_service.create_conversation(data)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
@router.get("/{conversation_id}", response_model=ConversationReadWithMessages)
|
|
94
|
+
async def get_conversation(
|
|
95
|
+
conversation_id: UUID,
|
|
96
|
+
conversation_service: ConversationSvc,
|
|
97
|
+
{%- if cookiecutter.use_jwt %}
|
|
98
|
+
current_user: CurrentUser,
|
|
99
|
+
{%- endif %}
|
|
100
|
+
):
|
|
101
|
+
"""Get a conversation with all its messages.
|
|
102
|
+
|
|
103
|
+
Raises 404 if the conversation does not exist.
|
|
104
|
+
"""
|
|
105
|
+
return await conversation_service.get_conversation(conversation_id, include_messages=True)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
@router.patch("/{conversation_id}", response_model=ConversationRead)
|
|
109
|
+
async def update_conversation(
|
|
110
|
+
conversation_id: UUID,
|
|
111
|
+
data: ConversationUpdate,
|
|
112
|
+
conversation_service: ConversationSvc,
|
|
113
|
+
{%- if cookiecutter.use_jwt %}
|
|
114
|
+
current_user: CurrentUser,
|
|
115
|
+
{%- endif %}
|
|
116
|
+
):
|
|
117
|
+
"""Update a conversation's title or archived status.
|
|
118
|
+
|
|
119
|
+
Raises 404 if the conversation does not exist.
|
|
120
|
+
"""
|
|
121
|
+
return await conversation_service.update_conversation(conversation_id, data)
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
@router.delete("/{conversation_id}", status_code=status.HTTP_204_NO_CONTENT)
|
|
125
|
+
async def delete_conversation(
|
|
126
|
+
conversation_id: UUID,
|
|
127
|
+
conversation_service: ConversationSvc,
|
|
128
|
+
{%- if cookiecutter.use_jwt %}
|
|
129
|
+
current_user: CurrentUser,
|
|
130
|
+
{%- endif %}
|
|
131
|
+
):
|
|
132
|
+
"""Delete a conversation and all its messages.
|
|
133
|
+
|
|
134
|
+
Raises 404 if the conversation does not exist.
|
|
135
|
+
"""
|
|
136
|
+
await conversation_service.delete_conversation(conversation_id)
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
@router.post(
|
|
140
|
+
"/{conversation_id}/archive",
|
|
141
|
+
response_model=ConversationRead,
|
|
142
|
+
)
|
|
143
|
+
async def archive_conversation(
|
|
144
|
+
conversation_id: UUID,
|
|
145
|
+
conversation_service: ConversationSvc,
|
|
146
|
+
{%- if cookiecutter.use_jwt %}
|
|
147
|
+
current_user: CurrentUser,
|
|
148
|
+
{%- endif %}
|
|
149
|
+
):
|
|
150
|
+
"""Archive a conversation.
|
|
151
|
+
|
|
152
|
+
Archived conversations are hidden from the default list view.
|
|
153
|
+
"""
|
|
154
|
+
return await conversation_service.archive_conversation(conversation_id)
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
@router.get("/{conversation_id}/messages", response_model=MessageList)
|
|
158
|
+
async def list_messages(
|
|
159
|
+
conversation_id: UUID,
|
|
160
|
+
conversation_service: ConversationSvc,
|
|
161
|
+
{%- if cookiecutter.use_jwt %}
|
|
162
|
+
current_user: CurrentUser,
|
|
163
|
+
{%- endif %}
|
|
164
|
+
skip: int = Query(0, ge=0),
|
|
165
|
+
limit: int = Query(100, ge=1, le=500),
|
|
166
|
+
):
|
|
167
|
+
"""List messages in a conversation.
|
|
168
|
+
|
|
169
|
+
Returns messages ordered by creation time (oldest first).
|
|
170
|
+
"""
|
|
171
|
+
items, total = await conversation_service.list_messages(conversation_id, skip=skip, limit=limit)
|
|
172
|
+
return MessageList(items=items, total=total)
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
@router.post(
|
|
176
|
+
"/{conversation_id}/messages",
|
|
177
|
+
response_model=MessageRead,
|
|
178
|
+
status_code=status.HTTP_201_CREATED,
|
|
179
|
+
)
|
|
180
|
+
async def add_message(
|
|
181
|
+
conversation_id: UUID,
|
|
182
|
+
data: MessageCreate,
|
|
183
|
+
conversation_service: ConversationSvc,
|
|
184
|
+
{%- if cookiecutter.use_jwt %}
|
|
185
|
+
current_user: CurrentUser,
|
|
186
|
+
{%- endif %}
|
|
187
|
+
):
|
|
188
|
+
"""Add a message to a conversation.
|
|
189
|
+
|
|
190
|
+
Raises 404 if the conversation does not exist.
|
|
191
|
+
"""
|
|
192
|
+
return await conversation_service.add_message(conversation_id, data)
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
{%- elif cookiecutter.use_sqlite %}
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
@router.get("", response_model=ConversationList)
|
|
199
|
+
def list_conversations(
|
|
200
|
+
conversation_service: ConversationSvc,
|
|
201
|
+
{%- if cookiecutter.use_jwt %}
|
|
202
|
+
current_user: CurrentUser,
|
|
203
|
+
{%- endif %}
|
|
204
|
+
skip: int = Query(0, ge=0, description="Number of conversations to skip"),
|
|
205
|
+
limit: int = Query(50, ge=1, le=100, description="Maximum conversations to return"),
|
|
206
|
+
include_archived: bool = Query(False, description="Include archived conversations"),
|
|
207
|
+
):
|
|
208
|
+
"""List conversations for the current user.
|
|
209
|
+
|
|
210
|
+
Returns conversations ordered by most recently updated.
|
|
211
|
+
"""
|
|
212
|
+
items, total = conversation_service.list_conversations(
|
|
213
|
+
{%- if cookiecutter.use_jwt %}
|
|
214
|
+
user_id=str(current_user.id),
|
|
215
|
+
{%- endif %}
|
|
216
|
+
skip=skip,
|
|
217
|
+
limit=limit,
|
|
218
|
+
include_archived=include_archived,
|
|
219
|
+
)
|
|
220
|
+
return ConversationList(items=items, total=total)
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
@router.post("", response_model=ConversationRead, status_code=status.HTTP_201_CREATED)
|
|
224
|
+
def create_conversation(
|
|
225
|
+
conversation_service: ConversationSvc,
|
|
226
|
+
{%- if cookiecutter.use_jwt %}
|
|
227
|
+
current_user: CurrentUser,
|
|
228
|
+
{%- endif %}
|
|
229
|
+
data: ConversationCreate | None = None,
|
|
230
|
+
):
|
|
231
|
+
"""Create a new conversation.
|
|
232
|
+
|
|
233
|
+
The title is optional and can be set later.
|
|
234
|
+
"""
|
|
235
|
+
if data is None:
|
|
236
|
+
data = ConversationCreate()
|
|
237
|
+
{%- if cookiecutter.use_jwt %}
|
|
238
|
+
data.user_id = str(current_user.id)
|
|
239
|
+
{%- endif %}
|
|
240
|
+
return conversation_service.create_conversation(data)
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
@router.get("/{conversation_id}", response_model=ConversationReadWithMessages)
|
|
244
|
+
def get_conversation(
|
|
245
|
+
conversation_id: str,
|
|
246
|
+
conversation_service: ConversationSvc,
|
|
247
|
+
{%- if cookiecutter.use_jwt %}
|
|
248
|
+
current_user: CurrentUser,
|
|
249
|
+
{%- endif %}
|
|
250
|
+
):
|
|
251
|
+
"""Get a conversation with all its messages.
|
|
252
|
+
|
|
253
|
+
Raises 404 if the conversation does not exist.
|
|
254
|
+
"""
|
|
255
|
+
return conversation_service.get_conversation(conversation_id, include_messages=True)
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
@router.patch("/{conversation_id}", response_model=ConversationRead)
|
|
259
|
+
def update_conversation(
|
|
260
|
+
conversation_id: str,
|
|
261
|
+
data: ConversationUpdate,
|
|
262
|
+
conversation_service: ConversationSvc,
|
|
263
|
+
{%- if cookiecutter.use_jwt %}
|
|
264
|
+
current_user: CurrentUser,
|
|
265
|
+
{%- endif %}
|
|
266
|
+
):
|
|
267
|
+
"""Update a conversation's title or archived status.
|
|
268
|
+
|
|
269
|
+
Raises 404 if the conversation does not exist.
|
|
270
|
+
"""
|
|
271
|
+
return conversation_service.update_conversation(conversation_id, data)
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
@router.delete("/{conversation_id}", status_code=status.HTTP_204_NO_CONTENT)
|
|
275
|
+
def delete_conversation(
|
|
276
|
+
conversation_id: str,
|
|
277
|
+
conversation_service: ConversationSvc,
|
|
278
|
+
{%- if cookiecutter.use_jwt %}
|
|
279
|
+
current_user: CurrentUser,
|
|
280
|
+
{%- endif %}
|
|
281
|
+
):
|
|
282
|
+
"""Delete a conversation and all its messages.
|
|
283
|
+
|
|
284
|
+
Raises 404 if the conversation does not exist.
|
|
285
|
+
"""
|
|
286
|
+
conversation_service.delete_conversation(conversation_id)
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
@router.post(
|
|
290
|
+
"/{conversation_id}/archive",
|
|
291
|
+
response_model=ConversationRead,
|
|
292
|
+
)
|
|
293
|
+
def archive_conversation(
|
|
294
|
+
conversation_id: str,
|
|
295
|
+
conversation_service: ConversationSvc,
|
|
296
|
+
{%- if cookiecutter.use_jwt %}
|
|
297
|
+
current_user: CurrentUser,
|
|
298
|
+
{%- endif %}
|
|
299
|
+
):
|
|
300
|
+
"""Archive a conversation.
|
|
301
|
+
|
|
302
|
+
Archived conversations are hidden from the default list view.
|
|
303
|
+
"""
|
|
304
|
+
return conversation_service.archive_conversation(conversation_id)
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
@router.get("/{conversation_id}/messages", response_model=MessageList)
|
|
308
|
+
def list_messages(
|
|
309
|
+
conversation_id: str,
|
|
310
|
+
conversation_service: ConversationSvc,
|
|
311
|
+
{%- if cookiecutter.use_jwt %}
|
|
312
|
+
current_user: CurrentUser,
|
|
313
|
+
{%- endif %}
|
|
314
|
+
skip: int = Query(0, ge=0),
|
|
315
|
+
limit: int = Query(100, ge=1, le=500),
|
|
316
|
+
):
|
|
317
|
+
"""List messages in a conversation.
|
|
318
|
+
|
|
319
|
+
Returns messages ordered by creation time (oldest first).
|
|
320
|
+
"""
|
|
321
|
+
items, total = conversation_service.list_messages(conversation_id, skip=skip, limit=limit)
|
|
322
|
+
return MessageList(items=items, total=total)
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
@router.post(
|
|
326
|
+
"/{conversation_id}/messages",
|
|
327
|
+
response_model=MessageRead,
|
|
328
|
+
status_code=status.HTTP_201_CREATED,
|
|
329
|
+
)
|
|
330
|
+
def add_message(
|
|
331
|
+
conversation_id: str,
|
|
332
|
+
data: MessageCreate,
|
|
333
|
+
conversation_service: ConversationSvc,
|
|
334
|
+
{%- if cookiecutter.use_jwt %}
|
|
335
|
+
current_user: CurrentUser,
|
|
336
|
+
{%- endif %}
|
|
337
|
+
):
|
|
338
|
+
"""Add a message to a conversation.
|
|
339
|
+
|
|
340
|
+
Raises 404 if the conversation does not exist.
|
|
341
|
+
"""
|
|
342
|
+
return conversation_service.add_message(conversation_id, data)
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
{%- elif cookiecutter.use_mongodb %}
|
|
346
|
+
|
|
347
|
+
|
|
348
|
+
@router.get("", response_model=ConversationList)
|
|
349
|
+
async def list_conversations(
|
|
350
|
+
conversation_service: ConversationSvc,
|
|
351
|
+
{%- if cookiecutter.use_jwt %}
|
|
352
|
+
current_user: CurrentUser,
|
|
353
|
+
{%- endif %}
|
|
354
|
+
skip: int = Query(0, ge=0, description="Number of conversations to skip"),
|
|
355
|
+
limit: int = Query(50, ge=1, le=100, description="Maximum conversations to return"),
|
|
356
|
+
include_archived: bool = Query(False, description="Include archived conversations"),
|
|
357
|
+
):
|
|
358
|
+
"""List conversations for the current user.
|
|
359
|
+
|
|
360
|
+
Returns conversations ordered by most recently updated.
|
|
361
|
+
"""
|
|
362
|
+
items, total = await conversation_service.list_conversations(
|
|
363
|
+
{%- if cookiecutter.use_jwt %}
|
|
364
|
+
user_id=str(current_user.id),
|
|
365
|
+
{%- endif %}
|
|
366
|
+
skip=skip,
|
|
367
|
+
limit=limit,
|
|
368
|
+
include_archived=include_archived,
|
|
369
|
+
)
|
|
370
|
+
return ConversationList(items=items, total=total)
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
@router.post("", response_model=ConversationRead, status_code=status.HTTP_201_CREATED)
|
|
374
|
+
async def create_conversation(
|
|
375
|
+
conversation_service: ConversationSvc,
|
|
376
|
+
{%- if cookiecutter.use_jwt %}
|
|
377
|
+
current_user: CurrentUser,
|
|
378
|
+
{%- endif %}
|
|
379
|
+
data: ConversationCreate | None = None,
|
|
380
|
+
):
|
|
381
|
+
"""Create a new conversation.
|
|
382
|
+
|
|
383
|
+
The title is optional and can be set later.
|
|
384
|
+
"""
|
|
385
|
+
if data is None:
|
|
386
|
+
data = ConversationCreate()
|
|
387
|
+
{%- if cookiecutter.use_jwt %}
|
|
388
|
+
data.user_id = str(current_user.id)
|
|
389
|
+
{%- endif %}
|
|
390
|
+
return await conversation_service.create_conversation(data)
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
@router.get("/{conversation_id}", response_model=ConversationReadWithMessages)
|
|
394
|
+
async def get_conversation(
|
|
395
|
+
conversation_id: str,
|
|
396
|
+
conversation_service: ConversationSvc,
|
|
397
|
+
{%- if cookiecutter.use_jwt %}
|
|
398
|
+
current_user: CurrentUser,
|
|
399
|
+
{%- endif %}
|
|
400
|
+
):
|
|
401
|
+
"""Get a conversation with all its messages.
|
|
402
|
+
|
|
403
|
+
Raises 404 if the conversation does not exist.
|
|
404
|
+
"""
|
|
405
|
+
return await conversation_service.get_conversation(conversation_id, include_messages=True)
|
|
406
|
+
|
|
407
|
+
|
|
408
|
+
@router.patch("/{conversation_id}", response_model=ConversationRead)
|
|
409
|
+
async def update_conversation(
|
|
410
|
+
conversation_id: str,
|
|
411
|
+
data: ConversationUpdate,
|
|
412
|
+
conversation_service: ConversationSvc,
|
|
413
|
+
{%- if cookiecutter.use_jwt %}
|
|
414
|
+
current_user: CurrentUser,
|
|
415
|
+
{%- endif %}
|
|
416
|
+
):
|
|
417
|
+
"""Update a conversation's title or archived status.
|
|
418
|
+
|
|
419
|
+
Raises 404 if the conversation does not exist.
|
|
420
|
+
"""
|
|
421
|
+
return await conversation_service.update_conversation(conversation_id, data)
|
|
422
|
+
|
|
423
|
+
|
|
424
|
+
@router.delete("/{conversation_id}", status_code=status.HTTP_204_NO_CONTENT)
|
|
425
|
+
async def delete_conversation(
|
|
426
|
+
conversation_id: str,
|
|
427
|
+
conversation_service: ConversationSvc,
|
|
428
|
+
{%- if cookiecutter.use_jwt %}
|
|
429
|
+
current_user: CurrentUser,
|
|
430
|
+
{%- endif %}
|
|
431
|
+
):
|
|
432
|
+
"""Delete a conversation and all its messages.
|
|
433
|
+
|
|
434
|
+
Raises 404 if the conversation does not exist.
|
|
435
|
+
"""
|
|
436
|
+
await conversation_service.delete_conversation(conversation_id)
|
|
437
|
+
|
|
438
|
+
|
|
439
|
+
@router.post(
|
|
440
|
+
"/{conversation_id}/archive",
|
|
441
|
+
response_model=ConversationRead,
|
|
442
|
+
)
|
|
443
|
+
async def archive_conversation(
|
|
444
|
+
conversation_id: str,
|
|
445
|
+
conversation_service: ConversationSvc,
|
|
446
|
+
{%- if cookiecutter.use_jwt %}
|
|
447
|
+
current_user: CurrentUser,
|
|
448
|
+
{%- endif %}
|
|
449
|
+
):
|
|
450
|
+
"""Archive a conversation.
|
|
451
|
+
|
|
452
|
+
Archived conversations are hidden from the default list view.
|
|
453
|
+
"""
|
|
454
|
+
return await conversation_service.archive_conversation(conversation_id)
|
|
455
|
+
|
|
456
|
+
|
|
457
|
+
@router.get("/{conversation_id}/messages", response_model=MessageList)
|
|
458
|
+
async def list_messages(
|
|
459
|
+
conversation_id: str,
|
|
460
|
+
conversation_service: ConversationSvc,
|
|
461
|
+
{%- if cookiecutter.use_jwt %}
|
|
462
|
+
current_user: CurrentUser,
|
|
463
|
+
{%- endif %}
|
|
464
|
+
skip: int = Query(0, ge=0),
|
|
465
|
+
limit: int = Query(100, ge=1, le=500),
|
|
466
|
+
):
|
|
467
|
+
"""List messages in a conversation.
|
|
468
|
+
|
|
469
|
+
Returns messages ordered by creation time (oldest first).
|
|
470
|
+
"""
|
|
471
|
+
items, total = await conversation_service.list_messages(conversation_id, skip=skip, limit=limit)
|
|
472
|
+
return MessageList(items=items, total=total)
|
|
473
|
+
|
|
474
|
+
|
|
475
|
+
@router.post(
|
|
476
|
+
"/{conversation_id}/messages",
|
|
477
|
+
response_model=MessageRead,
|
|
478
|
+
status_code=status.HTTP_201_CREATED,
|
|
479
|
+
)
|
|
480
|
+
async def add_message(
|
|
481
|
+
conversation_id: str,
|
|
482
|
+
data: MessageCreate,
|
|
483
|
+
conversation_service: ConversationSvc,
|
|
484
|
+
{%- if cookiecutter.use_jwt %}
|
|
485
|
+
current_user: CurrentUser,
|
|
486
|
+
{%- endif %}
|
|
487
|
+
):
|
|
488
|
+
"""Add a message to a conversation.
|
|
489
|
+
|
|
490
|
+
Raises 404 if the conversation does not exist.
|
|
491
|
+
"""
|
|
492
|
+
return await conversation_service.add_message(conversation_id, data)
|
|
493
|
+
|
|
494
|
+
|
|
495
|
+
{%- endif %}
|
|
496
|
+
{%- else %}
|
|
497
|
+
"""Conversation routes - not configured."""
|
|
498
|
+
{%- endif %}
|