django-spire 0.19.0__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 (24) hide show
  1. django_spire/ai/chat/intelligence/workflows/chat_workflow.py +29 -19
  2. django_spire/ai/chat/templates/django_spire/ai/chat/message/loading_response_message.html +1 -1
  3. django_spire/ai/chat/templates/django_spire/ai/chat/message/message.html +25 -34
  4. django_spire/ai/chat/templates/django_spire/ai/chat/widget/dialog_widget.html +1 -2
  5. django_spire/ai/chat/views/message_request_views.py +2 -2
  6. django_spire/consts.py +1 -1
  7. django_spire/core/management/commands/spire_startapp_pkg/__init__.py +4 -20
  8. django_spire/core/management/commands/spire_startapp_pkg/builder.py +2 -2
  9. django_spire/core/management/commands/spire_startapp_pkg/config.py +2 -2
  10. django_spire/core/management/commands/spire_startapp_pkg/filesystem.py +1 -19
  11. django_spire/core/management/commands/spire_startapp_pkg/generator.py +8 -8
  12. django_spire/core/management/commands/spire_startapp_pkg/processor.py +3 -3
  13. django_spire/core/management/commands/spire_startapp_pkg/registry.py +0 -16
  14. django_spire/core/management/commands/spire_startapp_pkg/reporter.py +1 -21
  15. django_spire/core/management/commands/spire_startapp_pkg/resolver.py +0 -15
  16. django_spire/core/management/commands/spire_startapp_pkg/template/app/views/form_views.py.template +2 -2
  17. django_spire/core/management/commands/spire_startapp_pkg/template/app/views/page_views.py.template +2 -2
  18. django_spire/core/management/commands/spire_startapp_pkg/validator.py +9 -9
  19. django_spire/core/templates/django_spire/page/full_page.html +5 -0
  20. {django_spire-0.19.0.dist-info → django_spire-0.19.1.dist-info}/METADATA +1 -1
  21. {django_spire-0.19.0.dist-info → django_spire-0.19.1.dist-info}/RECORD +24 -24
  22. {django_spire-0.19.0.dist-info → django_spire-0.19.1.dist-info}/WHEEL +0 -0
  23. {django_spire-0.19.0.dist-info → django_spire-0.19.1.dist-info}/licenses/LICENSE.md +0 -0
  24. {django_spire-0.19.0.dist-info → django_spire-0.19.1.dist-info}/top_level.txt +0 -0
@@ -2,38 +2,52 @@ from __future__ import annotations
2
2
 
3
3
  from typing import TYPE_CHECKING, Callable
4
4
 
5
+ from dandy import Bot
5
6
  from dandy.recorder import recorder_to_html_file
6
7
 
7
8
  from django_spire.ai.chat.intelligence.decoders.tools import generate_intent_decoder
9
+ from django_spire.ai.chat.message_intel import BaseMessageIntel, DefaultMessageIntel
8
10
  from django_spire.ai.decorators import log_ai_interaction_from_recorder
9
- from django_spire.conf import settings
10
- from django_spire.core.utils import (
11
- get_callable_from_module_string_and_validate_arguments,
12
- )
13
- from django_spire.ai.chat.message_intel import BaseMessageIntel
14
11
 
15
12
  if TYPE_CHECKING:
16
13
  from dandy.llm.request.message import MessageHistory
17
14
  from django.core.handlers.wsgi import WSGIRequest
18
15
 
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
+
20
42
  @recorder_to_html_file('spire_ai_chat_workflow')
21
43
  def chat_workflow(
22
44
  request: WSGIRequest,
23
45
  user_input: str,
24
46
  message_history: MessageHistory | None = None
25
47
  ) -> BaseMessageIntel:
26
- if settings.AI_CHAT_DEFAULT_CALLABLE is not None:
27
- default_process = get_callable_from_module_string_and_validate_arguments(
28
- module_string=settings.AI_CHAT_DEFAULT_CALLABLE,
29
- valid_args=('request', 'user_input', 'message_history'),
30
- )
31
- else:
32
- default_process = None
33
-
34
48
  intent_decoder = generate_intent_decoder(
35
49
  request=request,
36
- default_callable=default_process,
50
+ default_callable=default_chat_response,
37
51
  )
38
52
 
39
53
  intent_process = intent_decoder.process(user_input, max_return_values=1)[0]
