django-cfg 1.1.82__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 (244) 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/twilio_service.py +2 -2
  198. django_cfg/modules/django_unfold/__init__.py +69 -0
  199. django_cfg/modules/{unfold → django_unfold}/callbacks.py +23 -22
  200. django_cfg/modules/django_unfold/dashboard.py +278 -0
  201. django_cfg/modules/django_unfold/icons/README.md +145 -0
  202. django_cfg/modules/django_unfold/icons/__init__.py +12 -0
  203. django_cfg/modules/django_unfold/icons/constants.py +2851 -0
  204. django_cfg/modules/django_unfold/icons/generate_icons.py +486 -0
  205. django_cfg/modules/django_unfold/models/__init__.py +42 -0
  206. django_cfg/modules/django_unfold/models/config.py +601 -0
  207. django_cfg/modules/django_unfold/models/dashboard.py +206 -0
  208. django_cfg/modules/django_unfold/models/dropdown.py +40 -0
  209. django_cfg/modules/django_unfold/models/navigation.py +73 -0
  210. django_cfg/modules/django_unfold/models/tabs.py +25 -0
  211. django_cfg/modules/{unfold → django_unfold}/system_monitor.py +2 -2
  212. django_cfg/modules/django_unfold/utils.py +140 -0
  213. django_cfg/registry/__init__.py +23 -0
  214. django_cfg/registry/core.py +61 -0
  215. django_cfg/registry/exceptions.py +11 -0
  216. django_cfg/registry/modules.py +12 -0
  217. django_cfg/registry/services.py +26 -0
  218. django_cfg/registry/third_party.py +52 -0
  219. django_cfg/routing/__init__.py +19 -0
  220. django_cfg/routing/callbacks.py +198 -0
  221. django_cfg/routing/routers.py +48 -0
  222. django_cfg/templates/admin/layouts/dashboard_with_tabs.html +8 -9
  223. django_cfg/templatetags/__init__.py +0 -0
  224. django_cfg/templatetags/django_cfg.py +33 -0
  225. django_cfg/urls.py +33 -0
  226. django_cfg/utils/path_resolution.py +1 -1
  227. django_cfg/utils/smart_defaults.py +7 -61
  228. django_cfg/utils/toolkit.py +663 -0
  229. {django_cfg-1.1.82.dist-info → django_cfg-1.2.0.dist-info}/METADATA +83 -86
  230. django_cfg-1.2.0.dist-info/RECORD +441 -0
  231. django_cfg/archive/django_sample.zip +0 -0
  232. django_cfg/models/unfold.py +0 -271
  233. django_cfg/modules/unfold/__init__.py +0 -29
  234. django_cfg/modules/unfold/dashboard.py +0 -318
  235. django_cfg/pyproject.toml +0 -370
  236. django_cfg/routers.py +0 -83
  237. django_cfg-1.1.82.dist-info/RECORD +0 -278
  238. /django_cfg/{exceptions.py → core/exceptions.py} +0 -0
  239. /django_cfg/modules/{unfold → django_unfold}/models.py +0 -0
  240. /django_cfg/modules/{unfold → django_unfold}/tailwind.py +0 -0
  241. /django_cfg/{version_check.py → utils/version_check.py} +0 -0
  242. {django_cfg-1.1.82.dist-info → django_cfg-1.2.0.dist-info}/WHEEL +0 -0
  243. {django_cfg-1.1.82.dist-info → django_cfg-1.2.0.dist-info}/entry_points.txt +0 -0
  244. {django_cfg-1.1.82.dist-info → django_cfg-1.2.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,234 @@
1
+ """
2
+ Pre-built content processing agents.
3
+ """
4
+
5
+ from pydantic import BaseModel, Field
6
+ from typing import List, Dict, Any
7
+
8
+ from ..core.agent import DjangoAgent
9
+ from ..core.dependencies import ContentDeps, RunContext
10
+ from ..core.models import AnalysisResult, ProcessResult, ValidationResult
11
+
12
+
13
+ class ContentAnalysisResult(BaseModel):
14
+ """Result from content analysis."""
15
+ sentiment: str = Field(..., description="Sentiment: positive, negative, neutral")
16
+ confidence: float = Field(..., ge=0.0, le=1.0, description="Confidence score")
17
+ topics: List[str] = Field(default_factory=list, description="Extracted topics")
18
+ keywords: List[str] = Field(default_factory=list, description="Key terms")
19
+ summary: str = Field(default="", description="Content summary")
20
+ readability_score: float = Field(default=0.0, ge=0.0, le=100.0)
21
+ word_count: int = Field(default=0, ge=0)
22
+ language: str = Field(default="unknown", description="Detected language")
23
+
24
+
25
+ class ContentGenerationResult(BaseModel):
26
+ """Result from content generation."""
27
+ generated_content: str = Field(..., description="Generated content")
28
+ content_type: str = Field(..., description="Type of generated content")
29
+ word_count: int = Field(..., ge=0, description="Word count")
30
+ quality_score: float = Field(default=0.0, ge=0.0, le=1.0, description="Quality assessment")
31
+ metadata: Dict[str, Any] = Field(default_factory=dict, description="Additional metadata")
32
+
33
+
34
+ def ContentAnalyzerAgent() -> DjangoAgent[ContentDeps, ContentAnalysisResult]:
35
+ """
36
+ Create content analyzer agent.
37
+
38
+ Analyzes content for:
39
+ - Sentiment analysis
40
+ - Topic extraction
41
+ - Keyword identification
42
+ - Readability assessment
43
+ - Language detection
44
+ """
45
+ agent = DjangoAgent[ContentDeps, ContentAnalysisResult](
46
+ name="content_analyzer",
47
+ deps_type=ContentDeps,
48
+ output_type=ContentAnalysisResult,
49
+ instructions="""
50
+ You are a content analysis expert. Analyze the provided content and extract:
51
+
52
+ 1. Sentiment (positive, negative, neutral) with confidence score
53
+ 2. Main topics and themes
54
+ 3. Important keywords and phrases
55
+ 4. Content summary (2-3 sentences)
56
+ 5. Readability assessment (0-100 scale)
57
+ 6. Language detection
58
+
59
+ Be thorough but concise in your analysis.
60
+ """
61
+ )
62
+
63
+ @agent.tool
64
+ async def analyze_text_structure(ctx: RunContext[ContentDeps]) -> Dict[str, Any]:
65
+ """Analyze text structure and formatting."""
66
+ # This would integrate with actual text analysis libraries
67
+ return {
68
+ "paragraphs": 0,
69
+ "sentences": 0,
70
+ "avg_sentence_length": 0.0,
71
+ "complexity_score": 0.0
72
+ }
73
+
74
+ @agent.tool
75
+ async def extract_entities(ctx: RunContext[ContentDeps]) -> List[Dict[str, str]]:
76
+ """Extract named entities from content."""
77
+ # This would integrate with NER libraries
78
+ return [
79
+ {"text": "example", "label": "PERSON", "confidence": 0.95}
80
+ ]
81
+
82
+ @agent.tool
83
+ async def get_content_metadata(ctx: RunContext[ContentDeps]) -> Dict[str, Any]:
84
+ """Get content metadata from dependencies."""
85
+ return {
86
+ "content_id": ctx.deps.content_id,
87
+ "content_type": ctx.deps.content_type,
88
+ "target_audience": ctx.deps.target_audience,
89
+ "user_id": ctx.deps.user.id
90
+ }
91
+
92
+ return agent
93
+
94
+
95
+ def ContentGeneratorAgent() -> DjangoAgent[ContentDeps, ContentGenerationResult]:
96
+ """
97
+ Create content generator agent.
98
+
99
+ Generates content based on:
100
+ - Content type requirements
101
+ - Target audience
102
+ - Style guidelines
103
+ - Length specifications
104
+ """
105
+ agent = DjangoAgent[ContentDeps, ContentGenerationResult](
106
+ name="content_generator",
107
+ deps_type=ContentDeps,
108
+ output_type=ContentGenerationResult,
109
+ instructions="""
110
+ You are a professional content writer. Generate high-quality content based on:
111
+
112
+ 1. Content type (article, blog post, social media, etc.)
113
+ 2. Target audience preferences
114
+ 3. Specified tone and style
115
+ 4. Length requirements
116
+ 5. SEO considerations if applicable
117
+
118
+ Ensure the content is:
119
+ - Engaging and well-structured
120
+ - Appropriate for the target audience
121
+ - Original and creative
122
+ - Grammatically correct
123
+ - Optimized for readability
124
+ """
125
+ )
126
+
127
+ @agent.tool
128
+ async def get_style_guidelines(ctx: RunContext[ContentDeps]) -> Dict[str, Any]:
129
+ """Get style guidelines for content generation."""
130
+ return {
131
+ "tone": "professional",
132
+ "style": "informative",
133
+ "max_words": 1000,
134
+ "include_headers": True,
135
+ "target_audience": ctx.deps.target_audience
136
+ }
137
+
138
+ @agent.tool
139
+ async def check_content_requirements(ctx: RunContext[ContentDeps]) -> Dict[str, Any]:
140
+ """Check content requirements and constraints."""
141
+ return {
142
+ "content_type": ctx.deps.content_type,
143
+ "min_length": 300,
144
+ "max_length": 2000,
145
+ "required_keywords": [],
146
+ "forbidden_topics": []
147
+ }
148
+
149
+ @agent.tool
150
+ async def validate_generated_content(ctx: RunContext[ContentDeps], content: str) -> Dict[str, Any]:
151
+ """Validate generated content quality."""
152
+ word_count = len(content.split())
153
+
154
+ return {
155
+ "word_count": word_count,
156
+ "quality_score": 0.85, # This would be calculated by quality metrics
157
+ "passes_validation": word_count >= 100,
158
+ "suggestions": []
159
+ }
160
+
161
+ return agent
162
+
163
+
164
+ def ContentValidatorAgent() -> DjangoAgent[ContentDeps, ValidationResult]:
165
+ """
166
+ Create content validator agent.
167
+
168
+ Validates content for:
169
+ - Grammar and spelling
170
+ - Style consistency
171
+ - Factual accuracy
172
+ - Compliance with guidelines
173
+ - Plagiarism detection
174
+ """
175
+ agent = DjangoAgent[ContentDeps, ValidationResult](
176
+ name="content_validator",
177
+ deps_type=ContentDeps,
178
+ output_type=ValidationResult,
179
+ instructions="""
180
+ You are a content quality assurance expert. Validate content for:
181
+
182
+ 1. Grammar, spelling, and punctuation errors
183
+ 2. Style consistency and readability
184
+ 3. Factual accuracy and logical flow
185
+ 4. Compliance with content guidelines
186
+ 5. Potential plagiarism or copyright issues
187
+
188
+ Provide specific feedback and suggestions for improvement.
189
+ Mark content as valid only if it meets all quality standards.
190
+ """
191
+ )
192
+
193
+ @agent.tool
194
+ async def check_grammar_spelling(ctx: RunContext[ContentDeps], content: str) -> Dict[str, Any]:
195
+ """Check grammar and spelling."""
196
+ # This would integrate with grammar checking libraries
197
+ return {
198
+ "grammar_errors": [],
199
+ "spelling_errors": [],
200
+ "grammar_score": 0.95,
201
+ "suggestions": []
202
+ }
203
+
204
+ @agent.tool
205
+ async def check_style_consistency(ctx: RunContext[ContentDeps], content: str) -> Dict[str, Any]:
206
+ """Check style consistency."""
207
+ return {
208
+ "style_score": 0.90,
209
+ "inconsistencies": [],
210
+ "tone_analysis": "consistent",
211
+ "readability_grade": 8.5
212
+ }
213
+
214
+ @agent.tool
215
+ async def check_content_guidelines(ctx: RunContext[ContentDeps], content: str) -> Dict[str, Any]:
216
+ """Check compliance with content guidelines."""
217
+ return {
218
+ "guideline_compliance": True,
219
+ "violations": [],
220
+ "compliance_score": 0.98,
221
+ "recommendations": []
222
+ }
223
+
224
+ @agent.tool
225
+ async def check_factual_accuracy(ctx: RunContext[ContentDeps], content: str) -> Dict[str, Any]:
226
+ """Check factual accuracy of content."""
227
+ return {
228
+ "accuracy_score": 0.92,
229
+ "questionable_claims": [],
230
+ "fact_check_results": [],
231
+ "verification_needed": []
232
+ }
233
+
234
+ return agent
@@ -0,0 +1,15 @@
1
+ """
2
+ Django-specific toolsets for agent orchestration.
3
+ """
4
+
5
+ from .django_toolset import DjangoToolset
6
+ from .orm_toolset import ORMToolset
7
+ from .cache_toolset import CacheToolset
8
+ from .file_toolset import FileToolset
9
+
10
+ __all__ = [
11
+ "DjangoToolset",
12
+ "ORMToolset",
13
+ "CacheToolset",
14
+ "FileToolset",
15
+ ]
@@ -0,0 +1,285 @@
1
+ """
2
+ Django cache toolset for caching operations.
3
+ """
4
+
5
+ import logging
6
+ from typing import Any, Optional, Dict, List
7
+ from pydantic_ai.toolsets import AbstractToolset
8
+ from pydantic_ai import RunContext
9
+ from django.core.cache import cache, caches
10
+
11
+ from ..core.dependencies import DjangoDeps
12
+
13
+ logger = logging.getLogger(__name__)
14
+
15
+
16
+ class CacheToolset(AbstractToolset[DjangoDeps]):
17
+ """
18
+ Django cache toolset for caching operations.
19
+
20
+ Provides tools for:
21
+ - Cache get/set operations
22
+ - Cache key management
23
+ - Cache statistics
24
+ - Multi-cache support
25
+ """
26
+
27
+ def __init__(self, cache_alias: str = 'default', key_prefix: str = 'orchestrator'):
28
+ """
29
+ Initialize cache toolset.
30
+
31
+ Args:
32
+ cache_alias: Django cache alias to use
33
+ key_prefix: Prefix for all cache keys
34
+ """
35
+ self.cache_alias = cache_alias
36
+ self.key_prefix = key_prefix
37
+
38
+ @property
39
+ def id(self) -> str:
40
+ return f"django_cache_{self.cache_alias}"
41
+
42
+ def _get_cache(self):
43
+ """Get cache instance."""
44
+ if self.cache_alias == 'default':
45
+ return cache
46
+ else:
47
+ return caches[self.cache_alias]
48
+
49
+ def _make_key(self, key: str, user_id: Optional[int] = None) -> str:
50
+ """Create cache key with prefix and optional user scope."""
51
+ parts = [self.key_prefix]
52
+
53
+ if user_id:
54
+ parts.append(f"user_{user_id}")
55
+
56
+ parts.append(key)
57
+
58
+ return ':'.join(parts)
59
+
60
+ async def get_cached_value(
61
+ self,
62
+ ctx: RunContext[DjangoDeps],
63
+ key: str,
64
+ user_scoped: bool = False
65
+ ) -> Any:
66
+ """Get value from cache."""
67
+ cache_instance = self._get_cache()
68
+
69
+ user_id = ctx.deps.user.id if user_scoped else None
70
+ cache_key = self._make_key(key, user_id)
71
+
72
+ try:
73
+ value = cache_instance.get(cache_key)
74
+ logger.debug(f"Cache get: {cache_key} -> {'HIT' if value is not None else 'MISS'}")
75
+ return value
76
+ except Exception as e:
77
+ logger.error(f"Cache get failed for key '{cache_key}': {e}")
78
+ return None
79
+
80
+ async def set_cached_value(
81
+ self,
82
+ ctx: RunContext[DjangoDeps],
83
+ key: str,
84
+ value: Any,
85
+ timeout: Optional[int] = None,
86
+ user_scoped: bool = False
87
+ ) -> bool:
88
+ """Set value in cache."""
89
+ cache_instance = self._get_cache()
90
+
91
+ user_id = ctx.deps.user.id if user_scoped else None
92
+ cache_key = self._make_key(key, user_id)
93
+
94
+ try:
95
+ cache_instance.set(cache_key, value, timeout)
96
+ logger.debug(f"Cache set: {cache_key} (timeout: {timeout})")
97
+ return True
98
+ except Exception as e:
99
+ logger.error(f"Cache set failed for key '{cache_key}': {e}")
100
+ return False
101
+
102
+ async def delete_cached_value(
103
+ self,
104
+ ctx: RunContext[DjangoDeps],
105
+ key: str,
106
+ user_scoped: bool = False
107
+ ) -> bool:
108
+ """Delete value from cache."""
109
+ cache_instance = self._get_cache()
110
+
111
+ user_id = ctx.deps.user.id if user_scoped else None
112
+ cache_key = self._make_key(key, user_id)
113
+
114
+ try:
115
+ result = cache_instance.delete(cache_key)
116
+ logger.debug(f"Cache delete: {cache_key} -> {result}")
117
+ return bool(result)
118
+ except Exception as e:
119
+ logger.error(f"Cache delete failed for key '{cache_key}': {e}")
120
+ return False
121
+
122
+ async def get_or_set_cached_value(
123
+ self,
124
+ ctx: RunContext[DjangoDeps],
125
+ key: str,
126
+ default_value: Any,
127
+ timeout: Optional[int] = None,
128
+ user_scoped: bool = False
129
+ ) -> Any:
130
+ """Get value from cache or set default if not exists."""
131
+ cache_instance = self._get_cache()
132
+
133
+ user_id = ctx.deps.user.id if user_scoped else None
134
+ cache_key = self._make_key(key, user_id)
135
+
136
+ try:
137
+ value = cache_instance.get_or_set(cache_key, default_value, timeout)
138
+ logger.debug(f"Cache get_or_set: {cache_key}")
139
+ return value
140
+ except Exception as e:
141
+ logger.error(f"Cache get_or_set failed for key '{cache_key}': {e}")
142
+ return default_value
143
+
144
+ async def increment_cached_value(
145
+ self,
146
+ ctx: RunContext[DjangoDeps],
147
+ key: str,
148
+ delta: int = 1,
149
+ user_scoped: bool = False
150
+ ) -> Optional[int]:
151
+ """Increment numeric value in cache."""
152
+ cache_instance = self._get_cache()
153
+
154
+ user_id = ctx.deps.user.id if user_scoped else None
155
+ cache_key = self._make_key(key, user_id)
156
+
157
+ try:
158
+ # Check if cache backend supports increment
159
+ if hasattr(cache_instance, 'incr'):
160
+ try:
161
+ value = cache_instance.incr(cache_key, delta)
162
+ logger.debug(f"Cache increment: {cache_key} += {delta} -> {value}")
163
+ return value
164
+ except ValueError:
165
+ # Key doesn't exist, set initial value
166
+ cache_instance.set(cache_key, delta)
167
+ return delta
168
+ else:
169
+ # Fallback for backends without increment support
170
+ current = cache_instance.get(cache_key, 0)
171
+ new_value = current + delta
172
+ cache_instance.set(cache_key, new_value)
173
+ return new_value
174
+ except Exception as e:
175
+ logger.error(f"Cache increment failed for key '{cache_key}': {e}")
176
+ return None
177
+
178
+ async def get_cache_keys(
179
+ self,
180
+ ctx: RunContext[DjangoDeps],
181
+ pattern: Optional[str] = None,
182
+ user_scoped: bool = False
183
+ ) -> List[str]:
184
+ """Get cache keys matching pattern."""
185
+ cache_instance = self._get_cache()
186
+
187
+ # This is backend-dependent and may not work with all cache backends
188
+ try:
189
+ if hasattr(cache_instance, 'keys'):
190
+ if pattern:
191
+ user_id = ctx.deps.user.id if user_scoped else None
192
+ search_pattern = self._make_key(pattern, user_id)
193
+ keys = cache_instance.keys(search_pattern)
194
+ else:
195
+ keys = cache_instance.keys(f"{self.key_prefix}:*")
196
+
197
+ return list(keys)
198
+ else:
199
+ logger.warning("Cache backend does not support key listing")
200
+ return []
201
+ except Exception as e:
202
+ logger.error(f"Failed to get cache keys: {e}")
203
+ return []
204
+
205
+ async def clear_user_cache(self, ctx: RunContext[DjangoDeps]) -> bool:
206
+ """Clear all cache entries for current user."""
207
+ user_id = ctx.deps.user.id
208
+ pattern = f"{self.key_prefix}:user_{user_id}:*"
209
+
210
+ try:
211
+ keys = await self.get_cache_keys(ctx, pattern="*", user_scoped=True)
212
+
213
+ if keys:
214
+ cache_instance = self._get_cache()
215
+ cache_instance.delete_many(keys)
216
+ logger.info(f"Cleared {len(keys)} cache entries for user {user_id}")
217
+
218
+ return True
219
+ except Exception as e:
220
+ logger.error(f"Failed to clear user cache for user {user_id}: {e}")
221
+ return False
222
+
223
+ async def get_cache_stats(self, ctx: RunContext[DjangoDeps]) -> Dict[str, Any]:
224
+ """Get cache statistics (if supported by backend)."""
225
+ cache_instance = self._get_cache()
226
+
227
+ stats = {
228
+ 'cache_alias': self.cache_alias,
229
+ 'key_prefix': self.key_prefix,
230
+ 'backend': cache_instance.__class__.__name__,
231
+ }
232
+
233
+ try:
234
+ # Try to get backend-specific stats
235
+ if hasattr(cache_instance, '_cache') and hasattr(cache_instance._cache, 'get_stats'):
236
+ # Memcached backend
237
+ backend_stats = cache_instance._cache.get_stats()
238
+ stats['backend_stats'] = backend_stats
239
+ elif hasattr(cache_instance, 'info'):
240
+ # Redis backend
241
+ info = cache_instance.info()
242
+ stats['backend_stats'] = {
243
+ 'used_memory': info.get('used_memory_human'),
244
+ 'connected_clients': info.get('connected_clients'),
245
+ 'total_commands_processed': info.get('total_commands_processed'),
246
+ }
247
+
248
+ # Get key count if possible
249
+ keys = await self.get_cache_keys(ctx)
250
+ stats['total_keys'] = len(keys)
251
+
252
+ except Exception as e:
253
+ logger.warning(f"Could not get cache stats: {e}")
254
+ stats['error'] = str(e)
255
+
256
+ return stats
257
+
258
+ async def touch_cached_value(
259
+ self,
260
+ ctx: RunContext[DjangoDeps],
261
+ key: str,
262
+ timeout: Optional[int] = None,
263
+ user_scoped: bool = False
264
+ ) -> bool:
265
+ """Update cache key timeout without changing value."""
266
+ cache_instance = self._get_cache()
267
+
268
+ user_id = ctx.deps.user.id if user_scoped else None
269
+ cache_key = self._make_key(key, user_id)
270
+
271
+ try:
272
+ if hasattr(cache_instance, 'touch'):
273
+ result = cache_instance.touch(cache_key, timeout)
274
+ logger.debug(f"Cache touch: {cache_key} -> {result}")
275
+ return result
276
+ else:
277
+ # Fallback: get and set with new timeout
278
+ value = cache_instance.get(cache_key)
279
+ if value is not None:
280
+ cache_instance.set(cache_key, value, timeout)
281
+ return True
282
+ return False
283
+ except Exception as e:
284
+ logger.error(f"Cache touch failed for key '{cache_key}': {e}")
285
+ return False