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.
Files changed (392) hide show
  1. aegis/__init__.py +5 -0
  2. aegis/__main__.py +51 -0
  3. aegis/cli/__init__.py +6 -0
  4. aegis/cli/callbacks.py +114 -0
  5. aegis/cli/interactive.py +611 -0
  6. aegis/cli/utils.py +70 -0
  7. aegis/cli/validators.py +34 -0
  8. aegis/commands/__init__.py +6 -0
  9. aegis/commands/add.py +353 -0
  10. aegis/commands/add_service.py +332 -0
  11. aegis/commands/components.py +35 -0
  12. aegis/commands/init.py +370 -0
  13. aegis/commands/remove.py +227 -0
  14. aegis/commands/services.py +52 -0
  15. aegis/commands/update.py +252 -0
  16. aegis/commands/version.py +12 -0
  17. aegis/config/__init__.py +1 -0
  18. aegis/config/shared_files.py +136 -0
  19. aegis/core/CLAUDE.md +377 -0
  20. aegis/core/__init__.py +6 -0
  21. aegis/core/component_files.py +228 -0
  22. aegis/core/component_utils.py +220 -0
  23. aegis/core/components.py +127 -0
  24. aegis/core/copier_manager.py +315 -0
  25. aegis/core/copier_updater.py +475 -0
  26. aegis/core/dependency_resolver.py +119 -0
  27. aegis/core/manual_updater.py +554 -0
  28. aegis/core/post_gen_tasks.py +547 -0
  29. aegis/core/service_resolver.py +261 -0
  30. aegis/core/services.py +157 -0
  31. aegis/core/template_generator.py +266 -0
  32. aegis/core/version_compatibility.py +259 -0
  33. aegis/templates/CLAUDE.md +591 -0
  34. aegis/templates/cookiecutter-aegis-project/cookiecutter.json +39 -0
  35. aegis/templates/cookiecutter-aegis-project/hooks/post_gen_project.py +214 -0
  36. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/.dockerignore +71 -0
  37. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/.env.example.j2 +130 -0
  38. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/.gitignore +131 -0
  39. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/Dockerfile +53 -0
  40. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/Makefile +236 -0
  41. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/README.md.j2 +196 -0
  42. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/alembic/alembic.ini.j2 +111 -0
  43. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/alembic/env.py.j2 +91 -0
  44. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/alembic/script.py.mako +25 -0
  45. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/alembic/versions/001_initial_auth.py.j2 +51 -0
  46. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/__init__.py +5 -0
  47. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/cli/__init__.py +6 -0
  48. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/cli/ai.py.j2 +700 -0
  49. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/cli/ai_rendering.py +361 -0
  50. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/cli/auth.py.j2 +253 -0
  51. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/cli/health.py.j2 +419 -0
  52. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/cli/load_test.py.j2 +656 -0
  53. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/cli/main.py.j2 +65 -0
  54. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/cli/marko_terminal_renderer.py +489 -0
  55. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/cli/tasks.py.j2 +328 -0
  56. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/cli/{% if cookiecutter.include_scheduler == /"yes/" %}tasks.py{% endif %}" +340 -0
  57. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/__init__.py +0 -0
  58. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/__init__.py +0 -0
  59. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/ai/__init__.py +8 -0
  60. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/ai/router.py +329 -0
  61. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/auth/__init__.py +1 -0
  62. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/auth/router.py +64 -0
  63. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/deps.py +58 -0
  64. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/health.py +163 -0
  65. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/models.py.j2 +280 -0
  66. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/routing.py.j2 +32 -0
  67. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/scheduler.py.j2 +121 -0
  68. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/worker.py.j2 +478 -0
  69. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/hooks.py +144 -0
  70. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/main.py +31 -0
  71. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/middleware/__init__.py +1 -0
  72. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/middleware/cors.py +20 -0
  73. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/shutdown/__init__.py +1 -0
  74. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/shutdown/cleanup.py +14 -0
  75. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/startup/__init__.py +1 -0
  76. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/startup/component_health.py.j2 +418 -0
  77. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/startup/database_init.py.j2 +83 -0
  78. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/__init__.py +5 -0
  79. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/controls/__init__.py +27 -0
  80. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/controls/table.py +78 -0
  81. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/controls/text.py +142 -0
  82. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/__init__.py.j2 +47 -0
  83. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/ai_card.py +287 -0
  84. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/auth_card.py +198 -0
  85. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/base_card.py +256 -0
  86. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/card_factory.py +227 -0
  87. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/card_utils.py +333 -0
  88. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/database_card.py +420 -0
  89. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/fastapi_card.py +328 -0
  90. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/flet_card.py +267 -0
  91. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/redis_card.py +322 -0
  92. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/scheduler_card.py +352 -0
  93. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/services_card.py +233 -0
  94. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/worker_card.py +684 -0
  95. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/main.py.j2 +653 -0
  96. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/theme.py +48 -0
  97. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/scheduler/__init__.py +1 -0
  98. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/scheduler/main.py.j2 +156 -0
  99. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/CLAUDE.md.j2 +213 -0
  100. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/__init__.py +6 -0
  101. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/constants.py.j2 +30 -0
  102. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/pools.py +97 -0
  103. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/queues/__init__.py +1 -0
  104. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/queues/load_test.py +55 -0
  105. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/queues/media.py +49 -0
  106. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/queues/system.py +44 -0
  107. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/registry.py +139 -0
  108. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/tasks/__init__.py +120 -0
  109. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/tasks/load_tasks.py +507 -0
  110. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/tasks/simple_system_tasks.py +33 -0
  111. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/tasks/system_tasks.py +281 -0
  112. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/core/config.py.j2 +178 -0
  113. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/core/constants.py +58 -0
  114. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/core/db.py.j2 +176 -0
  115. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/core/log.py +92 -0
  116. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/core/security.py +62 -0
  117. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/entrypoints/__init__.py +1 -0
  118. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/entrypoints/webserver.py +40 -0
  119. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/entrypoints/{% if cookiecutter.include_scheduler == /"yes/" %}scheduler.py{% endif %}" +21 -0
  120. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/integrations/__init__.py +0 -0
  121. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/integrations/main.py +62 -0
  122. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/models/__init__.py +1 -0
  123. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/models/user.py +44 -0
  124. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/py.typed +0 -0
  125. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/__init__.py +1 -0
  126. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/ai/__init__.py +8 -0
  127. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/ai/config.py +130 -0
  128. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/ai/conversation.py +213 -0
  129. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/ai/health.py +96 -0
  130. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/ai/models.py +229 -0
  131. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/ai/providers.py +370 -0
  132. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/ai/service.py +388 -0
  133. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/auth/__init__.py +1 -0
  134. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/auth/auth_service.py +41 -0
  135. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/auth/health.py +164 -0
  136. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/auth/user_service.py +83 -0
  137. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/backend/middleware_inspector.py.j2 +223 -0
  138. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/backend/models.py.j2 +70 -0
  139. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/backend/route_inspector.py.j2 +155 -0
  140. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/load_test.py +679 -0
  141. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/load_test_models.py +266 -0
  142. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/scheduler/__init__.py.j2 +21 -0
  143. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/scheduler/models.py.j2 +119 -0
  144. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/scheduler/scheduled_task_manager.py.j2 +273 -0
  145. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/scheduler/task_monitor.py.j2 +189 -0
  146. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/shared/__init__.py +15 -0
  147. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/shared/models.py +26 -0
  148. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/system/__init__.py +52 -0
  149. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/system/alerts.py +94 -0
  150. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/system/backup.py.j2 +119 -0
  151. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/system/health.py.j2 +1333 -0
  152. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/system/models.py +243 -0
  153. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/system/ui.py +52 -0
  154. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/assets/aegis-manifesto-dark.png +0 -0
  155. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/assets/aegis-manifesto-square-backup.png +0 -0
  156. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/assets/aegis-manifesto.png +0 -0
  157. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/clean-validation/.dockerignore +71 -0
  158. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/clean-validation/.env.example.j2 +64 -0
  159. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/clean-validation/.gitignore +131 -0
  160. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/clean-validation/Dockerfile +53 -0
  161. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/clean-validation/Makefile +211 -0
  162. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/clean-validation/README.md.j2 +172 -0
  163. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/clean-validation/docker-compose.yml.j2 +78 -0
  164. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/clean-validation/mkdocs.yml.j2 +62 -0
  165. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/clean-validation/pyproject.toml.j2 +120 -0
  166. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/clean-validation/uv.lock +1673 -0
  167. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/docker-compose.yml.j2 +200 -0
  168. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/docs/api.md +191 -0
  169. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/docs/components/scheduler.md +0 -0
  170. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/docs/components/scheduler.md.j2 +621 -0
  171. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/docs/development.md +215 -0
  172. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/docs/health.md +240 -0
  173. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/docs/javascripts/mermaid-config.js +62 -0
  174. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/docs/stylesheets/mermaid.css +95 -0
  175. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/mkdocs.yml.j2 +62 -0
  176. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/pyproject.toml.j2 +131 -0
  177. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/scripts/entrypoint.sh +87 -0
  178. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/scripts/entrypoint.sh.j2 +93 -0
  179. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/scripts/gen_docs.py +16 -0
  180. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/api/__init__.py +1 -0
  181. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/api/test_auth_endpoints.py.j2 +307 -0
  182. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/api/test_health_endpoints.py.j2 +262 -0
  183. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/api/test_scheduler_endpoints.py.j2 +214 -0
  184. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/api/test_worker_endpoints.py.j2 +165 -0
  185. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/cli/test_ai_rendering.py +427 -0
  186. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/cli/test_conversation_memory.py +465 -0
  187. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/components/test_scheduler.py +43 -0
  188. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/conftest.py.j2 +195 -0
  189. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/__init__.py +1 -0
  190. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/ai/__init__.py +1 -0
  191. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/ai/conftest.py +78 -0
  192. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/ai/test_health.py +157 -0
  193. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/ai/test_models.py +164 -0
  194. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/ai/test_service.py +198 -0
  195. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/test_auth_integration.py.j2 +528 -0
  196. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/test_component_integration.py.j2 +387 -0
  197. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/test_conversation_persistence.py +342 -0
  198. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/test_health_logic.py.j2 +663 -0
  199. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/test_load_test_models.py +619 -0
  200. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/test_load_test_service.py +603 -0
  201. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/test_middleware_inspector.py.j2 +248 -0
  202. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/test_scheduled_task_manager.py.j2 +292 -0
  203. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/test_system_service.py +98 -0
  204. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/test_worker_health_registration.py.j2 +257 -0
  205. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/test_core.py +49 -0
  206. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/uv.lock +1673 -0
  207. aegis/templates/copier-aegis-project/{{ project_slug }}/.copier-answers.yml.jinja +21 -0
  208. aegis/templates/copier-aegis-project/{{ project_slug }}/.dockerignore +71 -0
  209. aegis/templates/copier-aegis-project/{{ project_slug }}/.env.example.jinja +130 -0
  210. aegis/templates/copier-aegis-project/{{ project_slug }}/.gitignore +131 -0
  211. aegis/templates/copier-aegis-project/{{ project_slug }}/Dockerfile +53 -0
  212. aegis/templates/copier-aegis-project/{{ project_slug }}/Makefile.jinja +236 -0
  213. aegis/templates/copier-aegis-project/{{ project_slug }}/README.md.jinja +196 -0
  214. aegis/templates/copier-aegis-project/{{ project_slug }}/alembic/alembic.ini.jinja +111 -0
  215. aegis/templates/copier-aegis-project/{{ project_slug }}/alembic/env.py.jinja +91 -0
  216. aegis/templates/copier-aegis-project/{{ project_slug }}/alembic/script.py.mako +25 -0
  217. aegis/templates/copier-aegis-project/{{ project_slug }}/alembic/versions/001_initial_auth.py.jinja +51 -0
  218. aegis/templates/copier-aegis-project/{{ project_slug }}/app/__init__.py.jinja +5 -0
  219. aegis/templates/copier-aegis-project/{{ project_slug }}/app/cli/__init__.py.jinja +6 -0
  220. aegis/templates/copier-aegis-project/{{ project_slug }}/app/cli/ai.py.jinja +700 -0
  221. aegis/templates/copier-aegis-project/{{ project_slug }}/app/cli/ai_rendering.py +360 -0
  222. aegis/templates/copier-aegis-project/{{ project_slug }}/app/cli/auth.py.jinja +253 -0
  223. aegis/templates/copier-aegis-project/{{ project_slug }}/app/cli/health.py.jinja +419 -0
  224. aegis/templates/copier-aegis-project/{{ project_slug }}/app/cli/load_test.py.jinja +656 -0
  225. aegis/templates/copier-aegis-project/{{ project_slug }}/app/cli/main.py.jinja +65 -0
  226. aegis/templates/copier-aegis-project/{{ project_slug }}/app/cli/marko_terminal_renderer.py +489 -0
  227. aegis/templates/copier-aegis-project/{{ project_slug }}/app/cli/tasks.py.jinja +328 -0
  228. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/__init__.py +0 -0
  229. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/__init__.py +0 -0
  230. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/ai/__init__.py +8 -0
  231. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/ai/router.py +329 -0
  232. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/auth/__init__.py +1 -0
  233. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/auth/router.py +64 -0
  234. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/deps.py +58 -0
  235. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/health.py.jinja +163 -0
  236. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/models.py.jinja +280 -0
  237. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/routing.py.jinja +32 -0
  238. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/scheduler.py.jinja +121 -0
  239. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/worker.py.jinja +478 -0
  240. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/hooks.py +144 -0
  241. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/main.py +31 -0
  242. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/middleware/__init__.py +1 -0
  243. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/middleware/cors.py +20 -0
  244. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/shutdown/__init__.py +1 -0
  245. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/shutdown/cleanup.py +14 -0
  246. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/startup/__init__.py +1 -0
  247. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/startup/component_health.py.jinja +418 -0
  248. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/startup/database_init.py.jinja +83 -0
  249. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/__init__.py +5 -0
  250. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/controls/__init__.py +27 -0
  251. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/controls/table.py +78 -0
  252. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/controls/text.py +142 -0
  253. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/__init__.py.jinja +47 -0
  254. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/ai_card.py +287 -0
  255. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/auth_card.py +198 -0
  256. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/base_card.py +256 -0
  257. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/card_factory.py +227 -0
  258. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/card_utils.py +333 -0
  259. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/database_card.py +420 -0
  260. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/fastapi_card.py +328 -0
  261. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/flet_card.py +267 -0
  262. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/redis_card.py +322 -0
  263. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/scheduler_card.py +352 -0
  264. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/services_card.py +233 -0
  265. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/worker_card.py +684 -0
  266. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/main.py.jinja +653 -0
  267. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/theme.py +48 -0
  268. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/scheduler/__init__.py +1 -0
  269. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/scheduler/main.py.jinja +156 -0
  270. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/CLAUDE.md.jinja +213 -0
  271. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/__init__.py +6 -0
  272. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/constants.py.jinja +30 -0
  273. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/pools.py +97 -0
  274. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/queues/__init__.py +1 -0
  275. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/queues/load_test.py +55 -0
  276. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/queues/media.py +49 -0
  277. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/queues/system.py +44 -0
  278. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/registry.py +139 -0
  279. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/tasks/__init__.py +120 -0
  280. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/tasks/load_tasks.py +507 -0
  281. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/tasks/simple_system_tasks.py +33 -0
  282. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/tasks/system_tasks.py +281 -0
  283. aegis/templates/copier-aegis-project/{{ project_slug }}/app/core/config.py.jinja +178 -0
  284. aegis/templates/copier-aegis-project/{{ project_slug }}/app/core/constants.py +58 -0
  285. aegis/templates/copier-aegis-project/{{ project_slug }}/app/core/db.py.jinja +176 -0
  286. aegis/templates/copier-aegis-project/{{ project_slug }}/app/core/log.py +92 -0
  287. aegis/templates/copier-aegis-project/{{ project_slug }}/app/core/security.py +62 -0
  288. aegis/templates/copier-aegis-project/{{ project_slug }}/app/entrypoints/__init__.py +1 -0
  289. aegis/templates/copier-aegis-project/{{ project_slug }}/app/entrypoints/scheduler.py.jinja +21 -0
  290. aegis/templates/copier-aegis-project/{{ project_slug }}/app/entrypoints/webserver.py +39 -0
  291. aegis/templates/copier-aegis-project/{{ project_slug }}/app/integrations/__init__.py +0 -0
  292. aegis/templates/copier-aegis-project/{{ project_slug }}/app/integrations/main.py +61 -0
  293. aegis/templates/copier-aegis-project/{{ project_slug }}/app/models/__init__.py +1 -0
  294. aegis/templates/copier-aegis-project/{{ project_slug }}/app/models/user.py +44 -0
  295. aegis/templates/copier-aegis-project/{{ project_slug }}/app/py.typed +0 -0
  296. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/__init__.py +1 -0
  297. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/ai/__init__.py +8 -0
  298. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/ai/config.py +130 -0
  299. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/ai/conversation.py +213 -0
  300. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/ai/health.py +96 -0
  301. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/ai/models.py +229 -0
  302. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/ai/providers.py.jinja +370 -0
  303. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/ai/service.py +387 -0
  304. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/auth/__init__.py +1 -0
  305. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/auth/auth_service.py +40 -0
  306. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/auth/health.py +162 -0
  307. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/auth/user_service.py +82 -0
  308. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/backend/middleware_inspector.py.jinja +223 -0
  309. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/backend/models.py.jinja +70 -0
  310. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/backend/route_inspector.py.jinja +155 -0
  311. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/load_test.py +678 -0
  312. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/load_test_models.py +265 -0
  313. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/scheduler/__init__.py.jinja +21 -0
  314. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/scheduler/models.py.jinja +119 -0
  315. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/scheduler/scheduled_task_manager.py.jinja +273 -0
  316. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/scheduler/task_monitor.py.jinja +189 -0
  317. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/shared/__init__.py +15 -0
  318. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/shared/models.py +26 -0
  319. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/system/__init__.py +52 -0
  320. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/system/alerts.py +94 -0
  321. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/system/backup.py.jinja +119 -0
  322. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/system/health.py.jinja +1333 -0
  323. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/system/models.py +243 -0
  324. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/system/ui.py +52 -0
  325. aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!57223!aegis-manifesto.png +0 -0
  326. aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!57224!aegis-manifesto-dark.png +0 -0
  327. aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!57225!aegis-manifesto-square-backup.png +0 -0
  328. aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!57533!aegis-manifesto.png +0 -0
  329. aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!57534!aegis-manifesto-dark.png +0 -0
  330. aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!57538!aegis-manifesto-square-backup.png +0 -0
  331. aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!57897!aegis-manifesto.png +0 -0
  332. aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!57898!aegis-manifesto-dark.png +0 -0
  333. aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!57904!aegis-manifesto-square-backup.png +0 -0
  334. aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!58315!aegis-manifesto.png +0 -0
  335. aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!58316!aegis-manifesto-dark.png +0 -0
  336. aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!58324!aegis-manifesto-square-backup.png +0 -0
  337. aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!58837!aegis-manifesto.png +0 -0
  338. aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!58838!aegis-manifesto-dark.png +0 -0
  339. aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!58849!aegis-manifesto-square-backup.png +0 -0
  340. aegis/templates/copier-aegis-project/{{ project_slug }}/assets/aegis-manifesto-dark.png +0 -0
  341. aegis/templates/copier-aegis-project/{{ project_slug }}/assets/aegis-manifesto-square-backup.png +0 -0
  342. aegis/templates/copier-aegis-project/{{ project_slug }}/assets/aegis-manifesto.png +0 -0
  343. aegis/templates/copier-aegis-project/{{ project_slug }}/clean-validation/.env.example.jinja +64 -0
  344. aegis/templates/copier-aegis-project/{{ project_slug }}/clean-validation/README.md.jinja +172 -0
  345. aegis/templates/copier-aegis-project/{{ project_slug }}/clean-validation/docker-compose.yml.jinja +78 -0
  346. aegis/templates/copier-aegis-project/{{ project_slug }}/clean-validation/mkdocs.yml.jinja +62 -0
  347. aegis/templates/copier-aegis-project/{{ project_slug }}/clean-validation/pyproject.toml.jinja +120 -0
  348. aegis/templates/copier-aegis-project/{{ project_slug }}/docker-compose.yml.jinja +200 -0
  349. aegis/templates/copier-aegis-project/{{ project_slug }}/docs/api.md.jinja +191 -0
  350. aegis/templates/copier-aegis-project/{{ project_slug }}/docs/components/scheduler.md +0 -0
  351. aegis/templates/copier-aegis-project/{{ project_slug }}/docs/components/scheduler.md.jinja +621 -0
  352. aegis/templates/copier-aegis-project/{{ project_slug }}/docs/development.md.jinja +215 -0
  353. aegis/templates/copier-aegis-project/{{ project_slug }}/docs/health.md.jinja +240 -0
  354. aegis/templates/copier-aegis-project/{{ project_slug }}/docs/javascripts/mermaid-config.js +62 -0
  355. aegis/templates/copier-aegis-project/{{ project_slug }}/docs/stylesheets/mermaid.css +95 -0
  356. aegis/templates/copier-aegis-project/{{ project_slug }}/mkdocs.yml.jinja +62 -0
  357. aegis/templates/copier-aegis-project/{{ project_slug }}/pyproject.toml.jinja +131 -0
  358. aegis/templates/copier-aegis-project/{{ project_slug }}/scripts/entrypoint.sh +87 -0
  359. aegis/templates/copier-aegis-project/{{ project_slug }}/scripts/entrypoint.sh.jinja +93 -0
  360. aegis/templates/copier-aegis-project/{{ project_slug }}/scripts/gen_docs.py +16 -0
  361. aegis/templates/copier-aegis-project/{{ project_slug }}/tests/api/__init__.py +1 -0
  362. aegis/templates/copier-aegis-project/{{ project_slug }}/tests/api/test_auth_endpoints.py.jinja +307 -0
  363. aegis/templates/copier-aegis-project/{{ project_slug }}/tests/api/test_health_endpoints.py.jinja +262 -0
  364. aegis/templates/copier-aegis-project/{{ project_slug }}/tests/api/test_scheduler_endpoints.py.jinja +214 -0
  365. aegis/templates/copier-aegis-project/{{ project_slug }}/tests/api/test_worker_endpoints.py.jinja +165 -0
  366. aegis/templates/copier-aegis-project/{{ project_slug }}/tests/cli/test_ai_rendering.py +427 -0
  367. aegis/templates/copier-aegis-project/{{ project_slug }}/tests/cli/test_conversation_memory.py +465 -0
  368. aegis/templates/copier-aegis-project/{{ project_slug }}/tests/components/test_scheduler.py +43 -0
  369. aegis/templates/copier-aegis-project/{{ project_slug }}/tests/conftest.py.jinja +195 -0
  370. aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/__init__.py +1 -0
  371. aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/ai/__init__.py +1 -0
  372. aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/ai/conftest.py +78 -0
  373. aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/ai/test_health.py +157 -0
  374. aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/ai/test_models.py +164 -0
  375. aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/ai/test_service.py +198 -0
  376. aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_auth_integration.py.jinja +528 -0
  377. aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_component_integration.py.jinja +387 -0
  378. aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_conversation_persistence.py +342 -0
  379. aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_health_logic.py.jinja +663 -0
  380. aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_load_test_models.py +619 -0
  381. aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_load_test_service.py +603 -0
  382. aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_middleware_inspector.py.jinja +248 -0
  383. aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_scheduled_task_manager.py.jinja +292 -0
  384. aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_system_service.py +98 -0
  385. aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_worker_health_registration.py.jinja +257 -0
  386. aegis/templates/copier-aegis-project/{{ project_slug }}/tests/test_core.py +49 -0
  387. aegis/templates/copier-aegis-project/{{ project_slug }}/uv.lock +1673 -0
  388. aegis_stack-0.2.0rc2.dist-info/METADATA +165 -0
  389. aegis_stack-0.2.0rc2.dist-info/RECORD +392 -0
  390. aegis_stack-0.2.0rc2.dist-info/WHEEL +4 -0
  391. aegis_stack-0.2.0rc2.dist-info/entry_points.txt +3 -0
  392. aegis_stack-0.2.0rc2.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,142 @@