@@ -48,12 +62,8 @@ def chat_workflow(
48
62
 
49
63
  message_intel = run_workflow_process(intent_process)
50
64
 
51
- if message_intel is None and default_process is not None:
52
- message_intel = run_workflow_process(default_process)
53
-
54
- if not issubclass(message_intel.__class__, BaseMessageIntel):
65
+ if not isinstance(message_intel, BaseMessageIntel):
55
66
  message = f'{intent_process.__qualname__} must return an instance of a {BaseMessageIntel.__name__} sub class.'
56
67
  raise TypeError(message)
57
68
 
58
69
  return message_intel
59
-
@@ -38,7 +38,7 @@
38
38
  {{ chat_workflow_name }}
39
39
  </div>
40
40
 
41
- <div class="col-12 ps-4 pt-2">
41
+ <div class="col-12 px-3 pt-2">
42
42
  <span class="spinner-border spinner-border-sm text-muted" role="status">
43
43
  <span class="visually-hidden">Loading...</span>
44
44
  </span>
@@ -5,8 +5,9 @@
5
5
 
6
6
  <div
7
7
  class="col-auto mb-1 {{ message_class }}"
8
- @mouseover="show_message_menu = true"
9
8
  @mouseleave="show_message_menu = false"
9
+ @mouseover="show_message_menu = true"
10
+ style="max-width: 70%;"
10
11
  x-data="{
11
12
  message_intel_str: '',
12
13
  show_message_menu: false,
@@ -18,43 +19,33 @@
18
19
  }
19
20
  }"
20
21
  >
21
- <div class="container-fluid">
22
- {{ message_intel.content_to_str|json_script:message_intel_id }}
22
+ {{ message_intel.content_to_str|json_script:message_intel_id }}
23
23
 
24
- <div class="row">
25
- <div class="col px-2 text-muted {{ sender_class }}" style="font-size: 0.7rem;">
26
- {% block message_sender %}
27
- <span class="fw-semibold">{{ sender }}</span>
28
- {% endblock %}
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 %}
29
28
 
30
- {% if message_timestamp %}
31
- <span>- {{ message_timestamp }}</span>
32
- {% endif %}
33
- </div>
34
- </div>
29
+ {% if message_timestamp %}
30
+ <span>- {{ message_timestamp }}</span>
31
+ {% endif %}
32
+ </div>
35
33
 
36
- <div class="row">
37
- <div class="col-12 px-3 py-2 rounded-3 shadow-sm {{ content_class|default:'border' }}">
38
- {% block message_content %}
39
- {{ message_intel.content_to_str|linebreaksbr }}
40
- {% endblock %}
41
- </div>
42
- </div>
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>
43
39
 
44
- <div
45
- class="row justify-content-end"
46
- :class="show_message_menu ? 'opacity-100' : 'opacity-0'"
47
- >
48
- <div class="col-auto px-0">
49
- <div @click="$dispatch('speak', {text: message_intel_str})" class="py-1 px-2 cursor-pointer">
50
- <i class="bi bi-soundwave"></i>
51
- </div>
52
- </div>
53
- <div class="col-auto pe-0 ps-1">
54
- <div @click="$dispatch('send-message', {message_body: message_intel_str})" class="py-1 px-2 cursor-pointer">
55
- <i class="bi bi-repeat"></i>
56
- </div>
57
- </div>
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>
46
+ </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>
58
49
  </div>
59
50
  </div>
60
51
  </div>
@@ -98,8 +98,7 @@
98
98
  </div>
99
99
 
100
100
  <div class="row mb-3">
101
- <div class="col-12 overflow-auto p-4" style="height: calc(100vh - 90px - var(--app-top-navigation-height));" x-ref="target_div">
102
- </div>
101
+ <div class="col-12 overflow-auto p-4" style="{{ dialog_height|default:'height: calc(100vh - 90px - var(--app-top-navigation-height));' }}" x-ref="target_div"></div>
103
102
  </div>
104
103
 
105
104
  <div class="row">
@@ -28,7 +28,7 @@ def request_message_render_view(request: WSGIRequest) -> HttpResponse:
28
28
  if chat_id in {0, '0', ''}:
29
29
  chat = Chat.objects.create(
30
30
  user=request.user,
31
- name=body_data['message_body'],
31
+ name=body_data['message_body'][:64],
32
32
  last_message_datetime=current_datetime
33
33
  )
34
34
  else:
@@ -39,7 +39,7 @@ def request_message_render_view(request: WSGIRequest) -> HttpResponse:
39
39
  )
40
40
 
41
41
  if chat.is_empty:
42
- chat.name = body_data['message_body']
42
+ chat.name = body_data['message_body'][:64]
43
43
  chat.save()
44
44
 
45
45
  message_response_group = MessageResponseGroup()
django_spire/consts.py CHANGED
@@ -1,4 +1,4 @@
1
- __VERSION__ = '0.19.0'
1
+ __VERSION__ = '0.19.1'
2
2
 
