django-cfg 1.3.7__py3-none-any.whl → 1.3.9__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 (251) hide show
  1. django_cfg/__init__.py +1 -1
  2. django_cfg/apps/accounts/admin/__init__.py +24 -8
  3. django_cfg/apps/accounts/admin/activity_admin.py +146 -0
  4. django_cfg/apps/accounts/admin/filters.py +98 -22
  5. django_cfg/apps/accounts/admin/group_admin.py +86 -0
  6. django_cfg/apps/accounts/admin/inlines.py +42 -13
  7. django_cfg/apps/accounts/admin/otp_admin.py +115 -0
  8. django_cfg/apps/accounts/admin/registration_admin.py +173 -0
  9. django_cfg/apps/accounts/admin/resources.py +123 -19
  10. django_cfg/apps/accounts/admin/twilio_admin.py +327 -0
  11. django_cfg/apps/accounts/admin/user_admin.py +362 -0
  12. django_cfg/apps/agents/admin/__init__.py +17 -4
  13. django_cfg/apps/agents/admin/execution_admin.py +204 -183
  14. django_cfg/apps/agents/admin/registry_admin.py +230 -255
  15. django_cfg/apps/agents/admin/toolsets_admin.py +274 -321
  16. django_cfg/apps/agents/core/__init__.py +1 -1
  17. django_cfg/apps/agents/core/django_agent.py +221 -0
  18. django_cfg/apps/agents/core/exceptions.py +14 -0
  19. django_cfg/apps/agents/core/orchestrator.py +18 -3
  20. django_cfg/apps/knowbase/admin/__init__.py +1 -1
  21. django_cfg/apps/knowbase/admin/archive_admin.py +352 -640
  22. django_cfg/apps/knowbase/admin/chat_admin.py +258 -192
  23. django_cfg/apps/knowbase/admin/document_admin.py +269 -262
  24. django_cfg/apps/knowbase/admin/external_data_admin.py +271 -489
  25. django_cfg/apps/knowbase/config/settings.py +21 -4
  26. django_cfg/apps/knowbase/views/chat_views.py +3 -0
  27. django_cfg/apps/leads/admin/__init__.py +3 -1
  28. django_cfg/apps/leads/admin/leads_admin.py +235 -35
  29. django_cfg/apps/maintenance/admin/__init__.py +2 -2
  30. django_cfg/apps/maintenance/admin/api_key_admin.py +125 -63
  31. django_cfg/apps/maintenance/admin/log_admin.py +143 -61
  32. django_cfg/apps/maintenance/admin/scheduled_admin.py +212 -301
  33. django_cfg/apps/maintenance/admin/site_admin.py +213 -352
  34. django_cfg/apps/newsletter/admin/__init__.py +29 -2
  35. django_cfg/apps/newsletter/admin/newsletter_admin.py +531 -193
  36. django_cfg/apps/payments/admin/__init__.py +18 -27
  37. django_cfg/apps/payments/admin/api_keys_admin.py +179 -546
  38. django_cfg/apps/payments/admin/balance_admin.py +166 -632
  39. django_cfg/apps/payments/admin/currencies_admin.py +235 -607
  40. django_cfg/apps/payments/admin/endpoint_groups_admin.py +127 -0
  41. django_cfg/apps/payments/admin/filters.py +83 -3
  42. django_cfg/apps/payments/admin/networks_admin.py +258 -0
  43. django_cfg/apps/payments/admin/payments_admin.py +171 -461
  44. django_cfg/apps/payments/admin/subscriptions_admin.py +119 -636
  45. django_cfg/apps/payments/admin/tariffs_admin.py +248 -0
  46. django_cfg/apps/payments/admin_interface/serializers/payment_serializers.py +105 -34
  47. django_cfg/apps/payments/admin_interface/templates/payments/payment_form.html +12 -16
  48. django_cfg/apps/payments/admin_interface/views/__init__.py +2 -0
  49. django_cfg/apps/payments/admin_interface/views/api/webhook_admin.py +13 -18
  50. django_cfg/apps/payments/management/commands/manage_currencies.py +236 -274
  51. django_cfg/apps/payments/management/commands/manage_providers.py +4 -1
  52. django_cfg/apps/payments/middleware/api_access.py +32 -6
  53. django_cfg/apps/payments/migrations/0002_currency_usd_rate_currency_usd_rate_updated_at.py +26 -0
  54. django_cfg/apps/payments/migrations/0003_remove_provider_currency_fields.py +28 -0
  55. django_cfg/apps/payments/migrations/0004_add_reserved_usd_field.py +30 -0
  56. django_cfg/apps/payments/models/balance.py +12 -0
  57. django_cfg/apps/payments/models/currencies.py +106 -32
  58. django_cfg/apps/payments/models/managers/currency_managers.py +65 -0
  59. django_cfg/apps/payments/services/core/currency_service.py +35 -28
  60. django_cfg/apps/payments/services/core/payment_service.py +1 -1
  61. django_cfg/apps/payments/services/providers/__init__.py +3 -0
  62. django_cfg/apps/payments/services/providers/base.py +95 -39
  63. django_cfg/apps/payments/services/providers/models/__init__.py +40 -0
  64. django_cfg/apps/payments/services/providers/models/base.py +122 -0
  65. django_cfg/apps/payments/services/providers/models/providers.py +87 -0
  66. django_cfg/apps/payments/services/providers/models/universal.py +48 -0
  67. django_cfg/apps/payments/services/providers/nowpayments/__init__.py +31 -0
  68. django_cfg/apps/payments/services/providers/nowpayments/config.py +70 -0
  69. django_cfg/apps/payments/services/providers/nowpayments/models.py +150 -0
  70. django_cfg/apps/payments/services/providers/nowpayments/parsers.py +879 -0
  71. django_cfg/apps/payments/services/providers/{nowpayments.py → nowpayments/provider.py} +240 -209
  72. django_cfg/apps/payments/services/providers/nowpayments/sync.py +196 -0
  73. django_cfg/apps/payments/services/providers/registry.py +4 -32
  74. django_cfg/apps/payments/services/providers/sync_service.py +277 -0
  75. django_cfg/apps/payments/static/payments/js/api-client.js +23 -5
  76. django_cfg/apps/payments/static/payments/js/payment-form.js +65 -8
  77. django_cfg/apps/payments/tasks/__init__.py +39 -0
  78. django_cfg/apps/payments/tasks/types.py +73 -0
  79. django_cfg/apps/payments/tasks/usage_tracking.py +308 -0
  80. django_cfg/apps/payments/templates/admin/payments/_components/dashboard_header.html +23 -0
  81. django_cfg/apps/payments/templates/admin/payments/_components/stats_card.html +25 -0
  82. django_cfg/apps/payments/templates/admin/payments/_components/stats_grid.html +16 -0
  83. django_cfg/apps/payments/templates/admin/payments/apikey/change_list.html +39 -0
  84. django_cfg/apps/payments/templates/admin/payments/balance/change_list.html +50 -0
  85. django_cfg/apps/payments/templates/admin/payments/currency/change_list.html +40 -0
  86. django_cfg/apps/payments/templates/admin/payments/payment/change_list.html +48 -0
  87. django_cfg/apps/payments/templates/admin/payments/subscription/change_list.html +48 -0
  88. django_cfg/apps/payments/urls_admin.py +1 -1
  89. django_cfg/apps/payments/views/api/currencies.py +5 -5
  90. django_cfg/apps/payments/views/overview/services.py +2 -2
  91. django_cfg/apps/payments/views/serializers/currencies.py +4 -3
  92. django_cfg/apps/support/admin/__init__.py +10 -1
  93. django_cfg/apps/support/admin/support_admin.py +338 -141
  94. django_cfg/apps/tasks/admin/__init__.py +11 -0
  95. django_cfg/apps/tasks/admin/tasks_admin.py +430 -0
  96. django_cfg/config.py +1 -1
  97. django_cfg/core/config.py +10 -5
  98. django_cfg/core/generation.py +1 -1
  99. django_cfg/management/commands/__init__.py +13 -1
  100. django_cfg/management/commands/app_agent_diagnose.py +470 -0
  101. django_cfg/management/commands/app_agent_generate.py +342 -0
  102. django_cfg/management/commands/app_agent_info.py +308 -0
  103. django_cfg/management/commands/migrate_all.py +9 -3
  104. django_cfg/management/commands/migrator.py +11 -6
  105. django_cfg/management/commands/rundramatiq.py +3 -2
  106. django_cfg/middleware/__init__.py +0 -2
  107. django_cfg/models/api_keys.py +115 -0
  108. django_cfg/modules/django_admin/__init__.py +64 -0
  109. django_cfg/modules/django_admin/decorators/__init__.py +13 -0
  110. django_cfg/modules/django_admin/decorators/actions.py +106 -0
  111. django_cfg/modules/django_admin/decorators/display.py +106 -0
  112. django_cfg/modules/django_admin/mixins/__init__.py +14 -0
  113. django_cfg/modules/django_admin/mixins/display_mixin.py +81 -0
  114. django_cfg/modules/django_admin/mixins/optimization_mixin.py +41 -0
  115. django_cfg/modules/django_admin/mixins/standalone_actions_mixin.py +202 -0
  116. django_cfg/modules/django_admin/models/__init__.py +20 -0
  117. django_cfg/modules/django_admin/models/action_models.py +33 -0
  118. django_cfg/modules/django_admin/models/badge_models.py +20 -0
  119. django_cfg/modules/django_admin/models/base.py +26 -0
  120. django_cfg/modules/django_admin/models/display_models.py +31 -0
  121. django_cfg/modules/django_admin/utils/badges.py +159 -0
  122. django_cfg/modules/django_admin/utils/displays.py +247 -0
  123. django_cfg/modules/django_app_agent/__init__.py +87 -0
  124. django_cfg/modules/django_app_agent/agents/__init__.py +40 -0
  125. django_cfg/modules/django_app_agent/agents/base/__init__.py +24 -0
  126. django_cfg/modules/django_app_agent/agents/base/agent.py +354 -0
  127. django_cfg/modules/django_app_agent/agents/base/context.py +236 -0
  128. django_cfg/modules/django_app_agent/agents/base/executor.py +430 -0
  129. django_cfg/modules/django_app_agent/agents/generation/__init__.py +12 -0
  130. django_cfg/modules/django_app_agent/agents/generation/app_generator/__init__.py +15 -0
  131. django_cfg/modules/django_app_agent/agents/generation/app_generator/config_validator.py +147 -0
  132. django_cfg/modules/django_app_agent/agents/generation/app_generator/main.py +99 -0
  133. django_cfg/modules/django_app_agent/agents/generation/app_generator/models.py +32 -0
  134. django_cfg/modules/django_app_agent/agents/generation/app_generator/prompt_manager.py +290 -0
  135. django_cfg/modules/django_app_agent/agents/interfaces.py +376 -0
  136. django_cfg/modules/django_app_agent/core/__init__.py +33 -0
  137. django_cfg/modules/django_app_agent/core/config.py +300 -0
  138. django_cfg/modules/django_app_agent/core/exceptions.py +359 -0
  139. django_cfg/modules/django_app_agent/models/__init__.py +71 -0
  140. django_cfg/modules/django_app_agent/models/base.py +283 -0
  141. django_cfg/modules/django_app_agent/models/context.py +496 -0
  142. django_cfg/modules/django_app_agent/models/enums.py +481 -0
  143. django_cfg/modules/django_app_agent/models/requests.py +500 -0
  144. django_cfg/modules/django_app_agent/models/responses.py +585 -0
  145. django_cfg/modules/django_app_agent/pytest.ini +6 -0
  146. django_cfg/modules/django_app_agent/services/__init__.py +42 -0
  147. django_cfg/modules/django_app_agent/services/app_generator/__init__.py +30 -0
  148. django_cfg/modules/django_app_agent/services/app_generator/ai_integration.py +133 -0
  149. django_cfg/modules/django_app_agent/services/app_generator/context.py +40 -0
  150. django_cfg/modules/django_app_agent/services/app_generator/main.py +202 -0
  151. django_cfg/modules/django_app_agent/services/app_generator/structure.py +316 -0
  152. django_cfg/modules/django_app_agent/services/app_generator/validation.py +125 -0
  153. django_cfg/modules/django_app_agent/services/base.py +437 -0
  154. django_cfg/modules/django_app_agent/services/context_builder/__init__.py +34 -0
  155. django_cfg/modules/django_app_agent/services/context_builder/code_extractor.py +141 -0
  156. django_cfg/modules/django_app_agent/services/context_builder/context_generator.py +276 -0
  157. django_cfg/modules/django_app_agent/services/context_builder/main.py +272 -0
  158. django_cfg/modules/django_app_agent/services/context_builder/models.py +40 -0
  159. django_cfg/modules/django_app_agent/services/context_builder/pattern_analyzer.py +85 -0
  160. django_cfg/modules/django_app_agent/services/project_scanner/__init__.py +31 -0
  161. django_cfg/modules/django_app_agent/services/project_scanner/app_discovery.py +311 -0
  162. django_cfg/modules/django_app_agent/services/project_scanner/main.py +221 -0
  163. django_cfg/modules/django_app_agent/services/project_scanner/models.py +59 -0
  164. django_cfg/modules/django_app_agent/services/project_scanner/pattern_detection.py +94 -0
  165. django_cfg/modules/django_app_agent/services/questioning_service/__init__.py +28 -0
  166. django_cfg/modules/django_app_agent/services/questioning_service/main.py +273 -0
  167. django_cfg/modules/django_app_agent/services/questioning_service/models.py +111 -0
  168. django_cfg/modules/django_app_agent/services/questioning_service/question_generator.py +251 -0
  169. django_cfg/modules/django_app_agent/services/questioning_service/response_processor.py +347 -0
  170. django_cfg/modules/django_app_agent/services/questioning_service/session_manager.py +356 -0
  171. django_cfg/modules/django_app_agent/services/report_service.py +332 -0
  172. django_cfg/modules/django_app_agent/services/template_manager/__init__.py +18 -0
  173. django_cfg/modules/django_app_agent/services/template_manager/jinja_engine.py +236 -0
  174. django_cfg/modules/django_app_agent/services/template_manager/main.py +159 -0
  175. django_cfg/modules/django_app_agent/services/template_manager/models.py +36 -0
  176. django_cfg/modules/django_app_agent/services/template_manager/template_loader.py +100 -0
  177. django_cfg/modules/django_app_agent/services/template_manager/templates/admin.py.j2 +105 -0
  178. django_cfg/modules/django_app_agent/services/template_manager/templates/apps.py.j2 +31 -0
  179. django_cfg/modules/django_app_agent/services/template_manager/templates/cfg_config.py.j2 +44 -0
  180. django_cfg/modules/django_app_agent/services/template_manager/templates/cfg_module.py.j2 +81 -0
  181. django_cfg/modules/django_app_agent/services/template_manager/templates/forms.py.j2 +107 -0
  182. django_cfg/modules/django_app_agent/services/template_manager/templates/models.py.j2 +139 -0
  183. django_cfg/modules/django_app_agent/services/template_manager/templates/serializers.py.j2 +91 -0
  184. django_cfg/modules/django_app_agent/services/template_manager/templates/tests.py.j2 +195 -0
  185. django_cfg/modules/django_app_agent/services/template_manager/templates/urls.py.j2 +35 -0
  186. django_cfg/modules/django_app_agent/services/template_manager/templates/views.py.j2 +211 -0
  187. django_cfg/modules/django_app_agent/services/template_manager/variable_processor.py +200 -0
  188. django_cfg/modules/django_app_agent/services/validation_service/__init__.py +25 -0
  189. django_cfg/modules/django_app_agent/services/validation_service/django_validator.py +333 -0
  190. django_cfg/modules/django_app_agent/services/validation_service/main.py +242 -0
  191. django_cfg/modules/django_app_agent/services/validation_service/models.py +66 -0
  192. django_cfg/modules/django_app_agent/services/validation_service/quality_validator.py +352 -0
  193. django_cfg/modules/django_app_agent/services/validation_service/security_validator.py +272 -0
  194. django_cfg/modules/django_app_agent/services/validation_service/syntax_validator.py +203 -0
  195. django_cfg/modules/django_app_agent/ui/__init__.py +25 -0
  196. django_cfg/modules/django_app_agent/ui/cli.py +419 -0
  197. django_cfg/modules/django_app_agent/ui/rich_components.py +622 -0
  198. django_cfg/modules/django_app_agent/utils/__init__.py +38 -0
  199. django_cfg/modules/django_app_agent/utils/logging.py +360 -0
  200. django_cfg/modules/django_app_agent/utils/validation.py +417 -0
  201. django_cfg/modules/django_currency/__init__.py +2 -2
  202. django_cfg/modules/django_currency/clients/__init__.py +2 -2
  203. django_cfg/modules/django_currency/clients/hybrid_client.py +587 -0
  204. django_cfg/modules/django_currency/core/converter.py +12 -12
  205. django_cfg/modules/django_currency/database/__init__.py +2 -2
  206. django_cfg/modules/django_currency/database/database_loader.py +93 -42
  207. django_cfg/modules/django_llm/llm/client.py +10 -2
  208. django_cfg/modules/django_unfold/callbacks/actions.py +1 -1
  209. django_cfg/modules/django_unfold/callbacks/statistics.py +1 -1
  210. django_cfg/modules/django_unfold/dashboard.py +14 -13
  211. django_cfg/modules/django_unfold/models/config.py +1 -1
  212. django_cfg/registry/core.py +3 -0
  213. django_cfg/registry/third_party.py +2 -2
  214. django_cfg/template_archive/django_sample.zip +0 -0
  215. {django_cfg-1.3.7.dist-info → django_cfg-1.3.9.dist-info}/METADATA +2 -1
  216. {django_cfg-1.3.7.dist-info → django_cfg-1.3.9.dist-info}/RECORD +223 -117
  217. django_cfg/apps/accounts/admin/activity.py +0 -96
  218. django_cfg/apps/accounts/admin/group.py +0 -17
  219. django_cfg/apps/accounts/admin/otp.py +0 -59
  220. django_cfg/apps/accounts/admin/registration_source.py +0 -97
  221. django_cfg/apps/accounts/admin/twilio_response.py +0 -227
  222. django_cfg/apps/accounts/admin/user.py +0 -300
  223. django_cfg/apps/agents/core/agent.py +0 -281
  224. django_cfg/apps/payments/admin_interface/old/payments/base.html +0 -175
  225. django_cfg/apps/payments/admin_interface/old/payments/components/dev_tool_card.html +0 -125
  226. django_cfg/apps/payments/admin_interface/old/payments/components/loading_spinner.html +0 -16
  227. django_cfg/apps/payments/admin_interface/old/payments/components/ngrok_status_card.html +0 -113
  228. django_cfg/apps/payments/admin_interface/old/payments/components/notification.html +0 -27
  229. django_cfg/apps/payments/admin_interface/old/payments/components/provider_card.html +0 -86
  230. django_cfg/apps/payments/admin_interface/old/payments/components/status_card.html +0 -35
  231. django_cfg/apps/payments/admin_interface/old/payments/currency_converter.html +0 -382
  232. django_cfg/apps/payments/admin_interface/old/payments/payment_dashboard.html +0 -309
  233. django_cfg/apps/payments/admin_interface/old/payments/payment_form.html +0 -303
  234. django_cfg/apps/payments/admin_interface/old/payments/payment_list.html +0 -382
  235. django_cfg/apps/payments/admin_interface/old/payments/payment_status.html +0 -500
  236. django_cfg/apps/payments/admin_interface/old/payments/webhook_dashboard.html +0 -518
  237. django_cfg/apps/payments/admin_interface/old/static/payments/css/components.css +0 -619
  238. django_cfg/apps/payments/admin_interface/old/static/payments/css/dashboard.css +0 -188
  239. django_cfg/apps/payments/admin_interface/old/static/payments/js/components.js +0 -545
  240. django_cfg/apps/payments/admin_interface/old/static/payments/js/ngrok-status.js +0 -163
  241. django_cfg/apps/payments/admin_interface/old/static/payments/js/utils.js +0 -412
  242. django_cfg/apps/tasks/admin.py +0 -320
  243. django_cfg/middleware/static_nocache.py +0 -55
  244. django_cfg/modules/django_currency/clients/yahoo_client.py +0 -157
  245. /django_cfg/modules/{django_unfold → django_admin}/icons/README.md +0 -0
  246. /django_cfg/modules/{django_unfold → django_admin}/icons/__init__.py +0 -0
  247. /django_cfg/modules/{django_unfold → django_admin}/icons/constants.py +0 -0
  248. /django_cfg/modules/{django_unfold → django_admin}/icons/generate_icons.py +0 -0
  249. {django_cfg-1.3.7.dist-info → django_cfg-1.3.9.dist-info}/WHEEL +0 -0
  250. {django_cfg-1.3.7.dist-info → django_cfg-1.3.9.dist-info}/entry_points.txt +0 -0
  251. {django_cfg-1.3.7.dist-info → django_cfg-1.3.9.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,622 @@
1
+ """
2
+ Rich UI Components for Django App Agent Module.
3
+
4
+ This module provides beautiful terminal UI components using Rich library
5
+ for progress tracking, question interfaces, error display, and status updates.
6
+ """
7
+
8
+ from typing import Dict, List, Optional, Any, Generator, ContextManager
9
+ from contextlib import contextmanager
10
+ from datetime import datetime, timedelta
11
+ import time
12
+
13
+ from rich.console import Console
14
+ from rich.panel import Panel
15
+ from rich.progress import (
16
+ Progress, SpinnerColumn, TextColumn, BarColumn,
17
+ TimeElapsedColumn, TimeRemainingColumn, MofNCompleteColumn
18
+ )
19
+ from rich.prompt import Prompt, Confirm, IntPrompt
20
+ from rich.syntax import Syntax
21
+ from rich.table import Table
22
+ from rich.tree import Tree
23
+ from rich.layout import Layout
24
+ from rich.live import Live
25
+ from rich.text import Text
26
+ from rich.align import Align
27
+ from rich.columns import Columns
28
+ from rich.status import Status
29
+
30
+ from ..models.requests import AppGenerationRequest
31
+ from ..models.responses import AppGenerationResult
32
+ from ..models.enums import AppType, AppComplexity, AppFeature
33
+
34
+
35
+ class RichTheme:
36
+ """Consistent color theme for Rich UI components."""
37
+
38
+ PRIMARY = "bright_blue"
39
+ SECONDARY = "bright_green"
40
+ ACCENT = "bright_yellow"
41
+ SUCCESS = "bright_green"
42
+ WARNING = "bright_yellow"
43
+ ERROR = "bright_red"
44
+ INFO = "bright_cyan"
45
+ MUTED = "dim white"
46
+ CODE = "bright_magenta"
47
+
48
+
49
+ class RichProgressTracker:
50
+ """Rich progress tracking for long-running operations."""
51
+
52
+ def __init__(self, console: Console):
53
+ """Initialize progress tracker."""
54
+ self.console = console
55
+ self.theme = RichTheme()
56
+
57
+ @contextmanager
58
+ def track_generation(self, app_name: str) -> ContextManager['GenerationProgress']:
59
+ """Track application generation progress."""
60
+ progress = GenerationProgress(self.console, app_name)
61
+ try:
62
+ yield progress
63
+ finally:
64
+ progress.complete()
65
+
66
+ @contextmanager
67
+ def track_scanning(self) -> ContextManager['ScanningProgress']:
68
+ """Track project scanning progress."""
69
+ progress = ScanningProgress(self.console)
70
+ try:
71
+ yield progress
72
+ finally:
73
+ progress.complete()
74
+
75
+
76
+ class GenerationProgress:
77
+ """Progress tracker for application generation."""
78
+
79
+ def __init__(self, console: Console, app_name: str):
80
+ """Initialize generation progress."""
81
+ self.console = console
82
+ self.app_name = app_name
83
+ self.start_time = datetime.now()
84
+
85
+ # Create progress components
86
+ self.progress = Progress(
87
+ SpinnerColumn(),
88
+ TextColumn("[progress.description]{task.description}"),
89
+ BarColumn(),
90
+ MofNCompleteColumn(),
91
+ TimeElapsedColumn(),
92
+ TimeRemainingColumn(),
93
+ console=console,
94
+ transient=False
95
+ )
96
+
97
+ # Define generation phases
98
+ self.phases = [
99
+ "🔍 Analyzing project structure",
100
+ "🧠 Building development context",
101
+ "❓ Processing requirements",
102
+ "📋 Creating app manifest",
103
+ "🏗️ Generating code files",
104
+ "✅ Validating code quality",
105
+ "📊 Calculating metrics",
106
+ "📄 Creating documentation"
107
+ ]
108
+
109
+ self.current_phase = 0
110
+ self.task_id = None
111
+
112
+ def start(self):
113
+ """Start progress tracking."""
114
+ self.progress.start()
115
+ self.task_id = self.progress.add_task(
116
+ f"Generating {self.app_name}...",
117
+ total=len(self.phases)
118
+ )
119
+
120
+ # Show initial phase
121
+ self.update_phase(0)
122
+
123
+ def update_phase(self, phase_index: int, message: Optional[str] = None):
124
+ """Update current phase."""
125
+ if phase_index < len(self.phases):
126
+ self.current_phase = phase_index
127
+ description = message or self.phases[phase_index]
128
+
129
+ self.progress.update(
130
+ self.task_id,
131
+ description=description,
132
+ completed=phase_index
133
+ )
134
+
135
+ def next_phase(self, message: Optional[str] = None):
136
+ """Move to next phase."""
137
+ self.update_phase(self.current_phase + 1, message)
138
+
139
+ def complete(self):
140
+ """Complete progress tracking."""
141
+ if self.task_id:
142
+ self.progress.update(
143
+ self.task_id,
144
+ description="✅ Generation completed!",
145
+ completed=len(self.phases)
146
+ )
147
+
148
+ self.progress.stop()
149
+
150
+ # Show completion summary
151
+ duration = datetime.now() - self.start_time
152
+ self._show_completion_summary(duration)
153
+
154
+ def _show_completion_summary(self, duration: timedelta):
155
+ """Show completion summary."""
156
+ summary_text = Text()
157
+ summary_text.append("🎉 Application generation completed!\n", style="bold green")
158
+ summary_text.append(f"⏱️ Total time: {duration.total_seconds():.1f} seconds\n", style="cyan")
159
+ summary_text.append(f"📱 App: {self.app_name}", style="blue")
160
+
161
+ panel = Panel(
162
+ summary_text,
163
+ title="Generation Complete",
164
+ border_style="green",
165
+ padding=(1, 2)
166
+ )
167
+
168
+ self.console.print(panel)
169
+
170
+
171
+ class ScanningProgress:
172
+ """Progress tracker for project scanning."""
173
+
174
+ def __init__(self, console: Console):
175
+ """Initialize scanning progress."""
176
+ self.console = console
177
+ self.status = Status("🔍 Scanning project...", console=console)
178
+
179
+ def start(self):
180
+ """Start scanning progress."""
181
+ self.status.start()
182
+
183
+ def update(self, message: str):
184
+ """Update scanning status."""
185
+ self.status.update(f"🔍 {message}")
186
+
187
+ def complete(self):
188
+ """Complete scanning."""
189
+ self.status.stop()
190
+
191
+
192
+ class RichQuestionInterface:
193
+ """Rich interface for interactive questioning."""
194
+
195
+ def __init__(self, console: Console):
196
+ """Initialize question interface."""
197
+ self.console = console
198
+ self.theme = RichTheme()
199
+
200
+ def ask_app_details(self) -> Dict[str, Any]:
201
+ """Ask for basic application details."""
202
+ self.console.print()
203
+ self._show_header("Application Details", "Let's gather some basic information about your app")
204
+
205
+ # App name
206
+ app_name = self._ask_app_name()
207
+
208
+ # Description
209
+ description = self._ask_description()
210
+
211
+ # App type
212
+ app_type = self._ask_app_type()
213
+
214
+ # Complexity
215
+ complexity = self._ask_complexity()
216
+
217
+ return {
218
+ "app_name": app_name,
219
+ "description": description,
220
+ "app_type": app_type,
221
+ "complexity": complexity
222
+ }
223
+
224
+ def ask_features(self, complexity: AppComplexity) -> List[AppFeature]:
225
+ """Ask for feature selection."""
226
+ self._show_header("Feature Selection", f"Select features for your {complexity.value} application")
227
+
228
+ recommended = complexity.get_recommended_features()
229
+ all_features = list(AppFeature)
230
+
231
+ # Show recommended features
232
+ self._show_recommended_features(recommended)
233
+
234
+ # Ask if user wants to customize
235
+ if Confirm.ask("\n[bold]Customize feature selection?[/bold]", default=False):
236
+ return self._customize_features(all_features, recommended)
237
+ else:
238
+ return list(recommended)
239
+
240
+ def ask_contextual_questions(self, questions: List[Dict[str, Any]]) -> Dict[str, Any]:
241
+ """Ask contextual questions based on project analysis."""
242
+ self._show_header("Contextual Questions", "Based on your project, we have some specific questions")
243
+
244
+ answers = {}
245
+
246
+ for i, question in enumerate(questions, 1):
247
+ self.console.print(f"\n[bold cyan]Question {i}/{len(questions)}:[/bold cyan]")
248
+
249
+ # Show question context if available
250
+ if question.get("context"):
251
+ self._show_question_context(question["context"])
252
+
253
+ # Ask the question
254
+ answer = self._ask_question(question)
255
+ answers[question["id"]] = answer
256
+
257
+ # Show progress
258
+ progress_bar = "█" * (i * 20 // len(questions)) + "░" * (20 - (i * 20 // len(questions)))
259
+ self.console.print(f"[dim]Progress: [{progress_bar}] {i}/{len(questions)}[/dim]")
260
+
261
+ return answers
262
+
263
+ def _show_header(self, title: str, subtitle: str = ""):
264
+ """Show section header."""
265
+ header_text = Text()
266
+ header_text.append(title, style=f"bold {self.theme.PRIMARY}")
267
+ if subtitle:
268
+ header_text.append(f"\n{subtitle}", style=self.theme.MUTED)
269
+
270
+ panel = Panel(
271
+ header_text,
272
+ border_style=self.theme.PRIMARY,
273
+ padding=(1, 2)
274
+ )
275
+
276
+ self.console.print(panel)
277
+
278
+ def _ask_app_name(self) -> str:
279
+ """Ask for application name."""
280
+ while True:
281
+ app_name = Prompt.ask(
282
+ "[bold]Application name[/bold]",
283
+ default="my_app"
284
+ )
285
+
286
+ # Basic validation
287
+ if app_name.replace("_", "").isalnum() and app_name[0].isalpha():
288
+ return app_name
289
+ else:
290
+ self.console.print("[red]❌ Invalid name. Use letters, numbers, and underscores only.[/red]")
291
+
292
+ def _ask_description(self) -> str:
293
+ """Ask for application description."""
294
+ return Prompt.ask(
295
+ "[bold]Brief description[/bold]",
296
+ default="A Django application"
297
+ )
298
+
299
+ def _ask_app_type(self) -> AppType:
300
+ """Ask for application type."""
301
+ self.console.print("\n[bold]Application Type:[/bold]")
302
+
303
+ table = Table(show_header=False, box=None, padding=(0, 2))
304
+ table.add_column("Option", style="cyan")
305
+ table.add_column("Description")
306
+
307
+ table.add_row("1", "🐍 Django - Standard Django application")
308
+ table.add_row("2", "⚙️ Django-CFG - Enhanced with configuration management")
309
+
310
+ self.console.print(table)
311
+
312
+ choice = Prompt.ask("Choose type", choices=["1", "2"], default="2")
313
+ return AppType.DJANGO if choice == "1" else AppType.DJANGO_CFG
314
+
315
+ def _ask_complexity(self) -> AppComplexity:
316
+ """Ask for complexity level."""
317
+ self.console.print("\n[bold]Complexity Level:[/bold]")
318
+
319
+ table = Table(show_header=True, header_style="bold magenta")
320
+ table.add_column("Option", style="cyan", width=8)
321
+ table.add_column("Level", style="green")
322
+ table.add_column("Description")
323
+ table.add_column("Time", style="yellow")
324
+
325
+ table.add_row("1", "Basic", "Simple app with core features", "~5 min")
326
+ table.add_row("2", "Moderate", "Standard app with common features", "~15 min")
327
+ table.add_row("3", "Advanced", "Complex app with advanced features", "~30 min")
328
+ table.add_row("4", "Enterprise", "Full-featured enterprise app", "~60 min")
329
+
330
+ self.console.print(table)
331
+
332
+ choice = Prompt.ask("Choose complexity", choices=["1", "2", "3", "4"], default="2")
333
+
334
+ complexity_map = {
335
+ "1": AppComplexity.SIMPLE,
336
+ "2": AppComplexity.MODERATE,
337
+ "3": AppComplexity.ADVANCED,
338
+ "4": AppComplexity.ENTERPRISE
339
+ }
340
+
341
+ return complexity_map[choice]
342
+
343
+ def _show_recommended_features(self, features: set):
344
+ """Show recommended features."""
345
+ self.console.print("\n[bold green]Recommended Features:[/bold green]")
346
+
347
+ columns = []
348
+ for feature in sorted(features, key=lambda x: x.value):
349
+ feature_text = Text()
350
+ feature_text.append("✓ ", style="green")
351
+ feature_text.append(feature.value.replace("_", " ").title(), style="white")
352
+ columns.append(Panel(feature_text, padding=(0, 1), border_style="dim"))
353
+
354
+ self.console.print(Columns(columns, equal=True, expand=True))
355
+
356
+ def _customize_features(self, all_features: List[AppFeature], recommended: set) -> List[AppFeature]:
357
+ """Allow feature customization."""
358
+ selected = recommended.copy()
359
+
360
+ self.console.print("\n[bold]Feature Customization:[/bold]")
361
+ self.console.print("[dim]Type feature name to toggle, 'done' to finish[/dim]")
362
+
363
+ while True:
364
+ # Show current selection in columns
365
+ self._show_feature_grid(all_features, selected)
366
+
367
+ choice = Prompt.ask(
368
+ "\nFeature to toggle (or 'done')",
369
+ default="done"
370
+ ).lower()
371
+
372
+ if choice == "done":
373
+ break
374
+
375
+ # Find matching feature
376
+ matching_feature = self._find_feature(choice, all_features)
377
+
378
+ if matching_feature:
379
+ if matching_feature in selected:
380
+ selected.remove(matching_feature)
381
+ self.console.print(f"[red]➖ Removed {matching_feature.value}[/red]")
382
+ else:
383
+ selected.add(matching_feature)
384
+ self.console.print(f"[green]➕ Added {matching_feature.value}[/green]")
385
+ else:
386
+ self.console.print(f"[red]❌ Feature '{choice}' not found[/red]")
387
+
388
+ return list(selected)
389
+
390
+ def _show_feature_grid(self, all_features: List[AppFeature], selected: set):
391
+ """Show features in a grid layout."""
392
+ table = Table(show_header=True, header_style="bold magenta")
393
+ table.add_column("Feature", style="white")
394
+ table.add_column("Status", width=8, style="center")
395
+ table.add_column("Description", style="dim")
396
+
397
+ for feature in all_features:
398
+ status = "✓" if feature in selected else " "
399
+ status_style = "green" if feature in selected else "dim"
400
+ description = self._get_feature_description(feature)
401
+
402
+ table.add_row(
403
+ feature.value.replace("_", " ").title(),
404
+ status,
405
+ description,
406
+ style=status_style
407
+ )
408
+
409
+ self.console.print(table)
410
+
411
+ def _find_feature(self, search: str, features: List[AppFeature]) -> Optional[AppFeature]:
412
+ """Find feature by partial name match."""
413
+ search = search.lower()
414
+
415
+ # Exact match first
416
+ for feature in features:
417
+ if feature.value.lower() == search:
418
+ return feature
419
+
420
+ # Partial match
421
+ for feature in features:
422
+ if search in feature.value.lower():
423
+ return feature
424
+
425
+ return None
426
+
427
+ def _get_feature_description(self, feature: AppFeature) -> str:
428
+ """Get feature description."""
429
+ descriptions = {
430
+ AppFeature.MODELS: "Database models and ORM",
431
+ AppFeature.VIEWS: "View functions and classes",
432
+ AppFeature.URLS: "URL routing configuration",
433
+ AppFeature.ADMIN: "Django admin interface",
434
+ AppFeature.FORMS: "Form classes and validation",
435
+ AppFeature.TEMPLATES: "HTML templates",
436
+ AppFeature.API: "REST API with DRF",
437
+ AppFeature.TESTS: "Unit and integration tests",
438
+ AppFeature.TASKS: "Background tasks",
439
+ AppFeature.DOCS: "Documentation",
440
+ AppFeature.CONFIG: "Configuration management",
441
+ AppFeature.SECURITY: "Security and permissions",
442
+ }
443
+ return descriptions.get(feature, "Additional feature")
444
+
445
+ def _show_question_context(self, context: Dict[str, Any]):
446
+ """Show context for a question."""
447
+ if context.get("code_snippet"):
448
+ code_panel = Panel(
449
+ Syntax(context["code_snippet"], "python", theme="monokai"),
450
+ title="📄 Relevant Code",
451
+ border_style="dim"
452
+ )
453
+ self.console.print(code_panel)
454
+
455
+ if context.get("explanation"):
456
+ self.console.print(f"[dim]{context['explanation']}[/dim]")
457
+
458
+ def _ask_question(self, question: Dict[str, Any]) -> Any:
459
+ """Ask a single question."""
460
+ question_type = question.get("type", "text")
461
+
462
+ if question_type == "yes_no":
463
+ return Confirm.ask(question["text"], default=question.get("default", True))
464
+
465
+ elif question_type == "choice":
466
+ choices = question.get("choices", [])
467
+ if choices:
468
+ self.console.print(f"\n[bold]{question['text']}[/bold]")
469
+ for i, choice in enumerate(choices, 1):
470
+ self.console.print(f" {i}. {choice}")
471
+
472
+ choice_num = IntPrompt.ask(
473
+ "Choose option",
474
+ choices=[str(i) for i in range(1, len(choices) + 1)],
475
+ default="1"
476
+ )
477
+ return choices[int(choice_num) - 1]
478
+
479
+ else: # text
480
+ return Prompt.ask(question["text"], default=question.get("default", ""))
481
+
482
+
483
+ class RichErrorDisplay:
484
+ """Rich error display with helpful suggestions."""
485
+
486
+ def __init__(self, console: Console):
487
+ """Initialize error display."""
488
+ self.console = console
489
+ self.theme = RichTheme()
490
+
491
+ def show_error(
492
+ self,
493
+ title: str,
494
+ message: str,
495
+ errors: Optional[List[str]] = None,
496
+ warnings: Optional[List[str]] = None,
497
+ suggestions: Optional[List[str]] = None
498
+ ):
499
+ """Show comprehensive error information."""
500
+ # Main error panel
501
+ error_text = Text()
502
+ error_text.append("❌ ", style=self.theme.ERROR)
503
+ error_text.append(message, style="white")
504
+
505
+ error_panel = Panel(
506
+ error_text,
507
+ title=f"[bold red]{title}[/bold red]",
508
+ border_style=self.theme.ERROR,
509
+ padding=(1, 2)
510
+ )
511
+
512
+ self.console.print(error_panel)
513
+
514
+ # Show detailed errors
515
+ if errors:
516
+ self._show_error_list("Errors", errors, self.theme.ERROR)
517
+
518
+ # Show warnings
519
+ if warnings:
520
+ self._show_error_list("Warnings", warnings, self.theme.WARNING)
521
+
522
+ # Show suggestions
523
+ if suggestions:
524
+ self._show_suggestions(suggestions)
525
+
526
+ def _show_error_list(self, title: str, items: List[str], style: str):
527
+ """Show list of errors or warnings."""
528
+ self.console.print(f"\n[bold {style}]{title}:[/bold {style}]")
529
+
530
+ for item in items:
531
+ self.console.print(f" • {item}", style=style)
532
+
533
+ def _show_suggestions(self, suggestions: List[str]):
534
+ """Show helpful suggestions."""
535
+ self.console.print(f"\n[bold {self.theme.INFO}]💡 Suggestions:[/bold {self.theme.INFO}]")
536
+
537
+ for suggestion in suggestions:
538
+ self.console.print(f" • {suggestion}", style=self.theme.INFO)
539
+
540
+
541
+ class RichStatusDisplay:
542
+ """Rich status display for various operations."""
543
+
544
+ def __init__(self, console: Console):
545
+ """Initialize status display."""
546
+ self.console = console
547
+ self.theme = RichTheme()
548
+
549
+ def show_generation_result(self, result: AppGenerationResult):
550
+ """Show application generation result."""
551
+ if result.status == "success":
552
+ self._show_success_result(result)
553
+ else:
554
+ self._show_failure_result(result)
555
+
556
+ def _show_success_result(self, result: AppGenerationResult):
557
+ """Show successful generation result."""
558
+ # Success header
559
+ success_text = Text()
560
+ success_text.append("🎉 Success! ", style="bold green")
561
+ success_text.append(f"Generated '{result.app_name}' application", style="white")
562
+
563
+ header_panel = Panel(
564
+ success_text,
565
+ border_style="green",
566
+ padding=(1, 2)
567
+ )
568
+
569
+ self.console.print(header_panel)
570
+
571
+ # Statistics table
572
+ stats_table = Table(title="Generation Statistics", show_header=True)
573
+ stats_table.add_column("Metric", style="cyan")
574
+ stats_table.add_column("Value", style="green")
575
+
576
+ stats_table.add_row("Files Generated", str(len(result.generated_files)))
577
+ stats_table.add_row("Duration", f"{result.duration_seconds:.1f} seconds")
578
+
579
+ if result.quality_metrics:
580
+ stats_table.add_row("Code Quality", f"{result.quality_metrics.code_readability_score:.2f}/1.0")
581
+ stats_table.add_row("Test Coverage", f"{result.quality_metrics.test_coverage_percentage:.1f}%")
582
+
583
+ self.console.print(stats_table)
584
+
585
+ # Next steps
586
+ self._show_next_steps(result.app_name)
587
+
588
+ def _show_failure_result(self, result: AppGenerationResult):
589
+ """Show failed generation result."""
590
+ error_text = Text()
591
+ error_text.append("❌ Generation Failed\n", style="bold red")
592
+ error_text.append(result.message, style="white")
593
+
594
+ error_panel = Panel(
595
+ error_text,
596
+ border_style="red",
597
+ padding=(1, 2)
598
+ )
599
+
600
+ self.console.print(error_panel)
601
+
602
+ # Show errors if any
603
+ if result.errors:
604
+ self.console.print("\n[bold red]Errors:[/bold red]")
605
+ for error in result.errors:
606
+ self.console.print(f" • {error}", style="red")
607
+
608
+ def _show_next_steps(self, app_name: str):
609
+ """Show next steps after successful generation."""
610
+ self.console.print("\n[bold]🚀 Next Steps:[/bold]")
611
+
612
+ steps = [
613
+ f"1. Add '{app_name}' to your INSTALLED_APPS",
614
+ "2. Run migrations: [cyan]python manage.py makemigrations && python manage.py migrate[/cyan]",
615
+ "3. Include URLs in your main urls.py",
616
+ "4. Start development! 🎯"
617
+ ]
618
+
619
+ for step in steps:
620
+ self.console.print(f" {step}")
621
+
622
+ self.console.print()
@@ -0,0 +1,38 @@
1
+ """
2
+ Utility functions and helpers for Django App Agent Module.
3
+
4
+ This module contains common utilities including:
5
+ - Structured logging
6
+ - Validation helpers
7
+ - File system utilities
8
+ - String processing functions
9
+ """
10
+
11
+ from .logging import (
12
+ get_logger,
13
+ setup_logging,
14
+ log_execution_time,
15
+ log_agent_operation,
16
+ StructuredLogger,
17
+ )
18
+ from .validation import (
19
+ validate_app_name,
20
+ validate_file_path,
21
+ validate_python_identifier,
22
+ sanitize_filename,
23
+ )
24
+
25
+ __all__ = [
26
+ # Logging
27
+ "get_logger",
28
+ "setup_logging",
29
+ "log_execution_time",
30
+ "log_agent_operation",
31
+ "StructuredLogger",
32
+
33
+ # Validation
34
+ "validate_app_name",
35
+ "validate_file_path",
36
+ "validate_python_identifier",
37
+ "sanitize_filename",
38
+ ]