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.
- 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 +55 -57
- 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 +9 -4
- django_spire/ai/chat/templates/django_spire/ai/chat/message/message.html +33 -33
- 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 -24
- 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/management/commands/spire_startapp_pkg/__init__.py +4 -20
- django_spire/core/management/commands/spire_startapp_pkg/builder.py +2 -2
- django_spire/core/management/commands/spire_startapp_pkg/config.py +2 -2
- django_spire/core/management/commands/spire_startapp_pkg/filesystem.py +1 -19
- django_spire/core/management/commands/spire_startapp_pkg/generator.py +8 -8
- django_spire/core/management/commands/spire_startapp_pkg/processor.py +3 -3
- django_spire/core/management/commands/spire_startapp_pkg/registry.py +0 -16
- django_spire/core/management/commands/spire_startapp_pkg/reporter.py +1 -21
- django_spire/core/management/commands/spire_startapp_pkg/resolver.py +0 -15
- django_spire/core/management/commands/spire_startapp_pkg/template/app/views/form_views.py.template +2 -2
- django_spire/core/management/commands/spire_startapp_pkg/template/app/views/page_views.py.template +2 -2
- django_spire/core/management/commands/spire_startapp_pkg/validator.py +9 -9
- 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 +223 -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.1.dist-info}/METADATA +3 -3
- {django_spire-0.18.3.dist-info → django_spire-0.19.1.dist-info}/RECORD +229 -190
- 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.1.dist-info}/WHEEL +0 -0
- {django_spire-0.18.3.dist-info → django_spire-0.19.1.dist-info}/licenses/LICENSE.md +0 -0
- {django_spire-0.18.3.dist-info → django_spire-0.19.1.dist-info}/top_level.txt +0 -0
django_spire/ai/admin.py
CHANGED
|
@@ -35,6 +35,7 @@ class AiUsageAdmin(AiUsageAdminMixin):
|
|
|
35
35
|
was_successful: bool | None = None,
|
|
36
36
|
) -> str:
|
|
37
37
|
was_successful_filter = '' if was_successful is None else f'&was_successful__exact={int(was_successful)}'
|
|
38
|
+
|
|
38
39
|
url = (
|
|
39
40
|
reverse("admin:django_spire_ai_aiinteraction_changelist")
|
|
40
41
|
+ "?"
|
django_spire/ai/chat/apps.py
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from django.apps import AppConfig
|
|
4
|
-
from django.conf import settings
|
|
5
|
-
|
|
6
|
-
from django_spire.consts import AI_CHAT_WORKFLOW_CLASS_SETTINGS_NAME
|
|
7
4
|
from django_spire.utils import check_required_apps
|
|
8
5
|
|
|
9
6
|
|
|
@@ -20,11 +17,7 @@ class AiChatConfig(AppConfig):
|
|
|
20
17
|
},
|
|
21
18
|
)
|
|
22
19
|
|
|
23
|
-
REQUIRED_APPS = ('django_spire_ai',)
|
|
20
|
+
REQUIRED_APPS = ('django_spire_ai', 'django_spire_ai_context')
|
|
24
21
|
|
|
25
22
|
def ready(self) -> None:
|
|
26
|
-
if not isinstance(getattr(settings, AI_CHAT_WORKFLOW_CLASS_SETTINGS_NAME), str):
|
|
27
|
-
message = f'"{AI_CHAT_WORKFLOW_CLASS_SETTINGS_NAME}" must be set in the django settings when using "{self.label}".'
|
|
28
|
-
raise TypeError(message)
|
|
29
|
-
|
|
30
23
|
check_required_apps(self.label)
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Callable, TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
from dandy import Decoder
|
|
6
|
+
|
|
7
|
+
from django_spire.auth.controller.controller import AppAuthController
|
|
8
|
+
from django_spire.knowledge.intelligence.workflows.knowledge_workflow import knowledge_search_workflow
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from django.core.handlers.wsgi import WSGIRequest
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def generate_intent_decoder(
|
|
15
|
+
request: WSGIRequest,
|
|
16
|
+
default_callable: Callable | None = None
|
|
17
|
+
) -> Decoder:
|
|
18
|
+
intent_dict = {}
|
|
19
|
+
|
|
20
|
+
if AppAuthController(app_name='knowledge', request=request).can_view():
|
|
21
|
+
intent_dict['The user is looking for information or knowledge on something.'] = knowledge_search_workflow
|
|
22
|
+
|
|
23
|
+
if default_callable is not None:
|
|
24
|
+
intent_dict['None of the above choices match the user\'s intent'] = default_callable
|
|
25
|
+
|
|
26
|
+
return Decoder(
|
|
27
|
+
mapping_keys_description='Intent of the User\'s Request',
|
|
28
|
+
mapping=intent_dict
|
|
29
|
+
)
|
|
@@ -2,18 +2,24 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from dandy import Prompt
|
|
4
4
|
|
|
5
|
-
from django_spire.
|
|
5
|
+
from django_spire.ai.context.intelligence.prompts.organization_prompts import (
|
|
6
|
+
organization_info_prompt
|
|
7
|
+
)
|
|
6
8
|
|
|
7
9
|
|
|
8
|
-
def
|
|
10
|
+
def chat_system_prompt() -> Prompt:
|
|
9
11
|
return (
|
|
10
12
|
Prompt()
|
|
11
|
-
.text(
|
|
13
|
+
.text(
|
|
14
|
+
'You are a chat assistant, please use the organization information below for answering questions.'
|
|
15
|
+
)
|
|
12
16
|
.line_break()
|
|
13
|
-
.
|
|
17
|
+
.prompt(organization_info_prompt())
|
|
14
18
|
.line_break()
|
|
15
19
|
.text('Make sure to follow the rules below')
|
|
16
|
-
.list(
|
|
17
|
-
|
|
18
|
-
|
|
20
|
+
.list(
|
|
21
|
+
[
|
|
22
|
+
'Do not talk about being an AI at all to maintain the illusion of being a human assistant.',
|
|
23
|
+
]
|
|
24
|
+
)
|
|
19
25
|
)
|
|
@@ -1,71 +1,69 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from typing import TYPE_CHECKING
|
|
3
|
+
from typing import TYPE_CHECKING, Callable
|
|
4
4
|
|
|
5
|
-
from dandy import
|
|
5
|
+
from dandy import Bot
|
|
6
6
|
from dandy.recorder import recorder_to_html_file
|
|
7
7
|
|
|
8
|
-
from django_spire.ai.chat.intelligence.
|
|
9
|
-
from django_spire.ai.chat.
|
|
10
|
-
from django_spire.ai.
|
|
11
|
-
from django_spire.ai.chat.message_intel import DefaultMessageIntel
|
|
12
|
-
from django_spire.auth.controller.controller import AppAuthController
|
|
8
|
+
from django_spire.ai.chat.intelligence.decoders.tools import generate_intent_decoder
|
|
9
|
+
from django_spire.ai.chat.message_intel import BaseMessageIntel, DefaultMessageIntel
|
|
10
|
+
from django_spire.ai.decorators import log_ai_interaction_from_recorder
|
|
13
11
|
|
|
14
12
|
if TYPE_CHECKING:
|
|
15
13
|
from dandy.llm.request.message import MessageHistory
|
|
16
14
|
from django.core.handlers.wsgi import WSGIRequest
|
|
17
15
|
|
|
18
|
-
from django_spire.ai.chat.message_intel import BaseMessageIntel
|
|
19
16
|
|
|
17
|
+
def SpireChatWorkflow(
|
|
18
|
+
request: WSGIRequest,
|
|
19
|
+
user_input: str,
|
|
20
|
+
message_history: MessageHistory | None = None
|
|
21
|
+
) -> BaseMessageIntel:
|
|
22
|
+
return chat_workflow(
|
|
23
|
+
request=request,
|
|
24
|
+
user_input=user_input,
|
|
25
|
+
message_history=message_history
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def default_chat_response(
|
|
30
|
+
request: WSGIRequest,
|
|
31
|
+
user_input: str,
|
|
32
|
+
message_history: MessageHistory | None = None
|
|
33
|
+
) -> BaseMessageIntel:
|
|
34
|
+
bot = Bot()
|
|
35
|
+
return bot.llm.prompt_to_intel(
|
|
36
|
+
prompt=user_input,
|
|
37
|
+
intel_class=DefaultMessageIntel,
|
|
38
|
+
message_history=message_history,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@recorder_to_html_file('spire_ai_chat_workflow')
|
|
43
|
+
def chat_workflow(
|
|
44
|
+
request: WSGIRequest,
|
|
45
|
+
user_input: str,
|
|
46
|
+
message_history: MessageHistory | None = None
|
|
47
|
+
) -> BaseMessageIntel:
|
|
48
|
+
intent_decoder = generate_intent_decoder(
|
|
49
|
+
request=request,
|
|
50
|
+
default_callable=default_chat_response,
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
intent_process = intent_decoder.process(user_input, max_return_values=1)[0]
|
|
54
|
+
|
|
55
|
+
@log_ai_interaction_from_recorder(request.user)
|
|
56
|
+
def run_workflow_process(callable_: Callable) -> BaseMessageIntel | None:
|
|
57
|
+
return callable_(
|
|
58
|
+
request=request,
|
|
59
|
+
user_input=user_input,
|
|
60
|
+
message_history=message_history,
|
|
61
|
+
)
|
|
20
62
|
|
|
21
|
-
|
|
22
|
-
@staticmethod
|
|
23
|
-
def _generate_intent_decoder(request: WSGIRequest) -> IntentDecoder:
|
|
24
|
-
from django_spire.knowledge.intelligence.workflows.knowledge_workflow import KnowledgeWorkflow
|
|
25
|
-
|
|
26
|
-
intent_dict = {}
|
|
27
|
-
|
|
28
|
-
if AppAuthController(app_name='knowledge', request=request).can_view():
|
|
29
|
-
intent_message = (
|
|
30
|
-
'The user is looking for information or knowledge on something.'
|
|
31
|
-
)
|
|
32
|
-
|
|
33
|
-
intent_dict[intent_message] = KnowledgeWorkflow
|
|
34
|
-
|
|
35
|
-
intent_dict['None of the above choices match the user\'s intent'] = None
|
|
36
|
-
|
|
37
|
-
decoder = IntentDecoder()
|
|
38
|
-
decoder.mapping = intent_dict
|
|
39
|
-
return decoder
|
|
40
|
-
|
|
41
|
-
@staticmethod
|
|
42
|
-
@recorder_to_html_file('spire_chat_workflow')
|
|
43
|
-
def process(
|
|
44
|
-
request: WSGIRequest,
|
|
45
|
-
user_input: str,
|
|
46
|
-
message_history: MessageHistory | None = None
|
|
47
|
-
) -> BaseMessageIntel:
|
|
48
|
-
intent_decoder = SpireChatWorkflow._generate_intent_decoder(request)
|
|
49
|
-
intents = intent_decoder.process(user_input, max_return_values=1)
|
|
50
|
-
|
|
51
|
-
chat_bot = ChatBot()
|
|
63
|
+
message_intel = run_workflow_process(intent_process)
|
|
52
64
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
intel_class=DefaultMessageIntel,
|
|
57
|
-
message_history=message_history,
|
|
58
|
-
postfix_system_prompt=organization_prompt()
|
|
59
|
-
)
|
|
65
|
+
if not isinstance(message_intel, BaseMessageIntel):
|
|
66
|
+
message = f'{intent_process.__qualname__} must return an instance of a {BaseMessageIntel.__name__} sub class.'
|
|
67
|
+
raise TypeError(message)
|
|
60
68
|
|
|
61
|
-
|
|
62
|
-
prompt=(
|
|
63
|
-
Prompt()
|
|
64
|
-
.text(f'User Input: {user_input}')
|
|
65
|
-
.line_break()
|
|
66
|
-
.text(intents[0].process(user_input))
|
|
67
|
-
),
|
|
68
|
-
intel_class=DefaultMessageIntel,
|
|
69
|
-
message_history=message_history,
|
|
70
|
-
postfix_system_prompt=organization_prompt()
|
|
71
|
-
)
|
|
69
|
+
return message_intel
|
django_spire/ai/chat/models.py
CHANGED
|
@@ -143,7 +143,8 @@ class ChatMessage(HistoryModelMixin):
|
|
|
143
143
|
return MessageResponse(
|
|
144
144
|
type=MessageResponseType(self.response_type),
|
|
145
145
|
sender=self.sender,
|
|
146
|
-
message_intel=self.intel
|
|
146
|
+
message_intel=self.intel,
|
|
147
|
+
message_timestamp=self.created_datetime.strftime('%b %d, %Y at %I:%M %p')
|
|
147
148
|
)
|
|
148
149
|
|
|
149
150
|
class Meta:
|
|
@@ -18,12 +18,14 @@ class MessageResponse:
|
|
|
18
18
|
type: MessageResponseType
|
|
19
19
|
sender: str
|
|
20
20
|
message_intel: BaseMessageIntel
|
|
21
|
+
message_timestamp: str | None = None
|
|
21
22
|
synthesis_speech: bool = False
|
|
22
23
|
|
|
23
24
|
def _render_template_to_html_string(self, template: str, context_data: dict[str, Any] | None = None) -> str:
|
|
24
25
|
return render_to_string(
|
|
25
26
|
template_name=template,
|
|
26
27
|
context={
|
|
28
|
+
'message_timestamp': self.message_timestamp,
|
|
27
29
|
'sender': self.sender,
|
|
28
30
|
'message_intel': self.message_intel,
|
|
29
31
|
'synthesis_speech': self.synthesis_speech,
|
|
@@ -63,6 +65,9 @@ class MessageResponseGroup:
|
|
|
63
65
|
def render_to_html_string(self, context_data: dict[str, Any] | None = None) -> str:
|
|
64
66
|
html_string = ''
|
|
65
67
|
|
|
68
|
+
context_data = context_data or {}
|
|
69
|
+
context_data['is_loading'] = context_data.get('is_loading', False)
|
|
70
|
+
|
|
66
71
|
for message_response in self.message_responses:
|
|
67
72
|
html_string += message_response.render_to_html_string(context_data)
|
|
68
73
|
|
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
|
|
7
7
|
{% block card_content %}
|
|
8
8
|
<div class="row">
|
|
9
|
-
<div class="col-12 vh-minus-nav">
|
|
10
|
-
{% include 'django_spire/ai/chat/widget/
|
|
9
|
+
<div class="col-12 vh-minus-top-nav">
|
|
10
|
+
{% include 'django_spire/ai/chat/widget/selection_widget.html' %}
|
|
11
11
|
</div>
|
|
12
12
|
</div>
|
|
13
13
|
{% endblock %}
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
{% endblock %}
|
|
12
12
|
|
|
13
13
|
{% block dropdown_content %}
|
|
14
|
-
{% include 'django_spire/dropdown/element/dropdown_link_element.html' with x_click="enable_rename_chat()" link_text='Rename' link_css='text-start' %}
|
|
14
|
+
{% include 'django_spire/dropdown/element/dropdown_link_element.html' with x_click="enable_rename_chat(); toggle_dropdown()" link_text='Rename' link_css='text-start' %}
|
|
15
15
|
|
|
16
16
|
{% url 'django_spire:ai:chat:template:confirm_delete' pk=recent_chat.id as delete_url %}
|
|
17
17
|
{% include 'django_spire/dropdown/element/ellipsis_dropdown_modal_link_element.html' with view_url=delete_url link_text='Delete' link_css='text-app-danger text-start' %}
|
|
@@ -1,84 +1,122 @@
|
|
|
1
1
|
<div
|
|
2
|
-
class="
|
|
2
|
+
class="mb-1"
|
|
3
3
|
x-data="{
|
|
4
4
|
can_rename_chat: false,
|
|
5
5
|
chat_name: '{{ recent_chat.name|escapejs }}',
|
|
6
|
+
is_active: false,
|
|
6
7
|
new_chat_name: '{{ recent_chat.name|escapejs }}',
|
|
7
8
|
show_recent_chat: true,
|
|
8
9
|
|
|
10
|
+
cancel_rename_chat() {
|
|
11
|
+
this.new_chat_name = this.chat_name
|
|
12
|
+
this.can_rename_chat = false
|
|
13
|
+
},
|
|
14
|
+
|
|
15
|
+
confirm_rename_chat() {
|
|
16
|
+
this.rename_chat()
|
|
17
|
+
},
|
|
18
|
+
|
|
9
19
|
disable_rename_chat() {
|
|
10
20
|
this.can_rename_chat = false
|
|
11
21
|
},
|
|
22
|
+
|
|
12
23
|
enable_rename_chat() {
|
|
13
24
|
this.can_rename_chat = true
|
|
25
|
+
|
|
26
|
+
$nextTick(() => {
|
|
27
|
+
let input = this.$el.querySelector('input')
|
|
28
|
+
if (input) input.focus()
|
|
29
|
+
})
|
|
14
30
|
},
|
|
31
|
+
|
|
15
32
|
async rename_chat() {
|
|
33
|
+
if (this.new_chat_name.trim() === '') {
|
|
34
|
+
this.new_chat_name = this.chat_name
|
|
35
|
+
this.can_rename_chat = false
|
|
36
|
+
return
|
|
37
|
+
}
|
|
38
|
+
|
|
16
39
|
let response = await django_glue_fetch(
|
|
17
40
|
'{% url "django_spire:ai:chat:json:rename" pk=recent_chat.pk %}',
|
|
18
41
|
{payload: {new_name: this.new_chat_name}}
|
|
19
42
|
)
|
|
20
43
|
|
|
21
44
|
let type = response.type
|
|
45
|
+
|
|
22
46
|
if (type === 'success') {
|
|
23
47
|
this.chat_name = this.new_chat_name
|
|
24
48
|
} else {
|
|
25
49
|
$dispatch('notify', {'type': type, 'message': response.message})
|
|
50
|
+
this.new_chat_name = this.chat_name
|
|
26
51
|
}
|
|
27
52
|
|
|
28
53
|
this.can_rename_chat = false
|
|
29
54
|
}
|
|
30
55
|
}"
|
|
31
56
|
x-show="show_recent_chat"
|
|
57
|
+
@chat-activated.window="is_active = ($event.detail.chat_id === {{ recent_chat.id }})"
|
|
58
|
+
@click.outside="if (can_rename_chat) cancel_rename_chat()"
|
|
32
59
|
@deleted_chat.window="if (show_recent_chat) show_recent_chat = $event.detail !== {{ recent_chat.id }}"
|
|
33
60
|
>
|
|
34
|
-
<div
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
61
|
+
<div
|
|
62
|
+
:class="is_active ? 'bg-app-primary-soft' : ''"
|
|
63
|
+
class="d-flex align-items-center justify-content-between px-2 py-1 rounded"
|
|
64
|
+
data-chat-id="{{ recent_chat.id }}"
|
|
65
|
+
style="transition: background-color 0.15s ease;"
|
|
66
|
+
>
|
|
67
|
+
<div class="d-flex align-items-center flex-grow-1" style="min-width: 0; width: 0;">
|
|
68
|
+
<i
|
|
69
|
+
:class="{
|
|
70
|
+
'bi-chat-dots-fill': !can_rename_chat,
|
|
71
|
+
'bi-chat-dots': can_rename_chat,
|
|
72
|
+
'text-app-primary': is_active || can_rename_chat,
|
|
73
|
+
'text-muted': !is_active && !can_rename_chat
|
|
42
74
|
}"
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
<
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
75
|
+
class="bi me-2"
|
|
76
|
+
style="flex-shrink: 0;"
|
|
77
|
+
></i>
|
|
78
|
+
|
|
79
|
+
<template x-if="!can_rename_chat">
|
|
80
|
+
<div @click="$dispatch('load-chat', {chat_id: {{ recent_chat.id }}})" class="cursor-pointer flex-grow-1 text-truncate">
|
|
81
|
+
<span class="px-2 fs-7" x-text="chat_name"></span>
|
|
82
|
+
</div>
|
|
83
|
+
</template>
|
|
84
|
+
|
|
85
|
+
<template x-if="can_rename_chat">
|
|
86
|
+
<div class="d-flex align-items-center position-relative w-100 py-0 px-1" style="flex: 1 1 0; min-width: 0;">
|
|
53
87
|
<input
|
|
54
|
-
x-model="new_chat_name"
|
|
55
|
-
class="col form-control d-inline p-0 mx-1 fs-7"
|
|
56
|
-
type="text"
|
|
57
|
-
style="max-width: 150px;"
|
|
58
|
-
@keydown.enter="rename_chat()"
|
|
59
|
-
@keydown.esc="disable_rename_chat()"
|
|
60
88
|
@focus="$el.select()"
|
|
89
|
+
@keydown.enter="confirm_rename_chat()"
|
|
90
|
+
@keydown.esc="cancel_rename_chat()"
|
|
91
|
+
class="form-control ps-1 pe-5 py-0 fs-7"
|
|
92
|
+
type="text"
|
|
93
|
+
x-init="$el.focus()"
|
|
94
|
+
x-model="new_chat_name"
|
|
61
95
|
/>
|
|
62
|
-
<
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
96
|
+
<div class="d-flex align-items-center position-absolute g-2" style="pointer-events: none; right: 8px;">
|
|
97
|
+
<i
|
|
98
|
+
@click="confirm_rename_chat()"
|
|
99
|
+
@mouseenter="$el.style.opacity = '0.75'"
|
|
100
|
+
@mouseleave="$el.style.opacity = '1'"
|
|
101
|
+
class="bi bi-check cursor-pointer text-success"
|
|
102
|
+
style="pointer-events: auto; transition: opacity 0.15s ease;"
|
|
103
|
+
title="Confirm"
|
|
104
|
+
></i>
|
|
105
|
+
<i
|
|
106
|
+
@click="cancel_rename_chat()"
|
|
107
|
+
@mouseenter="$el.style.opacity = '0.75'"
|
|
108
|
+
@mouseleave="$el.style.opacity = '1'"
|
|
109
|
+
class="bi bi-x cursor-pointer text-danger pe-1"
|
|
110
|
+
style="pointer-events: auto; transition: opacity 0.15s ease;"
|
|
111
|
+
title="Cancel"
|
|
112
|
+
></i>
|
|
113
|
+
</div>
|
|
80
114
|
</div>
|
|
81
|
-
|
|
115
|
+
</template>
|
|
116
|
+
</div>
|
|
117
|
+
|
|
118
|
+
<div class="ms-2" style="flex-shrink: 0; visibility: hidden;" :style="can_rename_chat ? '' : 'visibility: visible;'">
|
|
119
|
+
{% include 'django_spire/ai/chat/dropdown/ellipsis_dropdown.html' %}
|
|
82
120
|
</div>
|
|
83
121
|
</div>
|
|
84
122
|
</div>
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
{% load spire_core_tags %}
|
|
2
2
|
|
|
3
3
|
{% generate_id as response_message_intel_id %}
|
|
4
|
+
|
|
4
5
|
<div
|
|
5
6
|
x-data="{
|
|
6
7
|
show_loading: false,
|
|
7
8
|
show_reading: true,
|
|
8
9
|
show_typing: false,
|
|
10
|
+
|
|
9
11
|
init() {
|
|
10
12
|
this.response_message.render_outer($refs.loading_response_message)
|
|
11
13
|
|
|
@@ -14,6 +16,7 @@
|
|
|
14
16
|
setTimeout(() => {this.show_reading = false}, 4000)
|
|
15
17
|
setTimeout(() => {this.show_typing = true}, 4000)
|
|
16
18
|
},
|
|
19
|
+
|
|
17
20
|
response_message: new ViewGlue(
|
|
18
21
|
'{% url "django_spire:ai:chat:message:response:new" %}',
|
|
19
22
|
{
|
|
@@ -27,18 +30,20 @@
|
|
|
27
30
|
x-cloak
|
|
28
31
|
>
|
|
29
32
|
{{ message_intel.text|json_script:response_message_intel_id }}
|
|
33
|
+
|
|
30
34
|
<div x-ref="loading_response_message" class="row mt-2 pb-3">
|
|
31
35
|
<div class="col-auto align-self-center">
|
|
32
36
|
<div class="row align-items-center">
|
|
33
37
|
<div class="col-12 fs--1">
|
|
34
38
|
{{ chat_workflow_name }}
|
|
35
39
|
</div>
|
|
36
|
-
|
|
37
|
-
|
|
40
|
+
|
|
41
|
+
<div class="col-12 px-3 pt-2">
|
|
42
|
+
<span class="spinner-border spinner-border-sm text-muted" role="status">
|
|
38
43
|
<span class="visually-hidden">Loading...</span>
|
|
39
44
|
</span>
|
|
40
|
-
<span x-show="show_reading">Reading...</span>
|
|
41
|
-
<span x-show="show_typing">Typing...</span>
|
|
45
|
+
<span class="text-muted" x-show="show_reading">Reading...</span>
|
|
46
|
+
<span class="text-muted" x-show="show_typing">Typing...</span>
|
|
42
47
|
</div>
|
|
43
48
|
</div>
|
|
44
49
|
</div>
|
|
@@ -2,50 +2,50 @@
|
|
|
2
2
|
|
|
3
3
|
{% block message %}
|
|
4
4
|
{% generate_id as message_intel_id %}
|
|
5
|
+
|
|
5
6
|
<div
|
|
6
7
|
class="col-auto mb-1 {{ message_class }}"
|
|
7
|
-
@mouseover="show_message_menu = true"
|
|
8
8
|
@mouseleave="show_message_menu = false"
|
|
9
|
+
@mouseover="show_message_menu = true"
|
|
10
|
+
style="max-width: 70%;"
|
|
9
11
|
x-data="{
|
|
10
|
-
show_message_menu: false,
|
|
11
12
|
message_intel_str: '',
|
|
13
|
+
show_message_menu: false,
|
|
14
|
+
|
|
12
15
|
init() {
|
|
13
16
|
this.message_intel_str = JSON.parse(document.getElementById('{{ message_intel_id }}').textContent)
|
|
14
|
-
{% if synthesis_speech %}
|
|
15
|
-
$el.scrollIntoView({behavior: 'smooth'})
|
|
17
|
+
{% if synthesis_speech %}$dispatch('speak', {text: this.message_intel_str}){% endif %}
|
|
18
|
+
{% if not is_loading %}$el.scrollIntoView({behavior: 'smooth'}){% endif %}
|
|
16
19
|
}
|
|
17
20
|
}"
|
|
18
21
|
>
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
22
|
+
{{ message_intel.content_to_str|json_script:message_intel_id }}
|
|
23
|
+
|
|
24
|
+
<div class="px-1 text-muted {{ sender_class }}" style="font-size: 0.7rem;">
|
|
25
|
+
{% block message_sender %}
|
|
26
|
+
<span class="fw-semibold">{{ sender }}</span>
|
|
27
|
+
{% endblock %}
|
|
28
|
+
|
|
29
|
+
{% if message_timestamp %}
|
|
30
|
+
<span>- {{ message_timestamp }}</span>
|
|
31
|
+
{% endif %}
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
<div class="d-inline-block px-2 py-1 rounded-3 shadow-sm {{ content_class|default:'border' }}">
|
|
35
|
+
{% block message_content %}
|
|
36
|
+
{{ message_intel.content_to_str|linebreaksbr }}
|
|
37
|
+
{% endblock %}
|
|
38
|
+
</div>
|
|
39
|
+
|
|
40
|
+
<div
|
|
41
|
+
:class="show_message_menu ? 'opacity-100' : 'opacity-0'"
|
|
42
|
+
class="d-flex justify-content-end"
|
|
43
|
+
>
|
|
44
|
+
<div @click="$dispatch('speak', {text: message_intel_str})" class="py-1 px-2 cursor-pointer">
|
|
45
|
+
<i class="bi bi-soundwave"></i>
|
|
34
46
|
</div>
|
|
35
|
-
<div
|
|
36
|
-
class="
|
|
37
|
-
:class="show_message_menu ? 'opacity-100' : 'opacity-0'"
|
|
38
|
-
>
|
|
39
|
-
<div class="col-auto px-0">
|
|
40
|
-
<div @click="start_speaking(message_intel_str)" class="py-1 px-2 cursor-pointer">
|
|
41
|
-
<i class="bi bi-soundwave"></i>
|
|
42
|
-
</div>
|
|
43
|
-
</div>
|
|
44
|
-
<div class="col-auto pe-0 ps-1">
|
|
45
|
-
<div @click="send_chat({message_body: message_intel_str})" class="py-1 px-2 cursor-pointer">
|
|
46
|
-
<i class="bi bi-repeat"></i>
|
|
47
|
-
</div>
|
|
48
|
-
</div>
|
|
47
|
+
<div @click="$dispatch('send-message', {message_body: message_intel_str})" class="py-1 px-2 cursor-pointer">
|
|
48
|
+
<i class="bi bi-repeat"></i>
|
|
49
49
|
</div>
|
|
50
50
|
</div>
|
|
51
51
|
</div>
|
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
<div
|
|
2
|
-
class="row justify-content-end ps-4 ps-lg-5"
|
|
3
|
-
x-data="{
|
|
1
|
+
<div class="row justify-content-end ps-4 ps-lg-5" data-message-chat-id="{{ chat_id }}" {% if not is_loading %}x-data="{
|
|
4
2
|
show_message: false,
|
|
3
|
+
|
|
5
4
|
init() {
|
|
6
5
|
setTimeout(() => this.show_message = true, 500)
|
|
7
6
|
setTimeout(() => $el.scrollIntoView({behavior: 'smooth'}), 550)
|
|
8
7
|
}
|
|
9
|
-
}"
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
>
|
|
13
|
-
{% include message_intel.template with sender_class="text-end" speech_synthesis_class='justify-content-end' content_class="bg-app-layer-three" %}
|
|
8
|
+
}" x-show="show_message" x-transition{% endif %}>
|
|
9
|
+
|
|
10
|
+
{% include message_intel.template with sender_class="text-end" speech_synthesis_class='justify-content-end' content_class="bg-app-primary-soft" %}
|
|
14
11
|
</div>
|
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
<div
|
|
2
|
-
x-data="{
|
|
3
|
-
show_message: false,
|
|
4
|
-
init() {
|
|
5
|
-
setTimeout(() => this.show_message = true, 300)
|
|
6
|
-
setTimeout(() => $el.scrollIntoView({behavior: 'smooth'}), 350)
|
|
7
|
-
}
|
|
8
|
-
}"
|
|
9
2
|
class="row justify-content-start pe-4 pe-lg-5"
|
|
10
|
-
|
|
11
|
-
|
|
3
|
+
data-message-chat-id="{{ chat_id }}"
|
|
4
|
+
{% if not is_loading %}
|
|
5
|
+
x-data="{
|
|
6
|
+
show_message: false,
|
|
7
|
+
|
|
8
|
+
init() {
|
|
9
|
+
setTimeout(() => this.show_message = true, 300)
|
|
10
|
+
setTimeout(() => $el.scrollIntoView({behavior: 'smooth'}), 350)
|
|
11
|
+
}
|
|
12
|
+
}"
|
|
13
|
+
x-show="show_message"
|
|
14
|
+
x-transition
|
|
15
|
+
{% endif %}
|
|
12
16
|
>
|
|
13
|
-
{% include message_intel.template with content_class="bg-app-
|
|
17
|
+
{% include message_intel.template with content_class="bg-app-warning-soft" %}
|
|
14
18
|
</div>
|