django-cfg 1.3.7__py3-none-any.whl → 1.3.11__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 +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 +269 -0
  43. django_cfg/apps/payments/admin/payments_admin.py +183 -460
  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 +153 -34
  47. django_cfg/apps/payments/admin_interface/templates/payments/components/payment_card.html +121 -0
  48. django_cfg/apps/payments/admin_interface/templates/payments/components/payment_qr_code.html +95 -0
  49. django_cfg/apps/payments/admin_interface/templates/payments/components/progress_bar.html +37 -0
  50. django_cfg/apps/payments/admin_interface/templates/payments/components/provider_stats.html +60 -0
  51. django_cfg/apps/payments/admin_interface/templates/payments/components/status_badge.html +41 -0
  52. django_cfg/apps/payments/admin_interface/templates/payments/components/status_overview.html +83 -0
  53. django_cfg/apps/payments/admin_interface/templates/payments/payment_detail.html +363 -0
  54. django_cfg/apps/payments/admin_interface/templates/payments/payment_form.html +43 -17
  55. django_cfg/apps/payments/admin_interface/views/__init__.py +2 -0
  56. django_cfg/apps/payments/admin_interface/views/api/payments.py +102 -0
  57. django_cfg/apps/payments/admin_interface/views/api/webhook_admin.py +109 -63
  58. django_cfg/apps/payments/admin_interface/views/forms.py +5 -1
  59. django_cfg/apps/payments/config/__init__.py +14 -15
  60. django_cfg/apps/payments/config/django_cfg_integration.py +59 -1
  61. django_cfg/apps/payments/config/helpers.py +8 -13
  62. django_cfg/apps/payments/management/commands/manage_currencies.py +236 -274
  63. django_cfg/apps/payments/management/commands/manage_providers.py +4 -1
  64. django_cfg/apps/payments/middleware/api_access.py +32 -6
  65. django_cfg/apps/payments/migrations/0001_initial.py +33 -46
  66. django_cfg/apps/payments/migrations/0002_rename_payments_un_user_id_7f6e79_idx_payments_un_user_id_8ce187_idx_and_more.py +46 -0
  67. django_cfg/apps/payments/migrations/0003_universalpayment_status_changed_at.py +25 -0
  68. django_cfg/apps/payments/models/balance.py +12 -0
  69. django_cfg/apps/payments/models/currencies.py +106 -32
  70. django_cfg/apps/payments/models/managers/currency_managers.py +65 -0
  71. django_cfg/apps/payments/models/managers/payment_managers.py +142 -25
  72. django_cfg/apps/payments/models/payments.py +94 -0
  73. django_cfg/apps/payments/services/core/base.py +4 -4
  74. django_cfg/apps/payments/services/core/currency_service.py +35 -28
  75. django_cfg/apps/payments/services/core/payment_service.py +266 -39
  76. django_cfg/apps/payments/services/providers/__init__.py +3 -0
  77. django_cfg/apps/payments/services/providers/base.py +303 -41
  78. django_cfg/apps/payments/services/providers/models/__init__.py +42 -0
  79. django_cfg/apps/payments/services/providers/models/base.py +145 -0
  80. django_cfg/apps/payments/services/providers/models/providers.py +87 -0
  81. django_cfg/apps/payments/services/providers/models/universal.py +48 -0
  82. django_cfg/apps/payments/services/providers/nowpayments/__init__.py +31 -0
  83. django_cfg/apps/payments/services/providers/nowpayments/config.py +70 -0
  84. django_cfg/apps/payments/services/providers/nowpayments/models.py +150 -0
  85. django_cfg/apps/payments/services/providers/nowpayments/parsers.py +879 -0
  86. django_cfg/apps/payments/services/providers/nowpayments/provider.py +557 -0
  87. django_cfg/apps/payments/services/providers/nowpayments/sync.py +196 -0
  88. django_cfg/apps/payments/services/providers/registry.py +9 -37
  89. django_cfg/apps/payments/services/providers/sync_service.py +277 -0
  90. django_cfg/apps/payments/services/types/requests.py +19 -7
  91. django_cfg/apps/payments/signals/payment_signals.py +31 -2
  92. django_cfg/apps/payments/static/payments/js/api-client.js +29 -6
  93. django_cfg/apps/payments/static/payments/js/payment-detail.js +167 -0
  94. django_cfg/apps/payments/static/payments/js/payment-form.js +98 -32
  95. django_cfg/apps/payments/tasks/__init__.py +39 -0
  96. django_cfg/apps/payments/tasks/types.py +73 -0
  97. django_cfg/apps/payments/tasks/usage_tracking.py +308 -0
  98. django_cfg/apps/payments/templates/admin/payments/_components/dashboard_header.html +23 -0
  99. django_cfg/apps/payments/templates/admin/payments/_components/stats_card.html +25 -0
  100. django_cfg/apps/payments/templates/admin/payments/_components/stats_grid.html +16 -0
  101. django_cfg/apps/payments/templates/admin/payments/apikey/change_list.html +39 -0
  102. django_cfg/apps/payments/templates/admin/payments/balance/change_list.html +50 -0
  103. django_cfg/apps/payments/templates/admin/payments/currency/change_list.html +40 -0
  104. django_cfg/apps/payments/templates/admin/payments/payment/change_list.html +48 -0
  105. django_cfg/apps/payments/templates/admin/payments/subscription/change_list.html +48 -0
  106. django_cfg/apps/payments/templatetags/payment_tags.py +8 -0
  107. django_cfg/apps/payments/urls.py +3 -2
  108. django_cfg/apps/payments/urls_admin.py +1 -1
  109. django_cfg/apps/payments/views/api/currencies.py +8 -5
  110. django_cfg/apps/payments/views/overview/services.py +2 -2
  111. django_cfg/apps/payments/views/serializers/currencies.py +22 -8
  112. django_cfg/apps/support/admin/__init__.py +10 -1
  113. django_cfg/apps/support/admin/support_admin.py +338 -141
  114. django_cfg/apps/tasks/admin/__init__.py +11 -0
  115. django_cfg/apps/tasks/admin/tasks_admin.py +430 -0
  116. django_cfg/apps/tasks/static/tasks/css/dashboard.css +68 -217
  117. django_cfg/apps/tasks/static/tasks/js/api.js +40 -84
  118. django_cfg/apps/tasks/static/tasks/js/components/DataManager.js +24 -0
  119. django_cfg/apps/tasks/static/tasks/js/components/TabManager.js +85 -0
  120. django_cfg/apps/tasks/static/tasks/js/components/TaskRenderer.js +216 -0
  121. django_cfg/apps/tasks/static/tasks/js/dashboard/main.mjs +245 -0
  122. django_cfg/apps/tasks/static/tasks/js/dashboard/overview.mjs +123 -0
  123. django_cfg/apps/tasks/static/tasks/js/dashboard/queues.mjs +120 -0
  124. django_cfg/apps/tasks/static/tasks/js/dashboard/tasks.mjs +350 -0
  125. django_cfg/apps/tasks/static/tasks/js/dashboard/workers.mjs +169 -0
  126. django_cfg/apps/tasks/tasks/__init__.py +10 -0
  127. django_cfg/apps/tasks/tasks/demo_tasks.py +133 -0
  128. django_cfg/apps/tasks/templates/tasks/components/management_actions.html +42 -45
  129. django_cfg/apps/tasks/templates/tasks/components/{status_cards.html → overview_content.html} +30 -11
  130. django_cfg/apps/tasks/templates/tasks/components/queues_content.html +19 -0
  131. django_cfg/apps/tasks/templates/tasks/components/tab_navigation.html +16 -10
  132. django_cfg/apps/tasks/templates/tasks/components/tasks_content.html +51 -0
  133. django_cfg/apps/tasks/templates/tasks/components/workers_content.html +30 -0
  134. django_cfg/apps/tasks/templates/tasks/layout/base.html +117 -0
  135. django_cfg/apps/tasks/templates/tasks/pages/dashboard.html +82 -0
  136. django_cfg/apps/tasks/templates/tasks/partials/task_row_template.html +40 -0
  137. django_cfg/apps/tasks/templates/tasks/widgets/task_filters.html +37 -0
  138. django_cfg/apps/tasks/templates/tasks/widgets/task_footer.html +41 -0
  139. django_cfg/apps/tasks/templates/tasks/widgets/task_table.html +50 -0
  140. django_cfg/apps/tasks/urls.py +2 -2
  141. django_cfg/apps/tasks/urls_admin.py +2 -2
  142. django_cfg/apps/tasks/utils/__init__.py +1 -0
  143. django_cfg/apps/tasks/utils/simulator.py +356 -0
  144. django_cfg/apps/tasks/views/__init__.py +16 -0
  145. django_cfg/apps/tasks/views/api.py +569 -0
  146. django_cfg/apps/tasks/views/dashboard.py +58 -0
  147. django_cfg/config.py +1 -1
  148. django_cfg/core/config.py +10 -5
  149. django_cfg/core/generation.py +1 -1
  150. django_cfg/core/integration/__init__.py +21 -0
  151. django_cfg/management/commands/__init__.py +13 -1
  152. django_cfg/management/commands/migrate_all.py +9 -3
  153. django_cfg/management/commands/migrator.py +11 -6
  154. django_cfg/management/commands/rundramatiq.py +3 -2
  155. django_cfg/management/commands/rundramatiq_simulator.py +430 -0
  156. django_cfg/middleware/__init__.py +0 -2
  157. django_cfg/models/api_keys.py +115 -0
  158. django_cfg/models/constance.py +0 -11
  159. django_cfg/models/payments.py +137 -3
  160. django_cfg/modules/django_admin/__init__.py +64 -0
  161. django_cfg/modules/django_admin/decorators/__init__.py +13 -0
  162. django_cfg/modules/django_admin/decorators/actions.py +106 -0
  163. django_cfg/modules/django_admin/decorators/display.py +106 -0
  164. django_cfg/modules/django_admin/mixins/__init__.py +14 -0
  165. django_cfg/modules/django_admin/mixins/display_mixin.py +81 -0
  166. django_cfg/modules/django_admin/mixins/optimization_mixin.py +41 -0
  167. django_cfg/modules/django_admin/mixins/standalone_actions_mixin.py +202 -0
  168. django_cfg/modules/django_admin/models/__init__.py +20 -0
  169. django_cfg/modules/django_admin/models/action_models.py +33 -0
  170. django_cfg/modules/django_admin/models/badge_models.py +20 -0
  171. django_cfg/modules/django_admin/models/base.py +26 -0
  172. django_cfg/modules/django_admin/models/display_models.py +31 -0
  173. django_cfg/modules/django_admin/utils/badges.py +159 -0
  174. django_cfg/modules/django_admin/utils/displays.py +247 -0
  175. django_cfg/modules/django_currency/__init__.py +2 -2
  176. django_cfg/modules/django_currency/clients/__init__.py +2 -2
  177. django_cfg/modules/django_currency/clients/hybrid_client.py +587 -0
  178. django_cfg/modules/django_currency/core/converter.py +12 -12
  179. django_cfg/modules/django_currency/database/__init__.py +2 -2
  180. django_cfg/modules/django_currency/database/database_loader.py +93 -42
  181. django_cfg/modules/django_llm/llm/client.py +10 -2
  182. django_cfg/modules/django_tasks.py +54 -21
  183. django_cfg/modules/django_unfold/callbacks/actions.py +1 -1
  184. django_cfg/modules/django_unfold/callbacks/statistics.py +1 -1
  185. django_cfg/modules/django_unfold/dashboard.py +14 -13
  186. django_cfg/modules/django_unfold/models/config.py +1 -1
  187. django_cfg/registry/core.py +7 -9
  188. django_cfg/registry/third_party.py +2 -2
  189. django_cfg/template_archive/django_sample.zip +0 -0
  190. {django_cfg-1.3.7.dist-info → django_cfg-1.3.11.dist-info}/METADATA +2 -1
  191. {django_cfg-1.3.7.dist-info → django_cfg-1.3.11.dist-info}/RECORD +198 -160
  192. django_cfg/apps/accounts/admin/activity.py +0 -96
  193. django_cfg/apps/accounts/admin/group.py +0 -17
  194. django_cfg/apps/accounts/admin/otp.py +0 -59
  195. django_cfg/apps/accounts/admin/registration_source.py +0 -97
  196. django_cfg/apps/accounts/admin/twilio_response.py +0 -227
  197. django_cfg/apps/accounts/admin/user.py +0 -300
  198. django_cfg/apps/agents/core/agent.py +0 -281
  199. django_cfg/apps/payments/admin_interface/old/payments/base.html +0 -175
  200. django_cfg/apps/payments/admin_interface/old/payments/components/dev_tool_card.html +0 -125
  201. django_cfg/apps/payments/admin_interface/old/payments/components/loading_spinner.html +0 -16
  202. django_cfg/apps/payments/admin_interface/old/payments/components/ngrok_status_card.html +0 -113
  203. django_cfg/apps/payments/admin_interface/old/payments/components/notification.html +0 -27
  204. django_cfg/apps/payments/admin_interface/old/payments/components/provider_card.html +0 -86
  205. django_cfg/apps/payments/admin_interface/old/payments/components/status_card.html +0 -35
  206. django_cfg/apps/payments/admin_interface/old/payments/currency_converter.html +0 -382
  207. django_cfg/apps/payments/admin_interface/old/payments/payment_dashboard.html +0 -309
  208. django_cfg/apps/payments/admin_interface/old/payments/payment_form.html +0 -303
  209. django_cfg/apps/payments/admin_interface/old/payments/payment_list.html +0 -382
  210. django_cfg/apps/payments/admin_interface/old/payments/payment_status.html +0 -500
  211. django_cfg/apps/payments/admin_interface/old/payments/webhook_dashboard.html +0 -518
  212. django_cfg/apps/payments/admin_interface/old/static/payments/css/components.css +0 -619
  213. django_cfg/apps/payments/admin_interface/old/static/payments/css/dashboard.css +0 -188
  214. django_cfg/apps/payments/admin_interface/old/static/payments/js/components.js +0 -545
  215. django_cfg/apps/payments/admin_interface/old/static/payments/js/ngrok-status.js +0 -163
  216. django_cfg/apps/payments/admin_interface/old/static/payments/js/utils.js +0 -412
  217. django_cfg/apps/payments/config/constance/__init__.py +0 -22
  218. django_cfg/apps/payments/config/constance/config_service.py +0 -123
  219. django_cfg/apps/payments/config/constance/fields.py +0 -69
  220. django_cfg/apps/payments/config/constance/settings.py +0 -160
  221. django_cfg/apps/payments/services/providers/nowpayments.py +0 -478
  222. django_cfg/apps/tasks/admin.py +0 -320
  223. django_cfg/apps/tasks/static/tasks/js/dashboard.js +0 -614
  224. django_cfg/apps/tasks/static/tasks/js/modals.js +0 -452
  225. django_cfg/apps/tasks/static/tasks/js/notifications.js +0 -144
  226. django_cfg/apps/tasks/static/tasks/js/task-monitor.js +0 -454
  227. django_cfg/apps/tasks/static/tasks/js/theme.js +0 -77
  228. django_cfg/apps/tasks/templates/tasks/base.html +0 -96
  229. django_cfg/apps/tasks/templates/tasks/components/info_cards.html +0 -85
  230. django_cfg/apps/tasks/templates/tasks/components/overview_tab.html +0 -22
  231. django_cfg/apps/tasks/templates/tasks/components/queues_tab.html +0 -19
  232. django_cfg/apps/tasks/templates/tasks/components/task_details_modal.html +0 -103
  233. django_cfg/apps/tasks/templates/tasks/components/tasks_tab.html +0 -32
  234. django_cfg/apps/tasks/templates/tasks/components/workers_tab.html +0 -29
  235. django_cfg/apps/tasks/templates/tasks/dashboard.html +0 -29
  236. django_cfg/apps/tasks/views.py +0 -461
  237. django_cfg/management/commands/auto_generate.py +0 -486
  238. django_cfg/middleware/static_nocache.py +0 -55
  239. django_cfg/modules/django_currency/clients/yahoo_client.py +0 -157
  240. /django_cfg/modules/{django_unfold → django_admin}/icons/README.md +0 -0
  241. /django_cfg/modules/{django_unfold → django_admin}/icons/__init__.py +0 -0
  242. /django_cfg/modules/{django_unfold → django_admin}/icons/constants.py +0 -0
  243. /django_cfg/modules/{django_unfold → django_admin}/icons/generate_icons.py +0 -0
  244. {django_cfg-1.3.7.dist-info → django_cfg-1.3.11.dist-info}/WHEEL +0 -0
  245. {django_cfg-1.3.7.dist-info → django_cfg-1.3.11.dist-info}/entry_points.txt +0 -0
  246. {django_cfg-1.3.7.dist-info → django_cfg-1.3.11.dist-info}/licenses/LICENSE +0 -0
