aegis-stack 0.2.0rc2__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.
- aegis/__init__.py +5 -0
- aegis/__main__.py +51 -0
- aegis/cli/__init__.py +6 -0
- aegis/cli/callbacks.py +114 -0
- aegis/cli/interactive.py +611 -0
- aegis/cli/utils.py +70 -0
- aegis/cli/validators.py +34 -0
- aegis/commands/__init__.py +6 -0
- aegis/commands/add.py +353 -0
- aegis/commands/add_service.py +332 -0
- aegis/commands/components.py +35 -0
- aegis/commands/init.py +370 -0
- aegis/commands/remove.py +227 -0
- aegis/commands/services.py +52 -0
- aegis/commands/update.py +252 -0
- aegis/commands/version.py +12 -0
- aegis/config/__init__.py +1 -0
- aegis/config/shared_files.py +136 -0
- aegis/core/CLAUDE.md +377 -0
- aegis/core/__init__.py +6 -0
- aegis/core/component_files.py +228 -0
- aegis/core/component_utils.py +220 -0
- aegis/core/components.py +127 -0
- aegis/core/copier_manager.py +315 -0
- aegis/core/copier_updater.py +475 -0
- aegis/core/dependency_resolver.py +119 -0
- aegis/core/manual_updater.py +554 -0
- aegis/core/post_gen_tasks.py +547 -0
- aegis/core/service_resolver.py +261 -0
- aegis/core/services.py +157 -0
- aegis/core/template_generator.py +266 -0
- aegis/core/version_compatibility.py +259 -0
- aegis/templates/CLAUDE.md +591 -0
- aegis/templates/cookiecutter-aegis-project/cookiecutter.json +39 -0
- aegis/templates/cookiecutter-aegis-project/hooks/post_gen_project.py +214 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/.dockerignore +71 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/.env.example.j2 +130 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/.gitignore +131 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/Dockerfile +53 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/Makefile +236 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/README.md.j2 +196 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/alembic/alembic.ini.j2 +111 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/alembic/env.py.j2 +91 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/alembic/script.py.mako +25 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/alembic/versions/001_initial_auth.py.j2 +51 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/__init__.py +5 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/cli/__init__.py +6 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/cli/ai.py.j2 +700 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/cli/ai_rendering.py +361 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/cli/auth.py.j2 +253 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/cli/health.py.j2 +419 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/cli/load_test.py.j2 +656 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/cli/main.py.j2 +65 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/cli/marko_terminal_renderer.py +489 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/cli/tasks.py.j2 +328 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/cli/{% if cookiecutter.include_scheduler == /"yes/" %}tasks.py{% endif %}" +340 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/__init__.py +0 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/__init__.py +0 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/ai/__init__.py +8 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/ai/router.py +329 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/auth/__init__.py +1 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/auth/router.py +64 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/deps.py +58 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/health.py +163 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/models.py.j2 +280 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/routing.py.j2 +32 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/scheduler.py.j2 +121 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/worker.py.j2 +478 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/hooks.py +144 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/main.py +31 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/middleware/__init__.py +1 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/middleware/cors.py +20 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/shutdown/__init__.py +1 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/shutdown/cleanup.py +14 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/startup/__init__.py +1 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/startup/component_health.py.j2 +418 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/startup/database_init.py.j2 +83 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/__init__.py +5 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/controls/__init__.py +27 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/controls/table.py +78 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/controls/text.py +142 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/__init__.py.j2 +47 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/ai_card.py +287 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/auth_card.py +198 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/base_card.py +256 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/card_factory.py +227 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/card_utils.py +333 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/database_card.py +420 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/fastapi_card.py +328 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/flet_card.py +267 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/redis_card.py +322 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/scheduler_card.py +352 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/services_card.py +233 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/worker_card.py +684 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/main.py.j2 +653 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/theme.py +48 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/scheduler/__init__.py +1 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/scheduler/main.py.j2 +156 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/CLAUDE.md.j2 +213 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/__init__.py +6 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/constants.py.j2 +30 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/pools.py +97 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/queues/__init__.py +1 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/queues/load_test.py +55 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/queues/media.py +49 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/queues/system.py +44 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/registry.py +139 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/tasks/__init__.py +120 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/tasks/load_tasks.py +507 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/tasks/simple_system_tasks.py +33 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/tasks/system_tasks.py +281 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/core/config.py.j2 +178 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/core/constants.py +58 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/core/db.py.j2 +176 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/core/log.py +92 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/core/security.py +62 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/entrypoints/__init__.py +1 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/entrypoints/webserver.py +40 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/entrypoints/{% if cookiecutter.include_scheduler == /"yes/" %}scheduler.py{% endif %}" +21 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/integrations/__init__.py +0 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/integrations/main.py +62 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/models/__init__.py +1 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/models/user.py +44 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/py.typed +0 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/__init__.py +1 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/ai/__init__.py +8 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/ai/config.py +130 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/ai/conversation.py +213 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/ai/health.py +96 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/ai/models.py +229 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/ai/providers.py +370 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/ai/service.py +388 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/auth/__init__.py +1 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/auth/auth_service.py +41 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/auth/health.py +164 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/auth/user_service.py +83 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/backend/middleware_inspector.py.j2 +223 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/backend/models.py.j2 +70 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/backend/route_inspector.py.j2 +155 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/load_test.py +679 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/load_test_models.py +266 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/scheduler/__init__.py.j2 +21 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/scheduler/models.py.j2 +119 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/scheduler/scheduled_task_manager.py.j2 +273 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/scheduler/task_monitor.py.j2 +189 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/shared/__init__.py +15 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/shared/models.py +26 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/system/__init__.py +52 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/system/alerts.py +94 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/system/backup.py.j2 +119 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/system/health.py.j2 +1333 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/system/models.py +243 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/system/ui.py +52 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/assets/aegis-manifesto-dark.png +0 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/assets/aegis-manifesto-square-backup.png +0 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/assets/aegis-manifesto.png +0 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/clean-validation/.dockerignore +71 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/clean-validation/.env.example.j2 +64 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/clean-validation/.gitignore +131 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/clean-validation/Dockerfile +53 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/clean-validation/Makefile +211 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/clean-validation/README.md.j2 +172 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/clean-validation/docker-compose.yml.j2 +78 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/clean-validation/mkdocs.yml.j2 +62 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/clean-validation/pyproject.toml.j2 +120 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/clean-validation/uv.lock +1673 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/docker-compose.yml.j2 +200 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/docs/api.md +191 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/docs/components/scheduler.md +0 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/docs/components/scheduler.md.j2 +621 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/docs/development.md +215 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/docs/health.md +240 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/docs/javascripts/mermaid-config.js +62 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/docs/stylesheets/mermaid.css +95 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/mkdocs.yml.j2 +62 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/pyproject.toml.j2 +131 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/scripts/entrypoint.sh +87 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/scripts/entrypoint.sh.j2 +93 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/scripts/gen_docs.py +16 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/api/__init__.py +1 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/api/test_auth_endpoints.py.j2 +307 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/api/test_health_endpoints.py.j2 +262 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/api/test_scheduler_endpoints.py.j2 +214 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/api/test_worker_endpoints.py.j2 +165 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/cli/test_ai_rendering.py +427 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/cli/test_conversation_memory.py +465 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/components/test_scheduler.py +43 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/conftest.py.j2 +195 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/__init__.py +1 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/ai/__init__.py +1 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/ai/conftest.py +78 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/ai/test_health.py +157 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/ai/test_models.py +164 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/ai/test_service.py +198 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/test_auth_integration.py.j2 +528 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/test_component_integration.py.j2 +387 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/test_conversation_persistence.py +342 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/test_health_logic.py.j2 +663 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/test_load_test_models.py +619 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/test_load_test_service.py +603 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/test_middleware_inspector.py.j2 +248 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/test_scheduled_task_manager.py.j2 +292 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/test_system_service.py +98 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/test_worker_health_registration.py.j2 +257 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/test_core.py +49 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/uv.lock +1673 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/.copier-answers.yml.jinja +21 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/.dockerignore +71 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/.env.example.jinja +130 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/.gitignore +131 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/Dockerfile +53 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/Makefile.jinja +236 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/README.md.jinja +196 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/alembic/alembic.ini.jinja +111 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/alembic/env.py.jinja +91 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/alembic/script.py.mako +25 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/alembic/versions/001_initial_auth.py.jinja +51 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/__init__.py.jinja +5 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/cli/__init__.py.jinja +6 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/cli/ai.py.jinja +700 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/cli/ai_rendering.py +360 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/cli/auth.py.jinja +253 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/cli/health.py.jinja +419 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/cli/load_test.py.jinja +656 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/cli/main.py.jinja +65 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/cli/marko_terminal_renderer.py +489 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/cli/tasks.py.jinja +328 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/__init__.py +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/__init__.py +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/ai/__init__.py +8 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/ai/router.py +329 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/auth/__init__.py +1 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/auth/router.py +64 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/deps.py +58 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/health.py.jinja +163 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/models.py.jinja +280 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/routing.py.jinja +32 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/scheduler.py.jinja +121 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/worker.py.jinja +478 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/hooks.py +144 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/main.py +31 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/middleware/__init__.py +1 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/middleware/cors.py +20 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/shutdown/__init__.py +1 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/shutdown/cleanup.py +14 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/startup/__init__.py +1 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/startup/component_health.py.jinja +418 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/startup/database_init.py.jinja +83 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/__init__.py +5 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/controls/__init__.py +27 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/controls/table.py +78 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/controls/text.py +142 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/__init__.py.jinja +47 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/ai_card.py +287 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/auth_card.py +198 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/base_card.py +256 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/card_factory.py +227 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/card_utils.py +333 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/database_card.py +420 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/fastapi_card.py +328 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/flet_card.py +267 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/redis_card.py +322 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/scheduler_card.py +352 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/services_card.py +233 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/worker_card.py +684 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/main.py.jinja +653 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/theme.py +48 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/scheduler/__init__.py +1 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/scheduler/main.py.jinja +156 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/CLAUDE.md.jinja +213 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/__init__.py +6 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/constants.py.jinja +30 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/pools.py +97 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/queues/__init__.py +1 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/queues/load_test.py +55 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/queues/media.py +49 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/queues/system.py +44 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/registry.py +139 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/tasks/__init__.py +120 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/tasks/load_tasks.py +507 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/tasks/simple_system_tasks.py +33 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/tasks/system_tasks.py +281 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/core/config.py.jinja +178 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/core/constants.py +58 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/core/db.py.jinja +176 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/core/log.py +92 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/core/security.py +62 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/entrypoints/__init__.py +1 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/entrypoints/scheduler.py.jinja +21 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/entrypoints/webserver.py +39 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/integrations/__init__.py +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/integrations/main.py +61 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/models/__init__.py +1 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/models/user.py +44 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/py.typed +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/__init__.py +1 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/ai/__init__.py +8 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/ai/config.py +130 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/ai/conversation.py +213 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/ai/health.py +96 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/ai/models.py +229 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/ai/providers.py.jinja +370 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/ai/service.py +387 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/auth/__init__.py +1 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/auth/auth_service.py +40 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/auth/health.py +162 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/auth/user_service.py +82 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/backend/middleware_inspector.py.jinja +223 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/backend/models.py.jinja +70 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/backend/route_inspector.py.jinja +155 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/load_test.py +678 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/load_test_models.py +265 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/scheduler/__init__.py.jinja +21 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/scheduler/models.py.jinja +119 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/scheduler/scheduled_task_manager.py.jinja +273 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/scheduler/task_monitor.py.jinja +189 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/shared/__init__.py +15 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/shared/models.py +26 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/system/__init__.py +52 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/system/alerts.py +94 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/system/backup.py.jinja +119 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/system/health.py.jinja +1333 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/system/models.py +243 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/system/ui.py +52 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!57223!aegis-manifesto.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!57224!aegis-manifesto-dark.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!57225!aegis-manifesto-square-backup.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!57533!aegis-manifesto.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!57534!aegis-manifesto-dark.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!57538!aegis-manifesto-square-backup.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!57897!aegis-manifesto.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!57898!aegis-manifesto-dark.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!57904!aegis-manifesto-square-backup.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!58315!aegis-manifesto.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!58316!aegis-manifesto-dark.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!58324!aegis-manifesto-square-backup.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!58837!aegis-manifesto.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!58838!aegis-manifesto-dark.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!58849!aegis-manifesto-square-backup.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/aegis-manifesto-dark.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/aegis-manifesto-square-backup.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/aegis-manifesto.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/clean-validation/.env.example.jinja +64 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/clean-validation/README.md.jinja +172 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/clean-validation/docker-compose.yml.jinja +78 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/clean-validation/mkdocs.yml.jinja +62 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/clean-validation/pyproject.toml.jinja +120 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/docker-compose.yml.jinja +200 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/docs/api.md.jinja +191 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/docs/components/scheduler.md +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/docs/components/scheduler.md.jinja +621 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/docs/development.md.jinja +215 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/docs/health.md.jinja +240 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/docs/javascripts/mermaid-config.js +62 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/docs/stylesheets/mermaid.css +95 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/mkdocs.yml.jinja +62 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/pyproject.toml.jinja +131 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/scripts/entrypoint.sh +87 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/scripts/entrypoint.sh.jinja +93 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/scripts/gen_docs.py +16 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/api/__init__.py +1 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/api/test_auth_endpoints.py.jinja +307 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/api/test_health_endpoints.py.jinja +262 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/api/test_scheduler_endpoints.py.jinja +214 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/api/test_worker_endpoints.py.jinja +165 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/cli/test_ai_rendering.py +427 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/cli/test_conversation_memory.py +465 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/components/test_scheduler.py +43 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/conftest.py.jinja +195 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/__init__.py +1 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/ai/__init__.py +1 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/ai/conftest.py +78 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/ai/test_health.py +157 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/ai/test_models.py +164 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/ai/test_service.py +198 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_auth_integration.py.jinja +528 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_component_integration.py.jinja +387 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_conversation_persistence.py +342 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_health_logic.py.jinja +663 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_load_test_models.py +619 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_load_test_service.py +603 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_middleware_inspector.py.jinja +248 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_scheduled_task_manager.py.jinja +292 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_system_service.py +98 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_worker_health_registration.py.jinja +257 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/test_core.py +49 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/uv.lock +1673 -0
- aegis_stack-0.2.0rc2.dist-info/METADATA +165 -0
- aegis_stack-0.2.0rc2.dist-info/RECORD +392 -0
- aegis_stack-0.2.0rc2.dist-info/WHEEL +4 -0
- aegis_stack-0.2.0rc2.dist-info/entry_points.txt +3 -0
- aegis_stack-0.2.0rc2.dist-info/licenses/LICENSE +21 -0
aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/auth/router.py
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"""Authentication API routes."""
|
|
2
|
+
|
|
3
|
+
from app.components.backend.api.deps import get_async_db
|
|
4
|
+
from app.core.security import create_access_token, verify_password
|
|
5
|
+
from app.models.user import UserCreate, UserResponse
|
|
6
|
+
from app.services.auth.auth_service import get_current_user_from_token
|
|
7
|
+
from app.services.auth.user_service import UserService
|
|
8
|
+
from fastapi import APIRouter, Depends, HTTPException, status
|
|
9
|
+
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
|
|
10
|
+
from sqlmodel.ext.asyncio.session import AsyncSession
|
|
11
|
+
|
|
12
|
+
router = APIRouter(prefix="/auth", tags=["authentication"])
|
|
13
|
+
|
|
14
|
+
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/v1/auth/token")
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@router.post("/register", response_model=UserResponse)
|
|
18
|
+
async def register(user_data: UserCreate, db: AsyncSession = Depends(get_async_db)):
|
|
19
|
+
"""Register a new user."""
|
|
20
|
+
user_service = UserService(db)
|
|
21
|
+
|
|
22
|
+
# Check if user already exists
|
|
23
|
+
existing_user = await user_service.get_user_by_email(user_data.email)
|
|
24
|
+
if existing_user:
|
|
25
|
+
raise HTTPException(
|
|
26
|
+
status_code=status.HTTP_400_BAD_REQUEST, detail="Email already registered"
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
# Create new user
|
|
30
|
+
user = await user_service.create_user(user_data)
|
|
31
|
+
return UserResponse.model_validate(user)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@router.post("/token")
|
|
35
|
+
async def login(
|
|
36
|
+
form_data: OAuth2PasswordRequestForm = Depends(),
|
|
37
|
+
db: AsyncSession = Depends(get_async_db),
|
|
38
|
+
):
|
|
39
|
+
"""Login and get access token."""
|
|
40
|
+
user_service = UserService(db)
|
|
41
|
+
|
|
42
|
+
# Get user by email (username field in OAuth2 form)
|
|
43
|
+
user = await user_service.get_user_by_email(form_data.username)
|
|
44
|
+
|
|
45
|
+
if not user or not verify_password(form_data.password, user.hashed_password):
|
|
46
|
+
raise HTTPException(
|
|
47
|
+
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
48
|
+
detail="Incorrect email or password",
|
|
49
|
+
headers={"WWW-Authenticate": "Bearer"},
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
# Create access token
|
|
53
|
+
access_token = create_access_token(data={"sub": user.email})
|
|
54
|
+
return {"access_token": access_token, "token_type": "bearer"}
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
@router.get("/me", response_model=UserResponse)
|
|
58
|
+
async def get_current_user(
|
|
59
|
+
token: str = Depends(oauth2_scheme),
|
|
60
|
+
db: AsyncSession = Depends(get_async_db),
|
|
61
|
+
):
|
|
62
|
+
"""Get current authenticated user."""
|
|
63
|
+
user = await get_current_user_from_token(token, db)
|
|
64
|
+
return UserResponse.model_validate(user)
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"""FastAPI dependencies for the backend API."""
|
|
2
|
+
|
|
3
|
+
from collections.abc import AsyncGenerator, Generator
|
|
4
|
+
|
|
5
|
+
from app.core.db import AsyncSessionLocal, SessionLocal
|
|
6
|
+
from sqlmodel import Session
|
|
7
|
+
from sqlmodel.ext.asyncio.session import AsyncSession
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def get_db() -> Generator[Session, None, None]:
|
|
11
|
+
"""
|
|
12
|
+
Database dependency that provides a database session.
|
|
13
|
+
|
|
14
|
+
This dependency is used in FastAPI route functions to get access to
|
|
15
|
+
the database. It automatically handles session lifecycle - creating,
|
|
16
|
+
yielding, and closing the session properly.
|
|
17
|
+
|
|
18
|
+
Usage:
|
|
19
|
+
@router.get("/example")
|
|
20
|
+
def example_endpoint(db: Session = Depends(get_db)):
|
|
21
|
+
# Use db for database operations
|
|
22
|
+
pass
|
|
23
|
+
|
|
24
|
+
Yields:
|
|
25
|
+
Session: SQLModel database session
|
|
26
|
+
"""
|
|
27
|
+
db = SessionLocal()
|
|
28
|
+
try:
|
|
29
|
+
yield db
|
|
30
|
+
finally:
|
|
31
|
+
db.close()
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
async def get_async_db() -> AsyncGenerator[AsyncSession, None]:
|
|
35
|
+
"""
|
|
36
|
+
Async database dependency that provides an async database session.
|
|
37
|
+
|
|
38
|
+
This dependency is used in async FastAPI route functions to get access to
|
|
39
|
+
the database with non-blocking I/O operations. It automatically handles
|
|
40
|
+
session lifecycle - creating, yielding, committing and closing the session properly.
|
|
41
|
+
|
|
42
|
+
Usage:
|
|
43
|
+
@router.get("/example")
|
|
44
|
+
async def example_endpoint(db: AsyncSession = Depends(get_async_db)):
|
|
45
|
+
# Use db for async database operations with await
|
|
46
|
+
result = await db.exec(select(MyModel))
|
|
47
|
+
return result.first()
|
|
48
|
+
|
|
49
|
+
Yields:
|
|
50
|
+
AsyncSession: SQLModel async database session
|
|
51
|
+
"""
|
|
52
|
+
async with AsyncSessionLocal() as session:
|
|
53
|
+
try:
|
|
54
|
+
yield session
|
|
55
|
+
await session.commit()
|
|
56
|
+
except Exception:
|
|
57
|
+
await session.rollback()
|
|
58
|
+
raise
|
aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/health.py.jinja
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
from app.services.system import (
|
|
4
|
+
DetailedHealthResponse,
|
|
5
|
+
HealthResponse,
|
|
6
|
+
get_system_status,
|
|
7
|
+
)
|
|
8
|
+
from fastapi import APIRouter, HTTPException
|
|
9
|
+
from starlette import status
|
|
10
|
+
|
|
11
|
+
router = APIRouter()
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@router.get("/", response_model=HealthResponse)
|
|
15
|
+
async def health_check() -> HealthResponse:
|
|
16
|
+
"""
|
|
17
|
+
Quick health check endpoint.
|
|
18
|
+
|
|
19
|
+
Returns basic healthy/unhealthy status for load balancers and monitoring.
|
|
20
|
+
"""
|
|
21
|
+
try:
|
|
22
|
+
system_status = await get_system_status()
|
|
23
|
+
return HealthResponse(
|
|
24
|
+
healthy=system_status.overall_healthy,
|
|
25
|
+
status="healthy" if system_status.overall_healthy else "unhealthy",
|
|
26
|
+
components=system_status.components,
|
|
27
|
+
timestamp=system_status.timestamp.isoformat(),
|
|
28
|
+
)
|
|
29
|
+
except Exception:
|
|
30
|
+
# If health checks fail completely, consider unhealthy
|
|
31
|
+
return HealthResponse(
|
|
32
|
+
healthy=False,
|
|
33
|
+
status="unhealthy",
|
|
34
|
+
components={},
|
|
35
|
+
timestamp="",
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@router.get("/detailed", response_model=DetailedHealthResponse)
|
|
40
|
+
async def detailed_health() -> DetailedHealthResponse:
|
|
41
|
+
"""
|
|
42
|
+
Detailed health check with component information.
|
|
43
|
+
|
|
44
|
+
Returns comprehensive system status including individual component health,
|
|
45
|
+
system metrics, and diagnostic information.
|
|
46
|
+
"""
|
|
47
|
+
try:
|
|
48
|
+
system_status = await get_system_status()
|
|
49
|
+
|
|
50
|
+
# Always return 200 OK - service is available even if components are unhealthy
|
|
51
|
+
return DetailedHealthResponse(
|
|
52
|
+
healthy=system_status.overall_healthy,
|
|
53
|
+
status="healthy" if system_status.overall_healthy else "unhealthy",
|
|
54
|
+
service="{{ project_name }}",
|
|
55
|
+
version="0.1.0",
|
|
56
|
+
components=system_status.components,
|
|
57
|
+
system_info=system_status.system_info,
|
|
58
|
+
timestamp=system_status.timestamp.isoformat(),
|
|
59
|
+
healthy_components=system_status.healthy_components,
|
|
60
|
+
unhealthy_components=system_status.unhealthy_components,
|
|
61
|
+
health_percentage=system_status.health_percentage,
|
|
62
|
+
# Service-specific information
|
|
63
|
+
has_services=system_status.has_services,
|
|
64
|
+
service_names=system_status.service_names,
|
|
65
|
+
healthy_services=system_status.healthy_services,
|
|
66
|
+
unhealthy_services=system_status.unhealthy_services,
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
except HTTPException:
|
|
70
|
+
# Re-raise HTTP exceptions from unexpected errors
|
|
71
|
+
raise
|
|
72
|
+
except Exception as e:
|
|
73
|
+
# Handle unexpected errors
|
|
74
|
+
raise HTTPException(
|
|
75
|
+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
76
|
+
detail={
|
|
77
|
+
"message": "Health check failed",
|
|
78
|
+
"error": str(e),
|
|
79
|
+
"status": "unhealthy",
|
|
80
|
+
},
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
@router.get("/dashboard")
|
|
85
|
+
async def system_dashboard() -> dict[str, Any]:
|
|
86
|
+
"""
|
|
87
|
+
System dashboard endpoint optimized for frontend consumption.
|
|
88
|
+
|
|
89
|
+
Returns system status with additional dashboard metadata like
|
|
90
|
+
alert counts, trend data, and formatted display information.
|
|
91
|
+
"""
|
|
92
|
+
try:
|
|
93
|
+
system_status = await get_system_status()
|
|
94
|
+
|
|
95
|
+
# TODO: Implement alert tracking when alert management is enhanced
|
|
96
|
+
recent_alerts = 0
|
|
97
|
+
|
|
98
|
+
return {
|
|
99
|
+
"status": "healthy" if system_status.overall_healthy else "unhealthy",
|
|
100
|
+
"service": "{{ project_name }}",
|
|
101
|
+
"version": "0.1.0",
|
|
102
|
+
"dashboard_data": {
|
|
103
|
+
"overall_status": {
|
|
104
|
+
"healthy": system_status.overall_healthy,
|
|
105
|
+
"percentage": system_status.health_percentage,
|
|
106
|
+
"status_text": (
|
|
107
|
+
"System Healthy"
|
|
108
|
+
if system_status.overall_healthy
|
|
109
|
+
else "Issues Detected"
|
|
110
|
+
),
|
|
111
|
+
},
|
|
112
|
+
"components": {
|
|
113
|
+
name: {
|
|
114
|
+
"name": name,
|
|
115
|
+
"healthy": component.healthy,
|
|
116
|
+
"message": component.message,
|
|
117
|
+
"response_time_ms": component.response_time_ms,
|
|
118
|
+
"metadata": component.metadata,
|
|
119
|
+
}
|
|
120
|
+
for name, component in system_status.components.items()
|
|
121
|
+
},
|
|
122
|
+
"summary": {
|
|
123
|
+
"total_components": len(system_status.components),
|
|
124
|
+
"healthy_components": len(system_status.healthy_components),
|
|
125
|
+
"unhealthy_components": len(system_status.unhealthy_components),
|
|
126
|
+
"recent_alerts": recent_alerts,
|
|
127
|
+
# Service summary information
|
|
128
|
+
"has_services": system_status.has_services,
|
|
129
|
+
"total_services": len(system_status.service_names),
|
|
130
|
+
"healthy_services": len(system_status.healthy_services),
|
|
131
|
+
"unhealthy_services": len(system_status.unhealthy_services),
|
|
132
|
+
},
|
|
133
|
+
# Services section for frontend consumption
|
|
134
|
+
"services": {
|
|
135
|
+
"enabled": system_status.has_services,
|
|
136
|
+
"services": {
|
|
137
|
+
name: {
|
|
138
|
+
"name": name,
|
|
139
|
+
"healthy": service.healthy,
|
|
140
|
+
"message": service.message,
|
|
141
|
+
"response_time_ms": service.response_time_ms,
|
|
142
|
+
"metadata": service.metadata,
|
|
143
|
+
}
|
|
144
|
+
for name, service in (
|
|
145
|
+
system_status.services_status.sub_components.items()
|
|
146
|
+
if system_status.services_status
|
|
147
|
+
else {}
|
|
148
|
+
).items()
|
|
149
|
+
}
|
|
150
|
+
if system_status.has_services
|
|
151
|
+
else {},
|
|
152
|
+
},
|
|
153
|
+
"system_info": system_status.system_info,
|
|
154
|
+
"timestamp": system_status.timestamp.isoformat(),
|
|
155
|
+
"last_updated": system_status.timestamp.strftime("%H:%M:%S"),
|
|
156
|
+
},
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
except Exception as e:
|
|
160
|
+
raise HTTPException(
|
|
161
|
+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
162
|
+
detail={"message": "Dashboard data unavailable", "error": str(e)},
|
|
163
|
+
)
|
aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/models.py.jinja
ADDED
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
"""
|
|
2
|
+
API models for{%- if include_worker %} background tasks{%- endif %}{%- if include_worker and scheduler_backend != "memory" %} and{%- endif %}{%- if scheduler_backend != "memory" %} scheduled tasks{%- endif %} and responses.
|
|
3
|
+
|
|
4
|
+
This module contains all Pydantic models used by the API layer for
|
|
5
|
+
task management, status tracking, and response formatting.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
{%- if include_worker or scheduler_backend != "memory" %}
|
|
9
|
+
from datetime import datetime
|
|
10
|
+
from typing import Any
|
|
11
|
+
|
|
12
|
+
from pydantic import BaseModel, Field
|
|
13
|
+
{%- endif %}
|
|
14
|
+
|
|
15
|
+
{%- if include_worker %}
|
|
16
|
+
from app.components.worker.constants import LoadTestTypes
|
|
17
|
+
{%- endif %}
|
|
18
|
+
|
|
19
|
+
{%- if scheduler_backend != "memory" %}
|
|
20
|
+
from app.services.scheduler.models import ScheduledTask, TaskStatistics
|
|
21
|
+
{%- endif %}
|
|
22
|
+
|
|
23
|
+
{%- if include_worker %}
|
|
24
|
+
|
|
25
|
+
class TaskRequest(BaseModel):
|
|
26
|
+
"""Request model for enqueueing a background task."""
|
|
27
|
+
|
|
28
|
+
task_name: str = Field(..., description="Name of the task function to execute")
|
|
29
|
+
queue_type: str = Field(
|
|
30
|
+
"system", description="Functional queue type: media or system"
|
|
31
|
+
)
|
|
32
|
+
args: list[Any] = Field(
|
|
33
|
+
default_factory=list, description="Positional arguments for the task"
|
|
34
|
+
)
|
|
35
|
+
task_kwargs: dict[str, Any] = Field(
|
|
36
|
+
default_factory=dict, description="Keyword arguments for the task"
|
|
37
|
+
)
|
|
38
|
+
delay_seconds: int | None = Field(
|
|
39
|
+
None, description="Delay task execution by this many seconds"
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class TaskResponse(BaseModel):
|
|
44
|
+
"""Response model for task enqueue operations."""
|
|
45
|
+
|
|
46
|
+
task_id: str
|
|
47
|
+
task_name: str
|
|
48
|
+
queue_type: str
|
|
49
|
+
queued_at: datetime
|
|
50
|
+
estimated_start: datetime | None = None
|
|
51
|
+
message: str
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class TaskListResponse(BaseModel):
|
|
55
|
+
"""Response model for listing available tasks."""
|
|
56
|
+
|
|
57
|
+
available_tasks: list[str]
|
|
58
|
+
total_count: int
|
|
59
|
+
queues: dict[str, list[str]]
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class TaskStatusResponse(BaseModel):
|
|
63
|
+
"""Response model for task status checks."""
|
|
64
|
+
|
|
65
|
+
task_id: str
|
|
66
|
+
status: str = Field(
|
|
67
|
+
...,
|
|
68
|
+
description="Task status: queued, in_progress, complete, failed, unknown",
|
|
69
|
+
)
|
|
70
|
+
enqueue_time: datetime | None = Field(
|
|
71
|
+
None, description="When the task was enqueued"
|
|
72
|
+
)
|
|
73
|
+
start_time: datetime | None = Field(
|
|
74
|
+
None, description="When the task started processing"
|
|
75
|
+
)
|
|
76
|
+
finish_time: datetime | None = Field(None, description="When the task completed")
|
|
77
|
+
result_available: bool = Field(
|
|
78
|
+
False, description="Whether task result is available"
|
|
79
|
+
)
|
|
80
|
+
error: str | None = Field(None, description="Error message if task failed")
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class TaskResultResponse(BaseModel):
|
|
84
|
+
"""Response model for completed task results."""
|
|
85
|
+
|
|
86
|
+
task_id: str
|
|
87
|
+
status: str = Field(..., description="Task completion status")
|
|
88
|
+
result: Any = Field(..., description="The actual task result data")
|
|
89
|
+
enqueue_time: datetime | None = Field(
|
|
90
|
+
None, description="When the task was enqueued"
|
|
91
|
+
)
|
|
92
|
+
start_time: datetime | None = Field(
|
|
93
|
+
None, description="When the task started processing"
|
|
94
|
+
)
|
|
95
|
+
finish_time: datetime | None = Field(None, description="When the task completed")
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
class LoadTestRequest(BaseModel):
|
|
99
|
+
"""Request model for orchestrating load tests that measure queue throughput."""
|
|
100
|
+
|
|
101
|
+
num_tasks: int = Field(
|
|
102
|
+
100,
|
|
103
|
+
description="Number of tasks to spawn for the load test",
|
|
104
|
+
ge=10,
|
|
105
|
+
le=10000
|
|
106
|
+
)
|
|
107
|
+
task_type: LoadTestTypes = Field(
|
|
108
|
+
LoadTestTypes.CPU_INTENSIVE,
|
|
109
|
+
description="Type of worker task to spawn for load testing",
|
|
110
|
+
)
|
|
111
|
+
batch_size: int = Field(
|
|
112
|
+
10,
|
|
113
|
+
description="How many tasks to send concurrently per batch",
|
|
114
|
+
ge=1,
|
|
115
|
+
le=100
|
|
116
|
+
)
|
|
117
|
+
delay_ms: int = Field(
|
|
118
|
+
0,
|
|
119
|
+
description="Delay between batches in milliseconds",
|
|
120
|
+
ge=0,
|
|
121
|
+
le=5000
|
|
122
|
+
)
|
|
123
|
+
target_queue: str = Field(
|
|
124
|
+
"load_test",
|
|
125
|
+
description="Which queue to test (system, media, or load_test)",
|
|
126
|
+
pattern="^(system|media|load_test)$"
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
class Config:
|
|
130
|
+
schema_extra = {
|
|
131
|
+
"examples": [
|
|
132
|
+
{
|
|
133
|
+
"description": (
|
|
134
|
+
"Quick CPU load test - fibonacci calculations and operations"
|
|
135
|
+
),
|
|
136
|
+
"num_tasks": 50,
|
|
137
|
+
"task_type": "cpu_intensive",
|
|
138
|
+
"batch_size": 10,
|
|
139
|
+
"delay_ms": 0,
|
|
140
|
+
"target_queue": "system",
|
|
141
|
+
"expected_work": (
|
|
142
|
+
"Computational: fibonacci, prime checking, math operations"
|
|
143
|
+
),
|
|
144
|
+
"expected_metrics": [
|
|
145
|
+
"fibonacci_result",
|
|
146
|
+
"math_operations_sum",
|
|
147
|
+
"operations_per_ms",
|
|
148
|
+
]
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
"description": (
|
|
152
|
+
"I/O stress test - async operations and concurrent handling"
|
|
153
|
+
),
|
|
154
|
+
"num_tasks": 200,
|
|
155
|
+
"task_type": "io_simulation",
|
|
156
|
+
"batch_size": 20,
|
|
157
|
+
"delay_ms": 50,
|
|
158
|
+
"target_queue": "system",
|
|
159
|
+
"expected_work": (
|
|
160
|
+
"Async I/O: network delays, concurrent operations, files"
|
|
161
|
+
),
|
|
162
|
+
"expected_metrics": [
|
|
163
|
+
"concurrent_operations",
|
|
164
|
+
"io_efficiency_percent",
|
|
165
|
+
"concurrency_benefit",
|
|
166
|
+
]
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
"description": (
|
|
170
|
+
"Memory allocation test - data structures and GC pressure"
|
|
171
|
+
),
|
|
172
|
+
"num_tasks": 500,
|
|
173
|
+
"task_type": "memory_operations",
|
|
174
|
+
"batch_size": 25,
|
|
175
|
+
"delay_ms": 0,
|
|
176
|
+
"target_queue": "media",
|
|
177
|
+
"expected_work": (
|
|
178
|
+
"Memory: allocation patterns, data manipulation, cleanup"
|
|
179
|
+
),
|
|
180
|
+
"expected_metrics": [
|
|
181
|
+
"estimated_peak_memory_mb",
|
|
182
|
+
"memory_throughput_mb_per_sec",
|
|
183
|
+
"memory_operations_count",
|
|
184
|
+
]
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
"description": (
|
|
188
|
+
"Failure resilience test - ~20% random failures for errors"
|
|
189
|
+
),
|
|
190
|
+
"num_tasks": 100,
|
|
191
|
+
"task_type": "test_task_failure",
|
|
192
|
+
"batch_size": 15,
|
|
193
|
+
"delay_ms": 0,
|
|
194
|
+
"target_queue": "system",
|
|
195
|
+
"expected_work": (
|
|
196
|
+
"Failure testing: random errors, recovery patterns, resilience"
|
|
197
|
+
),
|
|
198
|
+
"expected_metrics": [
|
|
199
|
+
"failure_roll",
|
|
200
|
+
"failure_threshold",
|
|
201
|
+
"would_have_failed",
|
|
202
|
+
]
|
|
203
|
+
}
|
|
204
|
+
]
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
class LoadTestStatus(BaseModel):
|
|
209
|
+
"""Status model for monitoring active load tests."""
|
|
210
|
+
|
|
211
|
+
test_id: str = Field(..., description="Unique load test identifier")
|
|
212
|
+
status: str = Field(..., description="Test status: running, completed, failed")
|
|
213
|
+
tasks_sent: int = Field(..., description="Number of tasks sent to queue")
|
|
214
|
+
tasks_completed: int = Field(..., description="Number of tasks completed")
|
|
215
|
+
tasks_failed: int = Field(0, description="Number of tasks that failed")
|
|
216
|
+
elapsed_seconds: float = Field(..., description="Time elapsed since test start")
|
|
217
|
+
current_throughput: float = Field(..., description="Current tasks per second")
|
|
218
|
+
estimated_completion: datetime | None = Field(
|
|
219
|
+
None, description="Estimated completion time"
|
|
220
|
+
)
|
|
221
|
+
queue_depth: int = Field(0, description="Current queue depth")
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
class LoadTestResults(BaseModel):
|
|
225
|
+
"""Final results model for completed load tests."""
|
|
226
|
+
|
|
227
|
+
test_id: str = Field(..., description="Unique load test identifier")
|
|
228
|
+
status: str = Field(..., description="Final test status")
|
|
229
|
+
configuration: LoadTestRequest = Field(..., description="Test configuration used")
|
|
230
|
+
|
|
231
|
+
# Task metrics
|
|
232
|
+
tasks_sent: int = Field(..., description="Total tasks sent")
|
|
233
|
+
tasks_completed: int = Field(..., description="Total tasks completed")
|
|
234
|
+
tasks_failed: int = Field(..., description="Total tasks failed")
|
|
235
|
+
|
|
236
|
+
# Timing metrics
|
|
237
|
+
start_time: datetime = Field(..., description="Test start time")
|
|
238
|
+
end_time: datetime | None = Field(None, description="Test end time")
|
|
239
|
+
total_duration_seconds: float = Field(..., description="Total test duration")
|
|
240
|
+
|
|
241
|
+
# Performance metrics
|
|
242
|
+
overall_throughput: float = Field(..., description="Overall tasks per second")
|
|
243
|
+
peak_throughput: float = Field(..., description="Peak throughput achieved")
|
|
244
|
+
failure_rate: float = Field(..., description="Percentage of tasks that failed")
|
|
245
|
+
|
|
246
|
+
# Queue metrics
|
|
247
|
+
final_queue_metrics: dict[str, Any] = Field(
|
|
248
|
+
..., description="Final arq queue health data"
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
# Summary
|
|
252
|
+
performance_summary: str = Field(
|
|
253
|
+
..., description="Human readable performance summary"
|
|
254
|
+
)
|
|
255
|
+
{%- endif %}
|
|
256
|
+
|
|
257
|
+
{%- if scheduler_backend != "memory" %}
|
|
258
|
+
|
|
259
|
+
# ============================================================================
|
|
260
|
+
# SCHEDULED TASK API MODELS
|
|
261
|
+
# ============================================================================
|
|
262
|
+
|
|
263
|
+
class ScheduledTaskListResponse(BaseModel):
|
|
264
|
+
"""Response model for listing scheduled tasks."""
|
|
265
|
+
|
|
266
|
+
tasks: list[ScheduledTask] = Field(..., description="List of scheduled tasks")
|
|
267
|
+
total_count: int = Field(..., description="Total number of scheduled tasks")
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
class ScheduledTaskDetailResponse(BaseModel):
|
|
271
|
+
"""Response model for scheduled task details."""
|
|
272
|
+
|
|
273
|
+
task: ScheduledTask = Field(..., description="Detailed scheduled task information")
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
class ScheduledTaskStatisticsResponse(BaseModel):
|
|
277
|
+
"""Response model for scheduled task statistics."""
|
|
278
|
+
|
|
279
|
+
statistics: TaskStatistics = Field(..., description="Task statistics summary")
|
|
280
|
+
{%- endif %}
|
aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/routing.py.jinja
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
from fastapi import FastAPI
|
|
2
|
+
|
|
3
|
+
from app.components.backend.api import health
|
|
4
|
+
{%- if include_worker %}
|
|
5
|
+
from app.components.backend.api import worker
|
|
6
|
+
{%- endif %}
|
|
7
|
+
{%- if scheduler_backend != "memory" %}
|
|
8
|
+
from app.components.backend.api import scheduler
|
|
9
|
+
{%- endif %}
|
|
10
|
+
{%- if include_auth %}
|
|
11
|
+
from app.components.backend.api.auth.router import router as auth_router
|
|
12
|
+
{%- endif %}
|
|
13
|
+
{%- if include_ai %}
|
|
14
|
+
from app.components.backend.api.ai.router import router as ai_router
|
|
15
|
+
{%- endif %}
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def include_routers(app: FastAPI) -> None:
|
|
19
|
+
"""Include all API routers in the FastAPI app"""
|
|
20
|
+
app.include_router(health.router, prefix="/health", tags=["health"])
|
|
21
|
+
{%- if include_worker %}
|
|
22
|
+
app.include_router(worker.router, prefix="/api/v1", tags=["worker"])
|
|
23
|
+
{%- endif %}
|
|
24
|
+
{%- if scheduler_backend != "memory" %}
|
|
25
|
+
app.include_router(scheduler.router, prefix="/api/v1", tags=["scheduler"])
|
|
26
|
+
{%- endif %}
|
|
27
|
+
{%- if include_auth %}
|
|
28
|
+
app.include_router(auth_router, prefix="/api/v1")
|
|
29
|
+
{%- endif %}
|
|
30
|
+
{%- if include_ai %}
|
|
31
|
+
app.include_router(ai_router)
|
|
32
|
+
{%- endif %}
|