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,500 @@
1
+ """
2
+ Request models for Django App Agent Module.
3
+
4
+ This module defines all request models with:
5
+ - Complete Pydantic 2 validation
6
+ - Type-safe field definitions
7
+ - Business logic validation
8
+ - Clear documentation
9
+ """
10
+
11
+ from typing import List, Optional, Dict, Any, Set
12
+ from pathlib import Path
13
+ from pydantic import Field, field_validator, model_validator
14
+
15
+ from .base import BaseAgentModel, ValidationMixin
16
+ from .enums import AppFeature, AppComplexity, AppType, QuestionType, ImpactLevel
17
+ from ..utils.validation import validate_app_name, validate_description
18
+
19
+
20
+ class AppGenerationRequest(BaseAgentModel, ValidationMixin):
21
+ """Request for generating a Django application."""
22
+
23
+ # Core application details
24
+ app_name: str = Field(
25
+ description="Name of the Django application to generate",
26
+ min_length=2,
27
+ max_length=50,
28
+ pattern=r'^[a-z][a-z0-9_]*$'
29
+ )
30
+
31
+ description: str = Field(
32
+ description="Detailed description of the application purpose and functionality",
33
+ min_length=10,
34
+ max_length=500
35
+ )
36
+
37
+ # Application configuration
38
+ app_type: AppType = Field(
39
+ default=AppType.DJANGO_CFG,
40
+ description="Type of Django application to generate"
41
+ )
42
+
43
+ features: List[AppFeature] = Field(
44
+ default_factory=list,
45
+ description="List of features to include in the generated application"
46
+ )
47
+
48
+ complexity: AppComplexity = Field(
49
+ default=AppComplexity.MODERATE,
50
+ description="Complexity level of the application"
51
+ )
52
+
53
+ # Generation options
54
+ enable_questioning: bool = Field(
55
+ default=True,
56
+ description="Whether to enable intelligent questioning system"
57
+ )
58
+
59
+ max_questions: int = Field(
60
+ default=20,
61
+ ge=0,
62
+ le=50,
63
+ description="Maximum number of questions to ask during generation"
64
+ )
65
+
66
+ questioning_timeout_minutes: int = Field(
67
+ default=15,
68
+ ge=1,
69
+ le=60,
70
+ description="Timeout for questioning session in minutes"
71
+ )
72
+
73
+ # Quality requirements
74
+ quality_threshold: float = Field(
75
+ default=8.0,
76
+ ge=0.0,
77
+ le=10.0,
78
+ description="Minimum quality score required for generated code"
79
+ )
80
+
81
+ # Integration options
82
+ target_apps: List[str] = Field(
83
+ default_factory=list,
84
+ description="Existing apps to analyze for integration patterns"
85
+ )
86
+
87
+ exclude_patterns: List[str] = Field(
88
+ default_factory=list,
89
+ description="Patterns to exclude from generation"
90
+ )
91
+
92
+ # Output configuration
93
+ output_directory: Optional[Path] = Field(
94
+ default=None,
95
+ description="Custom output directory for generated files"
96
+ )
97
+
98
+ # Advanced options
99
+ custom_requirements: Dict[str, Any] = Field(
100
+ default_factory=dict,
101
+ description="Custom requirements and constraints"
102
+ )
103
+
104
+ # UI options
105
+ rich_interface: bool = Field(
106
+ default=True,
107
+ description="Enable Rich CLI interface with progress bars"
108
+ )
109
+
110
+ verbose_output: bool = Field(
111
+ default=False,
112
+ description="Enable verbose output during generation"
113
+ )
114
+
115
+ @field_validator('app_name')
116
+ @classmethod
117
+ def validate_app_name_field(cls, v: str) -> str:
118
+ """Validate application name using utility function."""
119
+ return validate_app_name(v, check_reserved=True)
120
+
121
+ @field_validator('description')
122
+ @classmethod
123
+ def validate_description_field(cls, v: str) -> str:
124
+ """Validate application description."""
125
+ return validate_description(v, min_length=10, max_length=500)
126
+
127
+ @field_validator('features')
128
+ @classmethod
129
+ def validate_features_list(cls, v: List[AppFeature]) -> List[AppFeature]:
130
+ """Validate and deduplicate features list."""
131
+ if not v:
132
+ return []
133
+
134
+ # Convert strings to enums if needed
135
+ enum_features = []
136
+ for feature in v:
137
+ if isinstance(feature, str):
138
+ enum_features.append(AppFeature(feature))
139
+ else:
140
+ enum_features.append(feature)
141
+
142
+ # Remove duplicates while preserving order
143
+ seen = set()
144
+ unique_features = []
145
+ for feature in enum_features:
146
+ if feature not in seen:
147
+ seen.add(feature)
148
+ unique_features.append(feature)
149
+
150
+ return unique_features
151
+
152
+ @field_validator('complexity')
153
+ @classmethod
154
+ def validate_complexity_enum(cls, v) -> AppComplexity:
155
+ """Ensure complexity is proper enum."""
156
+ if isinstance(v, str):
157
+ return AppComplexity(v)
158
+ return v
159
+
160
+ @field_validator('app_type')
161
+ @classmethod
162
+ def validate_app_type_enum(cls, v) -> AppType:
163
+ """Ensure app_type is proper enum."""
164
+ if isinstance(v, str):
165
+ return AppType(v)
166
+ return v
167
+
168
+ @field_validator('target_apps')
169
+ @classmethod
170
+ def validate_target_apps(cls, v: List[str]) -> List[str]:
171
+ """Validate target apps list."""
172
+ if not v:
173
+ return []
174
+
175
+ validated_apps = []
176
+ for app_name in v:
177
+ try:
178
+ validated_name = validate_app_name(app_name, check_reserved=False)
179
+ validated_apps.append(validated_name)
180
+ except Exception:
181
+ # Skip invalid app names
182
+ continue
183
+
184
+ return validated_apps
185
+
186
+ @model_validator(mode='after')
187
+ def validate_consistency(self) -> 'AppGenerationRequest':
188
+ """Validate consistency between fields."""
189
+ # Note: Pydantic 2 handles enum conversion automatically,
190
+ # so we don't need to manually convert them here
191
+
192
+ # Auto-populate features based on complexity if not specified
193
+ if not self.features:
194
+ self.features = list(self.complexity.get_recommended_features())
195
+
196
+ # Validate feature dependencies
197
+ all_features = set(self.features)
198
+ for feature in self.features:
199
+ dependencies = feature.get_dependencies()
200
+ missing_deps = dependencies - all_features
201
+ if missing_deps:
202
+ # Add missing dependencies
203
+ self.features.extend(list(missing_deps))
204
+
205
+ # Adjust max_questions based on complexity
206
+ if self.max_questions > self.complexity.get_max_questions():
207
+ self.max_questions = self.complexity.get_max_questions()
208
+
209
+ # Validate app type supports all requested features
210
+ unsupported_features = []
211
+ for feature in self.features:
212
+ if not self.app_type.supports_feature(feature):
213
+ unsupported_features.append(feature)
214
+
215
+ if unsupported_features:
216
+ raise ValueError(
217
+ f"App type {self.app_type} does not support features: {unsupported_features}"
218
+ )
219
+
220
+ return self
221
+
222
+ def get_estimated_time_minutes(self) -> int:
223
+ """Get estimated generation time in minutes."""
224
+ base_time = self.complexity.get_estimated_time_minutes()
225
+
226
+ # Add time for additional features
227
+ feature_multiplier = len(self.features) / len(self.complexity.get_recommended_features())
228
+ adjusted_time = int(base_time * max(1.0, feature_multiplier))
229
+
230
+ # Add questioning time if enabled
231
+ if self.enable_questioning:
232
+ adjusted_time += min(self.questioning_timeout_minutes, 10)
233
+
234
+ return adjusted_time
235
+
236
+ def get_feature_set(self) -> Set[AppFeature]:
237
+ """Get set of features for easy lookup."""
238
+ return set(self.features)
239
+
240
+ def has_feature(self, feature: AppFeature) -> bool:
241
+ """Check if a specific feature is requested."""
242
+ return feature in self.get_feature_set()
243
+
244
+
245
+ class QuestioningRequest(BaseAgentModel):
246
+ """Request for conducting an intelligent questioning session."""
247
+
248
+ user_intent: str = Field(
249
+ description="User's stated intent or goal for the application",
250
+ min_length=5,
251
+ max_length=200
252
+ )
253
+
254
+ project_path: Path = Field(
255
+ description="Path to the Django project for context analysis"
256
+ )
257
+
258
+ app_generation_request: AppGenerationRequest = Field(
259
+ description="Associated app generation request"
260
+ )
261
+
262
+ max_questions: int = Field(
263
+ default=20,
264
+ ge=1,
265
+ le=50,
266
+ description="Maximum number of questions to ask"
267
+ )
268
+
269
+ timeout_minutes: int = Field(
270
+ default=15,
271
+ ge=1,
272
+ le=60,
273
+ description="Maximum time for questioning session"
274
+ )
275
+
276
+ focus_areas: List[str] = Field(
277
+ default_factory=list,
278
+ description="Specific areas to focus questions on"
279
+ )
280
+
281
+ skip_basic_questions: bool = Field(
282
+ default=False,
283
+ description="Skip basic questions and focus on advanced topics"
284
+ )
285
+
286
+ @field_validator('project_path')
287
+ @classmethod
288
+ def validate_project_path(cls, v: Path) -> Path:
289
+ """Validate that project path exists and is a directory."""
290
+ from ..utils.validation import validate_file_path
291
+
292
+ return validate_file_path(
293
+ v,
294
+ must_exist=True,
295
+ must_be_dir=True
296
+ )
297
+
298
+
299
+ class DiagnosticRequest(BaseAgentModel):
300
+ """Request for diagnosing problems in Django applications."""
301
+
302
+ project_path: Path = Field(
303
+ description="Path to the Django project to diagnose"
304
+ )
305
+
306
+ app_name: Optional[str] = Field(
307
+ default=None,
308
+ description="Specific app to focus diagnosis on"
309
+ )
310
+
311
+ problem_description: str = Field(
312
+ description="Description of the problem or issue",
313
+ min_length=10,
314
+ max_length=1000
315
+ )
316
+
317
+ error_messages: List[str] = Field(
318
+ default_factory=list,
319
+ description="Any error messages encountered"
320
+ )
321
+
322
+ symptoms: List[str] = Field(
323
+ default_factory=list,
324
+ description="Observed symptoms of the problem"
325
+ )
326
+
327
+ recent_changes: List[str] = Field(
328
+ default_factory=list,
329
+ description="Recent changes that might be related"
330
+ )
331
+
332
+ urgency_level: ImpactLevel = Field(
333
+ default=ImpactLevel.MEDIUM,
334
+ description="Urgency level of the problem"
335
+ )
336
+
337
+ include_suggestions: bool = Field(
338
+ default=True,
339
+ description="Whether to include solution suggestions"
340
+ )
341
+
342
+ max_suggestions: int = Field(
343
+ default=5,
344
+ ge=1,
345
+ le=20,
346
+ description="Maximum number of solution suggestions"
347
+ )
348
+
349
+ @field_validator('project_path')
350
+ @classmethod
351
+ def validate_project_path(cls, v: Path) -> Path:
352
+ """Validate that project path exists."""
353
+ from ..utils.validation import validate_file_path
354
+
355
+ return validate_file_path(
356
+ v,
357
+ must_exist=True,
358
+ must_be_dir=True
359
+ )
360
+
361
+ @field_validator('app_name')
362
+ @classmethod
363
+ def validate_app_name_field(cls, v: Optional[str]) -> Optional[str]:
364
+ """Validate app name if provided."""
365
+ if v is None:
366
+ return v
367
+
368
+ return validate_app_name(v, check_reserved=False)
369
+
370
+ @field_validator('problem_description')
371
+ @classmethod
372
+ def validate_problem_description(cls, v: str) -> str:
373
+ """Validate problem description."""
374
+ return validate_description(v, min_length=10, max_length=1000)
375
+
376
+
377
+ class ContextualQuestion(BaseAgentModel):
378
+ """A contextual question generated by the intelligent questioning system."""
379
+
380
+ id: str = Field(description="Unique question identifier")
381
+
382
+ text: str = Field(
383
+ description="The question text to display to the user",
384
+ min_length=10,
385
+ max_length=500
386
+ )
387
+
388
+ question_type: QuestionType = Field(
389
+ description="Type of question (yes/no, multiple choice, etc.)"
390
+ )
391
+
392
+ impact_level: ImpactLevel = Field(
393
+ description="Impact level of this question on the final result"
394
+ )
395
+
396
+ context_evidence: List[str] = Field(
397
+ default_factory=list,
398
+ description="Evidence from codebase that prompted this question"
399
+ )
400
+
401
+ options: Optional[List[str]] = Field(
402
+ default=None,
403
+ description="Available options for multiple choice questions"
404
+ )
405
+
406
+ default_answer: Optional[str] = Field(
407
+ default=None,
408
+ description="Default answer if user skips"
409
+ )
410
+
411
+ architectural_implications: List[str] = Field(
412
+ default_factory=list,
413
+ description="How the answer affects architectural decisions"
414
+ )
415
+
416
+ @field_validator('question_type')
417
+ @classmethod
418
+ def validate_question_type_enum(cls, v) -> QuestionType:
419
+ """Ensure question_type is proper enum."""
420
+ if isinstance(v, str):
421
+ return QuestionType(v)
422
+ return v
423
+
424
+ @field_validator('impact_level')
425
+ @classmethod
426
+ def validate_impact_level_enum(cls, v) -> ImpactLevel:
427
+ """Ensure impact_level is proper enum."""
428
+ if isinstance(v, str):
429
+ return ImpactLevel(v)
430
+ return v
431
+
432
+ @model_validator(mode='after')
433
+ def validate_question_consistency(self) -> 'ContextualQuestion':
434
+ """Validate question consistency."""
435
+ # Note: Pydantic 2 handles enum conversion automatically
436
+
437
+ # Questions requiring options must have them
438
+ if self.question_type.requires_options() and not self.options:
439
+ raise ValueError(f"Question type {self.question_type} requires options")
440
+
441
+ # Validate default answer is in options if provided
442
+ if self.default_answer and self.options:
443
+ if self.default_answer not in self.options:
444
+ raise ValueError("Default answer must be one of the provided options")
445
+
446
+ return self
447
+
448
+
449
+ class QuestionResponse(BaseAgentModel):
450
+ """Response to a contextual question."""
451
+
452
+ question_id: str = Field(description="ID of the question being answered")
453
+
454
+ answer: str = Field(
455
+ description="User's answer to the question",
456
+ min_length=1,
457
+ max_length=1000
458
+ )
459
+
460
+ confidence: float = Field(
461
+ default=1.0,
462
+ ge=0.0,
463
+ le=1.0,
464
+ description="User's confidence in their answer (0-1)"
465
+ )
466
+
467
+ notes: Optional[str] = Field(
468
+ default=None,
469
+ max_length=500,
470
+ description="Additional notes or context from user"
471
+ )
472
+
473
+
474
+ class TemplateRequest(BaseAgentModel):
475
+ """Request for template rendering."""
476
+
477
+ template_name: str = Field(
478
+ description="Name of the template to render",
479
+ min_length=1,
480
+ max_length=100
481
+ )
482
+
483
+ app_type: AppType = Field(
484
+ description="Type of Django application"
485
+ )
486
+
487
+ features: List[AppFeature] = Field(
488
+ default_factory=list,
489
+ description="List of features to include in template"
490
+ )
491
+
492
+ variables: Dict[str, Any] = Field(
493
+ default_factory=dict,
494
+ description="Template variables for rendering"
495
+ )
496
+
497
+ custom_templates: Dict[str, str] = Field(
498
+ default_factory=dict,
499
+ description="Custom template overrides"
500
+ )