3
3
  MAINTENANCE_MODE_SETTINGS_NAME = 'MAINTENANCE_MODE'
4
4
 
@@ -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.
@@ -8,7 +8,7 @@ from django_spire.core.management.commands.spire_startapp_pkg.maps import genera
8
8
  if TYPE_CHECKING:
9
9
  from pathlib import Path
10
10
 
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
 
13
13
 
14
14
  class TemplateEngine:
@@ -40,12 +40,12 @@ class TemplateProcessor:
40
40
  and manages file renaming based on user configuration.
41
41
  """
42
42
 
43
- def __init__(self, engine: TemplateEngine, filesystem: FileSystemInterface):
43
+ def __init__(self, engine: TemplateEngine, filesystem: FileSystem):
44
44
  """
45
45
  Initializes the processor with an engine and file system.
46
46
 
47
47
  :param engine: Template engine for rendering strings.
48
- :param filesystem: File system interface for file operations.
48
+ :param filesystem: File system for file operations.
49
49
  """
50
50
 
51
51
  self._engine = engine
@@ -1,25 +1,9 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import Protocol
4
-
5
3
  from django.apps import apps
6
4
  from django.conf import settings
7
5
 
8
6
 
9
- class AppRegistryInterface(Protocol):
10
- """
11
- Protocol defining the interface for Django app registry operations.
12
-
13
- This protocol specifies methods for querying registered apps and
14
- validating app component paths.
15
- """
16
-
17
- def get_installed_apps(self) -> list[str]: ...
18
- def get_missing_components(self, components: list[str]) -> list[str]: ...
19
- def get_valid_root_apps(self) -> set[str]: ...
20
- def is_app_registered(self, app_path: str) -> bool: ...
21
-
22
-
23
7
  class AppRegistry:
24
8
  """
25
9
  Manages Django app registration information.
@@ -1,7 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from string import Template
4
- from typing import Protocol, TYPE_CHECKING
4
+ from typing import TYPE_CHECKING
5
5
 
6
6
  from django_spire.core.management.commands.spire_startapp_pkg.maps import generate_replacement_map
7
7
 
@@ -12,26 +12,6 @@ if TYPE_CHECKING:
12
12
  from django.core.management.base import BaseCommand
13
13
 
14
14
 
15
- class ReporterInterface(Protocol):
16
- """
17
- Protocol defining the interface for reporting and user interaction.
18
-
19
- This protocol specifies methods for displaying messages, prompts,
20
- and tree structures to the user during app creation.
21
- """
22
-
23
- def prompt_confirmation(self, message: str) -> bool: ...
24
- def report_app_creation_success(self, app: str) -> None: ...
25
- def report_app_exists(self, app: str, destination: Path) -> None: ...
26
- def report_creating_app(self, app: str, destination: Path) -> None: ...
27
- def report_creating_templates(self, app: str, destination: Path) -> None: ...
28
- def report_installed_apps_suggestion(self, missing_components: list[str]) -> None: ...
29
- def report_missing_components(self, missing_components: list[str]) -> None: ...
30
- def report_templates_creation_success(self, app: str) -> None: ...
31
- def report_templates_exist(self, app: str, destination: Path) -> None: ...
32
- def write(self, message: str, style: Callable[[str], str]) -> None: ...
33
-
34
-
35
15
  class Reporter:
36
16
  """
37
17
  Handles user interaction and console output for the app creation command.
@@ -1,25 +1,10 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from pathlib import Path
4
- from typing import Protocol
5
4
 
6
5
  from django.conf import settings
7
6
 
8
7
 
9
- class PathResolverInterface(Protocol):
10
- """
11
- Protocol defining the interface for resolving file system paths.
12
-
13
- This protocol specifies methods for determining where apps and
14
- templates should be created in the file system.
15
- """
16
-
17
- def get_app_destination(self, components: list[str]) -> Path: ...
18
- def get_base_dir(self) -> Path: ...
19
- def get_template_destination(self, components: list[str]) -> Path: ...
20
- def get_template_dir(self) -> Path: ...
21
-
22
-
23
8
  class PathResolver:
24
9
  """
25
10
  Resolves file system paths for app and template creation.
@@ -89,7 +89,7 @@ def _modal_form_view(request: WSGIRequest, pk: int = 0) -> TemplateResponse:
89
89
  return TemplateResponse(
90
90
  request,
91
91
  context=context_data,
92
- template='${template_directory_path}/modal/content/${form_template_name}'
92
+ template='${template_directory_path}/modal/content/${form_template_name}.html'
93
93
  )
94
94
 
95
95
 