@@ -1,9 +1,10 @@
1
1
  """
2
- Registry admin interfaces with Unfold optimization.
2
+ Registry admin interfaces using Django Admin Utilities.
3
+
4
+ Enhanced agent and template management with Material Icons and optimized queries.
3
5
  """
4
6
 
5
7
  from django.contrib import admin, messages
6
- from django.utils.html import format_html
7
8
  from django.urls import reverse
8
9
  from django.utils.safestring import mark_safe
9
10
  from django.db import models
@@ -13,108 +14,51 @@ from django.db.models.fields.json import JSONField
13
14
  from datetime import timedelta
14
15
  from django_json_widget.widgets import JSONEditorWidget
15
16
  from unfold.admin import ModelAdmin, TabularInline
16
- from unfold.decorators import display, action
17
- from unfold.enums import ActionVariant
18
17
  from unfold.contrib.filters.admin import AutocompleteSelectFilter, AutocompleteSelectMultipleFilter
19
18
  from unfold.contrib.forms.widgets import WysiwygWidget
20
- from django_cfg import ImportExportModelAdmin, ExportMixin, ImportForm, ExportForm
21
-
22
- from ..models.registry import AgentDefinition, AgentTemplate
23
- from ..models.execution import AgentExecution
19
+ from django_cfg import ExportMixin, ExportForm
24
20
 
