django-cfg 1.1.81__py3-none-any.whl → 1.2.0__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 (246) hide show
  1. django_cfg/__init__.py +20 -448
  2. django_cfg/apps/accounts/README.md +3 -3
  3. django_cfg/apps/accounts/admin/__init__.py +0 -2
  4. django_cfg/apps/accounts/admin/activity.py +2 -9
  5. django_cfg/apps/accounts/admin/filters.py +0 -42
  6. django_cfg/apps/accounts/admin/inlines.py +8 -8
  7. django_cfg/apps/accounts/admin/otp.py +5 -5
  8. django_cfg/apps/accounts/admin/registration_source.py +1 -8
  9. django_cfg/apps/accounts/admin/user.py +12 -20
  10. django_cfg/apps/accounts/managers/user_manager.py +2 -129
  11. django_cfg/apps/accounts/migrations/0006_remove_twilioresponse_otp_secret_and_more.py +46 -0
  12. django_cfg/apps/accounts/models.py +3 -123
  13. django_cfg/apps/accounts/serializers/otp.py +40 -44
  14. django_cfg/apps/accounts/serializers/profile.py +0 -2
  15. django_cfg/apps/accounts/services/otp_service.py +98 -186
  16. django_cfg/apps/accounts/signals.py +25 -15
  17. django_cfg/apps/accounts/utils/auth_email_service.py +84 -0
  18. django_cfg/apps/accounts/views/otp.py +35 -36
  19. django_cfg/apps/agents/README.md +129 -0
  20. django_cfg/apps/agents/__init__.py +68 -0
  21. django_cfg/apps/agents/admin/__init__.py +17 -0
  22. django_cfg/apps/agents/admin/execution_admin.py +460 -0
  23. django_cfg/apps/agents/admin/registry_admin.py +360 -0
  24. django_cfg/apps/agents/admin/toolsets_admin.py +482 -0
  25. django_cfg/apps/agents/apps.py +29 -0
  26. django_cfg/apps/agents/core/__init__.py +20 -0
  27. django_cfg/apps/agents/core/agent.py +281 -0
  28. django_cfg/apps/agents/core/dependencies.py +154 -0
  29. django_cfg/apps/agents/core/exceptions.py +66 -0
  30. django_cfg/apps/agents/core/models.py +106 -0
  31. django_cfg/apps/agents/core/orchestrator.py +391 -0
  32. django_cfg/apps/agents/examples/__init__.py +3 -0
  33. django_cfg/apps/agents/examples/simple_example.py +161 -0
  34. django_cfg/apps/agents/integration/__init__.py +14 -0
  35. django_cfg/apps/agents/integration/middleware.py +80 -0
  36. django_cfg/apps/agents/integration/registry.py +345 -0
  37. django_cfg/apps/agents/integration/signals.py +50 -0
  38. django_cfg/apps/agents/management/__init__.py +3 -0
  39. django_cfg/apps/agents/management/commands/__init__.py +3 -0
  40. django_cfg/apps/agents/management/commands/create_agent.py +365 -0
  41. django_cfg/apps/agents/management/commands/orchestrator_status.py +191 -0
  42. django_cfg/apps/agents/managers/__init__.py +23 -0
  43. django_cfg/apps/agents/managers/execution.py +236 -0
  44. django_cfg/apps/agents/managers/registry.py +254 -0
  45. django_cfg/apps/agents/managers/toolsets.py +496 -0
  46. django_cfg/apps/agents/migrations/0001_initial.py +286 -0
  47. django_cfg/apps/agents/migrations/__init__.py +5 -0
  48. django_cfg/apps/agents/models/__init__.py +15 -0
  49. django_cfg/apps/agents/models/execution.py +215 -0
  50. django_cfg/apps/agents/models/registry.py +220 -0
  51. django_cfg/apps/agents/models/toolsets.py +305 -0
  52. django_cfg/apps/agents/patterns/__init__.py +24 -0
  53. django_cfg/apps/agents/patterns/content_agents.py +234 -0
  54. django_cfg/apps/agents/toolsets/__init__.py +15 -0
  55. django_cfg/apps/agents/toolsets/cache_toolset.py +285 -0
  56. django_cfg/apps/agents/toolsets/django_toolset.py +220 -0
  57. django_cfg/apps/agents/toolsets/file_toolset.py +324 -0
  58. django_cfg/apps/agents/toolsets/orm_toolset.py +319 -0
  59. django_cfg/apps/agents/urls.py +46 -0
  60. django_cfg/apps/knowbase/README.md +150 -0
  61. django_cfg/apps/knowbase/__init__.py +27 -0
  62. django_cfg/apps/knowbase/admin/__init__.py +23 -0
  63. django_cfg/apps/knowbase/admin/archive_admin.py +857 -0
  64. django_cfg/apps/knowbase/admin/chat_admin.py +386 -0
  65. django_cfg/apps/knowbase/admin/document_admin.py +650 -0
  66. django_cfg/apps/knowbase/admin/external_data_admin.py +685 -0
  67. django_cfg/apps/knowbase/apps.py +81 -0
  68. django_cfg/apps/knowbase/config/README.md +176 -0
  69. django_cfg/apps/knowbase/config/__init__.py +51 -0
  70. django_cfg/apps/knowbase/config/constance_fields.py +186 -0
  71. django_cfg/apps/knowbase/config/constance_settings.py +200 -0
  72. django_cfg/apps/knowbase/config/settings.py +444 -0
  73. django_cfg/apps/knowbase/examples/__init__.py +3 -0
  74. django_cfg/apps/knowbase/examples/external_data_usage.py +191 -0
  75. django_cfg/apps/knowbase/management/__init__.py +0 -0
  76. django_cfg/apps/knowbase/management/commands/__init__.py +0 -0
  77. django_cfg/apps/knowbase/management/commands/knowbase_stats.py +158 -0
  78. django_cfg/apps/knowbase/management/commands/setup_knowbase.py +59 -0
  79. django_cfg/apps/knowbase/managers/__init__.py +22 -0
  80. django_cfg/apps/knowbase/managers/archive.py +426 -0
  81. django_cfg/apps/knowbase/managers/base.py +32 -0
  82. django_cfg/apps/knowbase/managers/chat.py +141 -0
  83. django_cfg/apps/knowbase/managers/document.py +203 -0
  84. django_cfg/apps/knowbase/managers/external_data.py +471 -0
  85. django_cfg/apps/knowbase/migrations/0001_initial.py +427 -0
  86. django_cfg/apps/knowbase/migrations/0002_archiveitem_archiveitemchunk_documentarchive_and_more.py +434 -0
  87. django_cfg/apps/knowbase/migrations/__init__.py +5 -0
  88. django_cfg/apps/knowbase/mixins/__init__.py +15 -0
  89. django_cfg/apps/knowbase/mixins/config.py +108 -0
  90. django_cfg/apps/knowbase/mixins/creator.py +81 -0
  91. django_cfg/apps/knowbase/mixins/examples/vehicle_model_example.py +199 -0
  92. django_cfg/apps/knowbase/mixins/external_data_mixin.py +813 -0
  93. django_cfg/apps/knowbase/mixins/service.py +362 -0
  94. django_cfg/apps/knowbase/models/__init__.py +41 -0
  95. django_cfg/apps/knowbase/models/archive.py +599 -0
  96. django_cfg/apps/knowbase/models/base.py +58 -0
  97. django_cfg/apps/knowbase/models/chat.py +157 -0
  98. django_cfg/apps/knowbase/models/document.py +267 -0
  99. django_cfg/apps/knowbase/models/external_data.py +376 -0
  100. django_cfg/apps/knowbase/serializers/__init__.py +68 -0
  101. django_cfg/apps/knowbase/serializers/archive_serializers.py +386 -0
  102. django_cfg/apps/knowbase/serializers/chat_serializers.py +137 -0
  103. django_cfg/apps/knowbase/serializers/document_serializers.py +94 -0
  104. django_cfg/apps/knowbase/serializers/external_data_serializers.py +256 -0
  105. django_cfg/apps/knowbase/serializers/public_serializers.py +74 -0
  106. django_cfg/apps/knowbase/services/__init__.py +40 -0
  107. django_cfg/apps/knowbase/services/archive/__init__.py +42 -0
  108. django_cfg/apps/knowbase/services/archive/archive_service.py +541 -0
  109. django_cfg/apps/knowbase/services/archive/chunking_service.py +791 -0
  110. django_cfg/apps/knowbase/services/archive/exceptions.py +52 -0
  111. django_cfg/apps/knowbase/services/archive/extraction_service.py +508 -0
  112. django_cfg/apps/knowbase/services/archive/vectorization_service.py +362 -0
  113. django_cfg/apps/knowbase/services/base.py +53 -0
  114. django_cfg/apps/knowbase/services/chat_service.py +239 -0
  115. django_cfg/apps/knowbase/services/document_service.py +144 -0
  116. django_cfg/apps/knowbase/services/embedding/__init__.py +43 -0
  117. django_cfg/apps/knowbase/services/embedding/async_processor.py +244 -0
  118. django_cfg/apps/knowbase/services/embedding/batch_processor.py +250 -0
  119. django_cfg/apps/knowbase/services/embedding/batch_result.py +61 -0
  120. django_cfg/apps/knowbase/services/embedding/models.py +229 -0
  121. django_cfg/apps/knowbase/services/embedding/processors.py +148 -0
  122. django_cfg/apps/knowbase/services/embedding/utils.py +176 -0
  123. django_cfg/apps/knowbase/services/prompt_builder.py +191 -0
  124. django_cfg/apps/knowbase/services/search_service.py +293 -0
  125. django_cfg/apps/knowbase/signals/__init__.py +21 -0
  126. django_cfg/apps/knowbase/signals/archive_signals.py +211 -0
  127. django_cfg/apps/knowbase/signals/chat_signals.py +37 -0
  128. django_cfg/apps/knowbase/signals/document_signals.py +143 -0
  129. django_cfg/apps/knowbase/signals/external_data_signals.py +157 -0
  130. django_cfg/apps/knowbase/tasks/__init__.py +39 -0
  131. django_cfg/apps/knowbase/tasks/archive_tasks.py +316 -0
  132. django_cfg/apps/knowbase/tasks/document_processing.py +341 -0
  133. django_cfg/apps/knowbase/tasks/external_data_tasks.py +341 -0
  134. django_cfg/apps/knowbase/tasks/maintenance.py +195 -0
  135. django_cfg/apps/knowbase/urls.py +43 -0
  136. django_cfg/apps/knowbase/utils/__init__.py +12 -0
  137. django_cfg/apps/knowbase/utils/chunk_settings.py +261 -0
  138. django_cfg/apps/knowbase/utils/text_processing.py +375 -0
  139. django_cfg/apps/knowbase/utils/validation.py +99 -0
  140. django_cfg/apps/knowbase/views/__init__.py +28 -0
  141. django_cfg/apps/knowbase/views/archive_views.py +469 -0
  142. django_cfg/apps/knowbase/views/base.py +49 -0
  143. django_cfg/apps/knowbase/views/chat_views.py +181 -0
  144. django_cfg/apps/knowbase/views/document_views.py +183 -0
  145. django_cfg/apps/knowbase/views/public_views.py +129 -0
  146. django_cfg/apps/leads/admin.py +70 -0
  147. django_cfg/apps/newsletter/admin.py +234 -0
  148. django_cfg/apps/newsletter/admin_filters.py +124 -0
  149. django_cfg/apps/support/admin.py +196 -0
  150. django_cfg/apps/support/admin_filters.py +71 -0
  151. django_cfg/apps/support/templates/support/chat/ticket_chat.html +1 -1
  152. django_cfg/apps/urls.py +5 -4
  153. django_cfg/cli/README.md +1 -1
  154. django_cfg/cli/commands/create_project.py +2 -2
  155. django_cfg/cli/commands/info.py +1 -1
  156. django_cfg/config.py +44 -0
  157. django_cfg/core/config.py +29 -82
  158. django_cfg/core/environment.py +1 -1
  159. django_cfg/core/generation.py +19 -107
  160. django_cfg/{integration.py → core/integration.py} +18 -16
  161. django_cfg/core/validation.py +1 -1
  162. django_cfg/management/__init__.py +1 -1
  163. django_cfg/management/commands/__init__.py +1 -1
  164. django_cfg/management/commands/auto_generate.py +482 -0
  165. django_cfg/management/commands/migrator.py +19 -101
  166. django_cfg/management/commands/test_email.py +1 -1
  167. django_cfg/middleware/README.md +0 -158
  168. django_cfg/middleware/__init__.py +0 -2
  169. django_cfg/middleware/user_activity.py +3 -3
  170. django_cfg/models/api.py +145 -0
  171. django_cfg/models/base.py +287 -0
  172. django_cfg/models/cache.py +4 -4
  173. django_cfg/models/constance.py +25 -88
  174. django_cfg/models/database.py +9 -9
  175. django_cfg/models/drf.py +3 -36
  176. django_cfg/models/email.py +163 -0
  177. django_cfg/models/environment.py +276 -0
  178. django_cfg/models/limits.py +1 -1
  179. django_cfg/models/logging.py +366 -0
  180. django_cfg/models/revolution.py +41 -2
  181. django_cfg/models/security.py +125 -0
  182. django_cfg/models/services.py +1 -1
  183. django_cfg/modules/__init__.py +2 -56
  184. django_cfg/modules/base.py +78 -52
  185. django_cfg/modules/django_currency/service.py +2 -2
  186. django_cfg/modules/django_email.py +2 -2
  187. django_cfg/modules/django_health.py +267 -0
  188. django_cfg/modules/django_llm/llm/client.py +79 -17
  189. django_cfg/modules/django_llm/translator/translator.py +2 -2
  190. django_cfg/modules/django_logger.py +2 -2
  191. django_cfg/modules/django_ngrok.py +2 -2
  192. django_cfg/modules/django_tasks.py +68 -3
  193. django_cfg/modules/django_telegram.py +3 -3
  194. django_cfg/modules/django_twilio/sendgrid_service.py +2 -2
  195. django_cfg/modules/django_twilio/service.py +2 -2
  196. django_cfg/modules/django_twilio/simple_service.py +2 -2
  197. django_cfg/modules/django_twilio/templates/guide.md +266 -0
  198. django_cfg/modules/django_twilio/twilio_service.py +2 -2
  199. django_cfg/modules/django_unfold/__init__.py +69 -0
  200. django_cfg/modules/{unfold → django_unfold}/callbacks.py +23 -22
  201. django_cfg/modules/django_unfold/dashboard.py +278 -0
  202. django_cfg/modules/django_unfold/icons/README.md +145 -0
  203. django_cfg/modules/django_unfold/icons/__init__.py +12 -0
  204. django_cfg/modules/django_unfold/icons/constants.py +2851 -0
  205. django_cfg/modules/django_unfold/icons/generate_icons.py +486 -0
  206. django_cfg/modules/django_unfold/models/__init__.py +42 -0
  207. django_cfg/modules/django_unfold/models/config.py +601 -0
  208. django_cfg/modules/django_unfold/models/dashboard.py +206 -0
  209. django_cfg/modules/django_unfold/models/dropdown.py +40 -0
  210. django_cfg/modules/django_unfold/models/navigation.py +73 -0
  211. django_cfg/modules/django_unfold/models/tabs.py +25 -0
  212. django_cfg/modules/{unfold → django_unfold}/system_monitor.py +2 -2
  213. django_cfg/modules/django_unfold/utils.py +140 -0
  214. django_cfg/registry/__init__.py +23 -0
  215. django_cfg/registry/core.py +61 -0
  216. django_cfg/registry/exceptions.py +11 -0
  217. django_cfg/registry/modules.py +12 -0
  218. django_cfg/registry/services.py +26 -0
  219. django_cfg/registry/third_party.py +52 -0
  220. django_cfg/routing/__init__.py +19 -0
  221. django_cfg/routing/callbacks.py +198 -0
  222. django_cfg/routing/routers.py +48 -0
  223. django_cfg/templates/admin/layouts/dashboard_with_tabs.html +8 -9
  224. django_cfg/templatetags/__init__.py +0 -0
  225. django_cfg/templatetags/django_cfg.py +33 -0
  226. django_cfg/urls.py +33 -0
  227. django_cfg/utils/path_resolution.py +1 -1
  228. django_cfg/utils/smart_defaults.py +7 -61
  229. django_cfg/utils/toolkit.py +663 -0
  230. {django_cfg-1.1.81.dist-info → django_cfg-1.2.0.dist-info}/METADATA +83 -86
  231. django_cfg-1.2.0.dist-info/RECORD +441 -0
  232. django_cfg/apps/tasks/@docs/README.md +0 -195
  233. django_cfg/archive/django_sample.zip +0 -0
  234. django_cfg/models/unfold.py +0 -271
  235. django_cfg/modules/unfold/__init__.py +0 -29
  236. django_cfg/modules/unfold/dashboard.py +0 -318
  237. django_cfg/pyproject.toml +0 -370
  238. django_cfg/routers.py +0 -83
  239. django_cfg-1.1.81.dist-info/RECORD +0 -278
  240. /django_cfg/{exceptions.py → core/exceptions.py} +0 -0
  241. /django_cfg/modules/{unfold → django_unfold}/models.py +0 -0
  242. /django_cfg/modules/{unfold → django_unfold}/tailwind.py +0 -0
  243. /django_cfg/{version_check.py → utils/version_check.py} +0 -0
  244. {django_cfg-1.1.81.dist-info → django_cfg-1.2.0.dist-info}/WHEEL +0 -0
  245. {django_cfg-1.1.81.dist-info → django_cfg-1.2.0.dist-info}/entry_points.txt +0 -0
  246. {django_cfg-1.1.81.dist-info → django_cfg-1.2.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,365 @@
1
+ """
2
+ Management command to create agent definitions.
3
+ """
4
+
5
+ import asyncio
6
+ from django.core.management.base import BaseCommand, CommandError
7
+ from django.contrib.auth.models import User
8
+
9
+ from django_cfg.modules.django_orchestrator.models.registry import AgentDefinition
10
+
11
+
12
+ class Command(BaseCommand):
13
+ """Create agent definition from command line."""
14
+
15
+ help = 'Create a new agent definition'
16
+
17
+ def add_arguments(self, parser):
18
+ """Add command arguments."""
19
+ parser.add_argument('name', type=str, help='Agent name (unique identifier)')
20
+ parser.add_argument('instructions', type=str, help='Agent instructions/system prompt')
21
+
22
+ parser.add_argument(
23
+ '--deps-type',
24
+ type=str,
25
+ default='DjangoDeps',
26
+ help='Dependencies type (default: DjangoDeps)'
27
+ )
28
+ parser.add_argument(
29
+ '--output-type',
30
+ type=str,
31
+ default='ProcessResult',
32
+ help='Output type (default: ProcessResult)'
33
+ )
34
+ parser.add_argument(
35
+ '--model',
36
+ type=str,
37
+ default='openai:gpt-4o-mini',
38
+ help='LLM model to use (default: openai:gpt-4o-mini)'
39
+ )
40
+ parser.add_argument(
41
+ '--category',
42
+ type=str,
43
+ default='',
44
+ help='Agent category'
45
+ )
46
+ parser.add_argument(
47
+ '--timeout',
48
+ type=int,
49
+ default=300,
50
+ help='Execution timeout in seconds (default: 300)'
51
+ )
52
+ parser.add_argument(
53
+ '--max-retries',
54
+ type=int,
55
+ default=3,
56
+ help='Maximum retry attempts (default: 3)'
57
+ )
58
+ parser.add_argument(
59
+ '--public',
60
+ action='store_true',
61
+ help='Make agent public (accessible to all users)'
62
+ )
63
+ parser.add_argument(
64
+ '--no-cache',
65
+ action='store_true',
66
+ help='Disable caching for this agent'
67
+ )
68
+ parser.add_argument(
69
+ '--creator',
70
+ type=str,
71
+ help='Username of agent creator (defaults to first superuser)'
72
+ )
73
+ parser.add_argument(
74
+ '--description',
75
+ type=str,
76
+ default='',
77
+ help='Agent description'
78
+ )
79
+ parser.add_argument(
80
+ '--tags',
81
+ type=str,
82
+ nargs='*',
83
+ help='Agent tags (space-separated)'
84
+ )
85
+
86
+ def handle(self, *args, **options):
87
+ """Handle command execution."""
88
+ # Run async operations
89
+ asyncio.run(self._create_agent(options))
90
+
91
+ async def _create_agent(self, options):
92
+ """Create agent definition."""
93
+ name = options['name']
94
+ instructions = options['instructions']
95
+
96
+ # Validate name
97
+ if await AgentDefinition.objects.filter(name=name).aexists():
98
+ raise CommandError(f"Agent '{name}' already exists")
99
+
100
+ # Get creator user
101
+ creator = await self._get_creator_user(options.get('creator'))
102
+
103
+ # Prepare agent data
104
+ agent_data = {
105
+ 'name': name,
106
+ 'instructions': instructions,
107
+ 'deps_type': options['deps_type'],
108
+ 'output_type': options['output_type'],
109
+ 'model': options['model'],
110
+ 'category': options['category'],
111
+ 'timeout': options['timeout'],
112
+ 'max_retries': options['max_retries'],
113
+ 'is_public': options['public'],
114
+ 'enable_caching': not options['no_cache'],
115
+ 'created_by': creator,
116
+ 'description': options['description'],
117
+ }
118
+
119
+ # Add tags if provided
120
+ if options['tags']:
121
+ agent_data['tags'] = options['tags']
122
+
123
+ # Create agent definition
124
+ try:
125
+ agent_def = await AgentDefinition.objects.acreate(**agent_data)
126
+
127
+ self.stdout.write(
128
+ self.style.SUCCESS(f"āœ… Created agent definition: {agent_def.name}")
129
+ )
130
+
131
+ # Show agent details
132
+ self.stdout.write("\nAgent Details:")
133
+ self.stdout.write(f" Name: {agent_def.name}")
134
+ self.stdout.write(f" Display Name: {agent_def.display_name}")
135
+ self.stdout.write(f" Category: {agent_def.category or 'None'}")
136
+ self.stdout.write(f" Model: {agent_def.model}")
137
+ self.stdout.write(f" Dependencies: {agent_def.deps_type}")
138
+ self.stdout.write(f" Output Type: {agent_def.output_type}")
139
+ self.stdout.write(f" Timeout: {agent_def.timeout}s")
140
+ self.stdout.write(f" Max Retries: {agent_def.max_retries}")
141
+ self.stdout.write(f" Public: {agent_def.is_public}")
142
+ self.stdout.write(f" Caching: {agent_def.enable_caching}")
143
+ self.stdout.write(f" Created by: {agent_def.created_by.username}")
144
+
145
+ if agent_def.tags:
146
+ self.stdout.write(f" Tags: {', '.join(agent_def.tags)}")
147
+
148
+ if agent_def.description:
149
+ self.stdout.write(f" Description: {agent_def.description}")
150
+
151
+ # Instructions preview
152
+ instructions_preview = agent_def.instructions[:200]
153
+ if len(agent_def.instructions) > 200:
154
+ instructions_preview += "..."
155
+
156
+ self.stdout.write(f" Instructions: {instructions_preview}")
157
+
158
+ except Exception as e:
159
+ raise CommandError(f"Failed to create agent: {e}")
160
+
161
+ async def _get_creator_user(self, username):
162
+ """Get creator user."""
163
+ if username:
164
+ try:
165
+ return await User.objects.aget(username=username)
166
+ except User.DoesNotExist:
167
+ raise CommandError(f"User '{username}' not found")
168
+ else:
169
+ # Use first superuser
170
+ try:
171
+ return await User.objects.filter(is_superuser=True).afirst()
172
+ except User.DoesNotExist:
173
+ raise CommandError("No superuser found. Please create a superuser first or specify --creator")
174
+
175
+
176
+ class Command(BaseCommand):
177
+ """Load agent definitions from templates."""
178
+
179
+ help = 'Load pre-built agent templates'
180
+
181
+ def add_arguments(self, parser):
182
+ """Add command arguments."""
183
+ parser.add_argument(
184
+ '--list',
185
+ action='store_true',
186
+ help='List available templates'
187
+ )
188
+ parser.add_argument(
189
+ '--load',
190
+ type=str,
191
+ nargs='*',
192
+ help='Load specific templates (space-separated names)'
193
+ )
194
+ parser.add_argument(
195
+ '--load-all',
196
+ action='store_true',
197
+ help='Load all available templates'
198
+ )
199
+ parser.add_argument(
200
+ '--creator',
201
+ type=str,
202
+ help='Username of agent creator (defaults to first superuser)'
203
+ )
204
+
205
+ def handle(self, *args, **options):
206
+ """Handle command execution."""
207
+ if options['list']:
208
+ self._list_templates()
209
+ elif options['load'] or options['load_all']:
210
+ asyncio.run(self._load_templates(options))
211
+ else:
212
+ self.stdout.write(
213
+ self.style.ERROR('Please specify --list, --load, or --load-all')
214
+ )
215
+
216
+ def _list_templates(self):
217
+ """List available templates."""
218
+ templates = self._get_available_templates()
219
+
220
+ self.stdout.write(self.style.SUCCESS('šŸ“‹ Available Agent Templates:'))
221
+ self.stdout.write('=' * 40)
222
+
223
+ for category, agents in templates.items():
224
+ self.stdout.write(f"\n{category.upper()}:")
225
+ for agent_name, agent_info in agents.items():
226
+ self.stdout.write(f" • {agent_name}: {agent_info['description']}")
227
+
228
+ async def _load_templates(self, options):
229
+ """Load templates."""
230
+ creator = await self._get_creator_user(options.get('creator'))
231
+ templates = self._get_available_templates()
232
+
233
+ if options['load_all']:
234
+ # Load all templates
235
+ to_load = []
236
+ for category_templates in templates.values():
237
+ to_load.extend(category_templates.keys())
238
+ else:
239
+ to_load = options['load']
240
+
241
+ loaded_count = 0
242
+
243
+ for template_name in to_load:
244
+ # Find template
245
+ template_info = None
246
+ for category_templates in templates.values():
247
+ if template_name in category_templates:
248
+ template_info = category_templates[template_name]
249
+ break
250
+
251
+ if not template_info:
252
+ self.stdout.write(
253
+ self.style.WARNING(f"Template '{template_name}' not found")
254
+ )
255
+ continue
256
+
257
+ # Check if agent already exists
258
+ if await AgentDefinition.objects.filter(name=template_name).aexists():
259
+ self.stdout.write(
260
+ self.style.WARNING(f"Agent '{template_name}' already exists, skipping")
261
+ )
262
+ continue
263
+
264
+ # Create agent
265
+ try:
266
+ agent_data = template_info.copy()
267
+ agent_data['name'] = template_name
268
+ agent_data['created_by'] = creator
269
+
270
+ await AgentDefinition.objects.acreate(**agent_data)
271
+
272
+ self.stdout.write(
273
+ self.style.SUCCESS(f"āœ… Loaded template: {template_name}")
274
+ )
275
+ loaded_count += 1
276
+
277
+ except Exception as e:
278
+ self.stdout.write(
279
+ self.style.ERROR(f"Failed to load template '{template_name}': {e}")
280
+ )
281
+
282
+ self.stdout.write(
283
+ self.style.SUCCESS(f"\nšŸŽ‰ Loaded {loaded_count} agent templates")
284
+ )
285
+
286
+ def _get_available_templates(self):
287
+ """Get available agent templates."""
288
+ return {
289
+ 'content': {
290
+ 'content_analyzer': {
291
+ 'description': 'Analyze content sentiment, topics, and quality',
292
+ 'instructions': 'Analyze content for sentiment, topics, keywords, and quality metrics.',
293
+ 'deps_type': 'ContentDeps',
294
+ 'output_type': 'AnalysisResult',
295
+ 'category': 'content',
296
+ 'model': 'openai:gpt-4o-mini',
297
+ },
298
+ 'content_generator': {
299
+ 'description': 'Generate high-quality content based on requirements',
300
+ 'instructions': 'Generate engaging, well-structured content based on type, audience, and style requirements.',
301
+ 'deps_type': 'ContentDeps',
302
+ 'output_type': 'ProcessResult',
303
+ 'category': 'content',
304
+ 'model': 'openai:gpt-4o-mini',
305
+ },
306
+ 'content_validator': {
307
+ 'description': 'Validate content quality and compliance',
308
+ 'instructions': 'Validate content for grammar, style, accuracy, and guideline compliance.',
309
+ 'deps_type': 'ContentDeps',
310
+ 'output_type': 'ValidationResult',
311
+ 'category': 'content',
312
+ 'model': 'openai:gpt-4o-mini',
313
+ },
314
+ },
315
+ 'data': {
316
+ 'data_processor': {
317
+ 'description': 'Process and transform data',
318
+ 'instructions': 'Process, clean, and transform data according to specifications.',
319
+ 'deps_type': 'DataProcessingDeps',
320
+ 'output_type': 'ProcessResult',
321
+ 'category': 'data',
322
+ 'model': 'openai:gpt-4o-mini',
323
+ },
324
+ 'data_validator': {
325
+ 'description': 'Validate data quality and integrity',
326
+ 'instructions': 'Validate data quality, check for errors, and ensure integrity.',
327
+ 'deps_type': 'DataProcessingDeps',
328
+ 'output_type': 'ValidationResult',
329
+ 'category': 'data',
330
+ 'model': 'openai:gpt-4o-mini',
331
+ },
332
+ },
333
+ 'business': {
334
+ 'business_rules': {
335
+ 'description': 'Apply business rules and logic',
336
+ 'instructions': 'Apply business rules, validate decisions, and ensure compliance.',
337
+ 'deps_type': 'BusinessLogicDeps',
338
+ 'output_type': 'ProcessResult',
339
+ 'category': 'business',
340
+ 'model': 'openai:gpt-4o-mini',
341
+ },
342
+ 'decision_maker': {
343
+ 'description': 'Make decisions based on criteria',
344
+ 'instructions': 'Analyze options and make informed decisions based on criteria and context.',
345
+ 'deps_type': 'BusinessLogicDeps',
346
+ 'output_type': 'ProcessResult',
347
+ 'category': 'business',
348
+ 'model': 'openai:gpt-4o-mini',
349
+ },
350
+ }
351
+ }
352
+
353
+ async def _get_creator_user(self, username):
354
+ """Get creator user."""
355
+ if username:
356
+ try:
357
+ return await User.objects.aget(username=username)
358
+ except User.DoesNotExist:
359
+ raise CommandError(f"User '{username}' not found")
360
+ else:
361
+ # Use first superuser
362
+ try:
363
+ return await User.objects.filter(is_superuser=True).afirst()
364
+ except User.DoesNotExist:
365
+ raise CommandError("No superuser found. Please create a superuser first or specify --creator")
@@ -0,0 +1,191 @@
1
+ """
2
+ Management command to show orchestrator status.
3
+ """
4
+
5
+ import asyncio
6
+ from django.core.management.base import BaseCommand
7
+ from django.utils import timezone
8
+ from datetime import timedelta
9
+
10
+ from django_cfg.modules.django_orchestrator.integration.registry import get_registry
11
+ from django_cfg.modules.django_orchestrator.models.execution import AgentExecution, WorkflowExecution
12
+ from django_cfg.modules.django_orchestrator.models.registry import AgentDefinition
13
+
14
+
15
+ class Command(BaseCommand):
16
+ """Show Django Orchestrator status and statistics."""
17
+
18
+ help = 'Display Django Orchestrator status and statistics'
19
+
20
+ def add_arguments(self, parser):
21
+ """Add command arguments."""
22
+ parser.add_argument(
23
+ '--detailed',
24
+ action='store_true',
25
+ help='Show detailed statistics'
26
+ )
27
+ parser.add_argument(
28
+ '--agents',
29
+ action='store_true',
30
+ help='Show agent-specific statistics'
31
+ )
32
+ parser.add_argument(
33
+ '--recent',
34
+ type=int,
35
+ default=24,
36
+ help='Show statistics for recent hours (default: 24)'
37
+ )
38
+
39
+ def handle(self, *args, **options):
40
+ """Handle command execution."""
41
+ self.stdout.write(
42
+ self.style.SUCCESS('šŸ¤– Django Orchestrator Status')
43
+ )
44
+ self.stdout.write('=' * 50)
45
+
46
+ # Run async operations
47
+ asyncio.run(self._show_status(options))
48
+
49
+ async def _show_status(self, options):
50
+ """Show orchestrator status."""
51
+ # Registry status
52
+ await self._show_registry_status()
53
+
54
+ # Database statistics
55
+ await self._show_database_stats(options['recent'])
56
+
57
+ if options['detailed']:
58
+ await self._show_detailed_stats(options['recent'])
59
+
60
+ if options['agents']:
61
+ await self._show_agent_stats(options['recent'])
62
+
63
+ async def _show_registry_status(self):
64
+ """Show registry status."""
65
+ self.stdout.write('\nšŸ“‹ Registry Status:')
66
+
67
+ registry = get_registry()
68
+ metrics = registry.get_agent_metrics()
69
+
70
+ self.stdout.write(f" Runtime Agents: {metrics['runtime_agents_count']}")
71
+ self.stdout.write(f" Available Patterns: {len(metrics['orchestrator_metrics']['available_patterns'])}")
72
+
73
+ if metrics['agent_names']:
74
+ self.stdout.write(f" Loaded Agents: {', '.join(metrics['agent_names'])}")
75
+ else:
76
+ self.stdout.write(" No agents currently loaded")
77
+
78
+ async def _show_database_stats(self, recent_hours):
79
+ """Show database statistics."""
80
+ self.stdout.write('\nšŸ“Š Database Statistics:')
81
+
82
+ # Total counts
83
+ total_definitions = await AgentDefinition.objects.acount()
84
+ active_definitions = await AgentDefinition.objects.filter(is_active=True).acount()
85
+
86
+ self.stdout.write(f" Agent Definitions: {total_definitions} ({active_definitions} active)")
87
+
88
+ # Recent activity
89
+ since = timezone.now() - timedelta(hours=recent_hours)
90
+
91
+ recent_executions = await AgentExecution.objects.filter(created_at__gte=since).acount()
92
+ recent_workflows = await WorkflowExecution.objects.filter(created_at__gte=since).acount()
93
+
94
+ self.stdout.write(f" Recent Executions ({recent_hours}h): {recent_executions} agents, {recent_workflows} workflows")
95
+
96
+ # Success rates
97
+ total_executions = await AgentExecution.objects.acount()
98
+ successful_executions = await AgentExecution.objects.filter(status='completed').acount()
99
+
100
+ if total_executions > 0:
101
+ success_rate = (successful_executions / total_executions) * 100
102
+ self.stdout.write(f" Overall Success Rate: {success_rate:.1f}%")
103
+
104
+ async def _show_detailed_stats(self, recent_hours):
105
+ """Show detailed statistics."""
106
+ self.stdout.write('\nšŸ“ˆ Detailed Statistics:')
107
+
108
+ since = timezone.now() - timedelta(hours=recent_hours)
109
+
110
+ # Execution status breakdown
111
+ statuses = {}
112
+ async for execution in AgentExecution.objects.filter(created_at__gte=since):
113
+ statuses[execution.status] = statuses.get(execution.status, 0) + 1
114
+
115
+ if statuses:
116
+ self.stdout.write(f" Execution Status (last {recent_hours}h):")
117
+ for status, count in statuses.items():
118
+ self.stdout.write(f" {status.title()}: {count}")
119
+
120
+ # Average execution time
121
+ from django.db.models import Avg
122
+ avg_time = await AgentExecution.objects.filter(
123
+ created_at__gte=since,
124
+ execution_time__isnull=False
125
+ ).aaggregate(avg_time=Avg('execution_time'))
126
+
127
+ if avg_time['avg_time']:
128
+ self.stdout.write(f" Average Execution Time: {avg_time['avg_time']:.2f}s")
129
+
130
+ # Token usage
131
+ from django.db.models import Sum
132
+ token_stats = await AgentExecution.objects.filter(
133
+ created_at__gte=since
134
+ ).aaggregate(
135
+ total_tokens=Sum('tokens_used'),
136
+ total_cost=Sum('cost')
137
+ )
138
+
139
+ if token_stats['total_tokens']:
140
+ self.stdout.write(f" Total Tokens Used: {token_stats['total_tokens']:,}")
141
+
142
+ if token_stats['total_cost']:
143
+ self.stdout.write(f" Total Cost: ${token_stats['total_cost']:.4f}")
144
+
145
+ async def _show_agent_stats(self, recent_hours):
146
+ """Show agent-specific statistics."""
147
+ self.stdout.write('\nšŸ¤– Agent Statistics:')
148
+
149
+ since = timezone.now() - timedelta(hours=recent_hours)
150
+
151
+ # Most used agents
152
+ from django.db.models import Count
153
+ agent_usage = []
154
+
155
+ async for item in AgentExecution.objects.filter(
156
+ created_at__gte=since
157
+ ).values('agent_name').annotate(
158
+ count=Count('id')
159
+ ).order_by('-count')[:10]:
160
+ agent_usage.append((item['agent_name'], item['count']))
161
+
162
+ if agent_usage:
163
+ self.stdout.write(f" Most Used Agents (last {recent_hours}h):")
164
+ for agent_name, count in agent_usage:
165
+ self.stdout.write(f" {agent_name}: {count} executions")
166
+
167
+ # Agent definitions by category
168
+ categories = {}
169
+ async for agent_def in AgentDefinition.objects.filter(is_active=True):
170
+ category = agent_def.category or 'uncategorized'
171
+ categories[category] = categories.get(category, 0) + 1
172
+
173
+ if categories:
174
+ self.stdout.write(" Agents by Category:")
175
+ for category, count in sorted(categories.items()):
176
+ self.stdout.write(f" {category.title()}: {count}")
177
+
178
+ # Registry runtime status
179
+ registry = get_registry()
180
+ runtime_agents = registry.get_runtime_agents()
181
+
182
+ if runtime_agents:
183
+ self.stdout.write(" Runtime Agent Metrics:")
184
+ for agent_name, agent in runtime_agents.items():
185
+ metrics = agent.get_metrics()
186
+ self.stdout.write(
187
+ f" {agent_name}: "
188
+ f"{metrics['execution_count']} runs, "
189
+ f"{metrics['success_rate']:.1%} success, "
190
+ f"{metrics['cache_hit_rate']:.1%} cache hit"
191
+ )
@@ -0,0 +1,23 @@
1
+ """
2
+ Django Agents - Custom model managers.
3
+ """
4
+
5
+ from .execution import AgentExecutionManager, WorkflowExecutionManager
6
+ from .registry import AgentDefinitionManager, AgentTemplateManager
7
+ from .toolsets import ToolExecutionManager, ApprovalLogManager, ToolsetConfigurationManager, ToolPermissionManager
8
+
9
+ __all__ = [
10
+ # Execution managers
11
+ 'AgentExecutionManager',
12
+ 'WorkflowExecutionManager',
13
+
14
+ # Registry managers
15
+ 'AgentDefinitionManager',
16
+ 'AgentTemplateManager',
17
+
18
+ # Toolsets managers
19
+ 'ToolExecutionManager',
20
+ 'ApprovalLogManager',
21
+ 'ToolsetConfigurationManager',
22
+ 'ToolPermissionManager',
23
+ ]