django-spire 0.18.3__py3-none-any.whl → 0.19.1__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_spire/ai/admin.py +1 -0
  2. django_spire/ai/chat/apps.py +1 -8
  3. django_spire/ai/chat/intelligence/decoders/tools.py +29 -0
  4. django_spire/ai/chat/intelligence/prompts.py +13 -7
  5. django_spire/ai/chat/intelligence/workflows/chat_workflow.py +55 -57
  6. django_spire/ai/chat/models.py +2 -1
  7. django_spire/ai/chat/querysets.py +1 -3
  8. django_spire/ai/chat/responses.py +5 -0
  9. django_spire/ai/chat/templates/django_spire/ai/chat/card/chat_card.html +2 -2
  10. django_spire/ai/chat/templates/django_spire/ai/chat/dropdown/ellipsis_dropdown.html +1 -1
  11. django_spire/ai/chat/templates/django_spire/ai/chat/element/recent_chat_select_element.html +82 -44
  12. django_spire/ai/chat/templates/django_spire/ai/chat/message/loading_response_message.html +9 -4
  13. django_spire/ai/chat/templates/django_spire/ai/chat/message/message.html +33 -33
  14. django_spire/ai/chat/templates/django_spire/ai/chat/message/request_message.html +5 -8
  15. django_spire/ai/chat/templates/django_spire/ai/chat/message/response_message.html +14 -10
  16. django_spire/ai/chat/templates/django_spire/ai/chat/page/chat_page.html +35 -0
  17. django_spire/ai/chat/templates/django_spire/ai/chat/widget/dialog_widget.html +72 -24
  18. django_spire/ai/chat/templates/django_spire/ai/chat/widget/selection_widget.html +42 -0
  19. django_spire/ai/chat/tests/test_urls/test_json_urls.py +4 -2
  20. django_spire/ai/chat/urls/__init__.py +1 -1
  21. django_spire/ai/chat/urls/json_urls.py +1 -1
  22. django_spire/ai/chat/urls/page_urls.py +1 -1
  23. django_spire/ai/chat/urls/{template_urls.py → template/template_urls.py} +1 -1
  24. django_spire/ai/chat/views/json_views.py +4 -3
  25. django_spire/ai/chat/views/message_request_views.py +32 -14
  26. django_spire/ai/chat/views/message_response_views.py +14 -11
  27. django_spire/ai/chat/views/message_views.py +7 -1
  28. django_spire/ai/chat/views/page_views.py +2 -2
  29. django_spire/ai/chat/views/{template_views.py → template/template_views.py} +1 -7
  30. django_spire/ai/context/__init__.py +0 -0
  31. django_spire/ai/context/admin.py +15 -0
  32. django_spire/ai/context/apps.py +16 -0
  33. django_spire/ai/context/choices.py +11 -0
  34. django_spire/ai/context/intelligence/__init__.py +0 -0
  35. django_spire/ai/context/intelligence/prompts/__init__.py +0 -0
  36. django_spire/ai/context/intelligence/prompts/organization_prompts.py +19 -0
  37. django_spire/ai/context/migrations/0001_initial.py +67 -0
  38. django_spire/ai/context/migrations/__init__.py +0 -0
  39. django_spire/ai/context/models.py +67 -0
  40. django_spire/ai/context/querysets.py +15 -0
  41. django_spire/ai/context/seeding/__init__.py +0 -0
  42. django_spire/ai/context/seeding/seed.py +24 -0
  43. django_spire/ai/prompt/system/bots.py +3 -5
  44. django_spire/ai/prompt/tuning/bots.py +5 -10
  45. django_spire/ai/sms/admin.py +2 -0
  46. django_spire/ai/sms/apps.py +2 -7
  47. django_spire/ai/sms/decorators.py +2 -2
  48. django_spire/ai/sms/intelligence/workflows/sms_conversation_workflow.py +18 -18
  49. django_spire/ai/sms/tests/test_webhook.py +5 -4
  50. django_spire/ai/sms/urls.py +3 -0
  51. django_spire/ai/sms/views.py +3 -5
  52. django_spire/ai/urls.py +2 -0
  53. django_spire/auth/templates/django_spire/auth/form/login_form.html +25 -0
  54. django_spire/auth/templates/django_spire/auth/page/auth_page.html +2 -3
  55. django_spire/auth/templates/django_spire/auth/page/login_page.html +1 -25
  56. django_spire/conf.py +1 -3
  57. django_spire/consts.py +1 -7
  58. django_spire/contrib/seeding/intelligence/bots/seeder_generator_bot.py +3 -2
  59. django_spire/contrib/utils.py +2 -0
  60. django_spire/core/management/commands/spire_startapp_pkg/__init__.py +4 -20
  61. django_spire/core/management/commands/spire_startapp_pkg/builder.py +2 -2
  62. django_spire/core/management/commands/spire_startapp_pkg/config.py +2 -2
  63. django_spire/core/management/commands/spire_startapp_pkg/filesystem.py +1 -19
  64. django_spire/core/management/commands/spire_startapp_pkg/generator.py +8 -8
  65. django_spire/core/management/commands/spire_startapp_pkg/processor.py +3 -3
  66. django_spire/core/management/commands/spire_startapp_pkg/registry.py +0 -16
  67. django_spire/core/management/commands/spire_startapp_pkg/reporter.py +1 -21
  68. django_spire/core/management/commands/spire_startapp_pkg/resolver.py +0 -15
  69. django_spire/core/management/commands/spire_startapp_pkg/template/app/views/form_views.py.template +2 -2
  70. django_spire/core/management/commands/spire_startapp_pkg/template/app/views/page_views.py.template +2 -2
  71. django_spire/core/management/commands/spire_startapp_pkg/validator.py +9 -9
  72. django_spire/core/static/django_spire/css/app-button.css +11 -1
  73. django_spire/core/static/django_spire/css/app-import.css +2 -0
  74. django_spire/core/static/django_spire/css/app-layout.css +15 -0
  75. django_spire/core/static/django_spire/css/app-navigation.css +24 -2
  76. django_spire/core/static/django_spire/css/app-page.css +8 -0
  77. django_spire/core/static/django_spire/css/app-side-panel.css +102 -0
  78. django_spire/core/static/django_spire/css/app-text.css +19 -1
  79. django_spire/core/static/django_spire/css/bootstrap-extension.css +128 -7
  80. django_spire/core/static/django_spire/css/bootstrap-override.css +161 -111
  81. django_spire/core/static/django_spire/css/themes/ayu/app-dark.css +0 -4
  82. django_spire/core/static/django_spire/css/themes/ayu/app-light.css +0 -4
  83. django_spire/core/static/django_spire/css/themes/catppuccin/app-dark.css +0 -4
  84. django_spire/core/static/django_spire/css/themes/catppuccin/app-light.css +0 -4
  85. django_spire/core/static/django_spire/css/themes/default/app-dark.css +0 -4
  86. django_spire/core/static/django_spire/css/themes/default/app-light.css +0 -4
  87. django_spire/core/static/django_spire/css/themes/dracula/app-dark.css +0 -4
  88. django_spire/core/static/django_spire/css/themes/dracula/app-light.css +0 -4
  89. django_spire/core/static/django_spire/css/themes/gruvbox/app-dark.css +0 -4
  90. django_spire/core/static/django_spire/css/themes/gruvbox/app-light.css +0 -4
  91. django_spire/core/static/django_spire/css/themes/material/app-dark.css +0 -4
  92. django_spire/core/static/django_spire/css/themes/material/app-light.css +0 -4
  93. django_spire/core/static/django_spire/css/themes/nord/app-dark.css +0 -4
  94. django_spire/core/static/django_spire/css/themes/nord/app-light.css +0 -4
  95. django_spire/core/static/django_spire/css/themes/oceanic-next/app-dark.css +0 -4
  96. django_spire/core/static/django_spire/css/themes/oceanic-next/app-light.css +0 -4
  97. django_spire/core/static/django_spire/css/themes/one-dark/app-dark.css +0 -4
  98. django_spire/core/static/django_spire/css/themes/one-dark/app-light.css +0 -4
  99. django_spire/core/static/django_spire/css/themes/palenight/app-dark.css +0 -4
  100. django_spire/core/static/django_spire/css/themes/palenight/app-light.css +0 -4
  101. django_spire/core/static/django_spire/css/themes/rose-pine/app-dark.css +0 -4
  102. django_spire/core/static/django_spire/css/themes/rose-pine/app-light.css +0 -4
  103. django_spire/core/static/django_spire/css/themes/synthwave/app-dark.css +0 -4
  104. django_spire/core/static/django_spire/css/themes/synthwave/app-light.css +0 -4
  105. django_spire/core/static/django_spire/css/themes/tokyo-night/app-dark.css +0 -4
  106. django_spire/core/static/django_spire/css/themes/tokyo-night/app-light.css +0 -4
  107. django_spire/core/static/django_spire/font/Poppins-Black.ttf +0 -0
  108. django_spire/core/static/django_spire/font/Poppins-BlackItalic.ttf +0 -0
  109. django_spire/core/static/django_spire/font/Poppins-Bold.ttf +0 -0
  110. django_spire/core/static/django_spire/font/Poppins-BoldItalic.ttf +0 -0
  111. django_spire/core/static/django_spire/font/Poppins-ExtraBold.ttf +0 -0
  112. django_spire/core/static/django_spire/font/Poppins-ExtraBoldItalic.ttf +0 -0
  113. django_spire/core/static/django_spire/font/Poppins-ExtraLight.ttf +0 -0
  114. django_spire/core/static/django_spire/font/Poppins-ExtraLightItalic.ttf +0 -0
  115. django_spire/core/static/django_spire/font/Poppins-Italic.ttf +0 -0
  116. django_spire/core/static/django_spire/font/Poppins-Light.ttf +0 -0
  117. django_spire/core/static/django_spire/font/Poppins-LightItalic.ttf +0 -0
  118. django_spire/core/static/django_spire/font/Poppins-Medium.ttf +0 -0
  119. django_spire/core/static/django_spire/font/Poppins-MediumItalic.ttf +0 -0
  120. django_spire/core/static/django_spire/font/Poppins-SemiBold.ttf +0 -0
  121. django_spire/core/static/django_spire/font/Poppins-SemiBoldItalic.ttf +0 -0
  122. django_spire/core/static/django_spire/font/Poppins-Thin.ttf +0 -0
  123. django_spire/core/static/django_spire/font/Poppins-ThinItalic.ttf +0 -0
  124. django_spire/core/static/django_spire/js/ui.js +12 -0
  125. django_spire/core/templates/django_spire/button/base_button.html +1 -1
  126. django_spire/core/templates/django_spire/button/primary_dark_outlined_button.html +3 -0
  127. django_spire/core/templates/django_spire/dropdown/element/dropdown_link_element.html +12 -8
  128. django_spire/core/templates/django_spire/dropdown/element/ellipsis_dropdown_modal_link_element.html +2 -1
  129. django_spire/core/templates/django_spire/dropdown/ellipsis_dropdown.html +2 -1
  130. django_spire/core/templates/django_spire/navigation/accordion/nav_accordion.html +1 -1
  131. django_spire/core/templates/django_spire/navigation/elements/nav_link.html +1 -1
  132. django_spire/core/templates/django_spire/navigation/elements/nav_title_divider.html +1 -1
  133. django_spire/core/templates/django_spire/navigation/side_navigation.html +52 -8
  134. django_spire/core/templates/django_spire/navigation/top_navigation.html +8 -2
  135. django_spire/core/templates/django_spire/page/full_page.html +223 -11
  136. django_spire/core/utils.py +26 -2
  137. django_spire/knowledge/collection/models.py +24 -0
  138. django_spire/knowledge/collection/services/transformation_service.py +2 -1
  139. django_spire/knowledge/collection/tests/test_services/test_transformation_service.py +44 -42
  140. django_spire/knowledge/collection/urls/form_urls.py +1 -0
  141. django_spire/knowledge/collection/urls/page_urls.py +1 -0
  142. django_spire/knowledge/collection/views/form_views.py +13 -2
  143. django_spire/knowledge/collection/views/page_views.py +36 -4
  144. django_spire/knowledge/entry/models.py +32 -0
  145. django_spire/knowledge/entry/services/transformation_services.py +10 -10
  146. django_spire/knowledge/entry/version/block/data/data.py +2 -1
  147. django_spire/knowledge/entry/version/block/data/heading_data.py +2 -2
  148. django_spire/knowledge/entry/version/block/data/list/data.py +3 -4
  149. django_spire/knowledge/entry/version/block/data/maps.py +3 -5
  150. django_spire/knowledge/entry/version/block/data/text_data.py +2 -2
  151. django_spire/knowledge/entry/version/block/models.py +10 -7
  152. django_spire/knowledge/entry/version/block/services/factory_service.py +11 -10
  153. django_spire/knowledge/entry/version/block/tests/factories.py +6 -5
  154. django_spire/knowledge/entry/version/converters/docx_converter.py +1 -1
  155. django_spire/knowledge/entry/version/intelligence/bots/markdown_format_llm_bot.py +14 -12
  156. django_spire/knowledge/entry/version/seeding/seeder.py +3 -3
  157. django_spire/knowledge/entry/version/services/processor_service.py +36 -10
  158. django_spire/knowledge/entry/version/tests/test_converters/test_docx_converter.py +1 -1
  159. django_spire/knowledge/entry/version/tests/test_urls/test_page_urls.py +1 -1
  160. django_spire/knowledge/entry/version/urls/page_urls.py +1 -1
  161. django_spire/knowledge/entry/version/views/json_views.py +5 -3
  162. django_spire/knowledge/entry/version/views/page_views.py +11 -12
  163. django_spire/knowledge/entry/version/views/redirect_views.py +1 -1
  164. django_spire/knowledge/entry/views/form_views.py +1 -1
  165. django_spire/knowledge/intelligence/bots/entry_search_llm_bot.py +33 -11
  166. django_spire/knowledge/intelligence/decoders/__init__.py +0 -0
  167. django_spire/knowledge/intelligence/{maps/collection_map.py → decoders/collection_decoder.py} +5 -5
  168. django_spire/knowledge/intelligence/{maps/entry_map.py → decoders/entry_decoder.py} +3 -3
  169. django_spire/knowledge/intelligence/intel/collection_intel.py +1 -0
  170. django_spire/knowledge/intelligence/intel/entry_intel.py +5 -2
  171. django_spire/knowledge/intelligence/intel/message_intel.py +2 -0
  172. django_spire/knowledge/intelligence/workflows/knowledge_workflow.py +43 -51
  173. django_spire/knowledge/migrations/0007_alter_collection_options.py +17 -0
  174. django_spire/knowledge/static/django_spire/knowledge/entry/version/js/editor.js +24 -5
  175. django_spire/knowledge/templates/django_spire/knowledge/collection/card/top_level_list_card.html +21 -0
  176. django_spire/knowledge/templates/django_spire/knowledge/collection/component/x_collection_navigation.html +15 -6
  177. django_spire/knowledge/templates/django_spire/knowledge/collection/element/ellipsis_dropdown.html +22 -0
  178. django_spire/knowledge/templates/django_spire/knowledge/collection/form/form.html +21 -9
  179. django_spire/knowledge/templates/django_spire/knowledge/collection/item/collection_item.html +19 -0
  180. django_spire/knowledge/templates/django_spire/knowledge/collection/page/display_page.html +49 -0
  181. django_spire/knowledge/templates/django_spire/knowledge/collection/page/form_page.html +1 -1
  182. django_spire/knowledge/templates/django_spire/knowledge/container/container.html +33 -0
  183. django_spire/knowledge/templates/django_spire/knowledge/entry/file/page/list_page.html +1 -1
  184. django_spire/knowledge/templates/django_spire/knowledge/entry/item/list_item.html +2 -2
  185. django_spire/knowledge/templates/django_spire/knowledge/entry/page/form_page.html +1 -1
  186. django_spire/knowledge/templates/django_spire/knowledge/entry/page/import_form_page.html +1 -1
  187. django_spire/knowledge/templates/django_spire/knowledge/entry/version/container/detail_container.html +51 -45
  188. django_spire/knowledge/templates/django_spire/knowledge/entry/version/page/editor_page.html +54 -0
  189. django_spire/knowledge/templates/django_spire/knowledge/entry/version/page/form_page.html +1 -1
  190. django_spire/knowledge/templates/django_spire/knowledge/message/knowledge_message_intel.html +18 -1
  191. django_spire/knowledge/templates/django_spire/knowledge/page/full_page.html +37 -0
  192. django_spire/knowledge/templates/django_spire/knowledge/page/home_page.html +2 -2
  193. django_spire/knowledge/templates/django_spire/knowledge/sub_navigation/item/collection_sub_navigation_item.html +29 -0
  194. django_spire/knowledge/templates/django_spire/knowledge/sub_navigation/item/entry_sub_navigation_item.html +20 -0
  195. django_spire/knowledge/templates/django_spire/knowledge/{navigation/content/navigation_content.html → sub_navigation/widget/collection_entry_sub_navigation_widget.html} +42 -19
  196. django_spire/knowledge/views/page_views.py +4 -4
  197. django_spire/settings.py +3 -3
  198. django_spire/theme/templates/django_spire/theme/card/badges_preview_card.html +0 -1
  199. django_spire/theme/templates/django_spire/theme/card/base_preview_card.html +1 -0
  200. django_spire/theme/templates/django_spire/theme/card/typography_preview_card.html +1 -1
  201. django_spire/theme/templates/django_spire/theme/example/form/example_form.html +2 -0
  202. django_spire/theme/templates/django_spire/theme/example/form/example_form_card.html +5 -0
  203. django_spire/theme/templates/django_spire/theme/page/badges_page.html +7 -9
  204. django_spire/theme/templates/django_spire/theme/page/borders_page.html +6 -9
  205. django_spire/theme/templates/django_spire/theme/page/buttons_page.html +6 -9
  206. django_spire/theme/templates/django_spire/theme/page/colors_page.html +6 -6
  207. django_spire/theme/templates/django_spire/theme/page/dashboard_page.html +57 -0
  208. django_spire/theme/templates/django_spire/theme/page/django_glue_page.html +7 -9
  209. django_spire/theme/templates/django_spire/theme/page/theme_page.html +24 -0
  210. django_spire/theme/templates/django_spire/theme/page/typography_page.html +6 -9
  211. django_spire/theme/templates/django_spire/theme/section/badge_section_card.html +5 -0
  212. django_spire/theme/templates/django_spire/theme/section/border_section_card.html +5 -0
  213. django_spire/theme/templates/django_spire/theme/section/button_section.html +1 -0
  214. django_spire/theme/templates/django_spire/theme/section/button_section_card.html +5 -0
  215. django_spire/theme/templates/django_spire/theme/section/color_section.html +10 -10
  216. django_spire/theme/templates/django_spire/theme/section/color_section_card.html +5 -0
  217. django_spire/theme/templates/django_spire/theme/section/typography_section.html +41 -1
  218. django_spire/theme/templates/django_spire/theme/section/typography_section_card.html +5 -0
  219. {django_spire-0.18.3.dist-info → django_spire-0.19.1.dist-info}/METADATA +3 -3
  220. {django_spire-0.18.3.dist-info → django_spire-0.19.1.dist-info}/RECORD +229 -190
  221. django_spire/ai/chat/intelligence/bots/chat_bot.py +0 -8
  222. django_spire/ai/chat/intelligence/maps/intent_llm_map.py +0 -10
  223. django_spire/ai/chat/templates/django_spire/ai/chat/page/home_page.html +0 -9
  224. django_spire/ai/chat/templates/django_spire/ai/chat/widget/chat_widget.html +0 -64
  225. django_spire/ai/chat/templates/django_spire/ai/chat/widget/search_chat_results_widget.html +0 -25
  226. django_spire/ai/chat/templates/django_spire/ai/chat/widget/search_chat_widget.html +0 -39
  227. django_spire/ai/chat/templates/django_spire/ai/chat/widget/select_chat_widget.html +0 -24
  228. django_spire/ai/chat/tools.py +0 -57
  229. django_spire/ai/sms/tools.py +0 -57
  230. django_spire/core/static/django_spire/font/Karla-Bold.ttf +0 -0
  231. django_spire/core/static/django_spire/font/Merriweather.ttf +0 -0
  232. django_spire/knowledge/context_processors.py +0 -18
  233. django_spire/knowledge/templates/django_spire/knowledge/entry/version/page/detail_page.html +0 -25
  234. django_spire/knowledge/templates/django_spire/knowledge/navigation/card/navigation_card.html +0 -9
  235. django_spire/knowledge/templates/django_spire/knowledge/navigation/item/collection/collection_item.html +0 -29
  236. django_spire/knowledge/templates/django_spire/knowledge/navigation/item/entry/entry_item.html +0 -18
  237. django_spire/knowledge/templates/django_spire/knowledge/navigation/page/full_page.html +0 -90
  238. /django_spire/ai/chat/intelligence/{bots → decoders}/__init__.py +0 -0
  239. /django_spire/ai/chat/{intelligence/maps → urls/template}/__init__.py +0 -0
  240. /django_spire/{knowledge/intelligence/maps → ai/chat/views/template}/__init__.py +0 -0
  241. /django_spire/knowledge/entry/version/{constants.py → consts.py} +0 -0
  242. /django_spire/knowledge/templates/django_spire/knowledge/{navigation/item/collection/dropdown/navigation_ellipsis_dropdown.html → sub_navigation/element/collection_sub_navigation_ellipsis_dropdown.html} +0 -0
  243. /django_spire/knowledge/templates/django_spire/knowledge/{navigation/item/entry/dropdown/navigation_ellipsis_dropdown.html → sub_navigation/element/entry_sub_navigation_ellipsis_dropdown.html} +0 -0
  244. {django_spire-0.18.3.dist-info → django_spire-0.19.1.dist-info}/WHEEL +0 -0
  245. {django_spire-0.18.3.dist-info → django_spire-0.19.1.dist-info}/licenses/LICENSE.md +0 -0
  246. {django_spire-0.18.3.dist-info → django_spire-0.19.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,67 @@
1
+ from __future__ import annotations
2
+
3
+ from django.core.exceptions import ValidationError
4
+ from django.db import models
5
+
6
+ from django_spire.ai.context import querysets
7
+ from django_spire.ai.context.choices import PersonRoleChoices
8
+ from django_spire.auth.user.models import AuthUser
9
+ from django_spire.history.mixins import HistoryModelMixin
10
+
11
+
12
+ class Organization(HistoryModelMixin):
13
+ name = models.CharField(max_length=255, blank=True, null=True)
14
+ legal_name = models.CharField(max_length=255, blank=True, null=True)
15
+ description = models.TextField(blank=True, null=True)
16
+ sector = models.CharField(max_length=255, blank=True, null=True)
17
+ sub_sector = models.CharField(max_length=255, blank=True, null=True)
18
+ website = models.URLField(max_length=255, blank=True, null=True)
19
+ street_address = models.CharField(max_length=255, blank=True, null=True)
20
+ unit_number = models.CharField(max_length=32, blank=True, null=True)
21
+ city = models.CharField(max_length=255, blank=True, null=True)
22
+ province = models.CharField(max_length=255, blank=True, null=True)
23
+ postal_code = models.CharField(max_length=16, blank=True, null=True)
24
+ country = models.CharField(max_length=255, blank=True, null=True)
25
+ phone = models.CharField(max_length=255, blank=True, null=True)
26
+ email = models.EmailField(max_length=255, blank=True, null=True)
27
+
28
+ objects = querysets.OrganizationQuerySet.as_manager()
29
+
30
+ def save(self, *args, **kwargs) -> None:
31
+ if self.pk is None:
32
+ if self.__class__.objects.exists():
33
+ message = 'Only one AI Organization Context is allowed'
34
+ raise ValidationError(message)
35
+
36
+ return super().save(*args, **kwargs)
37
+
38
+ class Meta:
39
+ db_table = 'django_spire_ai_context_organization'
40
+ verbose_name = 'Organization Context'
41
+ verbose_name_plural = 'Organization Context'
42
+
43
+
44
+ class Person(HistoryModelMixin):
45
+ is_internal_to_organization = models.BooleanField(default=True)
46
+ user = models.ForeignKey(
47
+ AuthUser,
48
+ blank=True,
49
+ null=True,
50
+ on_delete=models.SET_NULL,
51
+ related_name='ai_context_people',
52
+ related_query_name='ai_context_person'
53
+ )
54
+ role = models.CharField(max_length=16, choices=PersonRoleChoices, default=PersonRoleChoices.ADMIN)
55
+ role_details = models.TextField(blank=True, null=True)
56
+ first_name = models.CharField(max_length=255, blank=True, null=True)
57
+ last_name = models.CharField(max_length=255, blank=True, null=True)
58
+ phone = models.CharField(max_length=255, blank=True, null=True)
59
+ email = models.EmailField(max_length=255, blank=True, null=True)
60
+
61
+ objects = querysets.PeopleQuerySet.as_manager()
62
+
63
+ class Meta:
64
+ db_table = 'django_spire_ai_context_person'
65
+ verbose_name = 'Person Context'
66
+ verbose_name_plural = 'People Context'
67
+
@@ -0,0 +1,15 @@
1
+ from __future__ import annotations
2
+
3
+ from django_spire.history.querysets import HistoryQuerySet
4
+
5
+
6
+ class OrganizationQuerySet(HistoryQuerySet):
7
+ def get_only_or_none(self):
8
+ try:
9
+ return self.earliest('id')
10
+ except self.model.DoesNotExist:
11
+ return None
12
+
13
+
14
+ class PeopleQuerySet(HistoryQuerySet):
15
+ pass
File without changes
@@ -0,0 +1,24 @@
1
+ from __future__ import annotations
2
+
3
+ from django_spire.ai.context import models
4
+ from django_spire.ai.context import choices
5
+
6
+ from faker import Faker
7
+
8
+
9
+ models.Organization.objects.create(
10
+ name='Spire Candy',
11
+ legal_name='Spire Candy Processors Limited',
12
+ )
13
+
14
+ for people_role_choice in choices.PersonRoleChoices:
15
+ first_name = Faker().first_name()
16
+ last_name = Faker().last_name()
17
+
18
+ people = models.Person.objects.create(
19
+ role=people_role_choice.value,
20
+ first_name=first_name,
21
+ last_name=last_name,
22
+ email=f'{first_name.lower()}.{last_name.lower()}@spirecandy.ca',
23
+ phone=Faker().phone_number(),
24
+ )
@@ -1,10 +1,8 @@
1
1
  from __future__ import annotations
2
2
 
3
- from dandy import Bot, LlmConfigOptions, recorder_to_html_file
3
+ from dandy import Bot, LlmConfigOptions
4
4
 
5
- from django_spire.ai.prompt.system import prompts
6
- from django_spire.ai.prompt.system import intel
7
- from django_spire.ai.prompt.system.intel import SystemPromptIntel
5
+ from django_spire.ai.prompt.system import intel, prompts
8
6
 
9
7
 
10
8
  class RoleSystemPromptBot(Bot):
@@ -70,7 +68,7 @@ class SystemPromptBot(Bot):
70
68
  guidelines = guidelines_bot.process(user_story)
71
69
  output_format = output_format_bot.process(user_story)
72
70
 
73
- return SystemPromptIntel(
71
+ return intel.SystemPromptIntel(
74
72
  role=role.result,
75
73
  task=task.result,
76
74
  guidelines=guidelines.result,
@@ -65,8 +65,7 @@ class FormattingBot(Bot):
65
65
  def process(self, system_prompt: str) -> intel.PromptTuningIntel:
66
66
  return self.llm.prompt_to_intel(
67
67
  prompt=prompts.specialized_bot_input_prompt(system_prompt),
68
- intel_class=intel.PromptTuningIntel,
69
- postfix_system_prompt=None
68
+ intel_class=intel.PromptTuningIntel
70
69
  )
71
70
 
72
71
 
@@ -76,8 +75,7 @@ class InstructionClarityBot(Bot):
76
75
  def process(self, system_prompt: str) -> intel.PromptTuningIntel:
77
76
  return self.llm.prompt_to_intel(
78
77
  prompt=prompts.specialized_bot_input_prompt(system_prompt),
79
- intel_class=intel.PromptTuningIntel,
80
- postfix_system_prompt=None
78
+ intel_class=intel.PromptTuningIntel
81
79
  )
82
80
 
83
81
 
@@ -87,8 +85,7 @@ class PersonaBot(Bot):
87
85
  def process(self, system_prompt: str) -> intel.PromptTuningIntel:
88
86
  return self.llm.prompt_to_intel(
89
87
  prompt=prompts.specialized_bot_input_prompt(system_prompt),
90
- intel_class=intel.PromptTuningIntel,
91
- postfix_system_prompt=None
88
+ intel_class=intel.PromptTuningIntel
92
89
  )
93
90
 
94
91
 
@@ -98,8 +95,7 @@ class DuplicationRemovalBot(Bot):
98
95
  def process(self, system_prompt: str) -> intel.PromptTuningIntel:
99
96
  return self.llm.prompt_to_intel(
100
97
  prompt=prompts.specialized_bot_input_prompt(system_prompt),
101
- intel_class=intel.PromptTuningIntel,
102
- postfix_system_prompt=None
98
+ intel_class=intel.PromptTuningIntel
103
99
  )
104
100
 
105
101
 
@@ -109,6 +105,5 @@ class ExampleOptimizationBot(Bot):
109
105
  def process(self, system_prompt: str) -> intel.PromptTuningIntel:
110
106
  return self.llm.prompt_to_intel(
111
107
  prompt=prompts.specialized_bot_input_prompt(system_prompt),
112
- intel_class=intel.PromptTuningIntel,
113
- postfix_system_prompt=None
108
+ intel_class=intel.PromptTuningIntel
114
109
  )
@@ -25,11 +25,13 @@ class SmsConversationAdmin(admin.ModelAdmin):
25
25
 
26
26
  def view_sms_messages_link(self, obj):
27
27
  count = obj.messages.count()
28
+
28
29
  url = (
29
30
  reverse("admin:django_spire_ai_sms_smsmessage_changelist")
30
31
  + "?"
31
32
  + urlencode({"sms_conversation__id": f"{obj.id}"})
32
33
  )
34
+
33
35
  return format_html('<a href="%s">%s Messages</a>' % (url, count))
34
36
 
35
37
  view_sms_messages_link.short_description = "Messages"
@@ -1,9 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from django.apps import AppConfig
4
- from django.conf import settings
5
4
 
6
- from django_spire.consts import AI_SMS_CONVERSATION_WORKFLOW_CLASS_SETTINGS_NAME
7
5
  from django_spire.utils import check_required_apps
8
6
 
9
7
 
@@ -12,10 +10,7 @@ class SmsConfig(AppConfig):
12
10
  name = 'django_spire.ai.sms'
13
11
  label = 'django_spire_ai_sms'
14
12
 
15
- REQUIRED_APPS = ('django_spire_ai',)
16
-
17
- def ready(self):
18
- if not isinstance(getattr(settings, AI_SMS_CONVERSATION_WORKFLOW_CLASS_SETTINGS_NAME), str):
19
- raise ValueError(f'"{AI_SMS_CONVERSATION_WORKFLOW_CLASS_SETTINGS_NAME}" must be set in the django settings when using "{self.label}".')
13
+ REQUIRED_APPS = ('django_spire_ai', 'django_spire_ai_context')
20
14
 
15
+ def ready(self) -> None:
21
16
  check_required_apps(self.label)
@@ -25,7 +25,7 @@ def twilio_auth_required(func):
25
25
 
26
26
  if request_valid:
27
27
  return func(request, *args, **kwargs)
28
- else:
29
- return HttpResponseForbidden()
28
+
29
+ return HttpResponseForbidden()
30
30
 
31
31
  return decorated_function
@@ -1,27 +1,27 @@
1
1
  from __future__ import annotations
2
2
 
3
+ from typing import TYPE_CHECKING
4
+
3
5
  from dandy.recorder import recorder_to_html_file
4
- from dandy.llm.request.message import MessageHistory
5
- from django.core.handlers.wsgi import WSGIRequest
6
6
 
7
- from django_spire.ai.chat.intelligence.workflows.chat_workflow import SpireChatWorkflow
7
+ from django_spire.ai.chat.intelligence.workflows.chat_workflow import chat_workflow
8
8
  from django_spire.ai.sms.intel import SmsIntel
9
9
 
10
+ if TYPE_CHECKING:
11
+ from django.core.handlers.wsgi import WSGIRequest
12
+ from dandy.llm.request.message import MessageHistory
13
+
10
14
 
11
- class SpireSmsConversationWorkflow:
12
- @staticmethod
13
- @recorder_to_html_file('sms_workflow')
14
- def process(
15
- request: WSGIRequest,
16
- user_input: str,
17
- message_history: MessageHistory | None = None
18
- ) -> SmsIntel:
19
- return SmsIntel(
20
- body=str(
21
- SpireChatWorkflow.process(
22
- request,
23
- user_input=user_input,
24
- message_history=message_history,
25
- )
15
+ @recorder_to_html_file('spire_ai_sms_conversation_workflow')
16
+ def sms_conversation_workflow(
17
+ request: WSGIRequest, user_input: str, message_history: MessageHistory | None = None, actor: str | None = None
18
+ ) -> SmsIntel:
19
+ return SmsIntel(
20
+ body=str(
21
+ chat_workflow(
22
+ request,
23
+ user_input=user_input,
24
+ message_history=message_history,
26
25
  )
27
26
  )
27
+ )
@@ -1,14 +1,15 @@
1
1
  from unittest.mock import patch
2
2
 
3
- from django.test import TestCase, Client
4
3
  from django.urls import reverse
5
4
 
6
5
  from django_spire.ai.sms.models import SmsConversation
6
+ from django_spire.core.tests.test_cases import BaseTestCase
7
7
 
8
8
 
9
- class SmsWebhookTests(TestCase):
9
+ class SmsWebhookTests(BaseTestCase):
10
10
  def setUp(self):
11
- self.client = Client()
11
+ super().setUp()
12
+
12
13
  self.webhook_url = reverse('django_spire:ai:sms:webhook')
13
14
 
14
15
  @patch('twilio.request_validator.RequestValidator.validate')
@@ -34,4 +35,4 @@ class SmsWebhookTests(TestCase):
34
35
  self.assertEqual(inbound_message.twilio_sid, 'SM123456789')
35
36
 
36
37
  outbound_message = conversation.messages.filter(is_inbound=False).first()
37
- self.assertTrue(len(outbound_message.body) > 0)
38
+ self.assertTrue(len(outbound_message.body) > 0)
@@ -1,7 +1,10 @@
1
+ from __future__ import annotations
2
+
1
3
  from django.urls import path
2
4
 
3
5
  from django_spire.ai.sms import views
4
6
 
7
+
5
8
  app_name = 'sms'
6
9
 
7
10
  urlpatterns = [
@@ -6,8 +6,8 @@ from django.views.decorators.http import require_POST
6
6
  from twilio.twiml.messaging_response import MessagingResponse
7
7
 
8
8
  from django_spire.ai.sms.decorators import twilio_auth_required
9
+ from django_spire.ai.sms.intelligence.workflows.sms_conversation_workflow import sms_conversation_workflow
9
10
  from django_spire.ai.sms.models import SmsConversation
10
- from django_spire.ai.sms.tools import sms_workflow_process
11
11
 
12
12
 
13
13
  @csrf_exempt
@@ -22,7 +22,7 @@ def webhook_view(request):
22
22
  body = request.POST.get('Body', '')
23
23
  message_sid = request.POST.get('MessageSid', '')
24
24
 
25
- conversation, created = SmsConversation.objects.get_or_create(
25
+ conversation, _ = SmsConversation.objects.get_or_create(
26
26
  phone_number=from_number
27
27
  )
28
28
 
@@ -33,8 +33,7 @@ def webhook_view(request):
33
33
  )
34
34
 
35
35
  try:
36
-
37
- sms_intel = sms_workflow_process(
36
+ sms_intel = sms_conversation_workflow(
38
37
  request=request,
39
38
  user_input=body,
40
39
  message_history=conversation.generate_message_history(),
@@ -55,7 +54,6 @@ def webhook_view(request):
55
54
  message.save()
56
55
 
57
56
  return HttpResponse(twiml_response)
58
-
59
57
  except:
60
58
  raise
61
59
 
django_spire/ai/urls.py CHANGED
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  from django.urls import include, path
2
4
 
3
5
 
@@ -0,0 +1,25 @@
1
+ <form
2
+ class="text-app-secondary"
3
+ method="post"
4
+ x-data="{
5
+ username: new GlueCharField('username', {required: true, label: {% block username_label %}'Email Address'{% endblock %}}),
6
+ password: new GlueCharField('password', {required: true})
7
+ }"
8
+ >
9
+ {% csrf_token %}
10
+ <div class="row">
11
+ <div class="col">
12
+ {% include 'django_glue/form/field/char_field.html' with glue_field='username' %}
13
+ </div>
14
+ </div>
15
+ <div class="row mt-2">
16
+ <div class="col">
17
+ {% include 'django_glue/form/field/password_field.html' with glue_field='password' %}
18
+ </div>
19
+ </div>
20
+ <div class="row mt-2">
21
+ <div class="col">
22
+ <button type="submit" class="d-block mx-auto btn btn-app-primary-outlined my-4 w-100">Login</button>
23
+ </div>
24
+ </div>
25
+ </form>
@@ -3,15 +3,14 @@
3
3
  {% load static %}
4
4
 
5
5
  {% block page_content %}
6
- <div class="row justify-content-center ps-3 mt-5">
6
+ <div class="row justify-content-center mx-auto mt-5">
7
7
  <div class="col-11 col-md-6 col-lg-4 bg-app-layer-one">
8
8
  <div class="px-4 py-5">
9
9
  {% block authentication_page_top_content %}
10
10
  <div class="text-center pb-5">
11
11
  <a href="/">
12
12
  {% block authentication_page_img %}
13
- <img class="ms-1 img-fluid" src="{% static 'django_spire/img/stratus_secondary_medium.png' %}"
14
- alt="">
13
+ <img height="120px" class="ms-1" src="{% static 'img/django_spire.png' %}" alt="">
15
14
  {% endblock %}
16
15
  </a>
17
16
  </div>
@@ -1,31 +1,7 @@
1
1
  {% extends 'django_spire/auth/page/auth_page.html' %}
2
2
 
3
3
  {% block authentication_page_content %}
4
- <form
5
- class="text-app-secondary"
6
- method="post"
7
- x-data="{
8
- username: new GlueCharField('username', {required: true, label: {% block username_label %}'Email Address'{% endblock %}}),
9
- password: new GlueCharField('password', {required: true})
10
- }"
11
- >
12
- {% csrf_token %}
13
- <div class="row">
14
- <div class="col">
15
- {% include 'django_glue/form/field/char_field.html' with glue_field='username' %}
16
- </div>
17
- </div>
18
- <div class="row mt-2">
19
- <div class="col">
20
- {% include 'django_glue/form/field/password_field.html' with glue_field='password' %}
21
- </div>
22
- </div>
23
- <div class="row mt-2">
24
- <div class="col">
25
- <button type="submit" class="d-block mx-auto btn btn-app-primary-outlined my-4 w-100">Login</button>
26
- </div>
27
- </div>
28
- </form>
4
+ {% include 'django_spire/auth/form/login_form.html' %}
29
5
 
30
6
  <div class="text-center">
31
7
  <a href="{% url 'django_spire:auth:admin:password_reset' %}"
django_spire/conf.py CHANGED
@@ -27,8 +27,6 @@ class Settings:
27
27
  if django_spire_value is not None:
28
28
  return django_spire_value
29
29
 
30
- message = f'No attribute {name} found in settings.'
31
- raise AttributeError(message)
32
-
30
+ return None
33
31
 
34
32
  settings = Settings()
django_spire/consts.py CHANGED
@@ -1,10 +1,4 @@
1
- __VERSION__ = '0.18.3'
2
-
3
-
4
- AI_CHAT_WORKFLOW_SENDER_SETTINGS_NAME = 'AI_CHAT_WORKFLOW_NAME'
5
- AI_CHAT_WORKFLOW_CLASS_SETTINGS_NAME = 'AI_CHAT_WORKFLOW_CLASS'
6
- AI_SMS_CONVERSATION_WORKFLOW_CLASS_SETTINGS_NAME = 'AI_SMS_CONVERSATION_WORKFLOW_CLASS'
7
-
1
+ __VERSION__ = '0.19.1'
8
2
 
9
3
  MAINTENANCE_MODE_SETTINGS_NAME = 'MAINTENANCE_MODE'
10
4
 
@@ -15,6 +15,8 @@ class SeederGeneratorBot(Bot):
15
15
  randomize_seed=True
16
16
  )
17
17
 
18
+ llm_guidelines = generate_django_model_seeder_system_prompt()
19
+
18
20
  llm_role = 'You are an expert Python developer specializing in Django model seeders.'
19
21
 
20
22
  def process(
@@ -27,6 +29,5 @@ class SeederGeneratorBot(Bot):
27
29
  model_import,
28
30
  model_description,
29
31
  ),
30
- intel_class=SourceIntel,
31
- postfix_system_prompt=generate_django_model_seeder_system_prompt()
32
+ intel_class=SourceIntel
32
33
  )
@@ -0,0 +1,2 @@
1
+ def truncate_string(string: str, length: int) -> str:
2
+ return string[:(length - 3)] + '...' if len(string) > length else string
@@ -6,10 +6,7 @@ from django_spire.core.management.commands.spire_startapp_pkg.config import (
6
6
  AppConfigFactory,
7
7
  PathConfig,
8
8
  )
9
- from django_spire.core.management.commands.spire_startapp_pkg.filesystem import (
10
- FileSystem,
11
- FileSystemInterface,
12
- )
9
+ from django_spire.core.management.commands.spire_startapp_pkg.filesystem import FileSystem
13
10
  from django_spire.core.management.commands.spire_startapp_pkg.generator import (
14
11
  AppGenerator,
15
12
  TemplateGenerator,
@@ -20,18 +17,9 @@ from django_spire.core.management.commands.spire_startapp_pkg.processor import (
20
17
  TemplateEngine,
21
18
  TemplateProcessor,
22
19
  )
23
- from django_spire.core.management.commands.spire_startapp_pkg.registry import (
24
- AppRegistry,
25
- AppRegistryInterface,
26
- )
27
- from django_spire.core.management.commands.spire_startapp_pkg.reporter import (
28
- Reporter,
29
- ReporterInterface,
30
- )
31
- from django_spire.core.management.commands.spire_startapp_pkg.resolver import (
32
- PathResolver,
33
- PathResolverInterface,
34
- )
20
+ from django_spire.core.management.commands.spire_startapp_pkg.registry import AppRegistry
21
+ from django_spire.core.management.commands.spire_startapp_pkg.reporter import Reporter
22
+ from django_spire.core.management.commands.spire_startapp_pkg.resolver import PathResolver
35
23
  from django_spire.core.management.commands.spire_startapp_pkg.user_input import UserInputCollector
36
24
  from django_spire.core.management.commands.spire_startapp_pkg.validator import AppValidator
37
25
 
@@ -41,16 +29,12 @@ __all__ = [
41
29
  'AppConfigFactory',
42
30
  'AppGenerator',
43
31
  'AppRegistry',
44
- 'AppRegistryInterface',
45
32
  'AppValidator',
46
33
  'FileSystem',
47
- 'FileSystemInterface',
48
34
  'PathConfig',
49
35
  'PathResolver',
50
- 'PathResolverInterface',
51
36
  'PermissionInheritanceHandler',
52
37
  'Reporter',
53
- 'ReporterInterface',
54
38
  'TemplateBuilder',
55
39
  'TemplateEngine',
56
40
  'TemplateGenerator',
@@ -7,7 +7,7 @@ from django_spire.core.management.commands.spire_startapp_pkg.maps import genera
7
7
  if TYPE_CHECKING:
8
8
  from pathlib import Path
9
9
 
10
- from django_spire.core.management.commands.spire_startapp_pkg.reporter import ReporterInterface
10
+ from django_spire.core.management.commands.spire_startapp_pkg.reporter import Reporter
11
11
 
12
12
 
13
13
  class TemplateBuilder:
@@ -18,7 +18,7 @@ class TemplateBuilder:
18
18
  that will be created for new apps and their associated templates.
19
19
  """
20
20
 
21
- def __init__(self, reporter: ReporterInterface):
21
+ def __init__(self, reporter: Reporter):
22
22
  """
23
23
  Initializes the TemplateBuilder with a reporter for output.
24
24
 
@@ -7,7 +7,7 @@ from pathlib import Path
7
7
  from typing import TYPE_CHECKING
8
8
 
9
9
  if TYPE_CHECKING:
10
- from django_spire.core.management.commands.spire_startapp_pkg.resolver import PathResolverInterface
10
+ from django_spire.core.management.commands.spire_startapp_pkg.resolver import PathResolver
11
11
 
12
12
 
13
13
  @dataclass(frozen=True)
@@ -84,7 +84,7 @@ class AppConfigFactory:
84
84
  paths and processing user inputs.
85
85
  """
86
86
 
87
- def __init__(self, path_resolver: PathResolverInterface):
87
+ def __init__(self, path_resolver: PathResolver):
88
88
  """
89
89
  Initializes the factory with a path resolver.
90
90
 
@@ -2,31 +2,13 @@ from __future__ import annotations
2
2
 
3
3
  import shutil
4
4
 
5
- from typing import Protocol, TYPE_CHECKING
5
+ from typing import TYPE_CHECKING
6
6
 
7
7
  if TYPE_CHECKING:
8
8
  from pathlib import Path
9
9
  from typing import Iterator
10
10
 
11
11
 
12
- class FileSystemInterface(Protocol):
13
- """
14
- Protocol defining the interface for file system operations.
15
-
16
- This protocol specifies the methods required for interacting with
17
- the file system during app creation.
18
- """
19
-
20
- def copy_tree(self, src: Path, dst: Path) -> None: ...
21
- def create_directory(self, path: Path) -> None: ...
22
- def exists(self, path: Path) -> bool: ...
23
- def has_content(self, path: Path) -> bool: ...
24
- def iterate_files(self, path: Path, pattern: str) -> Iterator[Path]: ...
25
- def read_file(self, path: Path) -> str: ...
26
- def rename(self, old: Path, new: Path) -> None: ...
27
- def write_file(self, path: Path, content: str) -> None: ...
28
-
29
-
30
12
  class FileSystem:
31
13
  """
32
14
  Implementation of file system operations for app generation.
@@ -8,9 +8,9 @@ if TYPE_CHECKING:
8
8
  from pathlib import Path
9
9
 
10
10
  from django_spire.core.management.commands.spire_startapp_pkg.config import AppConfig, PathConfig
11
- from django_spire.core.management.commands.spire_startapp_pkg.filesystem import FileSystemInterface
11
+ from django_spire.core.management.commands.spire_startapp_pkg.filesystem import FileSystem
12
12
  from django_spire.core.management.commands.spire_startapp_pkg.processor import TemplateProcessor
13
- from django_spire.core.management.commands.spire_startapp_pkg.reporter import ReporterInterface
13
+ from django_spire.core.management.commands.spire_startapp_pkg.reporter import Reporter
14
14
 
15
15
 
16
16
  class AppGenerator:
@@ -23,15 +23,15 @@ class AppGenerator:
23
23
 
24
24
  def __init__(
25
25
  self,
26
- filesystem: FileSystemInterface,
26
+ filesystem: FileSystem,
27
27
  processor: TemplateProcessor,
28
- reporter: ReporterInterface,
28
+ reporter: Reporter,
29
29
  path_config: PathConfig
30
30
  ):
31
31
  """
32
32
  Initializes the AppGenerator with required dependencies.
33
33
 
34
- :param filesystem: File system interface for file operations.
34
+ :param filesystem: File system for file operations.
35
35
  :param processor: Template processor for replacing placeholders.
36
36
  :param reporter: Reporter for user feedback and output.
37
37
  :param path_config: Configuration containing template paths.
@@ -100,15 +100,15 @@ class TemplateGenerator:
100
100
 
101
101
  def __init__(
102
102
  self,
103
- filesystem: FileSystemInterface,
103
+ filesystem: FileSystem,
104
104
  processor: TemplateProcessor,
105
- reporter: ReporterInterface,
105
+ reporter: Reporter,
106
106
  path_config: PathConfig
107
107
  ):
108
108
  """
109
109
  Initializes the TemplateGenerator with required dependencies.
110
110
 
111
- :param filesystem: File system interface for file operations.
111
+ :param filesystem: File system for file operations.
112
112
  :param processor: Template processor for replacing placeholders.
113
113
  :param reporter: Reporter for user feedback and output.
114
114
  :param path_config: Configuration containing template paths.