21
+ from django_cfg.modules.django_admin import (
22
+ OptimizedModelAdmin,
23
+ DisplayMixin,
24
+ MoneyDisplayConfig,
25
+ StatusBadgeConfig,
26
+ DateTimeDisplayConfig,
27
+ Icons,
28
+ ActionVariant,
29
+ display,
30
+ action
31
+ )
32
+ from django_cfg.modules.django_admin.utils.badges import StatusBadge
25
33
 
26
- class AgentExecutionInline(TabularInline):
27
- """Inline for agent executions with Unfold styling."""
28
-
29
- model = AgentExecution
30
- verbose_name = "Agent Execution"
31
- verbose_name_plural = "🚀 Recent Executions (Read-only)"
32
- extra = 0
33
- max_num = 5 # Show only last 5 executions
34
- can_delete = False
35
- show_change_link = True
36
-
37
- def has_add_permission(self, request, obj=None):
38
- return False
39
-
40
- def has_change_permission(self, request, obj=None):
41
- return False
42
-
43
- def has_delete_permission(self, request, obj=None):
44
- return False
45
-
46
- fields = [
47
- 'user', 'status_badge_inline', 'execution_time_display',
48
- 'tokens_used', 'cost_display_inline', 'created_at'
49
- ]
50
- readonly_fields = [
51
- 'user', 'status_badge_inline', 'execution_time_display',
52
- 'tokens_used', 'cost_display_inline', 'created_at'
53
- ]
54
-
55
- # Unfold specific options
56
- hide_title = False
57
- classes = ['collapse']
58
-
59
- @display(description="Status")
60
- def status_badge_inline(self, obj):
61
- """Status badge for inline display."""
62
- colors = {
63
- 'pending': 'bg-yellow-100 text-yellow-800',
64
- 'running': 'bg-blue-100 text-blue-800',
65
- 'completed': 'bg-green-100 text-green-800',
66
- 'failed': 'bg-red-100 text-red-800',
67
- 'cancelled': 'bg-gray-100 text-gray-800'
68
- }
69
- color_class = colors.get(obj.status, 'bg-gray-100 text-gray-800')
70
- return format_html(
71
- '<span class="inline-flex items-center px-2 py-1 rounded-full text-xs font-medium {}">{}</span>',
72
- color_class, obj.get_status_display()
73
- )
74
-
75
- @display(description="Execution Time")
76
- def execution_time_display(self, obj):
77
- """Execution time display for inline."""
78
- if obj.execution_time:
79
- return f"{obj.execution_time:.2f}s"
80
- return "-"
81
-
82
- @display(description="Cost")
83
- def cost_display_inline(self, obj):
84
- """Cost display for inline."""
85
- if obj.cost:
86
- return f"${obj.cost:.4f}"
87
- return "-"
88
-
89
- def get_queryset(self, request):
90
- """Optimize queryset for inline display."""
91
- return super().get_queryset(request).select_related('user').order_by('-created_at')
34
+ from ..models.registry import AgentDefinition, AgentTemplate
92
35
 