1
+ """
2
+ Custom text controls with proper theme-aware styling.
3
+
4
+ These components automatically use semantic Flet colors that adapt to light/dark themes,
5
+ following the same patterns as ee-toolset for consistent visual design.
6
+ """
7
+
8
+ from typing import Any
9
+
10
+ import flet as ft
11
+
12
+
13
+ class PrimaryText(ft.Text): # type: ignore[misc]
14
+ """
15
+ Primary text component using theme-aware ON_SURFACE color.
16
+
17
+ Automatically adapts to light/dark themes with proper contrast.
18
+ Use for main content text, labels, and primary information.
19
+ """
20
+
21
+ def __init__(self, value: str, opacity: float = 1.0, **kwargs: Any) -> None:
22
+ super().__init__(
23
+ value=value,
24
+ opacity=opacity,
25
+ no_wrap=False,
26
+ color=ft.Colors.ON_SURFACE, # Theme-aware primary text color
27
+ font_family="Roboto",
28
+ size=16,
29
+ weight=ft.FontWeight.W_400,
30
+ **kwargs,
31
+ )
32
+
33
+
34
+ class SecondaryText(ft.Text): # type: ignore[misc]
35
+ """
36
+ Secondary text component using theme-aware ON_SURFACE_VARIANT color.
37
+
38
+ Automatically adapts to light/dark themes with reduced contrast.
39
+ Use for supporting text, captions, and less prominent information.
40
+ """
41
+
42
+ def __init__(
43
+ self, value: str, opacity: float = 1.0, no_wrap: bool = False, **kwargs: Any
44
+ ) -> None:
45
+ super().__init__(
46
+ value=value,
47
+ opacity=opacity,
48
+ no_wrap=no_wrap,
49
+ color=ft.Colors.GREY_600, # Theme-aware secondary text color
50
+ font_family="Roboto",
51
+ size=14,
52
+ weight=ft.FontWeight.W_400,
53
+ **kwargs,
54
+ )
55
+
56
+
57
+ class TitleText(ft.Text): # type: ignore[misc]
58
+ """
59
+ Title text component for headings and prominent labels.
60
+
61
+ Uses theme-aware colors with larger size and bold weight.
62
+ """
63
+
64
+ def __init__(self, value: str, opacity: float = 1.0, **kwargs: Any) -> None:
65
+ # Set defaults, but allow kwargs to override
66
+ defaults = {
67
+ "color": ft.Colors.ON_SURFACE, # Theme-aware primary text color
68
+ "font_family": "Roboto",
69
+ "size": 24,
70
+ "weight": ft.FontWeight.W_700,
71
+ }
72
+ # Update defaults with any provided kwargs
73
+ defaults.update(kwargs)
74
+
75
+ super().__init__(
76
+ value=value,
77
+ opacity=opacity,
78
+ **defaults,
79
+ )
80
+
81
+
82
+ class ConfirmationText(ft.Text): # type: ignore[misc]
83
+ """
84
+ Confirmation/error text component with error coloring.
85
+
86
+ Uses theme-aware error colors for warnings, confirmations, and alerts.
87
+ """
88
+
89
+ def __init__(self, value: str, opacity: float = 1.0, **kwargs: Any) -> None:
90
+ super().__init__(
91
+ value=value,
92
+ opacity=opacity,
93
+ color=ft.Colors.ERROR, # Theme-aware error color
94
+ font_family="Roboto",
95
+ size=14,
96
+ weight=ft.FontWeight.W_400,
97
+ **kwargs,
98
+ )
99
+
100
+
101
+ class MetricText(ft.Text): # type: ignore[misc]
102
+ """
103
+ Specialized text for displaying metrics and numerical values.
104
+
105
+ Uses bold weight and primary color for emphasis on data points.
106
+ """
107
+
108
+ def __init__(self, value: str, opacity: float = 1.0, **kwargs: Any) -> None:
109
+ super().__init__(
110
+ value=value,
111
+ opacity=opacity,
112
+ color=ft.Colors.ON_SURFACE, # Theme-aware primary text color
113
+ font_family="Roboto",
114
+ size=16,
115
+ weight=ft.FontWeight.W_700, # Bold for emphasis
116
+ **kwargs,
117
+ )
118
+
119
+
120
+ class LabelText(ft.Text): # type: ignore[misc]
121
+ """
122
+ Label text component for form labels and small descriptive text.
123
+
124
+ Uses smaller size with medium weight for clear labeling.
125
+ """
126
+
127
+ def __init__(self, value: str, opacity: float = 1.0, **kwargs: Any) -> None:
128
+ # Set defaults, but allow kwargs to override
129
+ defaults = {
130
+ "color": ft.Colors.GREY_600, # Theme-aware secondary color
131
+ "font_family": "Roboto",
132
+ "size": 12,
133
+ "weight": ft.FontWeight.W_600, # Medium weight for labels
134
+ }
135
+ # Update defaults with any provided kwargs
136
+ defaults.update(kwargs)
137
+
138
+ super().__init__(
139
+ value=value,
140
+ opacity=opacity,
141
+ **defaults,
142
+ )
@@ -0,0 +1,47 @@
1
+ """Dashboard component cards."""
2
+
3
+ from .fastapi_card import FastAPICard
4
+ from .flet_card import FletCard
5
+ {%- if cookiecutter.include_ai == "yes" %}
6
+ from .ai_card import AICard
7
+ {%- endif %}
8
+ {%- if cookiecutter.include_auth == "yes" %}
9
+ from .auth_card import AuthCard
10
+ from .services_card import ServicesCard
11
+ {%- endif %}
12
+ {%- if cookiecutter.include_database == "yes" %}
13
+ from .database_card import DatabaseCard
14
+ {%- endif %}
15
+ {%- if cookiecutter.include_redis == "yes" %}
16
+ from .redis_card import RedisCard
17
+ {%- endif %}
18
+ {%- if cookiecutter.include_scheduler == "yes" %}
19
+ from .scheduler_card import SchedulerCard
20
+ {%- endif %}
21
+ {%- if cookiecutter.include_worker == "yes" %}
22
+ from .worker_card import WorkerCard
23
+ {%- endif %}
24
+
25
+ __all__ = [
26
+ "FastAPICard",
27
+ "FletCard",
28
+ {%- if cookiecutter.include_ai == "yes" %}
29
+ "AICard",
30
+ {%- endif %}
31
+ {%- if cookiecutter.include_auth == "yes" %}
32
+ "AuthCard",
33
+ "ServicesCard",
34
+ {%- endif %}
35
+ {%- if cookiecutter.include_database == "yes" %}
36
+ "DatabaseCard",
37
+ {%- endif %}
38
+ {%- if cookiecutter.include_redis == "yes" %}
39
+ "RedisCard",
40
+ {%- endif %}
41
+ {%- if cookiecutter.include_scheduler == "yes" %}
42
+ "SchedulerCard",
43
+ {%- endif %}
44
+ {%- if cookiecutter.include_worker == "yes" %}
45
+ "WorkerCard",
46
+ {%- endif %}
47
+ ]
@@ -0,0 +1,287 @@
1
+ """
2
+ AI Service Card
3
+
4
+ Modern card component for displaying AI service status, provider configuration,
5
+ and conversation metrics in a clean 2-column layout.
6
+ """
7
+
8
+ import flet as ft
9
+ from app.components.frontend.controls import LabelText, PrimaryText
10
+ from app.services.system.models import ComponentStatus
11
+
12
+ from .card_utils import (
13
+ create_hover_handler,
14
+ create_standard_card_container,
15
+ create_tech_badge,
16
+ get_status_colors,
17
+ )
18
+
19
+
20
+ class AICard:
21
+ """
22
+ A clean AI service card with provider info and key metrics.
23
+
24
+ Features:
25
+ - Real AI service metrics from health checks
26
+ - Clean 2-column layout (auth card pattern)
27
+ - Provider-specific color coding
28
+ - Highlighted metric containers
29
+ - Config validation display
30
+ - Responsive design
31
+ """
32
+
33
+ # Provider color mapping for visual consistency
34
+ PROVIDER_COLORS = {
35
+ "groq": ft.Colors.PURPLE,
36
+ "openai": ft.Colors.GREEN,
37
+ "anthropic": ft.Colors.ORANGE,
38
+ "google": ft.Colors.BLUE,
39
+ "mistral": ft.Colors.INDIGO,
40
+ "cohere": ft.Colors.TEAL,
41
+ "gemini": ft.Colors.BLUE,
42
+ }
43
+
44
+ def __init__(self, component_data: ComponentStatus):
45
+ """Initialize with AI service data from health check."""
46
+ self.component_data = component_data
47
+ self.metadata = component_data.metadata or {}
48
+
49
+ def _get_provider_color(self, provider: str) -> str:
50
+ """Get color for provider badge."""
51
+ return self.PROVIDER_COLORS.get(provider.lower(), ft.Colors.GREY)
52
+
53
+ def _truncate_model_name(self, model: str) -> str:
54
+ """Intelligently truncate model name for display."""
55
+ if not model:
56
+ return "Unknown"
57
+
58
+ # Keep it concise but recognizable
59
+ if len(model) <= 20:
60
+ return model
61
+
62
+ # Handle common patterns
63
+ if "claude" in model.lower():
64
+ # "claude-3-5-sonnet-20241022" -> "claude-3.5-sonnet"
65
+ parts = model.split("-")
66
+ if len(parts) >= 4:
67
+ return f"{parts[0]}-{parts[1]}.{parts[2]}-{parts[3]}"
68
+ elif "llama" in model.lower():
69
+ # "llama-3.1-70b-versatile" -> "llama-3.1-70b"
70
+ parts = model.split("-")
71
+ if len(parts) >= 3:
72
+ return "-".join(parts[:3])
73
+ elif "gpt" in model.lower():
74
+ # "gpt-4-turbo-preview" -> "gpt-4-turbo"
75
+ parts = model.split("-")
76
+ if len(parts) >= 3:
77
+ return "-".join(parts[:3])
78
+
79
+ # Fallback: truncate with ellipsis
80
+ return model[:20] + "..."
81
+
82
+ def _create_metric_container(
83
+ self, label: str, value: str, color: str = ft.Colors.BLUE
84
+ ) -> ft.Container:
85
+ """Create a properly sized metric container."""
86
+ return ft.Container(
87
+ content=ft.Column(
88
+ [
89
+ LabelText(label),
90
+ ft.Container(height=8), # Spacing
91
+ PrimaryText(value),
92
+ ],
93
+ spacing=0,
94
+ horizontal_alignment=ft.CrossAxisAlignment.START,
95
+ ),
96
+ padding=ft.padding.all(16),
97
+ bgcolor=ft.Colors.with_opacity(0.08, color),
98
+ border_radius=8,
99
+ border=ft.border.all(1, ft.Colors.with_opacity(0.15, color)),
100
+ height=80, # Match auth card metric height
101
+ expand=True,
102
+ )
103
+
104
+ def _create_left_section(self) -> ft.Container:
105
+ """Create the left section with tech badge."""
106
+ return ft.Container(
107
+ content=ft.Column(
108
+ [
109
+ self._create_technology_badge(),
110
+ ],
111
+ spacing=0,
112
+ ),
113
+ width=200,
114
+ padding=ft.padding.all(16),
115
+ )
116
+
117
+ def _create_technology_badge(self) -> ft.Container:
118
+ """Create technology badge for AI service."""
119
+ _, primary_color, _ = get_status_colors(self.component_data)
120
+
121
+ # Get provider for subtitle
122
+ provider = self.metadata.get("provider", "Unknown")
123
+ provider_display = provider.title()
124
+
125
+ return create_tech_badge(
126
+ title="AI Service",
127
+ subtitle=f"{provider_display} + PydanticAI",
128
+ icon="🤖",
129
+ badge_text="CHAT",
130
+ badge_color=primary_color,
131
+ primary_color=primary_color,
132
+ )
133
+
134
+ def _get_config_status_display(self) -> tuple[str, str]:
135
+ """
136
+ Get config status display text and color.
137
+
138
+ Returns:
139
+ Tuple of (status_text, color)
140
+ """
141
+ config_valid = self.metadata.get("configuration_valid", False)
142
+ validation_errors = self.metadata.get("validation_errors", [])
143
+
144
+ if config_valid:
145
+ return ("✅ Valid", ft.Colors.GREEN)
146
+
147
+ # Show specific error if only one
148
+ if len(validation_errors) == 1:
149
+ error_msg = validation_errors[0]
150
+ if "api key" in error_msg.lower():
151
+ return ("Missing API Key", ft.Colors.RED)
152
+ elif "disabled" in error_msg.lower():
153
+ return ("Disabled", ft.Colors.ORANGE)
154
+ else:
155
+ return ("Invalid", ft.Colors.RED)
156
+
157
+ # Multiple errors
158
+ if len(validation_errors) > 1:
159
+ return (f"Issues ({len(validation_errors)})", ft.Colors.RED)
160
+
161
+ # Shouldn't reach here, but just in case
162
+ return ("Unknown", ft.Colors.GREY)
163
+
164
+ def _get_response_time_color(self, response_time: float | None) -> str:
165
+ """Get color for response time based on value."""
166
+ if not response_time:
167
+ return ft.Colors.GREY
168
+
169
+ if response_time < 100:
170
+ return ft.Colors.GREEN
171
+ elif response_time < 500:
172
+ return ft.Colors.ORANGE
173
+ else:
174
+ return ft.Colors.RED
175
+
176
+ def _create_metrics_section(self) -> ft.Container:
177
+ """Create the metrics section with a clean grid layout."""
178
+ # Get real data from metadata
179
+ provider = self.metadata.get("provider", "Unknown")
180
+ model = self.metadata.get("model", "Unknown")
181
+ total_conversations = self.metadata.get("total_conversations", 0)
182
+ response_time = self.component_data.response_time_ms
183
+ enabled = self.metadata.get("enabled", True)
184
+
185
+ # Format values for display
186
+ provider_display = provider.title()
187
+ provider_color = self._get_provider_color(provider)
188
+ model_display = self._truncate_model_name(model)
189
+ conversations_display = str(total_conversations)
190
+ streaming_display = "✅ Available"
191
+ config_status, config_color = self._get_config_status_display()
192
+ response_time_display = f"{response_time:.1f}ms" if response_time else "N/A"
193
+ response_time_color = self._get_response_time_color(response_time)
194
+
195
+ # If service disabled, show that prominently
196
+ if not enabled:
197
+ config_status = "🔴 Disabled"
198
+ config_color = ft.Colors.RED
199
+
200
+ # Create metrics grid (3 rows x 2 columns)
201
+ return ft.Container(
202
+ content=ft.Column(
203
+ [
204
+ # Row 1: Provider and Model
205
+ ft.Row(
206
+ [
207
+ self._create_metric_container(
208
+ "Provider", provider_display, provider_color
209
+ ),
210
+ self._create_metric_container(
211
+ "Model", model_display, ft.Colors.BLUE
212
+ ),
213
+ ],
214
+ expand=True,
215
+ ),
216
+ ft.Container(height=12), # Vertical spacing
217
+ # Row 2: Conversations and Streaming
218
+ ft.Row(
219
+ [
220
+ self._create_metric_container(
221
+ "Conversations", conversations_display, ft.Colors.PURPLE
222
+ ),
223
+ self._create_metric_container(
224
+ "Streaming", streaming_display, ft.Colors.GREEN
225
+ ),
226
+ ],
227
+ expand=True,
228
+ ),
229
+ ft.Container(height=12), # Vertical spacing
230
+ # Row 3: Config Status and Response Time
231
+ ft.Row(
232
+ [
233
+ self._create_metric_container(
234
+ "Configuration", config_status, config_color
235
+ ),
236
+ self._create_metric_container(
237
+ "Response Time",
238
+ response_time_display,
239
+ response_time_color,
240
+ ),
241
+ ],
242
+ expand=True,
243
+ ),
244
+ ],
245
+ spacing=0,
246
+ ),
247
+ expand=True,
248
+ padding=ft.padding.all(16),
249
+ )
250
+
251
+ def build(self) -> ft.Container:
252
+ """Build and return the complete AI service card."""
253
+ # Get colors based on component status
254
+ background_color, primary_color, border_color = get_status_colors(
255
+ self.component_data
256
+ )
257
+
258
+ # Create clean 2-column layout
259
+ content = ft.Row(
260
+ [
261
+ self._create_left_section(),
262
+ ft.Container(
263
+ width=1,
264
+ height=160, # Adjust height to match content
265
+ bgcolor=ft.Colors.with_opacity(0.1, ft.Colors.GREY_400),
266
+ margin=ft.margin.symmetric(horizontal=16),
267
+ ),
268
+ self._create_metrics_section(),
269
+ ],
270
+ expand=True,
271
+ vertical_alignment=ft.CrossAxisAlignment.START,
272
+ )
273
+
274
+ # Create the container
275
+ card_container = create_standard_card_container(
276
+ content=content,
277
+ primary_color=primary_color,
278
+ border_color=border_color,
279
+ width=None,
280
+ hover_handler=None,
281
+ )
282
+
283
+ # Create hover handler for the card
284
+ hover_handler = create_hover_handler(card_container)
285
+ card_container.on_hover = hover_handler
286
+
287
+ return card_container
@@ -0,0 +1,198 @@
1
+ """
2
+ Authentication Service Card
3
+
4
+ Modern card component specifically designed for authentication service monitoring.
5
+ Shows auth-specific metrics with a clean, functional layout.
6
+ """
7
+
8
+ import flet as ft
9
+ from app.components.frontend.controls import LabelText, PrimaryText
10
+ from app.services.system.models import ComponentStatus
11
+
12
+ from .card_utils import (
13
+ create_hover_handler,
14
+ create_standard_card_container,
15
+ create_tech_badge,
16
+ get_status_colors,
17
+ )
18
+
19
+
20
+ class AuthCard:
21
+ """
22
+ A clean authentication service card with real metrics.
23
+
24
+ Features:
25
+ - Real authentication metrics from health checks
26
+ - Clean 2-column layout
27
+ - Highlighted metric containers
28
+ - Responsive design
29
+ """
30
+
31
+ def __init__(self, component_data: ComponentStatus):
32
+ """Initialize with authentication service data from health check."""
33
+ self.component_data = component_data
34
+ self.metadata = component_data.metadata or {}
35
+
36
+ def _create_metric_container(
37
+ self, label: str, value: str, color: str = ft.Colors.BLUE
38
+ ) -> ft.Container:
39
+ """Create a properly sized metric container."""
40
+ return ft.Container(
41
+ content=ft.Column(
42
+ [
43
+ LabelText(label),
44
+ ft.Container(height=8), # More spacing
45
+ PrimaryText(value),
46
+ ],
47
+ spacing=0,
48
+ horizontal_alignment=ft.CrossAxisAlignment.START,
49
+ ),
50
+ padding=ft.padding.all(16), # More padding
51
+ bgcolor=ft.Colors.with_opacity(0.08, color),
52
+ border_radius=8,
53
+ border=ft.border.all(1, ft.Colors.with_opacity(0.15, color)),
54
+ height=80, # Taller containers
55
+ expand=True,
56
+ )
57
+
58
+ def _create_left_section(self) -> ft.Container:
59
+ """Create the left section with just the tech badge."""
60
+ return ft.Container(
61
+ content=ft.Column(
62
+ [
63
+ self._create_technology_badge(),
64
+ ],
65
+ spacing=0,
66
+ ),
67
+ width=200,
68
+ padding=ft.padding.all(16),
69
+ )
70
+
71
+ def _create_technology_badge(self) -> ft.Container:
72
+ """Create technology badge for authentication service."""
73
+ _, primary_color, _ = get_status_colors(self.component_data)
74
+
75
+ return create_tech_badge(
76
+ title="Auth",
77
+ subtitle="JWT + OAuth",
78
+ icon="🔐",
79
+ badge_text="AUTH",
80
+ badge_color=primary_color,
81
+ primary_color=primary_color,
82
+ )
83
+
84
+ def _create_metrics_section(self) -> ft.Container:
85
+ """Create the metrics section with a clean grid layout."""
86
+ # Get real data from metadata
87
+ user_count_display = self.metadata.get("user_count_display", "0")
88
+ response_time = self.component_data.response_time_ms
89
+ database_available = self.metadata.get("database_available", False)
90
+ jwt_algorithm = self.metadata.get("jwt_algorithm", "HS256")
91
+ token_expiry_display = self.metadata.get("token_expiry_display", "30 min")
92
+ security_level = self.metadata.get("security_level", "standard")
93
+
94
+ # Color code security level
95
+ security_color = {
96
+ "high": ft.Colors.GREEN,
97
+ "standard": ft.Colors.BLUE,
98
+ "basic": ft.Colors.ORANGE,
99
+ }.get(security_level, ft.Colors.GREY)
100
+
101
+ # Create metrics grid (3 rows x 2 columns)
102
+ return ft.Container(
103
+ content=ft.Column(
104
+ [
105
+ # Row 1: User count and Response time
106
+ ft.Row(
107
+ [
108
+ self._create_metric_container(
109
+ "Total Users", user_count_display, ft.Colors.PURPLE
110
+ ),
111
+ self._create_metric_container(
112
+ "Response Time",
113
+ f"{response_time:.1f}ms" if response_time else "N/A",
114
+ (
115
+ ft.Colors.GREEN
116
+ if response_time and response_time < 100
117
+ else ft.Colors.ORANGE
118
+ ),
119
+ ),
120
+ ],
121
+ expand=True,
122
+ ),
123
+ ft.Container(height=12), # Vertical spacing
124
+ # Row 2: JWT Algorithm and Token Expiry
125
+ ft.Row(
126
+ [
127
+ self._create_metric_container(
128
+ "JWT Algorithm", jwt_algorithm, ft.Colors.BLUE
129
+ ),
130
+ self._create_metric_container(
131
+ "Token Expiry", token_expiry_display, ft.Colors.GREEN
132
+ ),
133
+ ],
134
+ expand=True,
135
+ ),
136
+ ft.Container(height=12), # Vertical spacing
137
+ # Row 3: Security Level and Database
138
+ ft.Row(
139
+ [
140
+ self._create_metric_container(
141
+ "Security Level", security_level.title(), security_color
142
+ ),
143
+ self._create_metric_container(
144
+ "Database",
145
+ "Available" if database_available else "Unavailable",
146
+ (
147
+ ft.Colors.GREEN
148
+ if database_available
149
+ else ft.Colors.RED
150
+ ),
151
+ ),
152
+ ],
153
+ expand=True,
154
+ ),
155
+ ],
156
+ spacing=0,
157
+ ),
158
+ expand=True,
159
+ padding=ft.padding.all(16),
160
+ )
161
+
162
+ def build(self) -> ft.Container:
163
+ """Build and return the complete authentication card."""
164
+ # Get colors based on component status
165
+ background_color, primary_color, border_color = get_status_colors(
166
+ self.component_data
167
+ )
168
+
169
+ # Create clean 2-column layout
170
+ content = ft.Row(
171
+ [
172
+ self._create_left_section(),
173
+ ft.Container(
174
+ width=1,
175
+ height=160, # Adjust height to match content
176
+ bgcolor=ft.Colors.with_opacity(0.1, ft.Colors.GREY_400),
177
+ margin=ft.margin.symmetric(horizontal=16),
178
+ ),
179
+ self._create_metrics_section(),
180
+ ],
181
+ expand=True,
182
+ vertical_alignment=ft.CrossAxisAlignment.START,
183
+ )
184
+
185
+ # Create the container
186
+ card_container = create_standard_card_container(
187
+ content=content,
188
+ primary_color=primary_color,
189
+ border_color=border_color,
190
+ width=None,
191
+ hover_handler=None,
192
+ )
193
+
194
+ # Create hover handler for the card
195
+ hover_handler = create_hover_handler(card_container)
196
+ card_container.on_hover = hover_handler
197
+
198
+ return card_container