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,356 @@
1
+ """
2
+ Session Manager for Intelligent Questioning Service.
3
+
4
+ This module manages questioning sessions, including creation,
5
+ progress tracking, and completion handling.
6
+ """
7
+
8
+ from typing import List, Dict, Any, Optional
9
+ import uuid
10
+ from datetime import datetime, timezone
11
+
12
+ from pydantic import BaseModel, Field
13
+
14
+ from ...core.config import AgentConfig
15
+ from ...models.context import ProjectContext
16
+ from ..base import ServiceDependencies
17
+ from .models import (
18
+ QuestioningRequest, QuestioningSession, ContextualQuestion,
19
+ QuestionResponse, QuestioningResult
20
+ )
21
+
22
+
23
+ class SessionManager(BaseModel):
24
+ """Manages questioning sessions and their lifecycle."""
25
+
26
+ config: AgentConfig = Field(description="Agent configuration")
27
+
28
+ # Session storage (in production, this would be a database)
29
+ active_sessions: Dict[str, QuestioningSession] = Field(
30
+ default_factory=dict,
31
+ description="Active questioning sessions"
32
+ )
33
+
34
+ async def create_session(
35
+ self,
36
+ request: QuestioningRequest,
37
+ questions: List[ContextualQuestion],
38
+ project_context: ProjectContext,
39
+ dependencies: ServiceDependencies
40
+ ) -> QuestioningSession:
41
+ """Create a new questioning session."""
42
+ session_id = str(uuid.uuid4())
43
+
44
+ session = QuestioningSession(
45
+ session_id=session_id,
46
+ questions=questions,
47
+ project_context=project_context,
48
+ user_intent=request.user_intent,
49
+ created_at=datetime.now(timezone.utc)
50
+ )
51
+
52
+ # Store session
53
+ self.active_sessions[session_id] = session
54
+
55
+ dependencies.log_operation(
56
+ "Questioning session created",
57
+ session_id=session_id,
58
+ questions_count=len(questions),
59
+ user_intent=request.user_intent
60
+ )
61
+
62
+ return session
63
+
64
+ async def add_response(
65
+ self,
66
+ session_id: str,
67
+ question_id: str,
68
+ answer: str,
69
+ confidence: float,
70
+ dependencies: ServiceDependencies
71
+ ) -> Optional[QuestioningSession]:
72
+ """Add a response to an existing session."""
73
+ session = self.active_sessions.get(session_id)
74
+ if not session:
75
+ dependencies.log_error(f"Session not found: {session_id}")
76
+ return None
77
+
78
+ # Validate question exists
79
+ question = self._find_question_by_id(session.questions, question_id)
80
+ if not question:
81
+ dependencies.log_error(f"Question not found: {question_id}")
82
+ return None
83
+
84
+ # Create response
85
+ response = QuestionResponse(
86
+ question_id=question_id,
87
+ answer=answer,
88
+ confidence=confidence,
89
+ timestamp=datetime.now(timezone.utc)
90
+ )
91
+
92
+ # Add to session
93
+ session.responses.append(response)
94
+ session.current_question_index = len(session.responses)
95
+
96
+ # Check if session is completed
97
+ if len(session.responses) >= len(session.questions):
98
+ session.is_completed = True
99
+ session.completed_at = datetime.now(timezone.utc)
100
+
101
+ dependencies.log_operation(
102
+ "Response added to session",
103
+ session_id=session_id,
104
+ question_id=question_id,
105
+ completion_percentage=session.completion_percentage,
106
+ is_completed=session.is_completed
107
+ )
108
+
109
+ return session
110
+
111
+ async def get_session(
112
+ self,
113
+ session_id: str,
114
+ dependencies: ServiceDependencies
115
+ ) -> Optional[QuestioningSession]:
116
+ """Get an existing session."""
117
+ session = self.active_sessions.get(session_id)
118
+
119
+ if not session:
120
+ dependencies.log_error(f"Session not found: {session_id}")
121
+
122
+ return session
123
+
124
+ async def get_next_question(
125
+ self,
126
+ session_id: str,
127
+ dependencies: ServiceDependencies
128
+ ) -> Optional[ContextualQuestion]:
129
+ """Get the next unanswered question in a session."""
130
+ session = self.active_sessions.get(session_id)
131
+ if not session:
132
+ return None
133
+
134
+ if session.is_completed:
135
+ return None
136
+
137
+ # Find next unanswered question
138
+ answered_question_ids = {r.question_id for r in session.responses}
139
+
140
+ for question in session.questions:
141
+ if question.id not in answered_question_ids:
142
+ return question
143
+
144
+ return None
145
+
146
+ async def complete_session(
147
+ self,
148
+ session_id: str,
149
+ dependencies: ServiceDependencies
150
+ ) -> Optional[QuestioningSession]:
151
+ """Mark a session as completed."""
152
+ session = self.active_sessions.get(session_id)
153
+ if not session:
154
+ return None
155
+
156
+ session.is_completed = True
157
+ session.completed_at = datetime.now(timezone.utc)
158
+
159
+ dependencies.log_operation(
160
+ "Session completed",
161
+ session_id=session_id,
162
+ total_responses=len(session.responses),
163
+ completion_percentage=session.completion_percentage
164
+ )
165
+
166
+ return session
167
+
168
+ async def cleanup_session(
169
+ self,
170
+ session_id: str,
171
+ dependencies: ServiceDependencies
172
+ ) -> bool:
173
+ """Remove a session from active sessions."""
174
+ if session_id in self.active_sessions:
175
+ del self.active_sessions[session_id]
176
+ dependencies.log_operation(f"Session cleaned up: {session_id}")
177
+ return True
178
+
179
+ return False
180
+
181
+ def calculate_confidence_score(
182
+ self,
183
+ session: QuestioningSession
184
+ ) -> float:
185
+ """Calculate overall confidence score for a session."""
186
+ if not session.responses:
187
+ return 0.0
188
+
189
+ # Weight confidence by question impact
190
+ impact_weights = {"critical": 1.0, "high": 0.8, "medium": 0.6, "low": 0.4}
191
+
192
+ weighted_confidence = 0.0
193
+ total_weight = 0.0
194
+
195
+ for response in session.responses:
196
+ question = self._find_question_by_id(session.questions, response.question_id)
197
+ if question:
198
+ weight = impact_weights.get(question.impact_level, 0.6)
199
+ weighted_confidence += response.confidence * weight
200
+ total_weight += weight
201
+
202
+ return weighted_confidence / total_weight if total_weight > 0 else 0.0
203
+
204
+ async def gather_agent_insights(
205
+ self,
206
+ session: QuestioningSession,
207
+ dependencies: ServiceDependencies
208
+ ) -> Dict[str, Any]:
209
+ """Gather insights from AI agents based on session responses."""
210
+ insights = {
211
+ "response_analysis": {},
212
+ "pattern_detection": {},
213
+ "recommendations": [],
214
+ "confidence_assessment": {}
215
+ }
216
+
217
+ try:
218
+ # Analyze response patterns
219
+ insights["response_analysis"] = self._analyze_response_patterns(session)
220
+
221
+ # Detect architectural patterns
222
+ insights["pattern_detection"] = self._detect_architectural_patterns(session)
223
+
224
+ # Generate recommendations
225
+ insights["recommendations"] = self._generate_recommendations(session)
226
+
227
+ # Assess confidence
228
+ insights["confidence_assessment"] = {
229
+ "overall_confidence": self.calculate_confidence_score(session),
230
+ "low_confidence_areas": self._identify_low_confidence_areas(session),
231
+ "high_confidence_areas": self._identify_high_confidence_areas(session)
232
+ }
233
+
234
+ except Exception as e:
235
+ dependencies.log_error("Failed to gather agent insights", e)
236
+
237
+ return insights
238
+
239
+ def _find_question_by_id(
240
+ self,
241
+ questions: List[ContextualQuestion],
242
+ question_id: str
243
+ ) -> Optional[ContextualQuestion]:
244
+ """Find question by ID."""
245
+ for question in questions:
246
+ if question.id == question_id:
247
+ return question
248
+ return None
249
+
250
+ def _analyze_response_patterns(
251
+ self,
252
+ session: QuestioningSession
253
+ ) -> Dict[str, Any]:
254
+ """Analyze patterns in user responses."""
255
+ patterns = {
256
+ "response_length_avg": 0.0,
257
+ "confidence_avg": 0.0,
258
+ "yes_no_ratio": 0.0,
259
+ "detailed_responses": 0
260
+ }
261
+
262
+ if not session.responses:
263
+ return patterns
264
+
265
+ # Calculate averages
266
+ total_length = sum(len(r.answer) for r in session.responses)
267
+ total_confidence = sum(r.confidence for r in session.responses)
268
+
269
+ patterns["response_length_avg"] = total_length / len(session.responses)
270
+ patterns["confidence_avg"] = total_confidence / len(session.responses)
271
+
272
+ # Count yes/no responses
273
+ yes_no_count = sum(
274
+ 1 for r in session.responses
275
+ if r.answer.lower() in ["yes", "no", "y", "n", "true", "false"]
276
+ )
277
+ patterns["yes_no_ratio"] = yes_no_count / len(session.responses)
278
+
279
+ # Count detailed responses (>20 characters)
280
+ patterns["detailed_responses"] = sum(
281
+ 1 for r in session.responses if len(r.answer) > 20
282
+ )
283
+
284
+ return patterns
285
+
286
+ def _detect_architectural_patterns(
287
+ self,
288
+ session: QuestioningSession
289
+ ) -> Dict[str, Any]:
290
+ """Detect architectural patterns from responses."""
291
+ patterns = {
292
+ "api_focused": False,
293
+ "admin_heavy": False,
294
+ "user_centric": False,
295
+ "data_intensive": False
296
+ }
297
+
298
+ # Analyze responses for architectural indicators
299
+ all_answers = " ".join(r.answer.lower() for r in session.responses)
300
+
301
+ patterns["api_focused"] = "api" in all_answers or "integration" in all_answers
302
+ patterns["admin_heavy"] = "admin" in all_answers or "management" in all_answers
303
+ patterns["user_centric"] = "user" in all_answers or "authentication" in all_answers
304
+ patterns["data_intensive"] = "data" in all_answers or "database" in all_answers
305
+
306
+ return patterns
307
+
308
+ def _generate_recommendations(
309
+ self,
310
+ session: QuestioningSession
311
+ ) -> List[str]:
312
+ """Generate development recommendations based on responses."""
313
+ recommendations = []
314
+
315
+ # Analyze confidence levels
316
+ avg_confidence = sum(r.confidence for r in session.responses) / len(session.responses) if session.responses else 0
317
+
318
+ if avg_confidence < 0.7:
319
+ recommendations.append("Consider additional planning phase due to low confidence in requirements")
320
+
321
+ # Analyze response patterns
322
+ detailed_count = sum(1 for r in session.responses if len(r.answer) > 50)
323
+ if detailed_count > len(session.responses) * 0.7:
324
+ recommendations.append("User provided detailed requirements - consider iterative development approach")
325
+
326
+ return recommendations
327
+
328
+ def _identify_low_confidence_areas(
329
+ self,
330
+ session: QuestioningSession
331
+ ) -> List[str]:
332
+ """Identify areas where user expressed low confidence."""
333
+ low_confidence_areas = []
334
+
335
+ for response in session.responses:
336
+ if response.confidence < 0.6:
337
+ question = self._find_question_by_id(session.questions, response.question_id)
338
+ if question:
339
+ low_confidence_areas.append(question.text)
340
+
341
+ return low_confidence_areas
342
+
343
+ def _identify_high_confidence_areas(
344
+ self,
345
+ session: QuestioningSession
346
+ ) -> List[str]:
347
+ """Identify areas where user expressed high confidence."""
348
+ high_confidence_areas = []
349
+
350
+ for response in session.responses:
351
+ if response.confidence > 0.8:
352
+ question = self._find_question_by_id(session.questions, response.question_id)
353
+ if question:
354
+ high_confidence_areas.append(question.text)
355
+
356
+ return high_confidence_areas
@@ -0,0 +1,332 @@
1
+ """
2
+ Report Service for Django App Agent Module.
3
+
4
+ This service generates comprehensive reports for application generation
5
+ processes, including detailed logs, metrics, and documentation.
6
+ """
7
+
8
+ from typing import List, Dict, Any, Optional
9
+ from pathlib import Path
10
+ from datetime import datetime, timezone
11
+ import json
12
+
13
+ from pydantic import BaseModel, Field, ConfigDict
14
+
15
+ from .base import BaseService, ServiceDependencies
16
+ from ..models.responses import AppGenerationResult, QualityMetrics, GeneratedFile
17
+ from ..core.exceptions import FileSystemError
18
+
19
+
20
+ class ReportRequest(BaseModel):
21
+ """Request for report generation."""
22
+
23
+ model_config = ConfigDict(extra='forbid', validate_assignment=True)
24
+
25
+ generation_result: AppGenerationResult = Field(description="Application generation result")
26
+ report_formats: List[str] = Field(
27
+ default_factory=lambda: ["markdown", "json"],
28
+ description="Report formats to generate"
29
+ )
30
+ include_code_samples: bool = Field(default=True, description="Whether to include code samples")
31
+ include_metrics: bool = Field(default=True, description="Whether to include quality metrics")
32
+ output_directory: Optional[Path] = Field(default=None, description="Custom output directory")
33
+
34
+
35
+ class ReportResult(BaseModel):
36
+ """Result of report generation."""
37
+
38
+ model_config = ConfigDict(extra='forbid', validate_assignment=True)
39
+
40
+ generated_reports: List[str] = Field(description="Paths to generated report files")
41
+ report_summary: Dict[str, Any] = Field(description="Summary of the report generation")
42
+ total_size_bytes: int = Field(default=0, description="Total size of generated reports")
43
+
44
+
45
+ class ReportService(BaseService[ReportRequest, ReportResult]):
46
+ """
47
+ Service for generating comprehensive reports of application generation processes.
48
+
49
+ Provides:
50
+ - Markdown reports with detailed information
51
+ - JSON reports for programmatic access
52
+ - Code sample inclusion
53
+ - Quality metrics visualization
54
+ - Process documentation
55
+ """
56
+
57
+ def __init__(self, config):
58
+ """Initialize report service."""
59
+ super().__init__("report", config)
60
+
61
+ async def process(
62
+ self,
63
+ request: ReportRequest,
64
+ dependencies: ServiceDependencies
65
+ ) -> ReportResult:
66
+ """
67
+ Process report generation request.
68
+
69
+ Args:
70
+ request: Report generation request
71
+ dependencies: Service dependencies
72
+
73
+ Returns:
74
+ ReportResult with generated reports
75
+ """
76
+ dependencies.log_operation(
77
+ f"Generating reports for app '{request.generation_result.app_name}'",
78
+ formats=request.report_formats,
79
+ include_code_samples=request.include_code_samples,
80
+ include_metrics=request.include_metrics
81
+ )
82
+
83
+ try:
84
+ generated_reports = []
85
+ total_size = 0
86
+
87
+ # Determine output directory
88
+ output_dir = request.output_directory or dependencies.get_output_path()
89
+ report_dir = output_dir / request.generation_result.app_name / "@report"
90
+ report_dir.mkdir(parents=True, exist_ok=True)
91
+
92
+ # Generate reports in requested formats
93
+ for format_type in request.report_formats:
94
+ if format_type == "markdown":
95
+ report_path = await self._generate_markdown_report(
96
+ request, report_dir, dependencies
97
+ )
98
+ elif format_type == "json":
99
+ report_path = await self._generate_json_report(
100
+ request, report_dir, dependencies
101
+ )
102
+ else:
103
+ dependencies.logger.warning(f"Unknown report format: {format_type}")
104
+ continue
105
+
106
+ if report_path and report_path.exists():
107
+ generated_reports.append(str(report_path))
108
+ total_size += report_path.stat().st_size
109
+
110
+ # Generate summary
111
+ summary = {
112
+ "app_name": request.generation_result.app_name,
113
+ "generation_status": request.generation_result.status,
114
+ "reports_generated": len(generated_reports),
115
+ "formats": request.report_formats,
116
+ "timestamp": datetime.now(timezone.utc).isoformat(),
117
+ "total_files_generated": len(request.generation_result.generated_files)
118
+ }
119
+
120
+ result = ReportResult(
121
+ generated_reports=generated_reports,
122
+ report_summary=summary,
123
+ total_size_bytes=total_size
124
+ )
125
+
126
+ dependencies.log_operation(
127
+ "Report generation completed successfully",
128
+ reports_count=len(generated_reports),
129
+ total_size_kb=total_size // 1024
130
+ )
131
+
132
+ return result
133
+
134
+ except Exception as e:
135
+ dependencies.log_error("Report generation failed", e)
136
+ raise
137
+
138
+ async def _generate_markdown_report(
139
+ self,
140
+ request: ReportRequest,
141
+ output_dir: Path,
142
+ dependencies: ServiceDependencies
143
+ ) -> Optional[Path]:
144
+ """Generate markdown report."""
145
+ try:
146
+ result = request.generation_result
147
+ report_path = output_dir / "GENERATION_REPORT.md"
148
+
149
+ # Build markdown content
150
+ content = self._build_markdown_content(request, dependencies)
151
+
152
+ # Write report
153
+ report_path.write_text(content, encoding='utf-8')
154
+
155
+ return report_path
156
+
157
+ except Exception as e:
158
+ dependencies.log_error("Failed to generate markdown report", e)
159
+ return None
160
+
161
+ async def _generate_json_report(
162
+ self,
163
+ request: ReportRequest,
164
+ output_dir: Path,
165
+ dependencies: ServiceDependencies
166
+ ) -> Optional[Path]:
167
+ """Generate JSON report."""
168
+ try:
169
+ result = request.generation_result
170
+ report_path = output_dir / "generation_report.json"
171
+
172
+ # Build JSON data
173
+ report_data = {
174
+ "metadata": {
175
+ "generated_at": datetime.now(timezone.utc).isoformat(),
176
+ "generator_version": "0.1.0",
177
+ "report_format": "json"
178
+ },
179
+ "application": {
180
+ "name": result.app_name,
181
+ "status": result.status,
182
+ "message": result.message,
183
+ "duration_seconds": result.duration_seconds
184
+ },
185
+ "generation_process": {
186
+ "files_generated": len(result.generated_files),
187
+ "errors": result.errors,
188
+ "warnings": result.warnings,
189
+ "ai_dialogue_log": result.ai_dialogue_log if request.include_code_samples else []
190
+ },
191
+ "quality_metrics": result.quality_metrics.model_dump() if result.quality_metrics and request.include_metrics else None,
192
+ "generated_files": [
193
+ {
194
+ "path": f.path,
195
+ "type": f.file_type,
196
+ "description": f.description,
197
+ "size_bytes": f.size_bytes,
198
+ "content": f.content if request.include_code_samples else None
199
+ }
200
+ for f in result.generated_files
201
+ ]
202
+ }
203
+
204
+ # Write JSON report
205
+ with open(report_path, 'w', encoding='utf-8') as f:
206
+ json.dump(report_data, f, indent=2, ensure_ascii=False)
207
+
208
+ return report_path
209
+
210
+ except Exception as e:
211
+ dependencies.log_error("Failed to generate JSON report", e)
212
+ return None
213
+
214
+ def _build_markdown_content(
215
+ self,
216
+ request: ReportRequest,
217
+ dependencies: ServiceDependencies
218
+ ) -> str:
219
+ """Build markdown report content."""
220
+ result = request.generation_result
221
+
222
+ content = f"""# Application Generation Report
223
+
224
+ ## 📋 Summary
225
+
226
+ **Application Name**: `{result.app_name}`
227
+ **Status**: {result.status.upper()}
228
+ **Generated**: {datetime.now(timezone.utc).strftime('%Y-%m-%d %H:%M:%S UTC')}
229
+ **Duration**: {result.duration_seconds:.2f} seconds
230
+
231
+ {result.message}
232
+
233
+ ## 📊 Generation Statistics
234
+
235
+ - **Files Generated**: {len(result.generated_files)}
236
+ - **Errors**: {len(result.errors)}
237
+ - **Warnings**: {len(result.warnings)}
238
+
239
+ """
240
+
241
+ # Add errors section if any
242
+ if result.errors:
243
+ content += "## ❌ Errors\n\n"
244
+ for error in result.errors:
245
+ content += f"- {error}\n"
246
+ content += "\n"
247
+
248
+ # Add warnings section if any
249
+ if result.warnings:
250
+ content += "## ⚠️ Warnings\n\n"
251
+ for warning in result.warnings:
252
+ content += f"- {warning}\n"
253
+ content += "\n"
254
+
255
+ # Add quality metrics if available and requested
256
+ if result.quality_metrics and request.include_metrics:
257
+ metrics = result.quality_metrics
258
+ content += f"""## 📈 Quality Metrics
259
+
260
+ - **Code Readability**: {metrics.code_readability_score:.2f}/1.0
261
+ - **Maintainability**: {metrics.maintainability_score:.2f}/1.0
262
+ - **Type Hint Completeness**: {metrics.type_hint_completeness:.2f}/1.0
263
+ - **Pydantic Compliance**: {metrics.pydantic_compliance_score:.2f}/1.0
264
+ - **Test Coverage**: {metrics.test_coverage_percentage:.1f}%
265
+ - **Security Vulnerabilities**: {metrics.security_vulnerabilities_found}
266
+ - **Performance Issues**: {metrics.performance_bottlenecks_found}
267
+
268
+ """
269
+
270
+ # Add generated files section
271
+ content += "## 📁 Generated Files\n\n"
272
+
273
+ # Group files by type
274
+ files_by_type = {}
275
+ for file in result.generated_files:
276
+ file_type = file.file_type
277
+ if file_type not in files_by_type:
278
+ files_by_type[file_type] = []
279
+ files_by_type[file_type].append(file)
280
+
281
+ for file_type, files in files_by_type.items():
282
+ content += f"### {file_type.title()} Files\n\n"
283
+ for file in files:
284
+ content += f"- **{file.path}**"
285
+ if file.description:
286
+ content += f" - {file.description}"
287
+ content += f" ({file.size_bytes} bytes)\n"
288
+ content += "\n"
289
+
290
+ # Add code samples if requested
291
+ if request.include_code_samples and result.generated_files:
292
+ content += "## 💻 Code Samples\n\n"
293
+
294
+ # Show a few key files
295
+ key_files = [f for f in result.generated_files if f.file_type == "python"][:3]
296
+
297
+ for file in key_files:
298
+ content += f"### {file.path}\n\n"
299
+ if file.description:
300
+ content += f"{file.description}\n\n"
301
+
302
+ content += f"```python\n{file.content}\n```\n\n"
303
+
304
+ # Add AI dialogue log if available and requested
305
+ if result.ai_dialogue_log and request.include_code_samples:
306
+ content += "## 🤖 AI Generation Process\n\n"
307
+
308
+ for entry in result.ai_dialogue_log:
309
+ agent = entry.get("agent", "Unknown")
310
+ timestamp = entry.get("timestamp", "")
311
+ output = entry.get("output", {})
312
+
313
+ content += f"### {agent} Agent\n\n"
314
+ content += f"**Timestamp**: {timestamp}\n\n"
315
+
316
+ if isinstance(output, dict):
317
+ for key, value in output.items():
318
+ content += f"- **{key}**: {value}\n"
319
+ else:
320
+ content += f"Output: {output}\n"
321
+
322
+ content += "\n"
323
+
324
+ # Add footer
325
+ content += f"""---
326
+
327
+ **Report Generated**: {datetime.now(timezone.utc).strftime('%Y-%m-%d %H:%M:%S UTC')}
328
+ **Generator**: Django App Agent v0.1.0
329
+ **Format**: Markdown
330
+ """
331
+
332
+ return content
@@ -0,0 +1,18 @@
1
+ """
2
+ Template Manager Service for Django App Agent Module.
3
+
4
+ This package provides sophisticated Jinja2-based template rendering
5
+ with feature-driven code generation capabilities.
6
+ """
7
+
8
+ from .main import TemplateManagerService
9
+ from .jinja_engine import JinjaTemplateEngine
10
+ from .template_loader import TemplateLoader
11
+ from .variable_processor import VariableProcessor
12
+
13
+ __all__ = [
14
+ "TemplateManagerService",
15
+ "JinjaTemplateEngine",
16
+ "TemplateLoader",
17
+ "VariableProcessor",
18
+ ]