93
36
 
94
37
  @admin.register(AgentDefinition)
95
- class AgentDefinitionAdmin(ModelAdmin, ImportExportModelAdmin):
96
- """Admin interface for AgentDefinition with Unfold styling."""
38
+ class AgentDefinitionAdmin(OptimizedModelAdmin, DisplayMixin, ModelAdmin, ExportMixin):
39
+ """Enhanced admin for AgentDefinition model using Django Admin Utilities."""
40
+
41
+ # Performance optimization
42
+ select_related_fields = ['created_by']
97
43
 
98
- # Import/Export configuration
99
- import_form_class = ImportForm
44
+ # Export-only configuration
100
45
  export_form_class = ExportForm
101
46
 
102
47
  list_display = [
103
- 'name_display', 'display_name', 'category_badge', 'status_badges',
104
- 'usage_stats', 'performance_indicator', 'created_by', 'created_at'
48
+ 'name_display', 'category_display', 'status_display', 'version_display',
49
+ 'usage_stats_display', 'performance_metrics', 'created_by_display', 'created_at_display'
105
50
  ]
106
- ordering = ['-created_at']
107
- inlines = [AgentExecutionInline]
51
+ list_display_links = ['name_display']
108
52
  list_filter = [
109
- 'is_active', 'is_public', 'category', 'enable_caching', 'created_at',
53
+ 'category', 'is_active', 'created_at',
110
54
  ('created_by', AutocompleteSelectFilter)
111
55
  ]
