django-cfg 1.3.5__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 (252) 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/apps/urls.py +1 -2
  97. django_cfg/config.py +1 -1
  98. django_cfg/core/config.py +10 -5
  99. django_cfg/core/generation.py +1 -1
  100. django_cfg/management/commands/__init__.py +13 -1
  101. django_cfg/management/commands/app_agent_diagnose.py +470 -0
  102. django_cfg/management/commands/app_agent_generate.py +342 -0
  103. django_cfg/management/commands/app_agent_info.py +308 -0
  104. django_cfg/management/commands/migrate_all.py +9 -3
  105. django_cfg/management/commands/migrator.py +11 -6
  106. django_cfg/management/commands/rundramatiq.py +3 -2
  107. django_cfg/middleware/__init__.py +0 -2
  108. django_cfg/models/api_keys.py +115 -0
  109. django_cfg/modules/django_admin/__init__.py +64 -0
  110. django_cfg/modules/django_admin/decorators/__init__.py +13 -0
  111. django_cfg/modules/django_admin/decorators/actions.py +106 -0
  112. django_cfg/modules/django_admin/decorators/display.py +106 -0
  113. django_cfg/modules/django_admin/mixins/__init__.py +14 -0
  114. django_cfg/modules/django_admin/mixins/display_mixin.py +81 -0
  115. django_cfg/modules/django_admin/mixins/optimization_mixin.py +41 -0
  116. django_cfg/modules/django_admin/mixins/standalone_actions_mixin.py +202 -0
  117. django_cfg/modules/django_admin/models/__init__.py +20 -0
  118. django_cfg/modules/django_admin/models/action_models.py +33 -0
  119. django_cfg/modules/django_admin/models/badge_models.py +20 -0
  120. django_cfg/modules/django_admin/models/base.py +26 -0
  121. django_cfg/modules/django_admin/models/display_models.py +31 -0
  122. django_cfg/modules/django_admin/utils/badges.py +159 -0
  123. django_cfg/modules/django_admin/utils/displays.py +247 -0
  124. django_cfg/modules/django_app_agent/__init__.py +87 -0
  125. django_cfg/modules/django_app_agent/agents/__init__.py +40 -0
  126. django_cfg/modules/django_app_agent/agents/base/__init__.py +24 -0
  127. django_cfg/modules/django_app_agent/agents/base/agent.py +354 -0
  128. django_cfg/modules/django_app_agent/agents/base/context.py +236 -0
  129. django_cfg/modules/django_app_agent/agents/base/executor.py +430 -0
  130. django_cfg/modules/django_app_agent/agents/generation/__init__.py +12 -0
  131. django_cfg/modules/django_app_agent/agents/generation/app_generator/__init__.py +15 -0
  132. django_cfg/modules/django_app_agent/agents/generation/app_generator/config_validator.py +147 -0
  133. django_cfg/modules/django_app_agent/agents/generation/app_generator/main.py +99 -0
  134. django_cfg/modules/django_app_agent/agents/generation/app_generator/models.py +32 -0
  135. django_cfg/modules/django_app_agent/agents/generation/app_generator/prompt_manager.py +290 -0
  136. django_cfg/modules/django_app_agent/agents/interfaces.py +376 -0
  137. django_cfg/modules/django_app_agent/core/__init__.py +33 -0
  138. django_cfg/modules/django_app_agent/core/config.py +300 -0
  139. django_cfg/modules/django_app_agent/core/exceptions.py +359 -0
  140. django_cfg/modules/django_app_agent/models/__init__.py +71 -0
  141. django_cfg/modules/django_app_agent/models/base.py +283 -0
  142. django_cfg/modules/django_app_agent/models/context.py +496 -0
  143. django_cfg/modules/django_app_agent/models/enums.py +481 -0
  144. django_cfg/modules/django_app_agent/models/requests.py +500 -0
  145. django_cfg/modules/django_app_agent/models/responses.py +585 -0
  146. django_cfg/modules/django_app_agent/pytest.ini +6 -0
  147. django_cfg/modules/django_app_agent/services/__init__.py +42 -0
  148. django_cfg/modules/django_app_agent/services/app_generator/__init__.py +30 -0
  149. django_cfg/modules/django_app_agent/services/app_generator/ai_integration.py +133 -0
  150. django_cfg/modules/django_app_agent/services/app_generator/context.py +40 -0
  151. django_cfg/modules/django_app_agent/services/app_generator/main.py +202 -0
  152. django_cfg/modules/django_app_agent/services/app_generator/structure.py +316 -0
  153. django_cfg/modules/django_app_agent/services/app_generator/validation.py +125 -0
  154. django_cfg/modules/django_app_agent/services/base.py +437 -0
  155. django_cfg/modules/django_app_agent/services/context_builder/__init__.py +34 -0
  156. django_cfg/modules/django_app_agent/services/context_builder/code_extractor.py +141 -0
  157. django_cfg/modules/django_app_agent/services/context_builder/context_generator.py +276 -0
  158. django_cfg/modules/django_app_agent/services/context_builder/main.py +272 -0
  159. django_cfg/modules/django_app_agent/services/context_builder/models.py +40 -0
  160. django_cfg/modules/django_app_agent/services/context_builder/pattern_analyzer.py +85 -0
  161. django_cfg/modules/django_app_agent/services/project_scanner/__init__.py +31 -0
  162. django_cfg/modules/django_app_agent/services/project_scanner/app_discovery.py +311 -0
  163. django_cfg/modules/django_app_agent/services/project_scanner/main.py +221 -0
  164. django_cfg/modules/django_app_agent/services/project_scanner/models.py +59 -0
  165. django_cfg/modules/django_app_agent/services/project_scanner/pattern_detection.py +94 -0
  166. django_cfg/modules/django_app_agent/services/questioning_service/__init__.py +28 -0
  167. django_cfg/modules/django_app_agent/services/questioning_service/main.py +273 -0
  168. django_cfg/modules/django_app_agent/services/questioning_service/models.py +111 -0
  169. django_cfg/modules/django_app_agent/services/questioning_service/question_generator.py +251 -0
  170. django_cfg/modules/django_app_agent/services/questioning_service/response_processor.py +347 -0
  171. django_cfg/modules/django_app_agent/services/questioning_service/session_manager.py +356 -0
  172. django_cfg/modules/django_app_agent/services/report_service.py +332 -0
  173. django_cfg/modules/django_app_agent/services/template_manager/__init__.py +18 -0
  174. django_cfg/modules/django_app_agent/services/template_manager/jinja_engine.py +236 -0
  175. django_cfg/modules/django_app_agent/services/template_manager/main.py +159 -0
  176. django_cfg/modules/django_app_agent/services/template_manager/models.py +36 -0
  177. django_cfg/modules/django_app_agent/services/template_manager/template_loader.py +100 -0
  178. django_cfg/modules/django_app_agent/services/template_manager/templates/admin.py.j2 +105 -0
  179. django_cfg/modules/django_app_agent/services/template_manager/templates/apps.py.j2 +31 -0
  180. django_cfg/modules/django_app_agent/services/template_manager/templates/cfg_config.py.j2 +44 -0
  181. django_cfg/modules/django_app_agent/services/template_manager/templates/cfg_module.py.j2 +81 -0
  182. django_cfg/modules/django_app_agent/services/template_manager/templates/forms.py.j2 +107 -0
  183. django_cfg/modules/django_app_agent/services/template_manager/templates/models.py.j2 +139 -0
  184. django_cfg/modules/django_app_agent/services/template_manager/templates/serializers.py.j2 +91 -0
  185. django_cfg/modules/django_app_agent/services/template_manager/templates/tests.py.j2 +195 -0
  186. django_cfg/modules/django_app_agent/services/template_manager/templates/urls.py.j2 +35 -0
  187. django_cfg/modules/django_app_agent/services/template_manager/templates/views.py.j2 +211 -0
  188. django_cfg/modules/django_app_agent/services/template_manager/variable_processor.py +200 -0
  189. django_cfg/modules/django_app_agent/services/validation_service/__init__.py +25 -0
  190. django_cfg/modules/django_app_agent/services/validation_service/django_validator.py +333 -0
  191. django_cfg/modules/django_app_agent/services/validation_service/main.py +242 -0
  192. django_cfg/modules/django_app_agent/services/validation_service/models.py +66 -0
  193. django_cfg/modules/django_app_agent/services/validation_service/quality_validator.py +352 -0
  194. django_cfg/modules/django_app_agent/services/validation_service/security_validator.py +272 -0
  195. django_cfg/modules/django_app_agent/services/validation_service/syntax_validator.py +203 -0
  196. django_cfg/modules/django_app_agent/ui/__init__.py +25 -0
  197. django_cfg/modules/django_app_agent/ui/cli.py +419 -0
  198. django_cfg/modules/django_app_agent/ui/rich_components.py +622 -0
  199. django_cfg/modules/django_app_agent/utils/__init__.py +38 -0
  200. django_cfg/modules/django_app_agent/utils/logging.py +360 -0
  201. django_cfg/modules/django_app_agent/utils/validation.py +417 -0
  202. django_cfg/modules/django_currency/__init__.py +2 -2
  203. django_cfg/modules/django_currency/clients/__init__.py +2 -2
  204. django_cfg/modules/django_currency/clients/hybrid_client.py +587 -0
  205. django_cfg/modules/django_currency/core/converter.py +12 -12
  206. django_cfg/modules/django_currency/database/__init__.py +2 -2
  207. django_cfg/modules/django_currency/database/database_loader.py +93 -42
  208. django_cfg/modules/django_llm/llm/client.py +10 -2
  209. django_cfg/modules/django_unfold/callbacks/actions.py +1 -1
  210. django_cfg/modules/django_unfold/callbacks/statistics.py +1 -1
  211. django_cfg/modules/django_unfold/dashboard.py +14 -13
  212. django_cfg/modules/django_unfold/models/config.py +1 -1
  213. django_cfg/registry/core.py +3 -0
  214. django_cfg/registry/third_party.py +2 -2
  215. django_cfg/template_archive/django_sample.zip +0 -0
  216. {django_cfg-1.3.5.dist-info → django_cfg-1.3.9.dist-info}/METADATA +2 -1
  217. {django_cfg-1.3.5.dist-info → django_cfg-1.3.9.dist-info}/RECORD +224 -118
  218. django_cfg/apps/accounts/admin/activity.py +0 -96
  219. django_cfg/apps/accounts/admin/group.py +0 -17
  220. django_cfg/apps/accounts/admin/otp.py +0 -59
  221. django_cfg/apps/accounts/admin/registration_source.py +0 -97
  222. django_cfg/apps/accounts/admin/twilio_response.py +0 -227
  223. django_cfg/apps/accounts/admin/user.py +0 -300
  224. django_cfg/apps/agents/core/agent.py +0 -281
  225. django_cfg/apps/payments/admin_interface/old/payments/base.html +0 -175
  226. django_cfg/apps/payments/admin_interface/old/payments/components/dev_tool_card.html +0 -125
  227. django_cfg/apps/payments/admin_interface/old/payments/components/loading_spinner.html +0 -16
  228. django_cfg/apps/payments/admin_interface/old/payments/components/ngrok_status_card.html +0 -113
  229. django_cfg/apps/payments/admin_interface/old/payments/components/notification.html +0 -27
  230. django_cfg/apps/payments/admin_interface/old/payments/components/provider_card.html +0 -86
  231. django_cfg/apps/payments/admin_interface/old/payments/components/status_card.html +0 -35
  232. django_cfg/apps/payments/admin_interface/old/payments/currency_converter.html +0 -382
  233. django_cfg/apps/payments/admin_interface/old/payments/payment_dashboard.html +0 -309
  234. django_cfg/apps/payments/admin_interface/old/payments/payment_form.html +0 -303
  235. django_cfg/apps/payments/admin_interface/old/payments/payment_list.html +0 -382
  236. django_cfg/apps/payments/admin_interface/old/payments/payment_status.html +0 -500
  237. django_cfg/apps/payments/admin_interface/old/payments/webhook_dashboard.html +0 -518
  238. django_cfg/apps/payments/admin_interface/old/static/payments/css/components.css +0 -619
  239. django_cfg/apps/payments/admin_interface/old/static/payments/css/dashboard.css +0 -188
  240. django_cfg/apps/payments/admin_interface/old/static/payments/js/components.js +0 -545
  241. django_cfg/apps/payments/admin_interface/old/static/payments/js/ngrok-status.js +0 -163
  242. django_cfg/apps/payments/admin_interface/old/static/payments/js/utils.js +0 -412
  243. django_cfg/apps/tasks/admin.py +0 -320
  244. django_cfg/middleware/static_nocache.py +0 -55
  245. django_cfg/modules/django_currency/clients/yahoo_client.py +0 -157
  246. /django_cfg/modules/{django_unfold → django_admin}/icons/README.md +0 -0
  247. /django_cfg/modules/{django_unfold → django_admin}/icons/__init__.py +0 -0
  248. /django_cfg/modules/{django_unfold → django_admin}/icons/constants.py +0 -0
  249. /django_cfg/modules/{django_unfold → django_admin}/icons/generate_icons.py +0 -0
  250. {django_cfg-1.3.5.dist-info → django_cfg-1.3.9.dist-info}/WHEEL +0 -0
  251. {django_cfg-1.3.5.dist-info → django_cfg-1.3.9.dist-info}/entry_points.txt +0 -0
  252. {django_cfg-1.3.5.dist-info → django_cfg-1.3.9.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,354 @@
1
+ """
2
+ Base Django Agent class with Pydantic AI integration.
3
+
4
+ This module provides the foundational DjangoAgent class that all
5
+ specialized agents inherit from, with proper django-cfg integration.
6
+ """
7
+
8
+ from typing import TypeVar, Generic, Optional, Dict, Any, List, Type, Union
9
+ from abc import ABC, abstractmethod
10
+ import asyncio
11
+ import uuid
12
+ from contextlib import asynccontextmanager
13
+
14
+ from pydantic_ai import Agent, RunContext
15
+ from pydantic_ai.models import Model, KnownModelName
16
+
17
+ from ...core.config import AgentConfig, ModelConfig, AIProvider, DEFAULT_MODELS
18
+ from ...core.exceptions import (
19
+ AgentExecutionError,
20
+ AuthenticationError,
21
+ RateLimitError,
22
+ TimeoutError as AgentTimeoutError
23
+ )
24
+ from ...utils.logging import log_agent_operation, StructuredLogger
25
+ from .context import AgentDependencies, AgentContext
26
+
27
+ # Type variables for generic agent
28
+ OutputT = TypeVar('OutputT')
29
+ DepsT = TypeVar('DepsT', bound=AgentDependencies)
30
+
31
+
32
+ class DjangoAgent(Generic[DepsT, OutputT], ABC):
33
+ """Base class for all Django App Agent AI agents.
34
+
35
+ This class provides:
36
+ - Integration with django-cfg configuration
37
+ - Pydantic AI agent management
38
+ - Error handling and retry logic
39
+ - Logging and monitoring
40
+ - Context management
41
+ """
42
+
43
+ def __init__(
44
+ self,
45
+ agent_name: str,
46
+ config: AgentConfig,
47
+ output_type: Type[OutputT] = str,
48
+ deps_type: Type[DepsT] = AgentDependencies,
49
+ model_override: Optional[str] = None,
50
+ **agent_kwargs: Any
51
+ ):
52
+ """Initialize Django Agent.
53
+
54
+ Args:
55
+ agent_name: Name of the agent for logging and identification
56
+ config: Agent configuration from django-cfg
57
+ output_type: Expected output type from the agent
58
+ deps_type: Dependencies type for dependency injection
59
+ model_override: Optional model override for testing
60
+ **agent_kwargs: Additional arguments for Pydantic AI Agent
61
+ """
62
+ self.agent_name = agent_name
63
+ self.config = config
64
+ self.output_type = output_type
65
+ self.deps_type = deps_type
66
+
67
+ # Get logger for this agent
68
+ self.logger = StructuredLogger(f"agents.{agent_name}")
69
+
70
+ # Determine model to use
71
+ model_config = self._get_model_config(model_override)
72
+
73
+ # Create Pydantic AI agent
74
+ self._agent = Agent[DepsT, OutputT](
75
+ model=model_config.provider.value + ":" + model_config.model_id,
76
+ output_type=output_type,
77
+ deps_type=deps_type,
78
+ name=agent_name,
79
+ retries=3, # Default retries
80
+ **agent_kwargs
81
+ )
82
+
83
+ # Register base instructions
84
+ self._register_instructions()
85
+
86
+ # Register tools
87
+ self._register_tools()
88
+
89
+ def _get_model_config(self, model_override: Optional[str] = None) -> ModelConfig:
90
+ """Get model configuration for this agent."""
91
+ if model_override:
92
+ # Parse model override (e.g., "openai:gpt-4")
93
+ if ":" in model_override:
94
+ provider_str, model_id = model_override.split(":", 1)
95
+ provider = AIProvider(provider_str)
96
+ else:
97
+ # Default to OpenRouter
98
+ provider = AIProvider.OPENROUTER
99
+ model_id = model_override
100
+
101
+ return ModelConfig(
102
+ provider=provider,
103
+ model_id=model_id,
104
+ tier="balanced",
105
+ max_tokens=100000,
106
+ temperature=0.1,
107
+ timeout_seconds=300.0
108
+ )
109
+
110
+ # Get model config for this agent type
111
+ model_config = self.config.get_model_config(self.agent_name)
112
+ if model_config:
113
+ return model_config
114
+
115
+ # Fall back to default model
116
+ default_key = "generation" # Default task type
117
+ if default_key in DEFAULT_MODELS:
118
+ return DEFAULT_MODELS[default_key]
119
+
120
+ # Ultimate fallback
121
+ return ModelConfig(
122
+ provider=AIProvider.OPENROUTER,
123
+ model_id="anthropic/claude-3-haiku",
124
+ tier="balanced",
125
+ max_tokens=50000,
126
+ temperature=0.1,
127
+ timeout_seconds=180.0
128
+ )
129
+
130
+ @abstractmethod
131
+ def _register_instructions(self) -> None:
132
+ """Register agent instructions. Must be implemented by subclasses."""
133
+ pass
134
+
135
+ @abstractmethod
136
+ def _register_tools(self) -> None:
137
+ """Register agent tools. Must be implemented by subclasses."""
138
+ pass
139
+
140
+ @log_agent_operation("base_agent", "run")
141
+ async def run(
142
+ self,
143
+ prompt: str,
144
+ deps: DepsT,
145
+ context: Optional[AgentContext] = None,
146
+ **run_kwargs: Any
147
+ ) -> OutputT:
148
+ """Run the agent with the given prompt and dependencies.
149
+
150
+ Args:
151
+ prompt: Input prompt for the agent
152
+ deps: Dependencies for the agent execution
153
+ context: Optional execution context
154
+ **run_kwargs: Additional arguments for agent.run()
155
+
156
+ Returns:
157
+ Agent output of type OutputT
158
+
159
+ Raises:
160
+ AgentExecutionError: If agent execution fails
161
+ AuthenticationError: If API authentication fails
162
+ RateLimitError: If rate limits are exceeded
163
+ AgentTimeoutError: If execution times out
164
+ """
165
+ if context:
166
+ context.update_progress(f"{self.agent_name}_execution", 0.0)
167
+
168
+ try:
169
+ # Validate API key
170
+ model_config = self._get_model_config()
171
+ if not self.config.has_api_key(model_config.provider):
172
+ raise AuthenticationError(
173
+ f"No API key configured for {model_config.provider}",
174
+ provider=model_config.provider.value
175
+ )
176
+
177
+ deps.log_operation(f"Starting {self.agent_name} execution", prompt_length=len(prompt))
178
+
179
+ # Run the agent with timeout
180
+ result = await asyncio.wait_for(
181
+ self._agent.run(prompt, deps=deps, **run_kwargs),
182
+ timeout=model_config.timeout_seconds
183
+ )
184
+
185
+ if context:
186
+ context.add_result({
187
+ "agent": self.agent_name,
188
+ "output_type": self.output_type.__name__,
189
+ "success": True
190
+ })
191
+ context.update_progress(f"{self.agent_name}_completed", 100.0)
192
+
193
+ deps.log_operation(f"Completed {self.agent_name} execution successfully")
194
+
195
+ return result.output
196
+
197
+ except asyncio.TimeoutError as e:
198
+ error_msg = f"Agent {self.agent_name} execution timed out"
199
+ deps.log_error(error_msg, e)
200
+ if context:
201
+ context.add_error(error_msg)
202
+ raise AgentTimeoutError(
203
+ error_msg,
204
+ operation=f"{self.agent_name}_execution",
205
+ timeout_seconds=model_config.timeout_seconds
206
+ )
207
+
208
+ except Exception as e:
209
+ error_msg = f"Agent {self.agent_name} execution failed: {e}"
210
+ deps.log_error(error_msg, e)
211
+ if context:
212
+ context.add_error(error_msg)
213
+
214
+ # Map specific exceptions
215
+ if "authentication" in str(e).lower() or "api key" in str(e).lower():
216
+ raise AuthenticationError(
217
+ error_msg,
218
+ provider=model_config.provider.value,
219
+ cause=e
220
+ )
221
+ elif "rate limit" in str(e).lower():
222
+ raise RateLimitError(
223
+ error_msg,
224
+ provider=model_config.provider.value,
225
+ cause=e
226
+ )
227
+ else:
228
+ raise AgentExecutionError(
229
+ error_msg,
230
+ agent_name=self.agent_name,
231
+ agent_operation="run",
232
+ cause=e
233
+ )
234
+
235
+ async def run_sync(
236
+ self,
237
+ prompt: str,
238
+ deps: DepsT,
239
+ context: Optional[AgentContext] = None,
240
+ **run_kwargs: Any
241
+ ) -> OutputT:
242
+ """Synchronous wrapper for run method."""
243
+ return await self.run(prompt, deps, context, **run_kwargs)
244
+
245
+ @asynccontextmanager
246
+ async def execution_context(
247
+ self,
248
+ operation_name: str,
249
+ correlation_id: Optional[str] = None
250
+ ):
251
+ """Context manager for agent execution with proper cleanup."""
252
+ if correlation_id is None:
253
+ correlation_id = str(uuid.uuid4())
254
+
255
+ context = AgentContext()
256
+
257
+ try:
258
+ with self.logger.operation_context(operation_name, correlation_id):
259
+ yield context
260
+ finally:
261
+ context.mark_completed()
262
+
263
+ def get_instructions(self) -> str:
264
+ """Get the current instructions for this agent."""
265
+ return getattr(self, '_instructions', f"You are {self.agent_name}, a specialized AI agent.")
266
+
267
+ def validate_dependencies(self, deps: DepsT) -> List[str]:
268
+ """Validate that dependencies are properly configured.
269
+
270
+ Args:
271
+ deps: Dependencies to validate
272
+
273
+ Returns:
274
+ List of validation errors (empty if valid)
275
+ """
276
+ errors = []
277
+
278
+ # Check API key availability
279
+ model_config = self._get_model_config()
280
+ if not deps.config.has_api_key(model_config.provider):
281
+ errors.append(f"No API key configured for {model_config.provider}")
282
+
283
+ # Check project context if required
284
+ if self._requires_project_context() and not deps.has_project_context():
285
+ errors.append("Project context is required but not provided")
286
+
287
+ return errors
288
+
289
+ def _requires_project_context(self) -> bool:
290
+ """Check if this agent requires project context. Override in subclasses."""
291
+ return False
292
+
293
+ @property
294
+ def agent(self) -> Agent[DepsT, OutputT]:
295
+ """Get the underlying Pydantic AI agent."""
296
+ return self._agent
297
+
298
+ def __repr__(self) -> str:
299
+ """String representation of the agent."""
300
+ return f"{self.__class__.__name__}(name='{self.agent_name}', output_type={self.output_type.__name__})"
301
+
302
+
303
+ class SimpleTextAgent(DjangoAgent[AgentDependencies, str]):
304
+ """Simple text-based agent for basic operations."""
305
+
306
+ def __init__(
307
+ self,
308
+ agent_name: str,
309
+ config: AgentConfig,
310
+ instructions: str,
311
+ **kwargs: Any
312
+ ):
313
+ """Initialize simple text agent.
314
+
315
+ Args:
316
+ agent_name: Name of the agent
317
+ config: Agent configuration
318
+ instructions: Instructions for the agent
319
+ **kwargs: Additional arguments
320
+ """
321
+ self._instructions = instructions
322
+ super().__init__(agent_name, config, str, AgentDependencies, **kwargs)
323
+
324
+ def _register_instructions(self) -> None:
325
+ """Register instructions for the agent."""
326
+ @self._agent.instructions
327
+ async def agent_instructions(ctx: RunContext[AgentDependencies]) -> str:
328
+ return self._instructions
329
+
330
+ def _register_tools(self) -> None:
331
+ """Register tools for the agent."""
332
+ # Simple text agent has no tools by default
333
+ pass
334
+
335
+
336
+ # Utility function for creating simple agents
337
+ def create_simple_agent(
338
+ name: str,
339
+ instructions: str,
340
+ config: AgentConfig,
341
+ **kwargs: Any
342
+ ) -> SimpleTextAgent:
343
+ """Create a simple text-based agent.
344
+
345
+ Args:
346
+ name: Agent name
347
+ instructions: Agent instructions
348
+ config: Agent configuration
349
+ **kwargs: Additional arguments
350
+
351
+ Returns:
352
+ Configured SimpleTextAgent
353
+ """
354
+ return SimpleTextAgent(name, config, instructions, **kwargs)
@@ -0,0 +1,236 @@
1
+ """
2
+ Context management for Django App Agent AI agents.
3
+
4
+ This module provides context classes for dependency injection and
5
+ execution management following Pydantic AI patterns.
6
+ """
7
+
8
+ from typing import Optional, Dict, Any, List
9
+ from dataclasses import dataclass, field
10
+ from pathlib import Path
11
+ from datetime import datetime, timezone
12
+
13
+ from pydantic import BaseModel, Field, ConfigDict
14
+
15
+ from ...core.config import AgentConfig, AIProvider
16
+ from ...models.context import ProjectContext, InfrastructureContext
17
+ from ...utils.logging import StructuredLogger, get_logger
18
+
19
+
20
+ class AgentDependencies(BaseModel):
21
+ """Base dependencies for all Django App Agent AI agents.
22
+
23
+ This follows Pydantic AI dependency injection patterns and provides
24
+ common dependencies that all agents need.
25
+ """
26
+
27
+ model_config = ConfigDict(
28
+ extra='forbid',
29
+ validate_assignment=True,
30
+ arbitrary_types_allowed=True # For logger and config objects
31
+ )
32
+
33
+ # Core configuration
34
+ config: AgentConfig = Field(description="Agent configuration")
35
+ logger: StructuredLogger = Field(description="Structured logger instance")
36
+
37
+ # Project context
38
+ project_context: Optional[ProjectContext] = Field(
39
+ default=None,
40
+ description="Django project context information"
41
+ )
42
+
43
+ infrastructure_context: Optional[InfrastructureContext] = Field(
44
+ default=None,
45
+ description="Infrastructure context for code generation"
46
+ )
47
+
48
+ # Execution context
49
+ correlation_id: str = Field(description="Correlation ID for tracing")
50
+ operation_name: str = Field(description="Name of the current operation")
51
+
52
+ # Working directories
53
+ project_root: Optional[Path] = Field(
54
+ default=None,
55
+ description="Root directory of the Django project"
56
+ )
57
+
58
+ output_directory: Optional[Path] = Field(
59
+ default=None,
60
+ description="Directory for generated output"
61
+ )
62
+
63
+ # Execution metadata
64
+ execution_metadata: Dict[str, Any] = Field(
65
+ default_factory=dict,
66
+ description="Additional metadata for execution"
67
+ )
68
+
69
+ def get_api_key(self, provider: str) -> Optional[str]:
70
+ """Get API key for AI provider."""
71
+ try:
72
+ ai_provider = AIProvider(provider)
73
+ return self.config.get_api_key(ai_provider)
74
+ except ValueError:
75
+ return None
76
+
77
+ def has_project_context(self) -> bool:
78
+ """Check if project context is available."""
79
+ return self.project_context is not None
80
+
81
+ def get_project_path(self) -> Optional[Path]:
82
+ """Get project path from context or direct setting."""
83
+ if self.project_context:
84
+ return self.project_context.project_path
85
+ return self.project_root
86
+
87
+ def log_operation(self, message: str, **metadata: Any) -> None:
88
+ """Log operation with context."""
89
+ self.logger.info(
90
+ message,
91
+ operation=self.operation_name,
92
+ correlation_id=self.correlation_id,
93
+ **metadata
94
+ )
95
+
96
+ def log_error(self, message: str, error: Exception, **metadata: Any) -> None:
97
+ """Log error with context."""
98
+ self.logger.error(
99
+ message,
100
+ operation=self.operation_name,
101
+ correlation_id=self.correlation_id,
102
+ error=str(error),
103
+ error_type=type(error).__name__,
104
+ **metadata
105
+ )
106
+
107
+
108
+ @dataclass
109
+ class AgentContext:
110
+ """Execution context for Django App Agent operations.
111
+
112
+ This class manages the execution context for agent operations,
113
+ including timing, progress tracking, and result collection.
114
+ """
115
+
116
+ # Execution tracking
117
+ start_time: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
118
+ end_time: Optional[datetime] = field(default=None)
119
+
120
+ # Progress tracking
121
+ current_stage: str = field(default="initialization")
122
+ progress_percentage: float = field(default=0.0)
123
+
124
+ # Result collection
125
+ intermediate_results: List[Dict[str, Any]] = field(default_factory=list)
126
+ errors: List[str] = field(default_factory=list)
127
+ warnings: List[str] = field(default_factory=list)
128
+
129
+ # Performance metrics
130
+ token_usage: Dict[str, int] = field(default_factory=dict)
131
+ api_calls_count: int = field(default=0)
132
+
133
+ def mark_completed(self) -> None:
134
+ """Mark the context as completed."""
135
+ self.end_time = datetime.now(timezone.utc)
136
+ self.progress_percentage = 100.0
137
+
138
+ def update_progress(self, stage: str, percentage: float) -> None:
139
+ """Update progress information."""
140
+ self.current_stage = stage
141
+ self.progress_percentage = min(100.0, max(0.0, percentage))
142
+
143
+ def add_result(self, result: Dict[str, Any]) -> None:
144
+ """Add intermediate result."""
145
+ self.intermediate_results.append({
146
+ **result,
147
+ "timestamp": datetime.now(timezone.utc).isoformat(),
148
+ "stage": self.current_stage
149
+ })
150
+
151
+ def add_error(self, error: str) -> None:
152
+ """Add error message."""
153
+ self.errors.append(error)
154
+
155
+ def add_warning(self, warning: str) -> None:
156
+ """Add warning message."""
157
+ self.warnings.append(warning)
158
+
159
+ def track_token_usage(self, provider: str, tokens: int) -> None:
160
+ """Track token usage by provider."""
161
+ self.token_usage[provider] = self.token_usage.get(provider, 0) + tokens
162
+
163
+ def increment_api_calls(self) -> None:
164
+ """Increment API calls counter."""
165
+ self.api_calls_count += 1
166
+
167
+ @property
168
+ def execution_time_seconds(self) -> float:
169
+ """Get execution time in seconds."""
170
+ end = self.end_time or datetime.now(timezone.utc)
171
+ return (end - self.start_time).total_seconds()
172
+
173
+ @property
174
+ def is_completed(self) -> bool:
175
+ """Check if execution is completed."""
176
+ return self.end_time is not None
177
+
178
+ @property
179
+ def has_errors(self) -> bool:
180
+ """Check if there are any errors."""
181
+ return len(self.errors) > 0
182
+
183
+ @property
184
+ def total_tokens_used(self) -> int:
185
+ """Get total tokens used across all providers."""
186
+ return sum(self.token_usage.values())
187
+
188
+ def get_summary(self) -> Dict[str, Any]:
189
+ """Get execution summary."""
190
+ return {
191
+ "start_time": self.start_time.isoformat(),
192
+ "end_time": self.end_time.isoformat() if self.end_time else None,
193
+ "execution_time_seconds": self.execution_time_seconds,
194
+ "current_stage": self.current_stage,
195
+ "progress_percentage": self.progress_percentage,
196
+ "is_completed": self.is_completed,
197
+ "results_count": len(self.intermediate_results),
198
+ "errors_count": len(self.errors),
199
+ "warnings_count": len(self.warnings),
200
+ "total_tokens_used": self.total_tokens_used,
201
+ "api_calls_count": self.api_calls_count,
202
+ }
203
+
204
+
205
+ def create_agent_dependencies(
206
+ config: AgentConfig,
207
+ correlation_id: str,
208
+ operation_name: str,
209
+ project_root: Optional[Path] = None,
210
+ output_directory: Optional[Path] = None,
211
+ **metadata: Any
212
+ ) -> AgentDependencies:
213
+ """Factory function to create AgentDependencies.
214
+
215
+ Args:
216
+ config: Agent configuration
217
+ correlation_id: Correlation ID for tracing
218
+ operation_name: Name of the operation
219
+ project_root: Optional project root directory
220
+ output_directory: Optional output directory
221
+ **metadata: Additional metadata
222
+
223
+ Returns:
224
+ Configured AgentDependencies instance
225
+ """
226
+ logger = get_logger(f"agents.{operation_name}")
227
+
228
+ return AgentDependencies(
229
+ config=config,
230
+ logger=logger,
231
+ correlation_id=correlation_id,
232
+ operation_name=operation_name,
233
+ project_root=project_root,
234
+ output_directory=output_directory,
235
+ execution_metadata=metadata
236
+ )