@@ -130,5 +130,5 @@ def _form_view(request: WSGIRequest, pk: int = 0) -> TemplateResponse|HttpRespon
130
130
  request,
131
131
  form=form,
132
132
  obj=${context_single_var},
133
- template='${template_directory_path}/page/${form_page_template_name}'
133
+ template='${template_directory_path}/page/${form_page_template_name}.html'
134
134
  )
@@ -26,7 +26,7 @@ def ${detail_page_view_name}(request: WSGIRequest, pk: int) -> TemplateResponse:
26
26
  request,
27
27
  obj=${context_single_var},
28
28
  context_data=context_data,
29
- template='${template_directory_path}/page/${detail_page_template_name}'
29
+ template='${template_directory_path}/page/${detail_page_template_name}.html'
30
30
  )
31
31
 
32
32
 
@@ -40,5 +40,5 @@ def ${list_page_view_name}(request: WSGIRequest) -> TemplateResponse:
40
40
  request,
41
41
  model=models.${model_class_name},
42
42
  context_data=context_data,
43
- template='${template_directory_path}/page/${list_page_template_name}'
43
+ template='${template_directory_path}/page/${list_page_template_name}.html'
44
44
  )
@@ -5,10 +5,10 @@ from typing import TYPE_CHECKING
5
5
  from django.core.management.base import CommandError
6
6
 
7
7
  if TYPE_CHECKING:
8
- from django_spire.core.management.commands.spire_startapp_pkg.filesystem import FileSystemInterface
9
- from django_spire.core.management.commands.spire_startapp_pkg.registry import AppRegistryInterface
10
- from django_spire.core.management.commands.spire_startapp_pkg.reporter import ReporterInterface
11
- from django_spire.core.management.commands.spire_startapp_pkg.resolver import PathResolverInterface
8
+ from django_spire.core.management.commands.spire_startapp_pkg.filesystem import FileSystem
9
+ from django_spire.core.management.commands.spire_startapp_pkg.registry import AppRegistry
10
+ from django_spire.core.management.commands.spire_startapp_pkg.reporter import Reporter
11
+ from django_spire.core.management.commands.spire_startapp_pkg.resolver import PathResolver
12
12
 
13
13
 
14
14
  class AppValidator:
@@ -21,10 +21,10 @@ class AppValidator:
21
21
 
22
22
  def __init__(
23
23
  self,
24
- reporter: ReporterInterface,
25
- registry: AppRegistryInterface,
26
- path_resolver: PathResolverInterface,
27
- filesystem: FileSystemInterface
24
+ reporter: Reporter,
25
+ registry: AppRegistry,
26
+ path_resolver: PathResolver,
27
+ filesystem: FileSystem
28
28
  ):
29
29
  """
30
30
  Initializes the validator with required dependencies.
@@ -32,7 +32,7 @@ class AppValidator:
32
32
  :param reporter: Reporter for displaying error messages.
33
33
  :param registry: Registry for checking installed apps.
34
34
  :param path_resolver: Path resolver for determining file locations.
35
- :param filesystem: File system interface for checking file existence.
35
+ :param filesystem: File system for checking file existence.
36
36
  """
37
37
 
38
38
  self._filesystem = filesystem
@@ -125,6 +125,11 @@
125
125
  >
126
126
  <div class="col">
127
127
  <div class="row pb-2 align-items-center">
128
+ <div class="col-auto px-1" style="visibility: hidden;">
129
+ <button class="btn-close-panel" type="button">
130
+ <i class="bi bi-x-lg f5"></i>
131
+ </button>
132
+ </div>
128
133
  <div class="col h5 text-app-primary text-center text-nowrap overflow-hidden text-truncate mb-0" style="min-width: 0;">
129
134
  {% block full_page_sub_navigation_title %}
130
135
  {% endblock %}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-spire
3
- Version: 0.19.0
3
+ Version: 0.19.1
4
4
  Summary: A project for Django Spire
5
5
  Author-email: Brayden Carlson <braydenc@stratusadv.com>, Nathan Johnson <nathanj@stratusadv.com>
6
6
  License: Copyright (c) 2024 Stratus Advanced Technologies and Contributors.
@@ -1,6 +1,6 @@
1
1
  django_spire/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  django_spire/conf.py,sha256=c5Hs-7lk9T15254tOasiQ2ZTFLQIVJof9_QJDfm1PAI,933
3
- django_spire/consts.py,sha256=LzG6L2WtlALcGN1XN_EOjl9OqZ_ZlBh0Fv7QQKVJjHY,171
3
+ django_spire/consts.py,sha256=GqwKKYevR0Ew6grst8Ii6x4u_9Cds318I-LxabTpU9I,171
4
4
  django_spire/exceptions.py,sha256=L5ndRO5ftMmh0pHkO2z_NG3LSGZviJ-dDHNT73SzTNw,48