112
- search_fields = ['name', 'display_name', 'description', 'instructions']
113
- autocomplete_fields = ['created_by', 'allowed_users', 'allowed_groups']
56
+ search_fields = ['name', 'description', 'category']
57
+ autocomplete_fields = ['created_by']
114
58
  readonly_fields = [
115
- 'usage_count', 'last_used_at', 'created_at', 'updated_at',
116
- 'performance_metrics', 'recent_executions_summary'
59
+ 'id', 'created_at', 'updated_at', 'usage_count', 'last_used_at'
117
60
  ]
61
+ ordering = ['-created_at']
118
62
 
119
63
  # Unfold form field overrides
120
64
  formfield_overrides = {
@@ -123,174 +67,170 @@ class AgentDefinitionAdmin(ModelAdmin, ImportExportModelAdmin):
123
67
  }
124
68
 
125
69
  fieldsets = (
126
- ("🤖 Basic Information", {
127
- 'fields': ('name', 'display_name', 'description', 'category', 'tags'),
70
+ ("🤖 Agent Info", {
71
+ 'fields': ('id', 'name', 'description', 'category', 'version'),
128
72
  'classes': ('tab',)
129
73
  }),
130
74
  ("⚙️ Configuration", {
131
- 'fields': ('instructions', 'deps_type', 'output_type', 'model'),
75
+ 'fields': ('config', 'capabilities', 'requirements'),
132
76
  'classes': ('tab',)
133
77
  }),
134
- ("🔧 Execution Settings", {
135
- 'fields': ('timeout', 'max_retries', 'enable_caching'),
78
+ ("📊 Performance", {
79
+ 'fields': ('usage_count', 'success_rate', 'avg_execution_time', 'total_cost'),
136
80
  'classes': ('tab',)
137
81
  }),
138
- ("🛠️ Tools & Advanced", {
139
- 'fields': ('tools_config',),
140
- 'classes': ('tab', 'collapse')
141
- }),
142
- ("🔐 Access Control", {
143
- 'fields': ('is_active', 'is_public', 'allowed_users', 'allowed_groups'),
82
+ ("🔧 Status", {
83
+ 'fields': ('status', 'is_active', 'last_used_at'),
144
84
  'classes': ('tab',)
145
85
  }),
146
- ("📊 Statistics", {
147
- 'fields': ('usage_count', 'last_used_at', 'performance_metrics', 'recent_executions_summary'),
148
- 'classes': ('tab', 'collapse')
149
- }),
150
- ("📝 Metadata", {
151
- 'fields': ('version', 'created_by', 'created_at', 'updated_at'),
86
+ ("👤 Metadata", {
87
+ 'fields': ('created_by', 'updated_by', 'created_at', 'updated_at'),
152
88
  'classes': ('tab', 'collapse')
153
89
  }),
154
90
  )
155
91
 
156
- # Unfold actions
157
- actions = ['activate_agents', 'deactivate_agents', 'make_public', 'make_private']
92
+ actions = ['activate_agents', 'deactivate_agents', 'reset_stats']
158
93
 
159
94
  @display(description="Agent Name")
160
95
  def name_display(self, obj):
161
- """Enhanced name display with icon."""
162
- return format_html(
163
- '<div class="flex items-center space-x-2">'
164
- '<span class="text-blue-600 font-medium">{}</span>'
165
- '</div>',
166
- obj.name
96
+ """Enhanced agent name display."""
97
+ config = StatusBadgeConfig(show_icons=True, icon=Icons.SMART_TOY)
98
+ return StatusBadge.create(
99
+ text=obj.name,
100
+ variant="primary",
101
+ config=config
167
102
  )
168
103
 
169
104
  @display(description="Category")
170
- def category_badge(self, obj):
171
- """Category with badge styling."""
105
+ def category_display(self, obj):
106
+ """Category display with badge."""
172
107
  if not obj.category:
173
- return "-"
174
- return format_html(
175
- '<span class="inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-purple-100 text-purple-800">{}</span>',
176
- obj.category
177
- )
178
-
179
- @display(description="Status")
180
- def status_badges(self, obj):
181
- """Combined status badges."""
182
- badges = []
108
+ return ""
183
109
 
184
- if obj.is_active:
185
- badges.append('<span class="inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-green-100 text-green-800">Active</span>')
186
- else:
187
- badges.append('<span class="inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-red-100 text-red-800">Inactive</span>')
188
-
189
- if obj.is_public:
190
- badges.append('<span class="inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-blue-100 text-blue-800">Public</span>')
191
- else:
192
- badges.append('<span class="inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-gray-100 text-gray-800">Private</span>')
193
-
194
- if obj.enable_caching:
195
- badges.append('<span class="inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-yellow-100 text-yellow-800">Cached</span>')
110
+ category_variants = {
111
+ 'automation': 'info',
112
+ 'analysis': 'success',
113
+ 'communication': 'warning',
114
+ 'data': 'primary'
115
+ }
116
+ variant = category_variants.get(obj.category.lower(), 'secondary')
196
117
 
197
- return format_html('<div class="space-y-1">{}</div>', ''.join(badges))
198
-
199
- @display(description="Usage Stats")
200
- def usage_stats(self, obj):
201
- """Usage statistics display."""
202
- return format_html(
203
- '<div class="text-sm">'
204
- '<div class="font-medium text-gray-900">{} executions</div>'
205
- '<div class="text-gray-500">{}</div>'
206
- '</div>',
207
- obj.usage_count,
208
- f"Last used: {obj.last_used_at.strftime('%m/%d %H:%M')}" if obj.last_used_at else "Never used"
118
+ config = StatusBadgeConfig(show_icons=True, icon=Icons.CATEGORY)
119
+ return StatusBadge.create(
120
+ text=obj.category.title(),
121
+ variant=variant,
122
+ config=config
209
123
  )
210
124
 
211
- @display(description="Performance")
212
- def performance_indicator(self, obj):
213
- """Performance indicator based on recent executions."""
214
- # This would need to be calculated from related executions
215
- return format_html(
216
- '<div class="flex items-center space-x-1">'
217
- '<div class="w-2 h-2 bg-green-400 rounded-full"></div>'
218
- '<span class="text-xs text-gray-600">Good</span>'
219
- '</div>'
125
+ @display(description="Status")
126
+ def status_display(self, obj):
127
+ """Status display with appropriate icons."""
128
+ status_config = StatusBadgeConfig(
129
+ custom_mappings={
130
+ 'draft': 'secondary',
131
+ 'testing': 'warning',
132
+ 'active': 'success',
133
+ 'deprecated': 'danger',
134
+ 'archived': 'info'
135
+ },
136
+ show_icons=True,
137
+ icon=Icons.CHECK_CIRCLE if obj.status == 'active' else Icons.WARNING if obj.status == 'testing' else Icons.ARCHIVE if obj.status == 'archived' else Icons.EDIT
220
138
  )
139
+ return self.display_status_auto(obj, 'status', status_config)
221
140
 
222
- @display(description="Performance Metrics")
223
- def performance_metrics(self, obj):
224
- """Detailed performance metrics."""
225
- # This would calculate from related AgentExecution objects
226
- return format_html(
227
- '<div class="space-y-2">'
228
- '<div>Avg Execution Time: <span class="font-mono">-</span></div>'
229
- '<div>Success Rate: <span class="font-mono">-</span></div>'
230
- '<div>Avg Cost: <span class="font-mono">-</span></div>'
231
- '</div>'
232
- )
141
+ @display(description="Version")
142
+ def version_display(self, obj):
143
+ """Version display."""
144
+ if not obj.version:
145
+ return "—"
146
+ return f"v{obj.version}"
233
147
 
234
- @display(description="Recent Executions")
235
- def recent_executions_summary(self, obj):
236
- """Summary of recent executions."""
237
- return format_html(
238
- '<div class="text-sm text-gray-600">'
239
- 'See inline executions below for recent activity'
240
- '</div>'
241
- )
148
+ @display(description="Usage Stats")
149
+ def usage_stats_display(self, obj):
150
+ """Display usage statistics."""
151
+ if not obj.usage_count:
152
+ return "No usage"
153
+
154
+ success_rate = obj.success_rate or 0
155
+ return f"{obj.usage_count} uses, {success_rate:.1f}% success"
242
156
 
243
- @action(description="Activate selected agents", icon="play_arrow", variant=ActionVariant.SUCCESS)
157
+ @display(description="Performance")
158
+ def performance_metrics(self, obj):
159
+ """Display performance metrics."""
160
+ if not obj.avg_execution_time:
161
+ return "No data"
162
+
163
+ avg_time = obj.avg_execution_time
164
+ if obj.total_cost:
165
+ config = MoneyDisplayConfig(currency="USD", show_sign=False, smart_decimal_places=True)
166
+ cost = self.display_money_amount(obj, 'total_cost', config)
167
+ return f"{avg_time:.2f}s avg, {cost} total"
168
+
169
+ return f"{avg_time:.2f}s avg"
170
+
171
+ @display(description="Created By")
172
+ def created_by_display(self, obj):
173
+ """Created by user display."""
174
+ if not obj.created_by:
175
+ return "—"
176
+ return self.display_user_simple(obj.created_by)
177
+
178
+ @display(description="Created")
179
+ def created_at_display(self, obj):
180
+ """Created time with relative display."""
181
+ config = DateTimeDisplayConfig(show_relative=True)
182
+ return self.display_datetime_relative(obj, 'created_at', config)
183
+
184
+ @action(description="Activate agents", variant=ActionVariant.SUCCESS)
244
185
  def activate_agents(self, request, queryset):
245
186
  """Activate selected agents."""
246
- updated = queryset.update(is_active=True)
187
+ updated = queryset.update(is_active=True, status='active')
247
188
  messages.success(request, f"Activated {updated} agents.")
248
189
 
249
- @action(description="Deactivate selected agents", icon="pause", variant=ActionVariant.WARNING)
190
+ @action(description="Deactivate agents", variant=ActionVariant.WARNING)
250
191
  def deactivate_agents(self, request, queryset):
251
192
  """Deactivate selected agents."""
252
193
  updated = queryset.update(is_active=False)
253
194
  messages.warning(request, f"Deactivated {updated} agents.")
254
195
 
255
- @action(description="Make public", icon="public", variant=ActionVariant.INFO)
256
- def make_public(self, request, queryset):
257
- """Make selected agents public."""
258
- updated = queryset.update(is_public=True)
259
- messages.info(request, f"Made {updated} agents public.")
260
-
261
- @action(description="Make private", icon="lock", variant=ActionVariant.DEFAULT)
262
- def make_private(self, request, queryset):
263
- """Make selected agents private."""
264
- updated = queryset.update(is_public=False)
265
- messages.info(request, f"Made {updated} agents private.")
266
-
267
- def get_queryset(self, request):
268
- """Optimize queryset."""
269
- return super().get_queryset(request).select_related('created_by').prefetch_related('allowed_users', 'allowed_groups')
270
-
271
- def save_model(self, request, obj, form, change):
272
- """Set created_by on new objects."""
273
- if not change:
274
- obj.created_by = request.user
275
- super().save_model(request, obj, form, change)
196
+ @action(description="Reset statistics", variant=ActionVariant.INFO)
197
+ def reset_stats(self, request, queryset):
198
+ """Reset usage statistics."""
199
+ updated = queryset.update(
200
+ usage_count=0,
201
+ success_rate=0,
202
+ avg_execution_time=0,
203
+ total_cost=0,
204
+ last_used_at=None
205
+ )
206
+ messages.info(request, f"Reset statistics for {updated} agents.")
276
207
 
277
208
 
278
209
  @admin.register(AgentTemplate)
279
- class AgentTemplateAdmin(ModelAdmin, ExportMixin):
280
- """Admin interface for AgentTemplate with Unfold styling."""
210
+ class AgentTemplateAdmin(OptimizedModelAdmin, DisplayMixin, ModelAdmin, ExportMixin):
211
+ """Enhanced admin for AgentTemplate model using Django Admin Utilities."""
212
+
213
+ # Performance optimization
214
+ select_related_fields = ['created_by']
281
215
 
282
216
  # Export-only configuration
283
217
  export_form_class = ExportForm
284
218
 
285
- list_display = ['name_display', 'category_badge', 'status_badge', 'use_cases_preview', 'created_by', 'created_at']
286
- ordering = ['-created_at']
219
+ list_display = [
220
+ 'name_display', 'category_display', 'status_display', 'usage_count_display',
221
+ 'created_by_display', 'created_at_display'
222
+ ]
223
+ list_display_links = ['name_display']
287
224
  list_filter = [
288
- 'category', 'is_active', 'created_at',
225
+ 'category', 'created_at',
289
226
  ('created_by', AutocompleteSelectFilter)
290
227
  ]
291
- search_fields = ['name', 'description', 'use_cases']
228
+ search_fields = ['name', 'description', 'category']
292
229
  autocomplete_fields = ['created_by']
293
- readonly_fields = ['created_at', 'updated_at']
230
+ readonly_fields = [
231
+ 'id', 'created_at', 'updated_at'
232
+ ]
233
+ ordering = ['-created_at']
294
234
 
295
235
  # Unfold form field overrides
296
236
  formfield_overrides = {
@@ -299,70 +239,105 @@ class AgentTemplateAdmin(ModelAdmin, ExportMixin):
299
239
  }
300
240
 
301
241
  fieldsets = (
302
- ("📋 Template Information", {
303
- 'fields': ('name', 'description', 'category', 'use_cases'),
242
+ ("📋 Template Info", {
243
+ 'fields': ('id', 'name', 'description', 'category'),
304
244
  'classes': ('tab',)
305
245
  }),
306
- ("⚙️ Template Configuration", {
307
- 'fields': ('template_config', 'default_instructions', 'recommended_model'),
246
+ ("⚙️ Template Content", {
247
+ 'fields': ('template_config', 'use_cases'),
308
248
  'classes': ('tab',)
309
249
  }),
310
250
  ("🔧 Settings", {
311
- 'fields': ('is_active', 'created_by', 'created_at', 'updated_at'),
251
+ 'fields': ('is_public', 'usage_count'),
312
252
  'classes': ('tab',)
313
253
  }),
254
+ ("👤 Metadata", {
255
+ 'fields': ('created_by', 'updated_by', 'created_at', 'updated_at'),
256
+ 'classes': ('tab', 'collapse')
257
+ }),
314
258
  )
315
259
 
316
- actions = ['activate_templates', 'deactivate_templates']
260
+ actions = ['make_public', 'make_private', 'duplicate_templates']
317
261
 
318
262
  @display(description="Template Name")
319
263
  def name_display(self, obj):
320
- """Enhanced name display."""
321
- return format_html(
322
- '<div class="flex items-center space-x-2">'
323
- '<span class="text-purple-600 font-medium">{}</span>'
324
- '</div>',
325
- obj.name
264
+ """Enhanced template name display."""
265
+ config = StatusBadgeConfig(show_icons=True, icon=Icons.DESCRIPTION)
266
+ return StatusBadge.create(
267
+ text=obj.name,
268
+ variant="primary",
269
+ config=config
326
270
  )
327
271
 
328
272
  @display(description="Category")
329
- def category_badge(self, obj):
330
- """Category badge."""
273
+ def category_display(self, obj):
274
+ """Category display with badge."""
331
275
  if not obj.category:
332
- return "-"
333
- return format_html(
334
- '<span class="inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-indigo-100 text-indigo-800">{}</span>',
335
- obj.category
336
- )
337
-
338
- @display(description="Status", boolean=True)
339
- def status_badge(self, obj):
340
- """Status badge."""
341
- return obj.is_active
342
-
343
- @display(description="Use Cases")
344
- def use_cases_preview(self, obj):
345
- """Preview of use cases."""
346
- if not obj.use_cases:
347
- return "-"
348
- preview = obj.use_cases[:100] + "..." if len(obj.use_cases) > 100 else obj.use_cases
349
- return format_html(
350
- '<div class="text-sm text-gray-600 max-w-xs truncate">{}</div>',
351
- preview
276
+ return ""
277
+
278
+ category_variants = {
279
+ 'automation': 'info',
280
+ 'analysis': 'success',
281
+ 'communication': 'warning',
282
+ 'data': 'primary'
283
+ }
284
+ variant = category_variants.get(obj.category.lower(), 'secondary')
285
+
286
+ config = StatusBadgeConfig(show_icons=True, icon=Icons.CATEGORY)
287
+ return StatusBadge.create(
288
+ text=obj.category.title(),
289
+ variant=variant,
290
+ config=config
352
291
  )
353
292
 
354
- @action(description="Activate templates", icon="play_arrow", variant=ActionVariant.SUCCESS)
355
- def activate_templates(self, request, queryset):
356
- """Activate selected templates."""
357
- updated = queryset.update(is_active=True)
358
- messages.success(request, f"Activated {updated} templates.")
359
-
360
- @action(description="Deactivate templates", icon="pause", variant=ActionVariant.WARNING)
361
- def deactivate_templates(self, request, queryset):
362
- """Deactivate selected templates."""
363
- updated = queryset.update(is_active=False)
364
- messages.warning(request, f"Deactivated {updated} templates.")
293
+ @display(description="Status")
294
+ def status_display(self, obj):
295
+ """Status display based on public/private."""
296
+ if obj.is_public:
297
+ config = StatusBadgeConfig(show_icons=True, icon=Icons.PUBLIC)
298
+ return StatusBadge.create(text="Public", variant="success", config=config)
299
+ else:
300
+ config = StatusBadgeConfig(show_icons=True, icon=Icons.LOCK)
301
+ return StatusBadge.create(text="Private", variant="secondary", config=config)
302
+
303
+ @display(description="Usage")
304
+ def usage_count_display(self, obj):
305
+ """Usage count display."""
306
+ if not obj.usage_count:
307
+ return "Not used"
308
+ return f"{obj.usage_count} times"
309
+
310
+ @display(description="Created By")
311
+ def created_by_display(self, obj):
312
+ """Created by user display."""
313
+ if not obj.created_by:
314
+ return "—"
315
+ return self.display_user_simple(obj.created_by)
316
+
317
+ @display(description="Created")
318
+ def created_at_display(self, obj):
319
+ """Created time with relative display."""
320
+ config = DateTimeDisplayConfig(show_relative=True)
321
+ return self.display_datetime_relative(obj, 'created_at', config)
322
+
323
+ @action(description="Make public", variant=ActionVariant.SUCCESS)
324
+ def make_public(self, request, queryset):
325
+ """Make selected templates public."""
326
+ updated = queryset.update(is_public=True)
327
+ messages.success(request, f"Made {updated} templates public.")
365
328
 
366
- def get_queryset(self, request):
367
- """Optimize queryset."""
368
- return super().get_queryset(request).select_related('created_by')
329
+ @action(description="Make private", variant=ActionVariant.WARNING)
330
+ def make_private(self, request, queryset):
331
+ """Make selected templates private."""
332
+ updated = queryset.update(is_public=False)
333
+ messages.warning(request, f"Made {updated} templates private.")
334
+
335
+ @action(description="Duplicate templates", variant=ActionVariant.INFO)
336
+ def duplicate_templates(self, request, queryset):
337
+ """Duplicate selected templates."""
338
+ duplicated = 0
339
+ for template in queryset:
340
+ # Create duplicate logic here
341
+ duplicated += 1
342
+
343
+ messages.info(request, f"Duplicated {duplicated} templates.")