tempest-fastapi-sdk 0.96.0__tar.gz → 0.97.0__tar.gz
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.
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/CHANGELOG.md +22 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/CLAUDE.md +9 -3
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/PKG-INFO +8 -2
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/README.md +3 -1
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/genai.en.md +77 -3
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/genai.md +78 -3
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/pyproject.toml +12 -1
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/__init__.py +1 -1
- tempest_fastapi_sdk-0.97.0/tempest_fastapi_sdk/genai/rag/__init__.py +39 -0
- tempest_fastapi_sdk-0.97.0/tempest_fastapi_sdk/genai/rag/context.py +85 -0
- tempest_fastapi_sdk-0.97.0/tempest_fastapi_sdk/genai/rag/extract.py +111 -0
- tempest_fastapi_sdk-0.97.0/tempest_fastapi_sdk/genai/rag/pdf.py +165 -0
- tempest_fastapi_sdk-0.97.0/tempest_fastapi_sdk/genai/rag/schemas.py +80 -0
- tempest_fastapi_sdk-0.97.0/tempest_fastapi_sdk/genai/rag/search.py +166 -0
- tempest_fastapi_sdk-0.97.0/tests/genai/test_rag.py +160 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/uv.lock +264 -2
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/.github/workflows/ci.yml +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/.github/workflows/docs.yml +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/.github/workflows/release-pypi.yml +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/.gitignore +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/.python-version +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/Makefile +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/architecture.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/architecture.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/changelog.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/changelog.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/contributing.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/contributing.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/index.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/index.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/installation.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/installation.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/learning/index.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/learning/index.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/learning/marketplace/api.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/learning/marketplace/api.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/learning/marketplace/business-rules.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/learning/marketplace/business-rules.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/learning/marketplace/domain.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/learning/marketplace/domain.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/learning/marketplace/flows.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/learning/marketplace/flows.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/learning/marketplace/index.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/learning/marketplace/index.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/migration.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/migration.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/admin.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/admin.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/audit-trail.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/audit-trail.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/auth-flow.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/auth-flow.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/br-helpers.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/br-helpers.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/cache.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/cache.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/cli.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/cli.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/database.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/database.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/deploy-safety.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/deploy-safety.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/downloads.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/downloads.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/email.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/email.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/feature-flags.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/feature-flags.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/fields.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/fields.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/file-store.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/file-store.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/http-client.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/http-client.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/http.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/http.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/idempotency.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/idempotency.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/index.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/index.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/logging.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/logging.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/metrics.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/metrics.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/mfa.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/mfa.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/multi-tenant.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/multi-tenant.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/observability.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/observability.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/offline-sync.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/offline-sync.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/outbox.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/outbox.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/queue-tasks.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/queue-tasks.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/realtime.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/realtime.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/refresh-tokens.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/refresh-tokens.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/security.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/security.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/sessions.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/sessions.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/sse.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/sse.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/storage.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/storage.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/stored-files.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/stored-files.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/testing.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/testing.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/typing.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/typing.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/uploads.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/uploads.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/utilities.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/utilities.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/vision.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/vision.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/webpush.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/webpush.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/websocket.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/recipes/websocket.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/reference.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/reference.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/roadmap.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/roadmap.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/ssr.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/ssr.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/tutorial.en.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/docs/tutorial.md +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/mkdocs.yml +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/mkdocs_hooks/llmstxt.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/scripts/extract_recipe.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/admin/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/admin/actions.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/admin/auth.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/admin/config.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/admin/discovery.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/admin/forms.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/admin/router.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/admin/session.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/admin/site.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/admin/static/admin.css +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/admin/templates/base.html +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/admin/templates/dashboard.html +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/admin/templates/detail.html +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/admin/templates/form.html +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/admin/templates/list.html +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/admin/templates/login.html +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/admin/templates/logs.html +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/admin/templates/mfa.html +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/admin/theme.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/api/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/api/cookies.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/api/dependencies/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/api/dependencies/auth.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/api/handlers.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/api/middlewares/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/api/middlewares/body_size.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/api/middlewares/cors.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/api/middlewares/csrf.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/api/middlewares/graceful.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/api/middlewares/idempotency.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/api/middlewares/rate_limit.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/api/middlewares/request_id.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/api/oauth.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/api/routers/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/api/routers/health.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/api/routers/logs.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/api/routers/metrics.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/api/routers/tool_spec.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/api/server.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/api/static.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/api/tracing.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/api/webhooks.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/auth/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/auth/guards.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/auth/locale.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/auth/page_renderer.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/auth/router.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/auth/schemas.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/auth/service.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/auth/templates/en-US/activation.html +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/auth/templates/en-US/activation_error.html +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/auth/templates/en-US/activation_success.html +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/auth/templates/en-US/email_change.html +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/auth/templates/en-US/email_change_error.html +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/auth/templates/en-US/email_change_success.html +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/auth/templates/en-US/email_changed_notice.html +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/auth/templates/en-US/email_verification.html +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/auth/templates/en-US/email_verification_error.html +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/auth/templates/en-US/email_verification_success.html +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/auth/templates/en-US/password_reset.html +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/auth/templates/en-US/password_reset_error.html +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/auth/templates/en-US/password_reset_form.html +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/auth/templates/en-US/password_reset_success.html +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/auth/templates/pt-BR/activation.html +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/auth/templates/pt-BR/activation_error.html +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/auth/templates/pt-BR/activation_success.html +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/auth/templates/pt-BR/email_change.html +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/auth/templates/pt-BR/email_change_error.html +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/auth/templates/pt-BR/email_change_success.html +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/auth/templates/pt-BR/email_changed_notice.html +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/auth/templates/pt-BR/email_verification.html +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/auth/templates/pt-BR/email_verification_error.html +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/auth/templates/pt-BR/email_verification_success.html +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/auth/templates/pt-BR/password_reset.html +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/auth/templates/pt-BR/password_reset_error.html +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/auth/templates/pt-BR/password_reset_form.html +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/auth/templates/pt-BR/password_reset_success.html +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/auth/token_delivery.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/cache/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/cache/decorator.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/cache/invalidation.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/cache/redis_manager.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/cli/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/cli/_templates/Dockerfile.tmpl +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/cli/_templates/README.md.tmpl +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/cli/_templates/dockerignore.tmpl +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/cli/_templates/env.example.tmpl +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/cli/_templates/gitignore.tmpl +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/cli/_templates/main.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/cli/_templates/pyproject.toml.tmpl +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/cli/_templates/src/__init__.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/cli/_templates/src/api/__init__.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/cli/_templates/src/api/app.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/cli/_templates/src/api/dependencies/__init__.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/cli/_templates/src/api/dependencies/auth.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/cli/_templates/src/api/dependencies/resources.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/cli/_templates/src/api/routers/__init__.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/cli/_templates/src/controllers/__init__.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/cli/_templates/src/core/__init__.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/cli/_templates/src/core/exceptions.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/cli/_templates/src/core/settings.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/cli/_templates/src/db/__init__.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/cli/_templates/src/db/models/__init__.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/cli/_templates/src/db/models/user.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/cli/_templates/src/db/repositories/__init__.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/cli/_templates/src/schemas/__init__.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/cli/_templates/src/server.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/cli/_templates/src/services/__init__.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/cli/_templates/src/utils/__init__.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/cli/_templates/tests/__init__.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/cli/_templates/tests/test_smoke.py.tmpl +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/cli/config.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/cli/db.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/cli/docker_compose.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/cli/generate.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/cli/lint.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/cli/main.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/cli/new.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/cli/secrets.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/cli/src_layers.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/cli/user.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/controllers/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/controllers/base.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/core/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/core/context.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/core/enums.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/core/logging.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/core/typed.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/db/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/db/_alembic_templates/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/db/_alembic_templates/env.py.template +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/db/alembic_hooks.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/db/audit.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/db/backup.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/db/connection.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/db/migrations.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/db/mixins.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/db/model.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/db/outbox.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/db/repository.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/db/slow_query.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/db/tenant.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/db/user_model.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/db/user_recovery_code_model.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/db/user_refresh_token_model.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/db/user_token_model.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/db/webpush_subscription_model.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/exceptions/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/exceptions/base.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/exceptions/conflict.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/exceptions/forbidden.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/exceptions/i18n.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/exceptions/jwt.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/exceptions/not_found.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/exceptions/too_many_requests.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/exceptions/unauthorized.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/exceptions/upload.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/exceptions/validation.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/flags/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/flags/backends.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/flags/dependencies.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/flags/service.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/genai/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/genai/hardware.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/genai/schemas.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/py.typed +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/queue/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/queue/broker.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/queue/consumer.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/queue/manager.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/schemas/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/schemas/base.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/schemas/link_headers.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/schemas/logs.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/schemas/pagination.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/schemas/response.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/services/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/services/base.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/services/file_mixin.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/sessions/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/sessions/dependencies.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/sessions/middleware.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/sessions/router.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/sessions/schemas.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/sessions/service.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/sessions/store.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/settings/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/settings/base.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/settings/mixins.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/sse/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/sse/broker.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/sse/event_stream.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/ssr/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/ssr/_static/htmx.min.js +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/ssr/assets.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/ssr/page.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/ssr/response.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/storage/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/storage/minio_client.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/tasks/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/tasks/cron.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/tasks/manager.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/tasks/oop.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/tasks/queue.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/tasks/scheduler.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/testing/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/testing/database.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/utils/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/utils/client_ip.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/utils/data/br_locations.json +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/utils/datetime.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/utils/dict.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/utils/download.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/utils/email.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/utils/fields.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/utils/file_store.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/utils/http_client.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/utils/jwt.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/utils/locations.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/utils/log.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/utils/metrics.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/utils/opaque_token.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/utils/password.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/utils/regex.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/utils/storage_backends.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/utils/throttle.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/utils/totp.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/utils/upload.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/vision/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/vision/mapping.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/vision/schemas.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/webpush/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/webpush/dispatcher.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/webpush/router.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/webpush/schemas.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/webpush/service.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/websockets/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/websockets/hub.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/websockets/router.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tempest_fastapi_sdk/websockets/schemas.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/admin/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/admin/test_actions.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/admin/test_auth.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/admin/test_discovery.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/admin/test_forms.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/admin/test_logs_nav.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/admin/test_mfa.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/admin/test_rich_filters.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/admin/test_router.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/admin/test_site.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/admin/test_theme.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/admin/test_upload_field.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/admin/test_user_model.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/api/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/api/test_body_size.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/api/test_cookies.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/api/test_cors.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/api/test_csrf.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/api/test_dependencies_auth.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/api/test_graceful.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/api/test_handlers.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/api/test_health_router.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/api/test_idempotency.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/api/test_jwt_dependency.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/api/test_logs_router.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/api/test_oauth.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/api/test_prometheus.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/api/test_rate_limit.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/api/test_rate_limit_extras.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/api/test_request_id_middleware.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/api/test_role_dependency.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/api/test_server.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/api/test_static.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/api/test_tool_spec.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/api/test_tracing.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/api/test_webhooks.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/api/test_webhooks_rsa.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/auth/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/auth/test_cookie_delivery.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/auth/test_email_change.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/auth/test_guards.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/auth/test_locale.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/auth/test_mfa.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/auth/test_refresh.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/auth/test_refresh_db.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/auth/test_service.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/cache/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/cache/test_decorator.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/cache/test_invalidation.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/cache/test_redis_manager.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/cli/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/cli/test_config.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/cli/test_db.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/cli/test_db_seed.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/cli/test_docker_compose.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/cli/test_generate.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/cli/test_lint_strictness.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/cli/test_main.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/cli/test_secrets.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/cli/test_user.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/conftest.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/controllers/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/controllers/test_base.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/core/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/core/test_context.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/core/test_enums.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/core/test_logging.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/core/test_typed.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/db/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/db/test_alembic_hooks.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/db/test_audit.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/db/test_backup.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/db/test_bulk_ops.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/db/test_connection.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/db/test_migrations.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/db/test_mixins.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/db/test_model.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/db/test_outbox.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/db/test_repository.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/db/test_safe_upgrade.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/db/test_slow_query.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/db/test_tenant.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/exceptions/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/exceptions/test_exceptions.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/exceptions/test_i18n.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/flags/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/flags/test_flags.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/genai/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/genai/test_hardware.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/queue/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/queue/test_broker.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/queue/test_consumer.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/queue/test_manager.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/schemas/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/schemas/test_base.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/schemas/test_cursor_pagination.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/schemas/test_link_headers.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/schemas/test_pagination.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/schemas/test_response.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/services/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/services/test_base.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/services/test_file_mixin.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/sessions/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/sessions/test_sessions.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/settings/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/settings/test_base.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/settings/test_mixins.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/sse/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/sse/test_broker.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/sse/test_event_stream.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/ssr/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/ssr/test_integration.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/ssr/test_page.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/ssr/test_response.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/storage/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/storage/test_minio_client.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/tasks/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/tasks/test_cron.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/tasks/test_manager.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/tasks/test_oop.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/tasks/test_queue.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/tasks/test_scheduler.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/testing/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/testing/test_database.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/utils/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/utils/test_client_ip.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/utils/test_datetime.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/utils/test_dict.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/utils/test_download.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/utils/test_email.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/utils/test_fields.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/utils/test_file_store.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/utils/test_http_client.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/utils/test_jwt.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/utils/test_lazy_extras.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/utils/test_locations.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/utils/test_log.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/utils/test_metrics.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/utils/test_opaque_token.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/utils/test_password.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/utils/test_regex.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/utils/test_storage_backends.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/utils/test_throttle.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/utils/test_upload.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/vision/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/vision/test_vision.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/webpush/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/webpush/test_dispatcher.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/webpush/test_router.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/webpush/test_schemas.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/webpush/test_service.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/websockets/__init__.py +0 -0
- {tempest_fastapi_sdk-0.96.0 → tempest_fastapi_sdk-0.97.0}/tests/websockets/test_hub_and_router.py +0 -0
|
@@ -5,6 +5,28 @@ All notable changes to **tempest-fastapi-sdk** are listed below.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.97.0] — 2026-07-05
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **Self-hosted GenAI — RAG context (`tempest_fastapi_sdk.genai.rag`)**,
|
|
13
|
+
slice 2: feed a local LLM with web + PDF knowledge, without shipping
|
|
14
|
+
data to a third party.
|
|
15
|
+
- **Web search** — `WebSearchBackend` Protocol + `SearxngBackend` (the
|
|
16
|
+
leviathan pattern: SearXNG JSON API over an injected `httpx` client)
|
|
17
|
+
+ `WebSearch` facade. Returns `SearchResult`s.
|
|
18
|
+
- **Content extraction** — `ContentExtractor` fetches a URL and pulls
|
|
19
|
+
the clean article body via `trafilatura`; failures surface as
|
|
20
|
+
`ExtractionResult(failed=True)`, never raised.
|
|
21
|
+
- **PDF reading** — `PdfReader` (PyMuPDF, detailed reading-order
|
|
22
|
+
extraction) → `Document` (text + per-page + metadata) and overlapping
|
|
23
|
+
`Chunk`s (`read` / `chunks`).
|
|
24
|
+
- **Context assembly** — `build_context(question, sources)` renders
|
|
25
|
+
`SearchResult`s and/or `Chunk`s into one prompt-ready, source-labeled
|
|
26
|
+
block (mix web + PDF, optional per-source truncation).
|
|
27
|
+
- New `[genai-rag]` extra (httpx + trafilatura + pymupdf); everything
|
|
28
|
+
imports lazily without it. Import from `tempest_fastapi_sdk.genai.rag`.
|
|
29
|
+
|
|
8
30
|
## [0.96.0] — 2026-07-05
|
|
9
31
|
|
|
10
32
|
### Added
|
|
@@ -139,9 +139,15 @@ The SDK currently covers (Sep 2025+, post-v0.31.x):
|
|
|
139
139
|
`ModelDtype`. Capacity fns import WITHOUT the extra. **Planned slices:**
|
|
140
140
|
`TextGenerator` (LLM + int4/int8 quant, lazy load + idle-unload),
|
|
141
141
|
`Embedder`, model/result cache, `BatchScheduler` (coalesce concurrent
|
|
142
|
-
calls)
|
|
143
|
-
|
|
144
|
-
|
|
142
|
+
calls). Classes-only (no bundled router). Submodule import like
|
|
143
|
+
queue/tasks/vision. **Shipped (v0.97) — RAG context**
|
|
144
|
+
(`tempest_fastapi_sdk.genai.rag`, `[genai-rag]` extra = httpx +
|
|
145
|
+
trafilatura + pymupdf): `WebSearchBackend` Protocol + `SearxngBackend`
|
|
146
|
+
(SearXNG JSON API, leviathan pattern) + `WebSearch`; `ContentExtractor`
|
|
147
|
+
(trafilatura, failures never raise); `PdfReader` (PyMuPDF detailed
|
|
148
|
+
extraction → `Document`/`Chunk`, `read`/`chunks` with overlap);
|
|
149
|
+
`build_context(question, sources)` → prompt block mixing web +
|
|
150
|
+
PDF. All import lazily.
|
|
145
151
|
- **SSR** (`[ssr]` extra) — `tempest_fastapi_sdk.ssr`: typed Python
|
|
146
152
|
pages rendered to HTML via `tempestweb`'s `render_to_html` /
|
|
147
153
|
`render_document`. `Page` (typed `Component` base — `body()` +
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tempest-fastapi-sdk
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.97.0
|
|
4
4
|
Summary: Shared FastAPI building blocks: base schemas, ORM model, async repository, exceptions, pagination and settings — the conventions used across Tempest projects.
|
|
5
5
|
Project-URL: Homepage, https://github.com/mauriciobenjamin700/tempest-fastapi-sdk
|
|
6
6
|
Project-URL: Repository, https://github.com/mauriciobenjamin700/tempest-fastapi-sdk
|
|
@@ -77,6 +77,10 @@ Requires-Dist: torch>=2.2.0; extra == 'genai'
|
|
|
77
77
|
Requires-Dist: transformers>=4.44.0; extra == 'genai'
|
|
78
78
|
Provides-Extra: genai-quant
|
|
79
79
|
Requires-Dist: bitsandbytes>=0.43.0; extra == 'genai-quant'
|
|
80
|
+
Provides-Extra: genai-rag
|
|
81
|
+
Requires-Dist: httpx>=0.28.0; extra == 'genai-rag'
|
|
82
|
+
Requires-Dist: pymupdf>=1.24.0; extra == 'genai-rag'
|
|
83
|
+
Requires-Dist: trafilatura>=1.12.0; extra == 'genai-rag'
|
|
80
84
|
Provides-Extra: http
|
|
81
85
|
Requires-Dist: httpx>=0.28.0; extra == 'http'
|
|
82
86
|
Provides-Extra: metrics
|
|
@@ -235,6 +239,7 @@ Feature-rich helpers pull in third-party dependencies that you only need when yo
|
|
|
235
239
|
| `[mfa]` | `pyotp` | `TOTPHelper` + MFA/2FA endpoints on the bundled auth flow |
|
|
236
240
|
| `[vision]` | `ort-vision-sdk` | `Detector` / `Classifier` / `Segmenter` (ONNX) + prediction schemas |
|
|
237
241
|
| `[genai]` (+ `[genai-quant]`) | `transformers`, `torch`, `accelerate`, `safetensors`, `huggingface-hub` (+ `bitsandbytes`) | Self-hosted GenAI — hardware capacity check (`probe_hardware` / `can_run` / `recommend`); model runners upcoming |
|
|
242
|
+
| `[genai-rag]` | `httpx`, `trafilatura`, `pymupdf` | RAG context for local LLMs — SearXNG web search, page extraction, PDF reading, `build_context` |
|
|
238
243
|
| `[ssr]` | `tempestweb` | `Page`, `html_response`, `make_htmx_router` — typed Python pages rendered to HTML |
|
|
239
244
|
| `[otel]` | `opentelemetry-sdk` + OTLP/gRPC exporter + FastAPI/SQLAlchemy/httpx instrumentors | `setup_tracing` — distributed tracing |
|
|
240
245
|
| `[sqlite]` | `aiosqlite` | SQLite async driver for `sqlite+aiosqlite://` URLs (dev default) |
|
|
@@ -277,7 +282,8 @@ Since `0.7.1` every optional dependency is imported lazily at first instantiatio
|
|
|
277
282
|
| `tempest_fastapi_sdk.utils.storage_backends` *(extra: `[upload]`)* | `UploadStorage` protocol, `LocalUploadStorage`, `MinIOUploadStorage`, `UploadResult`, `ContentValidator` |
|
|
278
283
|
| `tempest_fastapi_sdk.tasks` *(extra: `[tasks]`)* | `TaskQueue` (typed TaskIQ facade — `.rabbitmq`/`.redis`/`.memory`, `@tq.task` → `Task.enqueue`/`.run`, `@tq.cron`/`@tq.interval`, `start_scheduler`), `Task`; class-based tasks (`TaskDef` + `@task_method` + `TaskQueue.register`); cron helpers (`Cron` / `CronOffset` / `Weekday` + `daily`/`weekdays`/`every_n_minutes`/… builders); `AsyncTaskBrokerManager` / `AsyncTaskScheduler` (legacy wrappers) |
|
|
279
284
|
| `tempest_fastapi_sdk.vision` *(extra: `[vision]`)* | `Detector`, `Classifier`, `Segmenter` (ONNX, lazy), `DetectionSchema`/`ClassificationSchema`/`SegmentationSchema`/`BoundingBoxSchema`/`ClassProbabilitySchema`, `to_detection_schemas`/`to_classification_schema`/`to_segmentation_schemas` |
|
|
280
|
-
| `tempest_fastapi_sdk.genai` *(extra: `[genai]`; capacity check imports without it)* | Self-hosted GenAI capacity check: `probe_hardware`/`HardwareInfo`, `can_run`/`recommend`/`CapacityReport`, `estimate_model_bytes`/`bytes_per_param`/`fetch_num_params`, `ModelDtype` — model runners (`TextGenerator`, `Embedder`), caching
|
|
285
|
+
| `tempest_fastapi_sdk.genai` *(extra: `[genai]`; capacity check imports without it)* | Self-hosted GenAI capacity check: `probe_hardware`/`HardwareInfo`, `can_run`/`recommend`/`CapacityReport`, `estimate_model_bytes`/`bytes_per_param`/`fetch_num_params`, `ModelDtype` — model runners (`TextGenerator`, `Embedder`), caching and batching in upcoming slices |
|
|
286
|
+
| `tempest_fastapi_sdk.genai.rag` *(extra: `[genai-rag]`)* | RAG context for local LLMs: `WebSearch`/`SearxngBackend`/`WebSearchBackend` + `SearchResult`, `ContentExtractor` (trafilatura), `PdfReader` (PyMuPDF) + `Document`/`Chunk`/`PdfPage`, `build_context` |
|
|
281
287
|
| `tempest_fastapi_sdk.ssr` *(extra: `[ssr]`)* | `Page` (typed component base), `html_response` (widget tree → `HTMLResponse`, full document or HTMX fragment), `make_htmx_router` (serves bundled HTMX locally, no CDN) |
|
|
282
288
|
| `tempest_fastapi_sdk.utils` | `to_utc`, `utcnow`, `modify_dict`, `LogUtils`, `AttemptThrottle`/`ThrottleBackend`/`ThrottleStatus`, `generate_opaque_token`/`hash_opaque_token`/`verify_opaque_token`, `get_client_ip`/`get_client_ip_from_scope`, `PasswordUtils` *(extra: `[auth]`)*, `JWTUtils` *(extra: `[auth]`)*, `TOTPHelper` *(extra: `[mfa]`)*, `EmailUtils` *(extra: `[email]`)*, `UploadUtils`/`sniff_mime` *(extra: `[upload]`)*, `DownloadUtils`/`build_content_disposition` *(no extra)*, `FileStoreUtils` — unified upload+download+presign facade *(extra: `[upload]` local / `[minio]` MinIO)*, `MetricsUtils`/`CPUMetrics`/`MemoryMetrics`/`DiskMetrics`/`GPUMetrics`/`SystemMetrics` *(extra: `[metrics]`)*, validated field types (`PositiveIntField`, `NonNegativeIntField`, `CentsField`, `PortField`, `PositiveFloatField`, `NonNegativeFloatField`, `PercentField`, `RatioField`, `LatitudeField`, `LongitudeField`, `PriceField`, `NonEmptyStrField`, `SlugField`, `HexColorField`), BR regex helpers (`CPFField`, `CNPJField`, `CPFOrCNPJField`, `PhoneBRField`, `CEPField`, `PixKeyField` — old names without the suffix kept as deprecated aliases — `PixKeyType`/`detect_pix_key_type`/`is_valid_pix_key`, `is_valid_*`, `normalize_*`, `only_digits`, `*_PATTERN`), BR states/cities (`UF`, `Region`, `StateBR`, `CityBR`, `ChoiceBR`, `UFField`, `CityNameField`, `list_states`, `get_state`, `cities_by_uf`, `states_by_region`, `uf_choices`/`region_choices`/`city_choices`, `is_valid_uf`/`normalize_uf`, `is_valid_city`/`normalize_city`) |
|
|
283
289
|
| `tempest_fastapi_sdk.cli` | `tempest` console script — `new <name>` (scaffold layered service), `lint` / `format` / `fmt-check` / `type` / `test` / `check` (run preferred quality gates), `version` / `--version` |
|
|
@@ -118,6 +118,7 @@ Feature-rich helpers pull in third-party dependencies that you only need when yo
|
|
|
118
118
|
| `[mfa]` | `pyotp` | `TOTPHelper` + MFA/2FA endpoints on the bundled auth flow |
|
|
119
119
|
| `[vision]` | `ort-vision-sdk` | `Detector` / `Classifier` / `Segmenter` (ONNX) + prediction schemas |
|
|
120
120
|
| `[genai]` (+ `[genai-quant]`) | `transformers`, `torch`, `accelerate`, `safetensors`, `huggingface-hub` (+ `bitsandbytes`) | Self-hosted GenAI — hardware capacity check (`probe_hardware` / `can_run` / `recommend`); model runners upcoming |
|
|
121
|
+
| `[genai-rag]` | `httpx`, `trafilatura`, `pymupdf` | RAG context for local LLMs — SearXNG web search, page extraction, PDF reading, `build_context` |
|
|
121
122
|
| `[ssr]` | `tempestweb` | `Page`, `html_response`, `make_htmx_router` — typed Python pages rendered to HTML |
|
|
122
123
|
| `[otel]` | `opentelemetry-sdk` + OTLP/gRPC exporter + FastAPI/SQLAlchemy/httpx instrumentors | `setup_tracing` — distributed tracing |
|
|
123
124
|
| `[sqlite]` | `aiosqlite` | SQLite async driver for `sqlite+aiosqlite://` URLs (dev default) |
|
|
@@ -160,7 +161,8 @@ Since `0.7.1` every optional dependency is imported lazily at first instantiatio
|
|
|
160
161
|
| `tempest_fastapi_sdk.utils.storage_backends` *(extra: `[upload]`)* | `UploadStorage` protocol, `LocalUploadStorage`, `MinIOUploadStorage`, `UploadResult`, `ContentValidator` |
|
|
161
162
|
| `tempest_fastapi_sdk.tasks` *(extra: `[tasks]`)* | `TaskQueue` (typed TaskIQ facade — `.rabbitmq`/`.redis`/`.memory`, `@tq.task` → `Task.enqueue`/`.run`, `@tq.cron`/`@tq.interval`, `start_scheduler`), `Task`; class-based tasks (`TaskDef` + `@task_method` + `TaskQueue.register`); cron helpers (`Cron` / `CronOffset` / `Weekday` + `daily`/`weekdays`/`every_n_minutes`/… builders); `AsyncTaskBrokerManager` / `AsyncTaskScheduler` (legacy wrappers) |
|
|
162
163
|
| `tempest_fastapi_sdk.vision` *(extra: `[vision]`)* | `Detector`, `Classifier`, `Segmenter` (ONNX, lazy), `DetectionSchema`/`ClassificationSchema`/`SegmentationSchema`/`BoundingBoxSchema`/`ClassProbabilitySchema`, `to_detection_schemas`/`to_classification_schema`/`to_segmentation_schemas` |
|
|
163
|
-
| `tempest_fastapi_sdk.genai` *(extra: `[genai]`; capacity check imports without it)* | Self-hosted GenAI capacity check: `probe_hardware`/`HardwareInfo`, `can_run`/`recommend`/`CapacityReport`, `estimate_model_bytes`/`bytes_per_param`/`fetch_num_params`, `ModelDtype` — model runners (`TextGenerator`, `Embedder`), caching
|
|
164
|
+
| `tempest_fastapi_sdk.genai` *(extra: `[genai]`; capacity check imports without it)* | Self-hosted GenAI capacity check: `probe_hardware`/`HardwareInfo`, `can_run`/`recommend`/`CapacityReport`, `estimate_model_bytes`/`bytes_per_param`/`fetch_num_params`, `ModelDtype` — model runners (`TextGenerator`, `Embedder`), caching and batching in upcoming slices |
|
|
165
|
+
| `tempest_fastapi_sdk.genai.rag` *(extra: `[genai-rag]`)* | RAG context for local LLMs: `WebSearch`/`SearxngBackend`/`WebSearchBackend` + `SearchResult`, `ContentExtractor` (trafilatura), `PdfReader` (PyMuPDF) + `Document`/`Chunk`/`PdfPage`, `build_context` |
|
|
164
166
|
| `tempest_fastapi_sdk.ssr` *(extra: `[ssr]`)* | `Page` (typed component base), `html_response` (widget tree → `HTMLResponse`, full document or HTMX fragment), `make_htmx_router` (serves bundled HTMX locally, no CDN) |
|
|
165
167
|
| `tempest_fastapi_sdk.utils` | `to_utc`, `utcnow`, `modify_dict`, `LogUtils`, `AttemptThrottle`/`ThrottleBackend`/`ThrottleStatus`, `generate_opaque_token`/`hash_opaque_token`/`verify_opaque_token`, `get_client_ip`/`get_client_ip_from_scope`, `PasswordUtils` *(extra: `[auth]`)*, `JWTUtils` *(extra: `[auth]`)*, `TOTPHelper` *(extra: `[mfa]`)*, `EmailUtils` *(extra: `[email]`)*, `UploadUtils`/`sniff_mime` *(extra: `[upload]`)*, `DownloadUtils`/`build_content_disposition` *(no extra)*, `FileStoreUtils` — unified upload+download+presign facade *(extra: `[upload]` local / `[minio]` MinIO)*, `MetricsUtils`/`CPUMetrics`/`MemoryMetrics`/`DiskMetrics`/`GPUMetrics`/`SystemMetrics` *(extra: `[metrics]`)*, validated field types (`PositiveIntField`, `NonNegativeIntField`, `CentsField`, `PortField`, `PositiveFloatField`, `NonNegativeFloatField`, `PercentField`, `RatioField`, `LatitudeField`, `LongitudeField`, `PriceField`, `NonEmptyStrField`, `SlugField`, `HexColorField`), BR regex helpers (`CPFField`, `CNPJField`, `CPFOrCNPJField`, `PhoneBRField`, `CEPField`, `PixKeyField` — old names without the suffix kept as deprecated aliases — `PixKeyType`/`detect_pix_key_type`/`is_valid_pix_key`, `is_valid_*`, `normalize_*`, `only_digits`, `*_PATTERN`), BR states/cities (`UF`, `Region`, `StateBR`, `CityBR`, `ChoiceBR`, `UFField`, `CityNameField`, `list_states`, `get_state`, `cities_by_uf`, `states_by_region`, `uf_choices`/`region_choices`/`city_choices`, `is_valid_uf`/`normalize_uf`, `is_valid_city`/`normalize_city`) |
|
|
166
168
|
| `tempest_fastapi_sdk.cli` | `tempest` console script — `new <name>` (scaffold layered service), `lint` / `format` / `fmt-check` / `type` / `test` / `check` (run preferred quality gates), `version` / `--version` |
|
|
@@ -6,10 +6,11 @@ slices; this page covers the **first**: knowing, *before* you download
|
|
|
6
6
|
gigabytes of weights, whether the machine can handle the model.
|
|
7
7
|
|
|
8
8
|
!!! info "Module roadmap"
|
|
9
|
-
- **
|
|
9
|
+
- **v0.96:** `genai.hardware` — probing + `can_run` / `recommend`.
|
|
10
|
+
- **v0.97:** `genai.rag` — RAG context (SearXNG web search + PDF
|
|
11
|
+
reading) to inject into LLMs (this page, [RAG context](#rag-context)).
|
|
10
12
|
- **Coming:** `TextGenerator` (LLM + int4/int8 quantization),
|
|
11
|
-
`Embedder`, model/result caching, `BatchScheduler
|
|
12
|
-
(web search + PDF reading) to inject into LLMs.
|
|
13
|
+
`Embedder`, model/result caching, `BatchScheduler`.
|
|
13
14
|
|
|
14
15
|
The `[genai]` extra (transformers + torch + accelerate) is only needed to
|
|
15
16
|
**run** models. The capacity functions **import without the extra** —
|
|
@@ -81,10 +82,83 @@ The parameter count can be passed explicitly (`num_params=`) or read from
|
|
|
81
82
|
the Hub by `model_id` (via `huggingface_hub`, without downloading the
|
|
82
83
|
weights — safetensors metadata).
|
|
83
84
|
|
|
85
|
+
## RAG context
|
|
86
|
+
|
|
87
|
+
A local LLM only knows what it trained on. For current, grounded answers,
|
|
88
|
+
inject context: `tempest_fastapi_sdk.genai.rag` searches the web
|
|
89
|
+
(self-hosted SearXNG), extracts page bodies, reads PDFs, and assembles a
|
|
90
|
+
prompt-ready block — without sending data outside. Needs the `[genai-rag]`
|
|
91
|
+
extra (httpx + trafilatura + pymupdf); the pieces import lazily.
|
|
92
|
+
|
|
93
|
+
### Web search (SearXNG)
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
import httpx
|
|
97
|
+
from tempest_fastapi_sdk.genai.rag import SearxngBackend, WebSearch, build_context
|
|
98
|
+
|
|
99
|
+
client = httpx.AsyncClient()
|
|
100
|
+
search = WebSearch(SearxngBackend("http://localhost:8080", http_client=client))
|
|
101
|
+
|
|
102
|
+
results = await search.search("what is PIX?", max_results=5) # list[SearchResult]
|
|
103
|
+
context = build_context("what is PIX?", results, long_text=False, max_chars=2000)
|
|
104
|
+
# -> a string ready to inject into your TextGenerator prompt
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
The backend is a `Protocol` (`WebSearchBackend`) — swap SearXNG for another
|
|
108
|
+
provider without touching call sites. The `httpx.AsyncClient` is injected
|
|
109
|
+
(pool reuse; wire it in the FastAPI lifespan).
|
|
110
|
+
|
|
111
|
+
### Extract page bodies
|
|
112
|
+
|
|
113
|
+
Search snippets are thin. To give the LLM ground truth, fetch each page
|
|
114
|
+
and extract the clean text (via `trafilatura`):
|
|
115
|
+
|
|
116
|
+
```python
|
|
117
|
+
from tempest_fastapi_sdk.genai.rag import ContentExtractor
|
|
118
|
+
|
|
119
|
+
extractor = ContentExtractor(http_client=client)
|
|
120
|
+
for result in results:
|
|
121
|
+
outcome = await extractor.extract(result.url)
|
|
122
|
+
result.content = outcome.text # "" on failure; outcome.failed marks it
|
|
123
|
+
context = build_context("what is PIX?", results) # now with full bodies
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Failures (timeout, 4xx/5xx, empty page) **never** raise — they come back
|
|
127
|
+
as `ExtractionResult(text="", failed=True)`, so no source is silently
|
|
128
|
+
dropped.
|
|
129
|
+
|
|
130
|
+
### Read PDFs (knowledge base)
|
|
131
|
+
|
|
132
|
+
`PdfReader` (PyMuPDF — detailed, reading-order extraction) turns PDF paths
|
|
133
|
+
into text and prompt/embedding-ready chunks:
|
|
134
|
+
|
|
135
|
+
```python
|
|
136
|
+
from tempest_fastapi_sdk.genai.rag import PdfReader, build_context
|
|
137
|
+
|
|
138
|
+
reader = PdfReader()
|
|
139
|
+
doc = reader.read("/kb/manual.pdf") # Document: text + pages + metadata
|
|
140
|
+
chunks = reader.chunks("/kb/manual.pdf", max_chars=2000, overlap=200)
|
|
141
|
+
|
|
142
|
+
context = build_context("how to refund?", chunks) # cites "file (page N)"
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
`chunks(..., overlap=200)` shares characters between neighbors so a fact on
|
|
146
|
+
a boundary isn't cut in half; `per_page=True` (default) keeps each chunk on
|
|
147
|
+
a single page and records its page number.
|
|
148
|
+
|
|
149
|
+
!!! tip "Mix web + PDF in one context"
|
|
150
|
+
`build_context` accepts `SearchResult` and `Chunk` in the same list —
|
|
151
|
+
it delimits each source with `---` and labels the origin (URL or `file
|
|
152
|
+
(page N)`) so the LLM can cite. Pass `long_text=False` to truncate each
|
|
153
|
+
source to `max_chars`.
|
|
154
|
+
|
|
84
155
|
## Recap
|
|
85
156
|
|
|
86
157
|
- **`can_run` / `recommend`** — answer whether the host runs the model
|
|
87
158
|
and what to do if not, **before** the download.
|
|
159
|
+
- **RAG** — `WebSearch`/`SearxngBackend` (search), `ContentExtractor`
|
|
160
|
+
(page bodies), `PdfReader` (PDF → text/chunks) and `build_context`
|
|
161
|
+
(prompt block), all under the `[genai-rag]` extra.
|
|
88
162
|
- **`probe_hardware`** — a CPU/RAM/GPU/disk snapshot; degrades without the
|
|
89
163
|
extras.
|
|
90
164
|
- **`estimate_model_bytes` / `bytes_per_param`** — the estimation math,
|
|
@@ -6,10 +6,11 @@ está sendo entregue em fatias; esta página cobre a **primeira**: saber,
|
|
|
6
6
|
*antes* de baixar gigabytes de pesos, se a máquina aguenta o modelo.
|
|
7
7
|
|
|
8
8
|
!!! info "Roadmap do módulo"
|
|
9
|
-
- **
|
|
9
|
+
- **v0.96:** `genai.hardware` — sondagem + `can_run` / `recommend`.
|
|
10
|
+
- **v0.97:** `genai.rag` — contexto RAG (busca web SearXNG + leitura de
|
|
11
|
+
PDF) pra injetar nas LLMs (esta página, seção [Contexto RAG](#contexto-rag)).
|
|
10
12
|
- **Em breve:** `TextGenerator` (LLM + quantização int4/int8),
|
|
11
|
-
`Embedder`, cache de modelo/resultado, `BatchScheduler
|
|
12
|
-
contexto RAG (busca web + leitura de PDF) pra injetar nas LLMs.
|
|
13
|
+
`Embedder`, cache de modelo/resultado, `BatchScheduler`.
|
|
13
14
|
|
|
14
15
|
O extra `[genai]` (transformers + torch + accelerate) só é necessário pra
|
|
15
16
|
**rodar** modelos. As funções de capacidade **importam sem o extra** — o
|
|
@@ -81,10 +82,84 @@ O número de parâmetros pode vir explícito (`num_params=`) ou ser lido do
|
|
|
81
82
|
Hub por `model_id` (via `huggingface_hub`, sem baixar os pesos —
|
|
82
83
|
metadados safetensors).
|
|
83
84
|
|
|
85
|
+
## Contexto RAG
|
|
86
|
+
|
|
87
|
+
Uma LLM local só sabe o que treinou. Pra respostas atuais e fundamentadas,
|
|
88
|
+
injete contexto: `tempest_fastapi_sdk.genai.rag` busca na web (SearXNG
|
|
89
|
+
self-hosted), extrai o corpo das páginas, lê PDFs e monta um bloco pronto
|
|
90
|
+
pro prompt — tudo sem enviar dados pra fora. Requer o extra `[genai-rag]`
|
|
91
|
+
(httpx + trafilatura + pymupdf); as peças importam preguiçosamente.
|
|
92
|
+
|
|
93
|
+
### Busca web (SearXNG)
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
import httpx
|
|
97
|
+
from tempest_fastapi_sdk.genai.rag import SearxngBackend, WebSearch, build_context
|
|
98
|
+
|
|
99
|
+
client = httpx.AsyncClient()
|
|
100
|
+
search = WebSearch(SearxngBackend("http://localhost:8080", http_client=client))
|
|
101
|
+
|
|
102
|
+
results = await search.search("o que é PIX?", max_results=5) # list[SearchResult]
|
|
103
|
+
context = build_context("o que é PIX?", results, long_text=False, max_chars=2000)
|
|
104
|
+
# -> string pronta pra injetar no prompt do seu TextGenerator
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
O backend é um `Protocol` (`WebSearchBackend`) — troque o SearXNG por
|
|
108
|
+
outro provedor sem mexer no call site. O `httpx.AsyncClient` é injetado
|
|
109
|
+
(reaproveita o pool; ligue no lifespan do FastAPI).
|
|
110
|
+
|
|
111
|
+
### Extrair o corpo das páginas
|
|
112
|
+
|
|
113
|
+
O snippet do buscador é raso. Pra dar "verdade" pra LLM, busque cada
|
|
114
|
+
página e extraia o texto limpo (via `trafilatura`):
|
|
115
|
+
|
|
116
|
+
```python
|
|
117
|
+
from tempest_fastapi_sdk.genai.rag import ContentExtractor
|
|
118
|
+
|
|
119
|
+
extractor = ContentExtractor(http_client=client)
|
|
120
|
+
for result in results:
|
|
121
|
+
outcome = await extractor.extract(result.url)
|
|
122
|
+
result.content = outcome.text # "" quando falha; outcome.failed marca
|
|
123
|
+
context = build_context("o que é PIX?", results) # agora com corpo completo
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Falhas (timeout, 4xx/5xx, página sem corpo) **nunca** levantam — voltam
|
|
127
|
+
como `ExtractionResult(text="", failed=True)`, então nenhuma fonte some
|
|
128
|
+
silenciosamente.
|
|
129
|
+
|
|
130
|
+
### Ler PDFs (base de conhecimento)
|
|
131
|
+
|
|
132
|
+
`PdfReader` (PyMuPDF — extração detalhada, ordem de leitura) transforma
|
|
133
|
+
caminhos de PDF em texto e em chunks prontos pra prompt ou índice de
|
|
134
|
+
embeddings:
|
|
135
|
+
|
|
136
|
+
```python
|
|
137
|
+
from tempest_fastapi_sdk.genai.rag import PdfReader, build_context
|
|
138
|
+
|
|
139
|
+
reader = PdfReader()
|
|
140
|
+
doc = reader.read("/base/manual.pdf") # Document: text + pages + metadata
|
|
141
|
+
chunks = reader.chunks("/base/manual.pdf", max_chars=2000, overlap=200)
|
|
142
|
+
|
|
143
|
+
context = build_context("como estornar?", chunks) # cita "arquivo (page N)"
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
`chunks(..., overlap=200)` compartilha caracteres entre pedaços vizinhos,
|
|
147
|
+
pra um fato na fronteira não ser cortado ao meio; `per_page=True` (padrão)
|
|
148
|
+
mantém cada chunk numa página só, carregando o número dela.
|
|
149
|
+
|
|
150
|
+
!!! tip "Misture web + PDF no mesmo contexto"
|
|
151
|
+
`build_context` aceita `SearchResult` e `Chunk` na mesma lista —
|
|
152
|
+
delimita cada fonte com `---` e rotula a origem (URL ou `arquivo
|
|
153
|
+
(page N)`), pra LLM citar. Passe `long_text=False` pra truncar cada
|
|
154
|
+
fonte a `max_chars`.
|
|
155
|
+
|
|
84
156
|
## Recap
|
|
85
157
|
|
|
86
158
|
- **`can_run` / `recommend`** — respondem se o host roda o modelo e o que
|
|
87
159
|
fazer se não rodar, **antes** do download.
|
|
160
|
+
- **RAG** — `WebSearch`/`SearxngBackend` (busca), `ContentExtractor`
|
|
161
|
+
(corpo das páginas), `PdfReader` (PDF → texto/chunks) e `build_context`
|
|
162
|
+
(bloco pro prompt), todos sob o extra `[genai-rag]`.
|
|
88
163
|
- **`probe_hardware`** — snapshot de CPU/RAM/GPU/disco; degrada sem os
|
|
89
164
|
extras.
|
|
90
165
|
- **`estimate_model_bytes` / `bytes_per_param`** — a matemática da
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "tempest-fastapi-sdk"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.97.0"
|
|
4
4
|
description = "Shared FastAPI building blocks: base schemas, ORM model, async repository, exceptions, pagination and settings — the conventions used across Tempest projects."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.11"
|
|
@@ -101,6 +101,11 @@ genai = [
|
|
|
101
101
|
genai-quant = [
|
|
102
102
|
"bitsandbytes>=0.43.0",
|
|
103
103
|
]
|
|
104
|
+
genai-rag = [
|
|
105
|
+
"httpx>=0.28.0",
|
|
106
|
+
"trafilatura>=1.12.0",
|
|
107
|
+
"pymupdf>=1.24.0",
|
|
108
|
+
]
|
|
104
109
|
ssr = [
|
|
105
110
|
"tempestweb>=0.9.0",
|
|
106
111
|
]
|
|
@@ -205,6 +210,8 @@ dev = [
|
|
|
205
210
|
"nvidia-ml-py>=12.560.30",
|
|
206
211
|
"redis>=5.0.0",
|
|
207
212
|
"ruff>=0.8.0",
|
|
213
|
+
"trafilatura>=1.12.0",
|
|
214
|
+
"pymupdf>=1.24.0",
|
|
208
215
|
"faststream[rabbit]>=0.7.1",
|
|
209
216
|
"taskiq>=0.11.0",
|
|
210
217
|
"taskiq-aio-pika>=0.4.0",
|
|
@@ -320,6 +327,10 @@ module = [
|
|
|
320
327
|
"huggingface_hub.*",
|
|
321
328
|
"accelerate",
|
|
322
329
|
"accelerate.*",
|
|
330
|
+
"trafilatura",
|
|
331
|
+
"trafilatura.*",
|
|
332
|
+
"pymupdf",
|
|
333
|
+
"fitz",
|
|
323
334
|
"pyotp",
|
|
324
335
|
"pyotp.*",
|
|
325
336
|
"ort_vision_sdk",
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""RAG context — feed LLMs with web search + PDF knowledge.
|
|
2
|
+
|
|
3
|
+
Retrieve grounding for a local LLM without shipping data to a third
|
|
4
|
+
party: search a self-hosted SearXNG, extract page bodies, read PDFs, and
|
|
5
|
+
assemble it all into a prompt-ready context block. The heavy bits
|
|
6
|
+
(``httpx`` / ``trafilatura`` / ``pymupdf``) live behind the
|
|
7
|
+
``[genai-rag]`` extra and import lazily, so this package imports without
|
|
8
|
+
it — you only need the extra to actually fetch and read.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from tempest_fastapi_sdk.genai.rag.context import build_context as build_context
|
|
12
|
+
from tempest_fastapi_sdk.genai.rag.extract import (
|
|
13
|
+
ContentExtractor as ContentExtractor,
|
|
14
|
+
)
|
|
15
|
+
from tempest_fastapi_sdk.genai.rag.extract import (
|
|
16
|
+
ExtractionResult as ExtractionResult,
|
|
17
|
+
)
|
|
18
|
+
from tempest_fastapi_sdk.genai.rag.pdf import PdfReader as PdfReader
|
|
19
|
+
from tempest_fastapi_sdk.genai.rag.schemas import Chunk as Chunk
|
|
20
|
+
from tempest_fastapi_sdk.genai.rag.schemas import Document as Document
|
|
21
|
+
from tempest_fastapi_sdk.genai.rag.schemas import PdfPage as PdfPage
|
|
22
|
+
from tempest_fastapi_sdk.genai.rag.schemas import SearchResult as SearchResult
|
|
23
|
+
from tempest_fastapi_sdk.genai.rag.search import SearxngBackend as SearxngBackend
|
|
24
|
+
from tempest_fastapi_sdk.genai.rag.search import WebSearch as WebSearch
|
|
25
|
+
from tempest_fastapi_sdk.genai.rag.search import WebSearchBackend as WebSearchBackend
|
|
26
|
+
|
|
27
|
+
__all__: list[str] = [
|
|
28
|
+
"Chunk",
|
|
29
|
+
"ContentExtractor",
|
|
30
|
+
"Document",
|
|
31
|
+
"ExtractionResult",
|
|
32
|
+
"PdfPage",
|
|
33
|
+
"PdfReader",
|
|
34
|
+
"SearchResult",
|
|
35
|
+
"SearxngBackend",
|
|
36
|
+
"WebSearch",
|
|
37
|
+
"WebSearchBackend",
|
|
38
|
+
"build_context",
|
|
39
|
+
]
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"""Assemble retrieved sources into a single prompt-ready context block.
|
|
2
|
+
|
|
3
|
+
Turns web :class:`SearchResult`s and PDF :class:`Chunk`s into one plain-text
|
|
4
|
+
block you drop straight into a system/user prompt. Each source is
|
|
5
|
+
delimited and labeled with its origin so the model can cite it. Mirrors
|
|
6
|
+
the leviathan ContextBuilder: plain text, clear structure, optional
|
|
7
|
+
truncation per source.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from collections.abc import Sequence
|
|
13
|
+
|
|
14
|
+
from tempest_fastapi_sdk.genai.rag.schemas import Chunk, SearchResult
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _body(source: SearchResult | Chunk, *, long_text: bool, max_chars: int) -> str:
|
|
18
|
+
"""Return the text body of a source, truncated when not ``long_text``."""
|
|
19
|
+
if isinstance(source, SearchResult):
|
|
20
|
+
text = source.content or source.snippet
|
|
21
|
+
else:
|
|
22
|
+
text = source.text
|
|
23
|
+
text = text.strip()
|
|
24
|
+
if not long_text and len(text) > max_chars:
|
|
25
|
+
return text[:max_chars].rstrip() + " …"
|
|
26
|
+
return text
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _label(source: SearchResult | Chunk) -> str:
|
|
30
|
+
"""Return a citation label for a source."""
|
|
31
|
+
if isinstance(source, SearchResult):
|
|
32
|
+
title = source.title or source.url
|
|
33
|
+
return f"{title} ({source.url})"
|
|
34
|
+
if source.page is not None:
|
|
35
|
+
return f"{source.source} (page {source.page})"
|
|
36
|
+
return source.source
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def build_context(
|
|
40
|
+
question: str,
|
|
41
|
+
sources: Sequence[SearchResult | Chunk],
|
|
42
|
+
*,
|
|
43
|
+
long_text: bool = True,
|
|
44
|
+
max_chars: int = 2000,
|
|
45
|
+
) -> str:
|
|
46
|
+
"""Render retrieved sources into a single context string for an LLM.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
question (str): The user's question, echoed at the top so the model
|
|
50
|
+
has the task in view.
|
|
51
|
+
sources (Sequence[SearchResult | Chunk]): Web results and/or PDF
|
|
52
|
+
chunks, in the order they should appear.
|
|
53
|
+
long_text (bool): When ``True`` (default), include each source's
|
|
54
|
+
full body; when ``False``, truncate each to ``max_chars``.
|
|
55
|
+
max_chars (int): Per-source truncation cap when ``long_text`` is
|
|
56
|
+
``False``.
|
|
57
|
+
|
|
58
|
+
Returns:
|
|
59
|
+
str: A prompt-ready block. Sources are delimited by ``---`` and
|
|
60
|
+
labeled with their origin; returns a short notice when ``sources``
|
|
61
|
+
is empty.
|
|
62
|
+
"""
|
|
63
|
+
if not sources:
|
|
64
|
+
return f"Question: {question}\n\nNo sources were retrieved for this question."
|
|
65
|
+
|
|
66
|
+
parts: list[str] = [
|
|
67
|
+
f"Question: {question}",
|
|
68
|
+
"",
|
|
69
|
+
f"Below are {len(sources)} sources retrieved to answer this question. "
|
|
70
|
+
"Each is delimited by `---`. Use them as ground truth; cite the "
|
|
71
|
+
"source when relevant.",
|
|
72
|
+
"",
|
|
73
|
+
]
|
|
74
|
+
for index, source in enumerate(sources, start=1):
|
|
75
|
+
parts.append("---")
|
|
76
|
+
parts.append(f"[{index}] {_label(source)}")
|
|
77
|
+
parts.append(_body(source, long_text=long_text, max_chars=max_chars))
|
|
78
|
+
parts.append("")
|
|
79
|
+
parts.append("---")
|
|
80
|
+
return "\n".join(parts)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
__all__: list[str] = [
|
|
84
|
+
"build_context",
|
|
85
|
+
]
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"""Fetch a page and extract its main text (HTML → clean text).
|
|
2
|
+
|
|
3
|
+
Search snippets are thin; to give an LLM real ground truth you fetch each
|
|
4
|
+
result and pull the article body out of the HTML. Uses ``trafilatura``
|
|
5
|
+
(the leviathan choice) for cleaning. Failures never raise — a page that
|
|
6
|
+
times out or yields nothing comes back as ``failed=True`` with empty
|
|
7
|
+
text, so no source is silently dropped.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from dataclasses import dataclass
|
|
13
|
+
from typing import TYPE_CHECKING
|
|
14
|
+
|
|
15
|
+
if TYPE_CHECKING:
|
|
16
|
+
import httpx
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@dataclass(slots=True)
|
|
20
|
+
class ExtractionResult:
|
|
21
|
+
"""Outcome of fetching + extracting one URL.
|
|
22
|
+
|
|
23
|
+
Attributes:
|
|
24
|
+
text (str): The cleaned page body, or ``""`` on failure.
|
|
25
|
+
failed (bool): ``True`` when the page couldn't be fetched or no
|
|
26
|
+
text could be extracted.
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
text: str
|
|
30
|
+
failed: bool
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _require_trafilatura() -> object:
|
|
34
|
+
"""Import ``trafilatura`` or raise a helpful error.
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
object: The ``trafilatura`` module.
|
|
38
|
+
|
|
39
|
+
Raises:
|
|
40
|
+
ImportError: When the ``[genai-rag]`` extra is not installed.
|
|
41
|
+
"""
|
|
42
|
+
try:
|
|
43
|
+
import trafilatura
|
|
44
|
+
except ImportError as exc:
|
|
45
|
+
raise ImportError(
|
|
46
|
+
"Content extraction requires the optional [genai-rag] extra. "
|
|
47
|
+
"Install with: pip install tempest-fastapi-sdk[genai-rag]",
|
|
48
|
+
) from exc
|
|
49
|
+
return trafilatura
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class ContentExtractor:
|
|
53
|
+
"""Fetch URLs and extract their main text via ``trafilatura``.
|
|
54
|
+
|
|
55
|
+
The ``httpx.AsyncClient`` is injected so the connection pool is shared.
|
|
56
|
+
|
|
57
|
+
Attributes:
|
|
58
|
+
user_agent (str): ``User-Agent`` header sent with each fetch.
|
|
59
|
+
timeout (float): Per-request timeout in seconds.
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
def __init__(
|
|
63
|
+
self,
|
|
64
|
+
*,
|
|
65
|
+
http_client: httpx.AsyncClient,
|
|
66
|
+
user_agent: str = "tempest-fastapi-sdk/genai",
|
|
67
|
+
timeout: float = 10.0,
|
|
68
|
+
) -> None:
|
|
69
|
+
"""Initialize the extractor.
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
http_client (httpx.AsyncClient): Injected async client.
|
|
73
|
+
user_agent (str): ``User-Agent`` for fetches.
|
|
74
|
+
timeout (float): Per-request timeout in seconds.
|
|
75
|
+
"""
|
|
76
|
+
self._http = http_client
|
|
77
|
+
self.user_agent = user_agent
|
|
78
|
+
self.timeout = timeout
|
|
79
|
+
|
|
80
|
+
async def extract(self, url: str) -> ExtractionResult:
|
|
81
|
+
"""Fetch ``url`` and return its extracted main text.
|
|
82
|
+
|
|
83
|
+
Never raises: fetch/extraction failures come back as
|
|
84
|
+
``ExtractionResult(text="", failed=True)``.
|
|
85
|
+
|
|
86
|
+
Args:
|
|
87
|
+
url (str): The page to fetch.
|
|
88
|
+
|
|
89
|
+
Returns:
|
|
90
|
+
ExtractionResult: The extracted text or a failure marker.
|
|
91
|
+
"""
|
|
92
|
+
trafilatura = _require_trafilatura()
|
|
93
|
+
try:
|
|
94
|
+
response = await self._http.get(
|
|
95
|
+
url,
|
|
96
|
+
headers={"User-Agent": self.user_agent},
|
|
97
|
+
timeout=self.timeout,
|
|
98
|
+
follow_redirects=True,
|
|
99
|
+
)
|
|
100
|
+
response.raise_for_status()
|
|
101
|
+
except Exception:
|
|
102
|
+
return ExtractionResult(text="", failed=True)
|
|
103
|
+
|
|
104
|
+
text = trafilatura.extract(response.text) or "" # type: ignore[attr-defined]
|
|
105
|
+
return ExtractionResult(text=text, failed=not text)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
__all__: list[str] = [
|
|
109
|
+
"ContentExtractor",
|
|
110
|
+
"ExtractionResult",
|
|
111
|
+
]
|