5
5
  django_spire/settings.py,sha256=_bM5uUqJXq3sW-NZBNAzt4egZwmvLq_jA8DaQGHqVoE,661
6
6
  django_spire/urls.py,sha256=mKeZszb5U4iIGqddMb5Tt5fRC72U2wABEOi6mvOfEBU,656
@@ -27,7 +27,7 @@ django_spire/ai/chat/intelligence/prompts.py,sha256=jnFaN7EUUQM-wxloWJZ2UAGw1RDX
27
27
  django_spire/ai/chat/intelligence/decoders/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
28
  django_spire/ai/chat/intelligence/decoders/tools.py,sha256=8fSnuWL1Apr32-hH52Fz9UUAA0Ph54EYUgohAXnwGIM,933
29
29
  django_spire/ai/chat/intelligence/workflows/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
30
- django_spire/ai/chat/intelligence/workflows/chat_workflow.py,sha256=sq435kcM7071cpcd-vh-RryM4k6HE2DToY-cynzdzGw,2045
30
+ django_spire/ai/chat/intelligence/workflows/chat_workflow.py,sha256=-OEOAQzeOAEIZam7ru4IAOjcSiZvWk_G9fpYdDlSc58,2078
31
31
  django_spire/ai/chat/migrations/0001_initial.py,sha256=1cbREhX3_fNsbfumJoKAZ8w91Kq5NeXUn_iI45B7oGE,2632
32
32
  django_spire/ai/chat/migrations/0002_remove_chatmessage_content_chatmessage__content_and_more.py,sha256=KeNT7VRFmwA74odh9wxIE1Cr4KAO4Tmtqu0FuI2AmK0,752
33
33
  django_spire/ai/chat/migrations/0003_rename__content_chatmessage__intel_data_and_more.py,sha256=wAcJ6Ia3fWrGbqnVrqD2C3-3ijAot0LK-B3KZavoY_A,754
@@ -37,13 +37,13 @@ django_spire/ai/chat/templates/django_spire/ai/chat/card/chat_card.html,sha256=6
37
37
  django_spire/ai/chat/templates/django_spire/ai/chat/dropdown/ellipsis_dropdown.html,sha256=fiWuRkqcf8_oOVt5mRvsyKHhevAKM0hzbjhCdrZHZUU,736
38
38
  django_spire/ai/chat/templates/django_spire/ai/chat/element/recent_chat_select_element.html,sha256=NgKGSjbcoCVezdDvvd3aTnpLPgE7oCEsRkHXGxTLn9c,4838
39
39
  django_spire/ai/chat/templates/django_spire/ai/chat/message/default_message.html,sha256=6MT6O9jpkl8DCNKywZYa3YpRvxgQWhlmVJAu4NO70aU,143
40
- django_spire/ai/chat/templates/django_spire/ai/chat/message/loading_response_message.html,sha256=kuf2SdOqDzEmkxepWqOHZxuxseI0RT9_UOlN_WDzK8o,1845
41
- django_spire/ai/chat/templates/django_spire/ai/chat/message/message.html,sha256=dmFA83vVlVlLw_ygumPVIT5dy8n5Lytiz1vWZWAXVOY,2365
40
+ django_spire/ai/chat/templates/django_spire/ai/chat/message/loading_response_message.html,sha256=m3vcYC_tl7OYzbsguJWs8C6jPiJBKVsojginN4cSBkc,1845
41
+ django_spire/ai/chat/templates/django_spire/ai/chat/message/message.html,sha256=hIvM1S2ds_9eAss5gZmb672YzS6XrJoC1Ig7xgiinlw,1938
42
42
  django_spire/ai/chat/templates/django_spire/ai/chat/message/request_message.html,sha256=NwGYA_SgJEzAqhW8CgnXP9yEbOHEdonbJ_GIEI2s4c8,526
43
43
  django_spire/ai/chat/templates/django_spire/ai/chat/message/response_message.html,sha256=NZDDVY1nYxvyplQobO3gW6i-sevPZd8pXSIsNacF9Yw,525
44
44
  django_spire/ai/chat/templates/django_spire/ai/chat/page/chat_page.html,sha256=atgCFgXIAIVKnD6oEFzIF7MiUFTrS7GwN8klKRdB7LE,957
45
45
  django_spire/ai/chat/templates/django_spire/ai/chat/section/confirm_delete_section.html,sha256=yJr-zmu4CV7REGnHa2uA_MqgqiftSz-r2bb7U0_5CIY,720
