django-spire 0.18.3__py3-none-any.whl → 0.19.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.
- django_spire/ai/admin.py +1 -0
- django_spire/ai/chat/apps.py +1 -8
- django_spire/ai/chat/intelligence/decoders/tools.py +29 -0
- django_spire/ai/chat/intelligence/prompts.py +13 -7
- django_spire/ai/chat/intelligence/workflows/chat_workflow.py +40 -52
- django_spire/ai/chat/models.py +2 -1
- django_spire/ai/chat/querysets.py +1 -3
- django_spire/ai/chat/responses.py +5 -0
- django_spire/ai/chat/templates/django_spire/ai/chat/card/chat_card.html +2 -2
- django_spire/ai/chat/templates/django_spire/ai/chat/dropdown/ellipsis_dropdown.html +1 -1
- django_spire/ai/chat/templates/django_spire/ai/chat/element/recent_chat_select_element.html +82 -44
- django_spire/ai/chat/templates/django_spire/ai/chat/message/loading_response_message.html +8 -3
- django_spire/ai/chat/templates/django_spire/ai/chat/message/message.html +16 -7
- django_spire/ai/chat/templates/django_spire/ai/chat/message/request_message.html +5 -8
- django_spire/ai/chat/templates/django_spire/ai/chat/message/response_message.html +14 -10
- django_spire/ai/chat/templates/django_spire/ai/chat/page/chat_page.html +35 -0
- django_spire/ai/chat/templates/django_spire/ai/chat/widget/dialog_widget.html +72 -23
- django_spire/ai/chat/templates/django_spire/ai/chat/widget/selection_widget.html +42 -0
- django_spire/ai/chat/tests/test_urls/test_json_urls.py +4 -2
- django_spire/ai/chat/urls/__init__.py +1 -1
- django_spire/ai/chat/urls/json_urls.py +1 -1
- django_spire/ai/chat/urls/page_urls.py +1 -1
- django_spire/ai/chat/urls/{template_urls.py → template/template_urls.py} +1 -1
- django_spire/ai/chat/views/json_views.py +4 -3
- django_spire/ai/chat/views/message_request_views.py +32 -14
- django_spire/ai/chat/views/message_response_views.py +14 -11
- django_spire/ai/chat/views/message_views.py +7 -1
- django_spire/ai/chat/views/page_views.py +2 -2
- django_spire/ai/chat/views/{template_views.py → template/template_views.py} +1 -7
- django_spire/ai/context/__init__.py +0 -0
- django_spire/ai/context/admin.py +15 -0
- django_spire/ai/context/apps.py +16 -0
- django_spire/ai/context/choices.py +11 -0
- django_spire/ai/context/intelligence/__init__.py +0 -0
- django_spire/ai/context/intelligence/prompts/__init__.py +0 -0
- django_spire/ai/context/intelligence/prompts/organization_prompts.py +19 -0
- django_spire/ai/context/migrations/0001_initial.py +67 -0
- django_spire/ai/context/migrations/__init__.py +0 -0
- django_spire/ai/context/models.py +67 -0
- django_spire/ai/context/querysets.py +15 -0
- django_spire/ai/context/seeding/__init__.py +0 -0
- django_spire/ai/context/seeding/seed.py +24 -0
- django_spire/ai/prompt/system/bots.py +3 -5
- django_spire/ai/prompt/tuning/bots.py +5 -10
- django_spire/ai/sms/admin.py +2 -0
- django_spire/ai/sms/apps.py +2 -7
- django_spire/ai/sms/decorators.py +2 -2
- django_spire/ai/sms/intelligence/workflows/sms_conversation_workflow.py +18 -18
- django_spire/ai/sms/tests/test_webhook.py +5 -4
- django_spire/ai/sms/urls.py +3 -0
- django_spire/ai/sms/views.py +3 -5
- django_spire/ai/urls.py +2 -0
- django_spire/auth/templates/django_spire/auth/form/login_form.html +25 -0
- django_spire/auth/templates/django_spire/auth/page/auth_page.html +2 -3
- django_spire/auth/templates/django_spire/auth/page/login_page.html +1 -25
- django_spire/conf.py +1 -3
- django_spire/consts.py +1 -7
- django_spire/contrib/seeding/intelligence/bots/seeder_generator_bot.py +3 -2
- django_spire/contrib/utils.py +2 -0
- django_spire/core/static/django_spire/css/app-button.css +11 -1
- django_spire/core/static/django_spire/css/app-import.css +2 -0
- django_spire/core/static/django_spire/css/app-layout.css +15 -0
- django_spire/core/static/django_spire/css/app-navigation.css +24 -2
- django_spire/core/static/django_spire/css/app-page.css +8 -0
- django_spire/core/static/django_spire/css/app-side-panel.css +102 -0
- django_spire/core/static/django_spire/css/app-text.css +19 -1
- django_spire/core/static/django_spire/css/bootstrap-extension.css +128 -7
- django_spire/core/static/django_spire/css/bootstrap-override.css +161 -111
- django_spire/core/static/django_spire/css/themes/ayu/app-dark.css +0 -4
- django_spire/core/static/django_spire/css/themes/ayu/app-light.css +0 -4
- django_spire/core/static/django_spire/css/themes/catppuccin/app-dark.css +0 -4
- django_spire/core/static/django_spire/css/themes/catppuccin/app-light.css +0 -4
- django_spire/core/static/django_spire/css/themes/default/app-dark.css +0 -4
- django_spire/core/static/django_spire/css/themes/default/app-light.css +0 -4
- django_spire/core/static/django_spire/css/themes/dracula/app-dark.css +0 -4
- django_spire/core/static/django_spire/css/themes/dracula/app-light.css +0 -4
- django_spire/core/static/django_spire/css/themes/gruvbox/app-dark.css +0 -4
- django_spire/core/static/django_spire/css/themes/gruvbox/app-light.css +0 -4
- django_spire/core/static/django_spire/css/themes/material/app-dark.css +0 -4
- django_spire/core/static/django_spire/css/themes/material/app-light.css +0 -4
- django_spire/core/static/django_spire/css/themes/nord/app-dark.css +0 -4
- django_spire/core/static/django_spire/css/themes/nord/app-light.css +0 -4
- django_spire/core/static/django_spire/css/themes/oceanic-next/app-dark.css +0 -4
- django_spire/core/static/django_spire/css/themes/oceanic-next/app-light.css +0 -4
- django_spire/core/static/django_spire/css/themes/one-dark/app-dark.css +0 -4
- django_spire/core/static/django_spire/css/themes/one-dark/app-light.css +0 -4
- django_spire/core/static/django_spire/css/themes/palenight/app-dark.css +0 -4
- django_spire/core/static/django_spire/css/themes/palenight/app-light.css +0 -4
- django_spire/core/static/django_spire/css/themes/rose-pine/app-dark.css +0 -4
- django_spire/core/static/django_spire/css/themes/rose-pine/app-light.css +0 -4
- django_spire/core/static/django_spire/css/themes/synthwave/app-dark.css +0 -4
- django_spire/core/static/django_spire/css/themes/synthwave/app-light.css +0 -4
- django_spire/core/static/django_spire/css/themes/tokyo-night/app-dark.css +0 -4
- django_spire/core/static/django_spire/css/themes/tokyo-night/app-light.css +0 -4
- django_spire/core/static/django_spire/font/Poppins-Black.ttf +0 -0
- django_spire/core/static/django_spire/font/Poppins-BlackItalic.ttf +0 -0
- django_spire/core/static/django_spire/font/Poppins-Bold.ttf +0 -0
- django_spire/core/static/django_spire/font/Poppins-BoldItalic.ttf +0 -0
- django_spire/core/static/django_spire/font/Poppins-ExtraBold.ttf +0 -0
- django_spire/core/static/django_spire/font/Poppins-ExtraBoldItalic.ttf +0 -0
- django_spire/core/static/django_spire/font/Poppins-ExtraLight.ttf +0 -0
- django_spire/core/static/django_spire/font/Poppins-ExtraLightItalic.ttf +0 -0
- django_spire/core/static/django_spire/font/Poppins-Italic.ttf +0 -0
- django_spire/core/static/django_spire/font/Poppins-Light.ttf +0 -0
- django_spire/core/static/django_spire/font/Poppins-LightItalic.ttf +0 -0
- django_spire/core/static/django_spire/font/Poppins-Medium.ttf +0 -0
- django_spire/core/static/django_spire/font/Poppins-MediumItalic.ttf +0 -0
- django_spire/core/static/django_spire/font/Poppins-SemiBold.ttf +0 -0
- django_spire/core/static/django_spire/font/Poppins-SemiBoldItalic.ttf +0 -0
- django_spire/core/static/django_spire/font/Poppins-Thin.ttf +0 -0
- django_spire/core/static/django_spire/font/Poppins-ThinItalic.ttf +0 -0
- django_spire/core/static/django_spire/js/ui.js +12 -0
- django_spire/core/templates/django_spire/button/base_button.html +1 -1
- django_spire/core/templates/django_spire/button/primary_dark_outlined_button.html +3 -0
- django_spire/core/templates/django_spire/dropdown/element/dropdown_link_element.html +12 -8
- django_spire/core/templates/django_spire/dropdown/element/ellipsis_dropdown_modal_link_element.html +2 -1
- django_spire/core/templates/django_spire/dropdown/ellipsis_dropdown.html +2 -1
- django_spire/core/templates/django_spire/navigation/accordion/nav_accordion.html +1 -1
- django_spire/core/templates/django_spire/navigation/elements/nav_link.html +1 -1
- django_spire/core/templates/django_spire/navigation/elements/nav_title_divider.html +1 -1
- django_spire/core/templates/django_spire/navigation/side_navigation.html +52 -8
- django_spire/core/templates/django_spire/navigation/top_navigation.html +8 -2
- django_spire/core/templates/django_spire/page/full_page.html +218 -11
- django_spire/core/utils.py +26 -2
- django_spire/knowledge/collection/models.py +24 -0
- django_spire/knowledge/collection/services/transformation_service.py +2 -1
- django_spire/knowledge/collection/tests/test_services/test_transformation_service.py +44 -42
- django_spire/knowledge/collection/urls/form_urls.py +1 -0
- django_spire/knowledge/collection/urls/page_urls.py +1 -0
- django_spire/knowledge/collection/views/form_views.py +13 -2
- django_spire/knowledge/collection/views/page_views.py +36 -4
- django_spire/knowledge/entry/models.py +32 -0
- django_spire/knowledge/entry/services/transformation_services.py +10 -10
- django_spire/knowledge/entry/version/block/data/data.py +2 -1
- django_spire/knowledge/entry/version/block/data/heading_data.py +2 -2
- django_spire/knowledge/entry/version/block/data/list/data.py +3 -4
- django_spire/knowledge/entry/version/block/data/maps.py +3 -5
- django_spire/knowledge/entry/version/block/data/text_data.py +2 -2
- django_spire/knowledge/entry/version/block/models.py +10 -7
- django_spire/knowledge/entry/version/block/services/factory_service.py +11 -10
- django_spire/knowledge/entry/version/block/tests/factories.py +6 -5
- django_spire/knowledge/entry/version/converters/docx_converter.py +1 -1
- django_spire/knowledge/entry/version/intelligence/bots/markdown_format_llm_bot.py +14 -12
- django_spire/knowledge/entry/version/seeding/seeder.py +3 -3
- django_spire/knowledge/entry/version/services/processor_service.py +36 -10
- django_spire/knowledge/entry/version/tests/test_converters/test_docx_converter.py +1 -1
- django_spire/knowledge/entry/version/tests/test_urls/test_page_urls.py +1 -1
- django_spire/knowledge/entry/version/urls/page_urls.py +1 -1
- django_spire/knowledge/entry/version/views/json_views.py +5 -3
- django_spire/knowledge/entry/version/views/page_views.py +11 -12
- django_spire/knowledge/entry/version/views/redirect_views.py +1 -1
- django_spire/knowledge/entry/views/form_views.py +1 -1
- django_spire/knowledge/intelligence/bots/entry_search_llm_bot.py +33 -11
- django_spire/knowledge/intelligence/decoders/__init__.py +0 -0
- django_spire/knowledge/intelligence/{maps/collection_map.py → decoders/collection_decoder.py} +5 -5
- django_spire/knowledge/intelligence/{maps/entry_map.py → decoders/entry_decoder.py} +3 -3
- django_spire/knowledge/intelligence/intel/collection_intel.py +1 -0
- django_spire/knowledge/intelligence/intel/entry_intel.py +5 -2
- django_spire/knowledge/intelligence/intel/message_intel.py +2 -0
- django_spire/knowledge/intelligence/workflows/knowledge_workflow.py +43 -51
- django_spire/knowledge/migrations/0007_alter_collection_options.py +17 -0
- django_spire/knowledge/static/django_spire/knowledge/entry/version/js/editor.js +24 -5
- django_spire/knowledge/templates/django_spire/knowledge/collection/card/top_level_list_card.html +21 -0
- django_spire/knowledge/templates/django_spire/knowledge/collection/component/x_collection_navigation.html +15 -6
- django_spire/knowledge/templates/django_spire/knowledge/collection/element/ellipsis_dropdown.html +22 -0
- django_spire/knowledge/templates/django_spire/knowledge/collection/form/form.html +21 -9
- django_spire/knowledge/templates/django_spire/knowledge/collection/item/collection_item.html +19 -0
- django_spire/knowledge/templates/django_spire/knowledge/collection/page/display_page.html +49 -0
- django_spire/knowledge/templates/django_spire/knowledge/collection/page/form_page.html +1 -1
- django_spire/knowledge/templates/django_spire/knowledge/container/container.html +33 -0
- django_spire/knowledge/templates/django_spire/knowledge/entry/file/page/list_page.html +1 -1
- django_spire/knowledge/templates/django_spire/knowledge/entry/item/list_item.html +2 -2
- django_spire/knowledge/templates/django_spire/knowledge/entry/page/form_page.html +1 -1
- django_spire/knowledge/templates/django_spire/knowledge/entry/page/import_form_page.html +1 -1
- django_spire/knowledge/templates/django_spire/knowledge/entry/version/container/detail_container.html +51 -45
- django_spire/knowledge/templates/django_spire/knowledge/entry/version/page/editor_page.html +54 -0
- django_spire/knowledge/templates/django_spire/knowledge/entry/version/page/form_page.html +1 -1
- django_spire/knowledge/templates/django_spire/knowledge/message/knowledge_message_intel.html +18 -1
- django_spire/knowledge/templates/django_spire/knowledge/page/full_page.html +37 -0
- django_spire/knowledge/templates/django_spire/knowledge/page/home_page.html +2 -2
- django_spire/knowledge/templates/django_spire/knowledge/sub_navigation/item/collection_sub_navigation_item.html +29 -0
- django_spire/knowledge/templates/django_spire/knowledge/sub_navigation/item/entry_sub_navigation_item.html +20 -0
- django_spire/knowledge/templates/django_spire/knowledge/{navigation/content/navigation_content.html → sub_navigation/widget/collection_entry_sub_navigation_widget.html} +42 -19
- django_spire/knowledge/views/page_views.py +4 -4
- django_spire/settings.py +3 -3
- django_spire/theme/templates/django_spire/theme/card/badges_preview_card.html +0 -1
- django_spire/theme/templates/django_spire/theme/card/base_preview_card.html +1 -0
- django_spire/theme/templates/django_spire/theme/card/typography_preview_card.html +1 -1
- django_spire/theme/templates/django_spire/theme/example/form/example_form.html +2 -0
- django_spire/theme/templates/django_spire/theme/example/form/example_form_card.html +5 -0
- django_spire/theme/templates/django_spire/theme/page/badges_page.html +7 -9
- django_spire/theme/templates/django_spire/theme/page/borders_page.html +6 -9
- django_spire/theme/templates/django_spire/theme/page/buttons_page.html +6 -9
- django_spire/theme/templates/django_spire/theme/page/colors_page.html +6 -6
- django_spire/theme/templates/django_spire/theme/page/dashboard_page.html +57 -0
- django_spire/theme/templates/django_spire/theme/page/django_glue_page.html +7 -9
- django_spire/theme/templates/django_spire/theme/page/theme_page.html +24 -0
- django_spire/theme/templates/django_spire/theme/page/typography_page.html +6 -9
- django_spire/theme/templates/django_spire/theme/section/badge_section_card.html +5 -0
- django_spire/theme/templates/django_spire/theme/section/border_section_card.html +5 -0
- django_spire/theme/templates/django_spire/theme/section/button_section.html +1 -0
- django_spire/theme/templates/django_spire/theme/section/button_section_card.html +5 -0
- django_spire/theme/templates/django_spire/theme/section/color_section.html +10 -10
- django_spire/theme/templates/django_spire/theme/section/color_section_card.html +5 -0
- django_spire/theme/templates/django_spire/theme/section/typography_section.html +41 -1
- django_spire/theme/templates/django_spire/theme/section/typography_section_card.html +5 -0
- {django_spire-0.18.3.dist-info → django_spire-0.19.0.dist-info}/METADATA +3 -3
- {django_spire-0.18.3.dist-info → django_spire-0.19.0.dist-info}/RECORD +217 -178
- django_spire/ai/chat/intelligence/bots/chat_bot.py +0 -8
- django_spire/ai/chat/intelligence/maps/intent_llm_map.py +0 -10
- django_spire/ai/chat/templates/django_spire/ai/chat/page/home_page.html +0 -9
- django_spire/ai/chat/templates/django_spire/ai/chat/widget/chat_widget.html +0 -64
- django_spire/ai/chat/templates/django_spire/ai/chat/widget/search_chat_results_widget.html +0 -25
- django_spire/ai/chat/templates/django_spire/ai/chat/widget/search_chat_widget.html +0 -39
- django_spire/ai/chat/templates/django_spire/ai/chat/widget/select_chat_widget.html +0 -24
- django_spire/ai/chat/tools.py +0 -57
- django_spire/ai/sms/tools.py +0 -57
- django_spire/core/static/django_spire/font/Karla-Bold.ttf +0 -0
- django_spire/core/static/django_spire/font/Merriweather.ttf +0 -0
- django_spire/knowledge/context_processors.py +0 -18
- django_spire/knowledge/templates/django_spire/knowledge/entry/version/page/detail_page.html +0 -25
- django_spire/knowledge/templates/django_spire/knowledge/navigation/card/navigation_card.html +0 -9
- django_spire/knowledge/templates/django_spire/knowledge/navigation/item/collection/collection_item.html +0 -29
- django_spire/knowledge/templates/django_spire/knowledge/navigation/item/entry/entry_item.html +0 -18
- django_spire/knowledge/templates/django_spire/knowledge/navigation/page/full_page.html +0 -90
- /django_spire/ai/chat/intelligence/{bots → decoders}/__init__.py +0 -0
- /django_spire/ai/chat/{intelligence/maps → urls/template}/__init__.py +0 -0
- /django_spire/{knowledge/intelligence/maps → ai/chat/views/template}/__init__.py +0 -0
- /django_spire/knowledge/entry/version/{constants.py → consts.py} +0 -0
- /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
- /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
- {django_spire-0.18.3.dist-info → django_spire-0.19.0.dist-info}/WHEEL +0 -0
- {django_spire-0.18.3.dist-info → django_spire-0.19.0.dist-info}/licenses/LICENSE.md +0 -0
- {django_spire-0.18.3.dist-info → django_spire-0.19.0.dist-info}/top_level.txt +0 -0
|
@@ -4,75 +4,124 @@
|
|
|
4
4
|
<div
|
|
5
5
|
class="row"
|
|
6
6
|
x-data="{
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
chat_id: '{{ chat.id }}',
|
|
7
|
+
chat_id: '{{ chat.id|default:'0' }}',
|
|
8
|
+
chat_name: '{{ chat.name_shortened|default:'New Chat'|escapejs }}',
|
|
10
9
|
message_body: '',
|
|
10
|
+
request_message_view: new ViewGlue('{% url "django_spire:ai:chat:message:request:new" %}'),
|
|
11
11
|
|
|
12
12
|
init() {
|
|
13
|
-
|
|
13
|
+
if (this.chat_id && this.chat_id !== '0' && this.chat_id !== '') {
|
|
14
|
+
this.load_messages()
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
setTimeout(() => {
|
|
18
|
+
if (this.$refs.target_div) {
|
|
19
|
+
this.smooth_scroll_to_bottom()
|
|
20
|
+
}
|
|
21
|
+
}, 1500)
|
|
14
22
|
|
|
15
23
|
this.speech_recognition.onresult = () => {
|
|
16
24
|
this.message_body = this.speech_transcript
|
|
17
25
|
this.send_chat({message_body: this.message_body, synthesis_speech_for_response: true})
|
|
18
26
|
}
|
|
19
27
|
},
|
|
28
|
+
|
|
20
29
|
load_messages() {
|
|
21
|
-
|
|
30
|
+
let load_messages_view = new ViewGlue(`/django_spire/ai/chat/message/load/chat/${this.chat_id}/`)
|
|
31
|
+
load_messages_view.render_insert_adjacent(this.$refs.target_div, {})
|
|
22
32
|
},
|
|
33
|
+
|
|
34
|
+
smooth_scroll_to_bottom() {
|
|
35
|
+
let target = this.$refs.target_div
|
|
36
|
+
let start = target.scrollTop
|
|
37
|
+
let end = target.scrollHeight - target.clientHeight
|
|
38
|
+
let duration = 400
|
|
39
|
+
let start_time = performance.now()
|
|
40
|
+
|
|
41
|
+
function animate(current_time) {
|
|
42
|
+
let elapsed = current_time - start_time
|
|
43
|
+
let progress = Math.min(elapsed / duration, 1)
|
|
44
|
+
let ease = progress * (2 - progress)
|
|
45
|
+
|
|
46
|
+
target.scrollTop = start + (end - start) * ease
|
|
47
|
+
|
|
48
|
+
if (progress < 1) {
|
|
49
|
+
requestAnimationFrame(animate)
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
requestAnimationFrame(animate)
|
|
54
|
+
},
|
|
55
|
+
|
|
23
56
|
async send_chat({message_body = '', synthesis_speech_for_response = false}) {
|
|
24
57
|
if (message_body !== '') {
|
|
25
|
-
|
|
58
|
+
let was_new_chat = (this.chat_id === '0' || this.chat_id === 0 || this.chat_id === '')
|
|
59
|
+
|
|
60
|
+
let response_html = await this.request_message_view.render_insert_adjacent(
|
|
26
61
|
this.$refs.target_div,
|
|
27
62
|
{
|
|
28
|
-
message_body: message_body,
|
|
29
63
|
chat_id: this.chat_id,
|
|
64
|
+
message_body: message_body,
|
|
30
65
|
synthesis_speech: synthesis_speech_for_response
|
|
31
66
|
}
|
|
32
67
|
)
|
|
68
|
+
|
|
69
|
+
if (was_new_chat) {
|
|
70
|
+
this.chat_name = message_body
|
|
71
|
+
|
|
72
|
+
let message_element = this.$refs.target_div.querySelector('[data-message-chat-id]')
|
|
73
|
+
|
|
74
|
+
if (message_element) {
|
|
75
|
+
this.chat_id = message_element.dataset.messageChatId
|
|
76
|
+
$dispatch('new-chat-created', {chat_id: parseInt(this.chat_id)})
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
33
80
|
this.message_body = ''
|
|
81
|
+
$dispatch('chat-loaded')
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
|
|
85
|
+
speak_text(text) {
|
|
86
|
+
if ('speechSynthesis' in window) {
|
|
87
|
+
let utterance = new SpeechSynthesisUtterance(text)
|
|
88
|
+
window.speechSynthesis.speak(utterance)
|
|
34
89
|
}
|
|
35
90
|
}
|
|
36
91
|
}"
|
|
92
|
+
@send-message.window="send_chat({message_body: $event.detail.message_body})" @speak.window="speak_text($event.detail.text)"
|
|
37
93
|
>
|
|
38
94
|
<div class="col-12">
|
|
39
|
-
<div class="row px-0
|
|
40
|
-
<div class="col-
|
|
41
|
-
style="font-size: 1.6rem; margin-top: -0.2rem;">
|
|
42
|
-
<i x-show="!select_chat_visible" @click="open_chat_select()" class="bi bi-chat-left-text"></i>
|
|
43
|
-
</div>
|
|
44
|
-
<div class="col text-center fw-bold pb-2">
|
|
45
|
-
{{ chat.name_shortened }}
|
|
95
|
+
<div class="row border-bottom px-0">
|
|
96
|
+
<div class="col text-center pb-2" x-text="chat_name">
|
|
46
97
|
</div>
|
|
47
98
|
</div>
|
|
48
99
|
|
|
49
100
|
<div class="row mb-3">
|
|
50
|
-
<div
|
|
51
|
-
style="height: calc(100vh - 90px - var(--app-top-navigation-height));">
|
|
101
|
+
<div class="col-12 overflow-auto p-4" style="height: calc(100vh - 90px - var(--app-top-navigation-height));" x-ref="target_div">
|
|
52
102
|
</div>
|
|
53
103
|
</div>
|
|
54
104
|
|
|
55
105
|
<div class="row">
|
|
56
106
|
<div class="col-auto text-center ps-2 pe-1">
|
|
57
|
-
<button class="btn btn-app-primary-outlined" x-show="!speech_listening"
|
|
107
|
+
<button @click="start_listening()" class="btn btn-app-primary-outlined" x-show="!speech_listening">
|
|
58
108
|
<i class="bi bi-mic"></i>
|
|
59
109
|
</button>
|
|
60
|
-
<button class="btn btn-app-danger" x-show="speech_listening"
|
|
110
|
+
<button @click="stop_listening()" class="btn btn-app-danger" x-show="speech_listening">
|
|
61
111
|
<i class="bi bi-mic-fill"></i>
|
|
62
112
|
</button>
|
|
63
113
|
</div>
|
|
114
|
+
|
|
64
115
|
<div class="col text-center px-1">
|
|
65
|
-
<input type="text" x-init="$el.focus()" x-model="message_body"
|
|
66
|
-
class="form-control" autocomplete="off" name="request_message">
|
|
116
|
+
<input @keyup.enter="send_chat({message_body: message_body})" autocomplete="off" class="form-control" name="request_message" type="text" x-init="$el.focus()" x-model="message_body">
|
|
67
117
|
</div>
|
|
118
|
+
|
|
68
119
|
<div class="col-auto text-center ps-1 pe-2">
|
|
69
|
-
<button
|
|
120
|
+
<button @click="send_chat({message_body: message_body})" class="btn btn-app-primary">
|
|
70
121
|
<i class="bi bi-send"></i>
|
|
71
122
|
</button>
|
|
72
123
|
</div>
|
|
73
124
|
</div>
|
|
74
|
-
|
|
75
125
|
</div>
|
|
76
126
|
</div>
|
|
77
|
-
|
|
78
127
|
{% endblock %}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
<div
|
|
2
|
+
class="row"
|
|
3
|
+
x-data="{
|
|
4
|
+
active_chat_id: 0,
|
|
5
|
+
chat_content_type: '',
|
|
6
|
+
chat_load_recent_view: new ViewGlue('{% url "django_spire:ai:chat:template:recent" %}'),
|
|
7
|
+
chat_object_id: '',
|
|
8
|
+
|
|
9
|
+
init() {
|
|
10
|
+
this.load_recent_chats()
|
|
11
|
+
$dispatch('load-chat', {chat_id: 0})
|
|
12
|
+
},
|
|
13
|
+
async load_recent_chats() {
|
|
14
|
+
await this.chat_load_recent_view.render_inner(this.$refs.chat_recent_list)
|
|
15
|
+
$dispatch('chat-activated', {chat_id: this.active_chat_id})
|
|
16
|
+
}
|
|
17
|
+
}"
|
|
18
|
+
@chat-loaded.window="load_recent_chats()"
|
|
19
|
+
@new-chat-created.window="active_chat_id = $event.detail.chat_id; $dispatch('chat-activated', {chat_id: $event.detail.chat_id})"
|
|
20
|
+
@load-chat.window="active_chat_id = $event.detail.chat_id; $dispatch('chat-activated', {chat_id: $event.detail.chat_id})">
|
|
21
|
+
|
|
22
|
+
<div class="col-12 px-0">
|
|
23
|
+
<div class="px-2 pb-3">
|
|
24
|
+
<button @click="$dispatch('load-chat', {chat_id: 0})" class="btn btn-app-primary-outlined p-1 w-100">
|
|
25
|
+
<i class="bi bi-plus-lg me-2"></i>New Chat
|
|
26
|
+
</button>
|
|
27
|
+
</div>
|
|
28
|
+
|
|
29
|
+
<div class="border-top border-app-primary"></div>
|
|
30
|
+
|
|
31
|
+
<div class="px-3 py-2">
|
|
32
|
+
<div class="text-muted text-uppercase" style="font-size: 0.75rem; font-weight: 600; letter-spacing: 0.5px;">
|
|
33
|
+
Recent Chats
|
|
34
|
+
</div>
|
|
35
|
+
</div>
|
|
36
|
+
|
|
37
|
+
<div class="overflow-auto" style="height: calc(100vh - 180px - var(--app-top-navigation-height));">
|
|
38
|
+
<div class="px-2" x-ref="chat_recent_list">
|
|
39
|
+
</div>
|
|
40
|
+
</div>
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
@@ -1,15 +1,17 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
from django_spire.ai.chat.tests.test_urls.factories import create_test_chat
|
|
2
4
|
from django_spire.core.tests.test_cases import BaseTestCase
|
|
3
5
|
from django.urls import reverse
|
|
4
6
|
|
|
5
7
|
|
|
6
8
|
class ChatJsonUrlTests(BaseTestCase):
|
|
7
|
-
def setUp(self):
|
|
9
|
+
def setUp(self) -> None:
|
|
8
10
|
super().setUp()
|
|
9
11
|
|
|
10
12
|
self.test_chat = create_test_chat(user=self.super_user)
|
|
11
13
|
|
|
12
|
-
def test_delete_view_url_path(self):
|
|
14
|
+
def test_delete_view_url_path(self) -> None:
|
|
13
15
|
response = self.client.post(
|
|
14
16
|
reverse(
|
|
15
17
|
'django_spire:ai:chat:json:delete',
|
|
@@ -6,5 +6,5 @@ urlpatterns = [
|
|
|
6
6
|
path('json/', include('django_spire.ai.chat.urls.json_urls', namespace='json')),
|
|
7
7
|
path('message/', include('django_spire.ai.chat.urls.message_urls', namespace='message')),
|
|
8
8
|
path('page/', include('django_spire.ai.chat.urls.page_urls', namespace='page')),
|
|
9
|
-
path('template/', include('django_spire.ai.chat.urls.template_urls', namespace='template')),
|
|
9
|
+
path('template/', include('django_spire.ai.chat.urls.template.template_urls', namespace='template')),
|
|
10
10
|
]
|
|
@@ -8,5 +8,5 @@ app_name = 'json'
|
|
|
8
8
|
urlpatterns = [
|
|
9
9
|
path('<int:pk>/delete', json_views.delete_chat_view, name='delete'),
|
|
10
10
|
path('<int:pk>/rename', json_views.rename_chat_view, name='rename'),
|
|
11
|
-
path('workflow_process', json_views.
|
|
11
|
+
path('workflow_process', json_views.chat_workflow_view, name='workflow_process'),
|
|
12
12
|
]
|
|
@@ -3,10 +3,11 @@ from __future__ import annotations
|
|
|
3
3
|
import json
|
|
4
4
|
|
|
5
5
|
from typing import TYPE_CHECKING
|
|
6
|
+
|
|
6
7
|
from django.http import JsonResponse
|
|
7
8
|
|
|
9
|
+
from django_spire.ai.chat.intelligence.workflows.chat_workflow import chat_workflow
|
|
8
10
|
from django_spire.ai.chat.models import Chat
|
|
9
|
-
from django_spire.ai.chat.tools import chat_workflow_process
|
|
10
11
|
|
|
11
12
|
if TYPE_CHECKING:
|
|
12
13
|
from django.core.handlers.wsgi import WSGIRequest
|
|
@@ -50,6 +51,6 @@ def rename_chat_view(request: WSGIRequest, pk: int) -> JsonResponse:
|
|
|
50
51
|
return JsonResponse({'type': 'success'})
|
|
51
52
|
|
|
52
53
|
|
|
53
|
-
def
|
|
54
|
+
def chat_workflow_view(request: WSGIRequest) -> JsonResponse:
|
|
54
55
|
body = json.loads(request.body.decode('utf-8'))
|
|
55
|
-
return JsonResponse({'response':
|
|
56
|
+
return JsonResponse({'response': chat_workflow(request, body)})
|
|
@@ -2,28 +2,45 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
4
|
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
6
|
+
|
|
5
7
|
from django.conf import settings
|
|
6
8
|
from django.http import HttpResponse
|
|
9
|
+
from django.utils.timezone import now
|
|
7
10
|
|
|
11
|
+
from django_spire.ai.chat.choices import MessageResponseType
|
|
8
12
|
from django_spire.ai.chat.message_intel import DefaultMessageIntel
|
|
9
13
|
from django_spire.ai.chat.models import Chat
|
|
10
|
-
from django_spire.ai.chat.responses import
|
|
11
|
-
from django_spire.ai.chat.choices import MessageResponseType
|
|
12
|
-
from django_spire.consts import AI_CHAT_WORKFLOW_SENDER_SETTINGS_NAME
|
|
14
|
+
from django_spire.ai.chat.responses import MessageResponse, MessageResponseGroup
|
|
13
15
|
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
|
+
from django.core.handlers.wsgi import WSGIRequest
|
|
14
18
|
|
|
15
|
-
|
|
19
|
+
|
|
20
|
+
def request_message_render_view(request: WSGIRequest) -> HttpResponse:
|
|
16
21
|
body_data = json.loads(request.body)
|
|
17
22
|
|
|
18
|
-
|
|
19
|
-
Chat.objects
|
|
20
|
-
.by_user(request.user)
|
|
21
|
-
.get(id=body_data['chat_id'])
|
|
22
|
-
)
|
|
23
|
+
chat_id = body_data['chat_id']
|
|
23
24
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
current_datetime = now()
|
|
26
|
+
formatted_timestamp = current_datetime.strftime('%b %d, %Y at %I:%M %p')
|
|
27
|
+
|
|
28
|
+
if chat_id in {0, '0', ''}:
|
|
29
|
+
chat = Chat.objects.create(
|
|
30
|
+
user=request.user,
|
|
31
|
+
name=body_data['message_body'],
|
|
32
|
+
last_message_datetime=current_datetime
|
|
33
|
+
)
|
|
34
|
+
else:
|
|
35
|
+
chat = (
|
|
36
|
+
Chat.objects
|
|
37
|
+
.by_user(request.user)
|
|
38
|
+
.get(id=chat_id)
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
if chat.is_empty:
|
|
42
|
+
chat.name = body_data['message_body']
|
|
43
|
+
chat.save()
|
|
27
44
|
|
|
28
45
|
message_response_group = MessageResponseGroup()
|
|
29
46
|
|
|
@@ -32,7 +49,8 @@ def request_message_render_view(request):
|
|
|
32
49
|
sender='You',
|
|
33
50
|
message_intel=DefaultMessageIntel(
|
|
34
51
|
text=body_data['message_body']
|
|
35
|
-
)
|
|
52
|
+
),
|
|
53
|
+
message_timestamp=formatted_timestamp
|
|
36
54
|
)
|
|
37
55
|
|
|
38
56
|
message_response_group.add_message_response(
|
|
@@ -56,7 +74,7 @@ def request_message_render_view(request):
|
|
|
56
74
|
message_response_group.render_to_html_string(
|
|
57
75
|
context_data={
|
|
58
76
|
"chat_id": chat.id,
|
|
59
|
-
"chat_workflow_name":
|
|
77
|
+
"chat_workflow_name": settings.AI_PERSONA_NAME,
|
|
60
78
|
}
|
|
61
79
|
)
|
|
62
80
|
)
|
|
@@ -2,38 +2,41 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
4
|
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
6
|
+
|
|
5
7
|
from django.conf import settings
|
|
6
8
|
from django.http import HttpResponse
|
|
9
|
+
from django.utils.timezone import now
|
|
7
10
|
|
|
11
|
+
from django_spire.ai.chat.intelligence.workflows.chat_workflow import chat_workflow
|
|
8
12
|
from django_spire.ai.chat.models import Chat
|
|
9
13
|
from django_spire.ai.chat.responses import MessageResponse
|
|
10
14
|
from django_spire.ai.chat.choices import MessageResponseType
|
|
11
|
-
from django_spire.ai.chat.tools import chat_workflow_process
|
|
12
|
-
from django_spire.consts import AI_CHAT_WORKFLOW_SENDER_SETTINGS_NAME
|
|
13
|
-
|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
|
+
from django.core.handlers.wsgi import WSGIRequest
|
|
17
18
|
|
|
18
|
-
chat_workflow_name = getattr(settings, AI_CHAT_WORKFLOW_SENDER_SETTINGS_NAME)
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
raise ValueError(message)
|
|
20
|
+
def response_message_render_view(request: WSGIRequest) -> HttpResponse:
|
|
21
|
+
body_data = json.loads(request.body)
|
|
23
22
|
|
|
24
23
|
chat = Chat.objects.by_user(request.user).get(id=body_data['chat_id'])
|
|
25
24
|
|
|
26
|
-
message_intel =
|
|
25
|
+
message_intel = chat_workflow(
|
|
27
26
|
request,
|
|
28
27
|
body_data['message_body'],
|
|
29
28
|
message_history=chat.generate_message_history(),
|
|
30
29
|
)
|
|
31
30
|
|
|
31
|
+
current_datetime = now()
|
|
32
|
+
formatted_timestamp = current_datetime.strftime('%b %d, %Y at %I:%M %p')
|
|
33
|
+
|
|
32
34
|
response_message = MessageResponse(
|
|
33
35
|
type=MessageResponseType.RESPONSE,
|
|
34
|
-
sender=
|
|
36
|
+
sender=settings.AI_PERSONA_NAME,
|
|
35
37
|
message_intel=message_intel,
|
|
36
38
|
synthesis_speech=body_data.get('synthesis_speech', False),
|
|
39
|
+
message_timestamp=formatted_timestamp
|
|
37
40
|
)
|
|
38
41
|
|
|
39
42
|
chat.add_message_response(response_message)
|
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
3
5
|
from django.http import HttpResponse
|
|
4
6
|
|
|
5
7
|
from django_spire.ai.chat.models import Chat
|
|
6
8
|
from django_spire.ai.chat.responses import MessageResponseGroup
|
|
7
9
|
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from django.core.handlers.wsgi import WSGIRequest
|
|
12
|
+
|
|
8
13
|
|
|
9
|
-
def load_messages_render_view(request, chat_id):
|
|
14
|
+
def load_messages_render_view(request: WSGIRequest, chat_id: int) -> HttpResponse:
|
|
10
15
|
chat = (
|
|
11
16
|
Chat.objects
|
|
12
17
|
.by_user(request.user)
|
|
@@ -24,6 +29,7 @@ def load_messages_render_view(request, chat_id):
|
|
|
24
29
|
message_group.render_to_html_string(
|
|
25
30
|
{
|
|
26
31
|
'chat_id': chat.id,
|
|
32
|
+
'is_loading': True,
|
|
27
33
|
}
|
|
28
34
|
)
|
|
29
35
|
)
|
|
@@ -12,7 +12,7 @@ if TYPE_CHECKING:
|
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
@AppAuthController('ai_chat').permission_required('can_delete')
|
|
15
|
-
def
|
|
15
|
+
def chat_view(request: WSGIRequest) -> TemplateResponse:
|
|
16
16
|
breadcrumbs = Breadcrumbs()
|
|
17
17
|
breadcrumbs.add_breadcrumb(name='AI Chat')
|
|
18
18
|
|
|
@@ -22,5 +22,5 @@ def home_view(request: WSGIRequest) -> TemplateResponse:
|
|
|
22
22
|
page_title='AI Chat',
|
|
23
23
|
page_description='Chat with AI',
|
|
24
24
|
breadcrumbs=breadcrumbs,
|
|
25
|
-
template='django_spire/ai/chat/page/
|
|
25
|
+
template='django_spire/ai/chat/page/chat_page.html',
|
|
26
26
|
)
|
|
@@ -23,13 +23,7 @@ def dialog_widget_view(request) -> TemplateResponse:
|
|
|
23
23
|
chat_id = body_data['chat_id']
|
|
24
24
|
|
|
25
25
|
if chat_id == 0:
|
|
26
|
-
chat =
|
|
27
|
-
user=request.user
|
|
28
|
-
)
|
|
29
|
-
chat.name = 'New Chat'
|
|
30
|
-
chat.last_message_datetime = now()
|
|
31
|
-
chat.save()
|
|
32
|
-
|
|
26
|
+
chat = None
|
|
33
27
|
else:
|
|
34
28
|
chat = Chat.objects.get(
|
|
35
29
|
id=chat_id,
|
|
File without changes
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from django.contrib import admin
|
|
4
|
+
|
|
5
|
+
from django_spire.ai.context import models
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@admin.register(models.Organization)
|
|
9
|
+
class OrganizationAdmin(admin.ModelAdmin):
|
|
10
|
+
list_display = ('id', 'name', 'created_datetime', 'is_deleted')
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@admin.register(models.Person)
|
|
14
|
+
class PersonAdmin(admin.ModelAdmin):
|
|
15
|
+
list_display = ('id', 'first_name', 'created_datetime', 'is_deleted')
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from django.apps import AppConfig
|
|
4
|
+
|
|
5
|
+
from django_spire.utils import check_required_apps
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class AiContextConfig(AppConfig):
|
|
9
|
+
default_auto_field = 'django.db.models.BigAutoField'
|
|
10
|
+
name = 'django_spire.ai.context'
|
|
11
|
+
label = 'django_spire_ai_context'
|
|
12
|
+
|
|
13
|
+
REQUIRED_APPS = ('django_spire_ai',)
|
|
14
|
+
|
|
15
|
+
def ready(self) -> None:
|
|
16
|
+
check_required_apps(self.label)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from django.db.models import TextChoices
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class PersonRoleChoices(TextChoices):
|
|
5
|
+
ADMIN = 'admin', 'Admin'
|
|
6
|
+
HUMAN_RESOURCES = 'human_resources', 'Human Resources'
|
|
7
|
+
SALES = 'sales', 'Sales'
|
|
8
|
+
MANAGER = 'manager', 'Manager'
|
|
9
|
+
MARKETING = 'marketing', 'Marketing'
|
|
10
|
+
TECHNICAL = 'technical', 'Technical'
|
|
11
|
+
IT_SUPPORT = 'it_support', 'IT Support'
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dandy import Prompt
|
|
4
|
+
from django.forms import model_to_dict
|
|
5
|
+
|
|
6
|
+
from django_spire.ai.context.models import Organization
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def organization_info_prompt() -> Prompt:
|
|
10
|
+
org = Organization.objects.get_only_or_none()
|
|
11
|
+
|
|
12
|
+
if org is None:
|
|
13
|
+
return Prompt().text('There is no organization information available.')
|
|
14
|
+
|
|
15
|
+
org_dict = model_to_dict(
|
|
16
|
+
org, exclude=['id', 'created_datetime', 'is_active', 'is_deleted']
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
return Prompt().heading('Organization Information').dict(org_dict)
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Generated by Django 5.2.7 on 2025-10-27 16:34
|
|
2
|
+
|
|
3
|
+
import django.db.models.deletion
|
|
4
|
+
import django.utils.timezone
|
|
5
|
+
from django.db import migrations, models
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Migration(migrations.Migration):
|
|
9
|
+
|
|
10
|
+
initial = True
|
|
11
|
+
|
|
12
|
+
dependencies = [
|
|
13
|
+
('django_spire_auth_user', '0001_initial'),
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
operations = [
|
|
17
|
+
migrations.CreateModel(
|
|
18
|
+
name='Organization',
|
|
19
|
+
fields=[
|
|
20
|
+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
21
|
+
('is_active', models.BooleanField(default=True, editable=False)),
|
|
22
|
+
('is_deleted', models.BooleanField(default=False, editable=False)),
|
|
23
|
+
('created_datetime', models.DateTimeField(default=django.utils.timezone.localtime, editable=False)),
|
|
24
|
+
('name', models.CharField(blank=True, max_length=255, null=True)),
|
|
25
|
+
('legal_name', models.CharField(blank=True, max_length=255, null=True)),
|
|
26
|
+
('description', models.TextField(blank=True, null=True)),
|
|
27
|
+
('sector', models.CharField(blank=True, max_length=255, null=True)),
|
|
28
|
+
('sub_sector', models.CharField(blank=True, max_length=255, null=True)),
|
|
29
|
+
('website', models.URLField(blank=True, max_length=255, null=True)),
|
|
30
|
+
('street_address', models.CharField(blank=True, max_length=255, null=True)),
|
|
31
|
+
('unit_number', models.CharField(blank=True, max_length=32, null=True)),
|
|
32
|
+
('city', models.CharField(blank=True, max_length=255, null=True)),
|
|
33
|
+
('province', models.CharField(blank=True, max_length=255, null=True)),
|
|
34
|
+
('postal_code', models.CharField(blank=True, max_length=16, null=True)),
|
|
35
|
+
('country', models.CharField(blank=True, max_length=255, null=True)),
|
|
36
|
+
('phone', models.CharField(blank=True, max_length=255, null=True)),
|
|
37
|
+
('email', models.EmailField(blank=True, max_length=255, null=True)),
|
|
38
|
+
],
|
|
39
|
+
options={
|
|
40
|
+
'verbose_name': 'Organization Context',
|
|
41
|
+
'verbose_name_plural': 'Organization Context',
|
|
42
|
+
'db_table': 'django_spire_ai_context_organization',
|
|
43
|
+
},
|
|
44
|
+
),
|
|
45
|
+
migrations.CreateModel(
|
|
46
|
+
name='Person',
|
|
47
|
+
fields=[
|
|
48
|
+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
49
|
+
('is_active', models.BooleanField(default=True, editable=False)),
|
|
50
|
+
('is_deleted', models.BooleanField(default=False, editable=False)),
|
|
51
|
+
('created_datetime', models.DateTimeField(default=django.utils.timezone.localtime, editable=False)),
|
|
52
|
+
('is_internal_to_organization', models.BooleanField(default=True)),
|
|
53
|
+
('role', models.CharField(choices=[('admin', 'Admin'), ('human_resources', 'Human Resources'), ('sales', 'Sales'), ('manager', 'Manager'), ('marketing', 'Marketing'), ('technical', 'Technical'), ('it_support', 'IT Support')], default='admin', max_length=16)),
|
|
54
|
+
('role_details', models.TextField(blank=True, null=True)),
|
|
55
|
+
('first_name', models.CharField(blank=True, max_length=255, null=True)),
|
|
56
|
+
('last_name', models.CharField(blank=True, max_length=255, null=True)),
|
|
57
|
+
('phone', models.CharField(blank=True, max_length=255, null=True)),
|
|
58
|
+
('email', models.EmailField(blank=True, max_length=255, null=True)),
|
|
59
|
+
('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='ai_context_people', related_query_name='ai_context_person', to='django_spire_auth_user.authuser')),
|
|
60
|
+
],
|
|
61
|
+
options={
|
|
62
|
+
'verbose_name': 'Person Context',
|
|
63
|
+
'verbose_name_plural': 'People Context',
|
|
64
|
+
'db_table': 'django_spire_ai_context_person',
|
|
65
|
+
},
|
|
66
|
+
),
|
|
67
|
+
]
|
|
File without changes
|