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,470 @@
1
+ """
2
+ Django management command for project diagnosis.
3
+
4
+ This command provides AI-powered diagnosis of Django/Django-cfg projects
5
+ to help identify and solve common problems.
6
+ """
7
+
8
+ import asyncio
9
+ import sys
10
+ from pathlib import Path
11
+ from typing import List, Optional
12
+
13
+ from django.core.management.base import BaseCommand, CommandError
14
+ from django.conf import settings
15
+
16
+ try:
17
+ from django_cfg.modules.django_app_agent.services import (
18
+ ProjectScannerService,
19
+ ContextBuilderService
20
+ )
21
+ from django_cfg.modules.django_app_agent.models.requests import (
22
+ ProjectScanRequest,
23
+ ContextBuildRequest
24
+ )
25
+ from django_cfg.modules.django_app_agent.core.exceptions import DjangoAppAgentError
26
+ from django_cfg.modules.django_app_agent.core.config import AgentConfig
27
+ from django_cfg.modules.django_app_agent.utils.logging import get_logger
28
+ from django_cfg.modules.django_app_agent.ui.rich_components import (
29
+ RichProgressTracker,
30
+ InteractiveQuestioningUI
31
+ )
32
+ except ImportError as e:
33
+ print(f"Error importing django_app_agent module: {e}")
34
+ print("Make sure the django_app_agent module is properly installed.")
35
+ sys.exit(1)
36
+
37
+
38
+ class Command(BaseCommand):
39
+ """Django management command for project diagnosis."""
40
+
41
+ help = "Diagnose problems in Django/Django-cfg projects using AI (Django App Agent)"
42
+
43
+ def add_arguments(self, parser):
44
+ """Add command line arguments."""
45
+
46
+ parser.add_argument(
47
+ '--app',
48
+ type=str,
49
+ help='Specific application name to diagnose'
50
+ )
51
+
52
+ parser.add_argument(
53
+ '--category',
54
+ choices=[
55
+ 'database', 'views', 'templates', 'static',
56
+ 'admin', 'auth', 'performance', 'deployment',
57
+ 'config', 'security', 'testing', 'other'
58
+ ],
59
+ help='Problem category to focus on'
60
+ )
61
+
62
+ parser.add_argument(
63
+ '--description',
64
+ type=str,
65
+ help='Description of the problem you are experiencing'
66
+ )
67
+
68
+ parser.add_argument(
69
+ '--severity',
70
+ choices=['low', 'medium', 'high', 'critical'],
71
+ default='medium',
72
+ help='Problem severity level (default: medium)'
73
+ )
74
+
75
+ parser.add_argument(
76
+ '--interactive',
77
+ action='store_true',
78
+ default=True,
79
+ help='Enable interactive diagnosis mode (default: True)'
80
+ )
81
+
82
+ parser.add_argument(
83
+ '--non-interactive',
84
+ action='store_true',
85
+ help='Disable interactive mode'
86
+ )
87
+
88
+ parser.add_argument(
89
+ '--scan-only',
90
+ action='store_true',
91
+ help='Only scan the project without AI diagnosis'
92
+ )
93
+
94
+ parser.add_argument(
95
+ '--output-format',
96
+ choices=['text', 'json', 'markdown'],
97
+ default='text',
98
+ help='Output format for diagnosis results (default: text)'
99
+ )
100
+
101
+ parser.add_argument(
102
+ '--save-report',
103
+ type=str,
104
+ help='Save diagnosis report to specified file'
105
+ )
106
+
107
+ parser.add_argument(
108
+ '--verbose',
109
+ action='store_true',
110
+ help='Enable verbose output'
111
+ )
112
+
113
+ def handle(self, *args, **options):
114
+ """Handle the command execution."""
115
+
116
+ try:
117
+ # Initialize logger
118
+ logger = get_logger("management.commands.diagnose_project")
119
+
120
+ # Determine interactive mode
121
+ interactive = options.get('interactive', True) and not options.get('non_interactive', False)
122
+
123
+ # Show welcome message
124
+ self.stdout.write(
125
+ self.style.SUCCESS("šŸ” Django Project Diagnostic Tool")
126
+ )
127
+ self.stdout.write("Analyzing your project for potential issues...\n")
128
+
129
+ # Run diagnosis
130
+ if interactive and not options.get('description'):
131
+ return self._run_interactive_diagnosis(options)
132
+ else:
133
+ return self._run_direct_diagnosis(options)
134
+
135
+ except DjangoAppAgentError as e:
136
+ logger.error(f"Diagnosis failed: {e}")
137
+ raise CommandError(f"Diagnosis failed: {e}")
138
+ except Exception as e:
139
+ logger.error(f"Unexpected error: {e}")
140
+ raise CommandError(f"Unexpected error: {e}")
141
+
142
+ def _run_interactive_diagnosis(self, options):
143
+ """Run interactive diagnosis with user prompts."""
144
+ try:
145
+ self.stdout.write("šŸ¤– Starting interactive diagnosis...\n")
146
+
147
+ # Gather information interactively
148
+ problem_info = self._gather_problem_info()
149
+
150
+ # Merge with command line options
151
+ diagnosis_options = {**options, **problem_info}
152
+
153
+ # Run diagnosis
154
+ return self._run_diagnosis_process(diagnosis_options)
155
+
156
+ except KeyboardInterrupt:
157
+ self.stdout.write("\nšŸ›‘ Diagnosis cancelled by user")
158
+ except Exception as e:
159
+ raise CommandError(f"Interactive diagnosis failed: {e}")
160
+
161
+ def _run_direct_diagnosis(self, options):
162
+ """Run diagnosis with provided parameters."""
163
+ return self._run_diagnosis_process(options)
164
+
165
+ def _gather_problem_info(self):
166
+ """Gather problem information interactively."""
167
+ problem_info = {}
168
+
169
+ # Ask for problem description
170
+ self.stdout.write("šŸ“ Please describe the problem you're experiencing:")
171
+ description = input("Description: ").strip()
172
+ if description:
173
+ problem_info['description'] = description
174
+
175
+ # Ask for category
176
+ self.stdout.write("\nšŸ“‚ What category best describes your problem?")
177
+ categories = [
178
+ 'database', 'views', 'templates', 'static',
179
+ 'admin', 'auth', 'performance', 'deployment',
180
+ 'config', 'security', 'testing', 'other'
181
+ ]
182
+
183
+ for i, category in enumerate(categories, 1):
184
+ self.stdout.write(f" {i}. {category}")
185
+
186
+ try:
187
+ choice = input("\nEnter number (or press Enter to skip): ").strip()
188
+ if choice and choice.isdigit():
189
+ idx = int(choice) - 1
190
+ if 0 <= idx < len(categories):
191
+ problem_info['category'] = categories[idx]
192
+ except (ValueError, IndexError):
193
+ pass
194
+
195
+ # Ask for specific app
196
+ self.stdout.write("\nšŸŽÆ Is this problem specific to a particular app?")
197
+ app_name = input("App name (or press Enter to skip): ").strip()
198
+ if app_name:
199
+ problem_info['app'] = app_name
200
+
201
+ # Ask for severity
202
+ self.stdout.write("\nāš ļø How severe is this problem?")
203
+ severities = ['low', 'medium', 'high', 'critical']
204
+ for i, severity in enumerate(severities, 1):
205
+ self.stdout.write(f" {i}. {severity}")
206
+
207
+ try:
208
+ choice = input("\nEnter number (default: 2 for medium): ").strip()
209
+ if choice and choice.isdigit():
210
+ idx = int(choice) - 1
211
+ if 0 <= idx < len(severities):
212
+ problem_info['severity'] = severities[idx]
213
+ else:
214
+ problem_info['severity'] = 'medium'
215
+ except (ValueError, IndexError):
216
+ problem_info['severity'] = 'medium'
217
+
218
+ return problem_info
219
+
220
+ def _run_diagnosis_process(self, options):
221
+ """Run the actual diagnosis process."""
222
+ try:
223
+ # Initialize configuration
224
+ config = AgentConfig()
225
+ logger = get_logger("management.commands.diagnose_project")
226
+
227
+ # Show current configuration
228
+ if options.get('verbose'):
229
+ self.stdout.write(f"šŸ”§ Project root: {settings.BASE_DIR}")
230
+ if options.get('app'):
231
+ self.stdout.write(f"šŸŽÆ Target app: {options['app']}")
232
+ if options.get('category'):
233
+ self.stdout.write(f"šŸ“‚ Category: {options['category']}")
234
+ if options.get('description'):
235
+ self.stdout.write(f"šŸ“ Problem: {options['description']}")
236
+ self.stdout.write("")
237
+
238
+ # Step 1: Scan project
239
+ self.stdout.write("šŸ” Step 1: Scanning project structure...")
240
+ scan_result = self._scan_project(options)
241
+
242
+ if options.get('scan_only'):
243
+ return self._display_scan_results(scan_result, options)
244
+
245
+ # Step 2: Build context
246
+ self.stdout.write("🧠 Step 2: Building project context...")
247
+ context = self._build_context(scan_result, options)
248
+
249
+ # Step 3: AI Diagnosis (placeholder for now)
250
+ self.stdout.write("šŸ¤– Step 3: Running AI diagnosis...")
251
+ diagnosis = self._run_ai_diagnosis(context, options)
252
+
253
+ # Step 4: Display results
254
+ self.stdout.write("šŸ“Š Step 4: Generating diagnosis report...")
255
+ return self._display_diagnosis_results(diagnosis, options)
256
+
257
+ except Exception as e:
258
+ raise CommandError(f"Diagnosis process failed: {e}")
259
+
260
+ def _scan_project(self, options):
261
+ """Scan the project structure."""
262
+ try:
263
+ # Initialize scanner service
264
+ config = AgentConfig()
265
+ logger = get_logger("project_scanner")
266
+
267
+ scanner = ProjectScannerService(config, logger)
268
+
269
+ # Create scan request
270
+ request = ProjectScanRequest(
271
+ project_root=str(settings.BASE_DIR),
272
+ target_app=options.get('app'),
273
+ scan_depth=3,
274
+ include_tests=True,
275
+ include_migrations=True
276
+ )
277
+
278
+ # Run scan (async)
279
+ if sys.platform == 'win32':
280
+ asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy())
281
+
282
+ result = asyncio.run(scanner.process(request))
283
+ return result
284
+
285
+ except Exception as e:
286
+ raise CommandError(f"Project scan failed: {e}")
287
+
288
+ def _build_context(self, scan_result, options):
289
+ """Build project context for diagnosis."""
290
+ try:
291
+ # Initialize context builder
292
+ config = AgentConfig()
293
+ logger = get_logger("context_builder")
294
+
295
+ builder = ContextBuilderService(config, logger)
296
+
297
+ # Create context request
298
+ request = ContextBuildRequest(
299
+ project_root=str(settings.BASE_DIR),
300
+ scan_result=scan_result,
301
+ focus_area=options.get('category'),
302
+ target_app=options.get('app')
303
+ )
304
+
305
+ # Build context (async)
306
+ result = asyncio.run(builder.process(request))
307
+ return result
308
+
309
+ except Exception as e:
310
+ raise CommandError(f"Context building failed: {e}")
311
+
312
+ def _run_ai_diagnosis(self, context, options):
313
+ """Run AI-powered diagnosis (placeholder implementation)."""
314
+ # This is a placeholder implementation
315
+ # In the real implementation, this would use AI agents
316
+
317
+ diagnosis = {
318
+ 'status': 'completed',
319
+ 'findings': [
320
+ {
321
+ 'category': options.get('category', 'general'),
322
+ 'severity': options.get('severity', 'medium'),
323
+ 'title': 'Project Structure Analysis',
324
+ 'description': 'Basic project structure appears to be well-organized.',
325
+ 'recommendations': [
326
+ 'Consider adding more comprehensive tests',
327
+ 'Review security settings for production deployment',
328
+ 'Optimize database queries for better performance'
329
+ ]
330
+ }
331
+ ],
332
+ 'summary': 'Project analysis completed. No critical issues found.',
333
+ 'confidence': 0.75
334
+ }
335
+
336
+ return diagnosis
337
+
338
+ def _display_scan_results(self, scan_result, options):
339
+ """Display project scan results."""
340
+ self.stdout.write(self.style.SUCCESS("\nšŸ“Š Project Scan Results"))
341
+ self.stdout.write("=" * 50)
342
+
343
+ if hasattr(scan_result, 'project_info'):
344
+ info = scan_result.project_info
345
+ self.stdout.write(f"Project Name: {info.get('name', 'Unknown')}")
346
+ self.stdout.write(f"Django Version: {info.get('django_version', 'Unknown')}")
347
+ self.stdout.write(f"Total Apps: {info.get('total_apps', 0)}")
348
+
349
+ if hasattr(scan_result, 'apps') and scan_result.apps:
350
+ self.stdout.write(f"\nšŸ“± Applications ({len(scan_result.apps)}):")
351
+ for app in scan_result.apps:
352
+ self.stdout.write(f" • {app.name} ({app.path})")
353
+
354
+ self.stdout.write(f"\nāœ… Scan completed successfully!")
355
+
356
+ def _display_diagnosis_results(self, diagnosis, options):
357
+ """Display diagnosis results."""
358
+ self.stdout.write(self.style.SUCCESS("\nšŸŽÆ Diagnosis Results"))
359
+ self.stdout.write("=" * 50)
360
+
361
+ # Summary
362
+ self.stdout.write(f"Status: {diagnosis['status']}")
363
+ self.stdout.write(f"Summary: {diagnosis['summary']}")
364
+ self.stdout.write(f"Confidence: {diagnosis['confidence']:.0%}")
365
+
366
+ # Findings
367
+ if diagnosis.get('findings'):
368
+ self.stdout.write(f"\nšŸ” Findings ({len(diagnosis['findings'])}):")
369
+
370
+ for i, finding in enumerate(diagnosis['findings'], 1):
371
+ severity_style = {
372
+ 'low': self.style.SUCCESS,
373
+ 'medium': self.style.WARNING,
374
+ 'high': self.style.ERROR,
375
+ 'critical': self.style.ERROR
376
+ }.get(finding['severity'], self.style.WARNING)
377
+
378
+ self.stdout.write(f"\n{i}. {finding['title']}")
379
+ self.stdout.write(severity_style(f" Severity: {finding['severity'].upper()}"))
380
+ self.stdout.write(f" Category: {finding['category']}")
381
+ self.stdout.write(f" Description: {finding['description']}")
382
+
383
+ if finding.get('recommendations'):
384
+ self.stdout.write(" Recommendations:")
385
+ for rec in finding['recommendations']:
386
+ self.stdout.write(f" • {rec}")
387
+
388
+ # Save report if requested
389
+ if options.get('save_report'):
390
+ self._save_diagnosis_report(diagnosis, options)
391
+
392
+ self.stdout.write(f"\nāœ… Diagnosis completed!")
393
+
394
+ def _save_diagnosis_report(self, diagnosis, options):
395
+ """Save diagnosis report to file."""
396
+ try:
397
+ report_path = Path(options['save_report'])
398
+
399
+ # Generate report content based on format
400
+ format_type = options.get('output_format', 'text')
401
+
402
+ if format_type == 'json':
403
+ import json
404
+ content = json.dumps(diagnosis, indent=2)
405
+ elif format_type == 'markdown':
406
+ content = self._generate_markdown_report(diagnosis)
407
+ else: # text
408
+ content = self._generate_text_report(diagnosis)
409
+
410
+ # Write to file
411
+ report_path.write_text(content, encoding='utf-8')
412
+
413
+ self.stdout.write(f"šŸ“„ Report saved to: {report_path}")
414
+
415
+ except Exception as e:
416
+ self.stdout.write(
417
+ self.style.WARNING(f"Failed to save report: {e}")
418
+ )
419
+
420
+ def _generate_markdown_report(self, diagnosis):
421
+ """Generate markdown format report."""
422
+ content = f"""# Project Diagnosis Report
423
+
424
+ ## Summary
425
+ - **Status**: {diagnosis['status']}
426
+ - **Confidence**: {diagnosis['confidence']:.0%}
427
+ - **Summary**: {diagnosis['summary']}
428
+
429
+ ## Findings
430
+ """
431
+
432
+ for i, finding in enumerate(diagnosis.get('findings', []), 1):
433
+ content += f"""
434
+ ### {i}. {finding['title']}
435
+ - **Severity**: {finding['severity'].upper()}
436
+ - **Category**: {finding['category']}
437
+ - **Description**: {finding['description']}
438
+
439
+ **Recommendations**:
440
+ """
441
+ for rec in finding.get('recommendations', []):
442
+ content += f"- {rec}\n"
443
+
444
+ return content
445
+
446
+ def _generate_text_report(self, diagnosis):
447
+ """Generate plain text report."""
448
+ content = f"""PROJECT DIAGNOSIS REPORT
449
+ {'=' * 50}
450
+
451
+ STATUS: {diagnosis['status']}
452
+ CONFIDENCE: {diagnosis['confidence']:.0%}
453
+ SUMMARY: {diagnosis['summary']}
454
+
455
+ FINDINGS:
456
+ """
457
+
458
+ for i, finding in enumerate(diagnosis.get('findings', []), 1):
459
+ content += f"""
460
+ {i}. {finding['title']}
461
+ Severity: {finding['severity'].upper()}
462
+ Category: {finding['category']}
463
+ Description: {finding['description']}
464
+
465
+ Recommendations:
466
+ """
467
+ for rec in finding.get('recommendations', []):
468
+ content += f" • {rec}\n"
469
+
470
+ return content