46
- django_spire/ai/chat/templates/django_spire/ai/chat/widget/dialog_widget.html,sha256=Gz1R-HwLlcYoOJ87VfDtgUAfeHmZeA2DyVeag9q2BAk,5226
46
+ django_spire/ai/chat/templates/django_spire/ai/chat/widget/dialog_widget.html,sha256=tSUbcdmotVJxU4DqmgLkqlFOVoJpxbMPy0BruPeU6yc,5239
47
47
  django_spire/ai/chat/templates/django_spire/ai/chat/widget/recent_chat_list_widget.html,sha256=pbn8yyVL2i0ugyS84cmNX-nrr1K-oOAQiHnsjlQ_wYc,132
48
48
  django_spire/ai/chat/templates/django_spire/ai/chat/widget/selection_widget.html,sha256=Fa5Ja2i7J4rL5hU53b90RKPjFFyDpGujqOp5LpnyfCU,1617
49
49
  django_spire/ai/chat/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -60,7 +60,7 @@ django_spire/ai/chat/urls/template/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQe
60
60
  django_spire/ai/chat/urls/template/template_urls.py,sha256=gq44AmAgYcxdzSM_ilIqgCVAKs9lwysDX51lEwkZprc,461
61
61
  django_spire/ai/chat/views/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
62
62
  django_spire/ai/chat/views/json_views.py,sha256=G6YojdOhzWbJhetgAxTflFfj9MGnqHqwA-SGktqNFNw,1569
63
- django_spire/ai/chat/views/message_request_views.py,sha256=2A1yK2_rD-c3sIPAIwHHdDWnxoFUOjI-Sa7aj0cJBMA,2251
63
+ django_spire/ai/chat/views/message_request_views.py,sha256=k6GX81w6OFapt8CdHOiCtH-F8EXHUXjw841uCsMtG64,2261
64
64
  django_spire/ai/chat/views/message_response_views.py,sha256=HpsIAIzCPUL29p4gCl7FnYdN5QadUGJDpGJwYgg_drE,1380
65
65
  django_spire/ai/chat/views/message_views.py,sha256=8_valLgpJVKdN3LTSTdKRh3PbU_4H18yVWB1xveHJLw,872
66
66
  django_spire/ai/chat/views/page_views.py,sha256=hbNLKWDiAvHQ2JP__RB9fvxrL0NSGK7OZttEfxWskz8,831
@@ -429,19 +429,19 @@ django_spire/core/management/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NM
429
429
  django_spire/core/management/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
430
430
  django_spire/core/management/commands/spire_remove_migration.py,sha256=G3dibVdzvEm9ZMfE_czOk6SyPDn5IEpJ3m1nw-rxuYs,1755
431
431
  django_spire/core/management/commands/spire_startapp.py,sha256=XAA3m7a-dKL4ZYO_WDzKW8ZDgB3__j2RAyiz6qllYjk,4572
432
- django_spire/core/management/commands/spire_startapp_pkg/__init__.py,sha256=DN9Zllp-XszJawudgbcMKfhhTIPnjWzeTGUSRlwEaG4,1894
433
- django_spire/core/management/commands/spire_startapp_pkg/builder.py,sha256=1rGZlHdnTM9QdTFFjDf87xCSCA2QIUd8ndtVvf-PbGE,3170
434
- django_spire/core/management/commands/spire_startapp_pkg/config.py,sha256=qoIGKUYJcRAnYW1WbdpSxKerWckeJGxoDVCZ9yWxrgY,3390
435
- django_spire/core/management/commands/spire_startapp_pkg/filesystem.py,sha256=shYly0AElxhUsb1WOsK8FdcB3qcsMmghZeEP1IByHq8,3719
436
- django_spire/core/management/commands/spire_startapp_pkg/generator.py,sha256=MleLiKyFnILhCiQy_BcMRVCdw-1JOhB-7EZBMFdukKc,5989
432
+ django_spire/core/management/commands/spire_startapp_pkg/__init__.py,sha256=h5TZNMjuVGC5jIUUa5hkg6fpzMl70OauxldOhKbpf2k,1648
433
+ django_spire/core/management/commands/spire_startapp_pkg/builder.py,sha256=gb401Tqnflv1OVyz-FzHjyO_2qV15D3NQMq66bHnung,3152
434
+ django_spire/core/management/commands/spire_startapp_pkg/config.py,sha256=yBtlIcyoK0MFpgP8izB6yzX9jWQIenQ_5D62kYM2D3o,3372
435
+ django_spire/core/management/commands/spire_startapp_pkg/filesystem.py,sha256=TjZZGKqVGrTRr37rWxc0vCcUsviV28DcNCZ2Fo5yz80,3020
436
+ django_spire/core/management/commands/spire_startapp_pkg/generator.py,sha256=JEU8-TstU2hiS_zBegWGFuCZ_lyf7P4iedx3hcX2BLA,5915
437
437
  django_spire/core/management/commands/spire_startapp_pkg/maps.py,sha256=m0SKcy_TZ4O-mjI74qkxyhVjoDN4QvMmQxgvbbn6mAE,22977
438
438
  django_spire/core/management/commands/spire_startapp_pkg/permissions.py,sha256=czSE-ZNBw-3LsGrtkaD7CBFnitYX18KQjgJ_jjbap7k,5260
439
- django_spire/core/management/commands/spire_startapp_pkg/processor.py,sha256=fqnbgaw8AsNHQBZnbDLmU4WPueFx5bQzA9Cwi_lD_KQ,5928
440
- django_spire/core/management/commands/spire_startapp_pkg/registry.py,sha256=izf5SHkek2nIEf0UkODXL4uY1SkWXmoL3_s6pihF2QE,2689
441
- django_spire/core/management/commands/spire_startapp_pkg/reporter.py,sha256=C48v1dLgnzmGijE9m_G_k5dMuOmNq3Am1zETjiEzEuQ,11085
442
- django_spire/core/management/commands/spire_startapp_pkg/resolver.py,sha256=-y86EMmWU65bMzGeS5mI_O0iVu-xfVrdVKXtrOgbwUg,2835
439
+ django_spire/core/management/commands/spire_startapp_pkg/processor.py,sha256=zQhuIn2EPU6h-75DrVX8mZOZIBzc5F8GKds8m83QGiA,5900
440
+ django_spire/core/management/commands/spire_startapp_pkg/registry.py,sha256=olBBFvDir6-zOoltQRIzHNIWkRG6CnA1FcP80tU7S3s,2185
441
+ django_spire/core/management/commands/spire_startapp_pkg/reporter.py,sha256=CS8cufg6kQq48A5fO4qIdUNDZWsCriHaW_wqQhzlqUc,10062
442
+ django_spire/core/management/commands/spire_startapp_pkg/resolver.py,sha256=loVIG8zCN_Bo6vjBV2UsUF930Rc5SG5P2klJl3qp0pc,2331
443
443
  django_spire/core/management/commands/spire_startapp_pkg/user_input.py,sha256=VUyY9PrqM07vRvgbVJhkC4lgNolnBik3K8S_8U9s_zM,9518
444
- django_spire/core/management/commands/spire_startapp_pkg/validator.py,sha256=cVzQqaShGZ0ae-M69tHFDgXlYBmtR2Zg0zblIj55-Nc,3404
444
+ django_spire/core/management/commands/spire_startapp_pkg/validator.py,sha256=q6fsyRmR1kcN2eAFu-5pDaadJ05FDog7N23eR215Yx0,3322
445
445
  django_spire/core/management/commands/spire_startapp_pkg/template/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
446
446
  django_spire/core/management/commands/spire_startapp_pkg/template/app/__init__.py.template,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
447
447
  django_spire/core/management/commands/spire_startapp_pkg/template/app/apps.py.template,sha256=hry02l60eqkUVUraogSZ9XRoZAFqrUkJw51U0KOcBuc,393
@@ -482,8 +482,8 @@ django_spire/core/management/commands/spire_startapp_pkg/template/app/urls/__ini
482
482
  django_spire/core/management/commands/spire_startapp_pkg/template/app/urls/form_urls.py.template,sha256=D2ReVjflX_ZIVU3xGJzokHWnWdwpLEfW92gAMQxo-Pw,641
483
483
  django_spire/core/management/commands/spire_startapp_pkg/template/app/urls/page_urls.py.template,sha256=f3y2mJCP92HrLMw37T7xSUc1E6Ky8ZnqiFIzJYnM3jc,262
484
484
  django_spire/core/management/commands/spire_startapp_pkg/template/app/views/__init__.py.template,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
485
- django_spire/core/management/commands/spire_startapp_pkg/template/app/views/form_views.py.template,sha256=KWvIdPrhfPdpvuJMHYvoUQXi1_ngUeSx28OX691JO10,4538
486
- django_spire/core/management/commands/spire_startapp_pkg/template/app/views/page_views.py.template,sha256=h1MBeRmY7c3bioVp46zHwTINtHYJ5dmCf_kmMRDUHC8,1399
485
+ django_spire/core/management/commands/spire_startapp_pkg/template/app/views/form_views.py.template,sha256=np31b1k9htY_alOGc9VqDasomtiQRUfNtRKVObAP3H4,4548
486
+ django_spire/core/management/commands/spire_startapp_pkg/template/app/views/page_views.py.template,sha256=QMozesEIYhDMhsvVJH_MxgobE-SVnczP5dRmTdxyMFM,1409
487
487
  django_spire/core/management/commands/spire_startapp_pkg/template/templates/card/${detail_card_template_name}.html.template,sha256=-TtrmvKgiB5fMmVtP6ZZdg3tkkKvKdG0Z6DNtdzL1Lw,1004
488
488
  django_spire/core/management/commands/spire_startapp_pkg/template/templates/card/${form_card_template_name}.html.template,sha256=Tybi6-14YHAoXeqPFDE4ZIesCaEggPBlAP6wHJ7uzPw,236
489
489
  django_spire/core/management/commands/spire_startapp_pkg/template/templates/card/${list_card_template_name}.html.template,sha256=s8w4sibmXKMmAa3OWM43OrjKUplbWAQMRxtjDgKgXk8,677
@@ -670,7 +670,7 @@ django_spire/core/templates/django_spire/page/center_card_page.html,sha256=CqUtX
670
670
  django_spire/core/templates/django_spire/page/delete_confirmation_form_page.html,sha256=kmAA2eeD-5s3oAdS-HdFwbqHnzPlqihqh5JwxMJIP_o,168
671
671
  django_spire/core/templates/django_spire/page/delete_form_page.html,sha256=0ZYlWgl3eVq2OTbu_C0UiHVfSIbj2gg_iJ7xeafHVu4,240
672
672
  django_spire/core/templates/django_spire/page/form_full_page.html,sha256=5yp3EfOC2LlcTc0PYQ5MLuQvuw1QFPsMtnPvRdP0A2g,299
673
- django_spire/core/templates/django_spire/page/full_page.html,sha256=hhWtS9AX15gpfGurfXKFFZJuGc18dGtXKB9u1MbqNXA,11320
673
+ django_spire/core/templates/django_spire/page/full_page.html,sha256=s2N2wIs_w5_mh0_t-gMP-qgZQJL1rhJEHRB3vdgrj3o,11646
674
674
  django_spire/core/templates/django_spire/page/page.html,sha256=D6qoyoo3E0_Qu8qov6c2YaYbJQ-LnZnCLKHb5bN0sOs,397
675
675
  django_spire/core/templates/django_spire/speech/speech_recognition.html,sha256=0SiRq9L4wFPFl_c8WnwflsYFfQ2wVUPi7aklEPdZPjQ,805
676
676
  django_spire/core/templates/django_spire/speech/speech_synthesis.html,sha256=25HetXDLzVWxC8hBnIuVbNXfvGxfaYvtZUPPtN0fkQY,805
@@ -1132,8 +1132,8 @@ django_spire/theme/urls/page_urls.py,sha256=S8nkKkgbhG3XHI3uMUL-piOjXIrRkuY2UlM_
1132
1132
  django_spire/theme/views/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1133
1133
  django_spire/theme/views/json_views.py,sha256=W1khC2K_EMbEzAFmMxC_P76_MFnkRH4-eVdodrRfAhw,1904
1134
1134
  django_spire/theme/views/page_views.py,sha256=pHr8iekjtR99xs7w1taj35HEo133Svq1dvDD0y0VL1c,3933
1135
- django_spire-0.19.0.dist-info/licenses/LICENSE.md,sha256=tlTbOtgKoy-xAQpUk9gPeh9O4oRXCOzoWdW3jJz0wnA,1091
1136
- django_spire-0.19.0.dist-info/METADATA,sha256=O70cIYvseAbvCiuE-lE6_MAkzTSxaWqxcUfKWhEoaKM,4967
1137
- django_spire-0.19.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
1138
- django_spire-0.19.0.dist-info/top_level.txt,sha256=xf3QV1e--ONkVpgMDQE9iqjQ1Vg4--_6C8wmO-KxPHQ,13
1139
- django_spire-0.19.0.dist-info/RECORD,,
1135
+ django_spire-0.19.1.dist-info/licenses/LICENSE.md,sha256=tlTbOtgKoy-xAQpUk9gPeh9O4oRXCOzoWdW3jJz0wnA,1091
1136
+ django_spire-0.19.1.dist-info/METADATA,sha256=U5ZUHeqx7phdgXI0WZv-aTRSdGz8LqP0-XmsGHAgZBY,4967
1137
+ django_spire-0.19.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
1138
+ django_spire-0.19.1.dist-info/top_level.txt,sha256=xf3QV1e--ONkVpgMDQE9iqjQ1Vg4--_6C8wmO-KxPHQ,13
1139
+ django_spire-0.19.1.dist-info/RECORD,,