iatoolkit 0.12.0__tar.gz → 0.14.0__tar.gz

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.

Potentially problematic release.


This version of iatoolkit might be problematic. Click here for more details.

Files changed (116) hide show
  1. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/PKG-INFO +1 -1
  2. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/pyproject.toml +1 -1
  3. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/common/routes.py +8 -10
  4. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/iatoolkit.py +8 -0
  5. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/templates/base.html +3 -3
  6. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/templates/chat.html +5 -5
  7. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/templates/home.html +0 -9
  8. iatoolkit-0.14.0/src/iatoolkit/templates/login_shell.html +185 -0
  9. iatoolkit-0.12.0/src/iatoolkit/views/external_chat_login_view.py → iatoolkit-0.14.0/src/iatoolkit/views/login_external_id_view.py +30 -14
  10. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/views/login_view.py +16 -5
  11. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit.egg-info/PKG-INFO +1 -1
  12. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit.egg-info/SOURCES.txt +2 -2
  13. iatoolkit-0.12.0/src/iatoolkit/views/external_login_view.py +0 -40
  14. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/readme.md +0 -0
  15. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/requirements.txt +0 -0
  16. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/setup.cfg +0 -0
  17. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/__init__.py +0 -0
  18. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/base_company.py +0 -0
  19. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/cli_commands.py +0 -0
  20. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/common/__init__.py +0 -0
  21. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/common/auth.py +0 -0
  22. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/common/exceptions.py +0 -0
  23. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/common/session_manager.py +0 -0
  24. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/common/util.py +0 -0
  25. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/company_registry.py +0 -0
  26. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/infra/__init__.py +0 -0
  27. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/infra/call_service.py +0 -0
  28. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/infra/connectors/__init__.py +0 -0
  29. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/infra/connectors/file_connector.py +0 -0
  30. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/infra/connectors/file_connector_factory.py +0 -0
  31. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/infra/connectors/google_cloud_storage_connector.py +0 -0
  32. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/infra/connectors/google_drive_connector.py +0 -0
  33. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/infra/connectors/local_file_connector.py +0 -0
  34. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/infra/connectors/s3_connector.py +0 -0
  35. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/infra/gemini_adapter.py +0 -0
  36. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/infra/google_chat_app.py +0 -0
  37. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/infra/llm_client.py +0 -0
  38. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/infra/llm_proxy.py +0 -0
  39. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/infra/llm_response.py +0 -0
  40. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/infra/mail_app.py +0 -0
  41. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/infra/openai_adapter.py +0 -0
  42. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/infra/redis_session_manager.py +0 -0
  43. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/repositories/__init__.py +0 -0
  44. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/repositories/database_manager.py +0 -0
  45. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/repositories/document_repo.py +0 -0
  46. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/repositories/llm_query_repo.py +0 -0
  47. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/repositories/models.py +0 -0
  48. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/repositories/profile_repo.py +0 -0
  49. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/repositories/tasks_repo.py +0 -0
  50. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/repositories/vs_repo.py +0 -0
  51. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/services/__init__.py +0 -0
  52. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/services/benchmark_service.py +0 -0
  53. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/services/branding_service.py +0 -0
  54. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/services/dispatcher_service.py +0 -0
  55. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/services/document_service.py +0 -0
  56. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/services/excel_service.py +0 -0
  57. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/services/file_processor_service.py +0 -0
  58. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/services/history_service.py +0 -0
  59. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/services/jwt_service.py +0 -0
  60. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/services/load_documents_service.py +0 -0
  61. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/services/mail_service.py +0 -0
  62. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/services/profile_service.py +0 -0
  63. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/services/prompt_manager_service.py +0 -0
  64. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/services/query_service.py +0 -0
  65. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/services/search_service.py +0 -0
  66. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/services/sql_service.py +0 -0
  67. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/services/tasks_service.py +0 -0
  68. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/services/user_feedback_service.py +0 -0
  69. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/services/user_session_context_service.py +0 -0
  70. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/static/images/arrow_up.png +0 -0
  71. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/static/images/diagrama_iatoolkit.jpg +0 -0
  72. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/static/images/logo_clinica.png +0 -0
  73. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/static/images/logo_iatoolkit.png +0 -0
  74. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/static/images/logo_maxxa.png +0 -0
  75. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/static/images/logo_notaria.png +0 -0
  76. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/static/images/logo_tarjeta.png +0 -0
  77. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/static/images/logo_umayor.png +0 -0
  78. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/static/images/upload.png +0 -0
  79. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/static/js/chat_feedback.js +0 -0
  80. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/static/js/chat_filepond.js +0 -0
  81. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/static/js/chat_history.js +0 -0
  82. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/static/js/chat_main.js +0 -0
  83. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/static/styles/chat_iatoolkit.css +0 -0
  84. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/static/styles/chat_info.css +0 -0
  85. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/static/styles/chat_modal.css +0 -0
  86. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/static/styles/llm_output.css +0 -0
  87. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/system_prompts/format_styles.prompt +0 -0
  88. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/system_prompts/query_main.prompt +0 -0
  89. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/system_prompts/sql_rules.prompt +0 -0
  90. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/templates/about.html +0 -0
  91. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/templates/change_password.html +0 -0
  92. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/templates/chat_modals.html +0 -0
  93. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/templates/error.html +0 -0
  94. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/templates/forgot_password.html +0 -0
  95. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/templates/header.html +0 -0
  96. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/templates/login.html +0 -0
  97. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/templates/signup.html +0 -0
  98. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/templates/test.html +0 -0
  99. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/views/__init__.py +0 -0
  100. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/views/change_password_view.py +0 -0
  101. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/views/chat_token_request_view.py +0 -0
  102. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/views/download_file_view.py +0 -0
  103. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/views/file_store_view.py +0 -0
  104. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/views/forgot_password_view.py +0 -0
  105. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/views/history_view.py +0 -0
  106. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/views/home_view.py +0 -0
  107. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/views/llmquery_view.py +0 -0
  108. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/views/prompt_view.py +0 -0
  109. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/views/signup_view.py +0 -0
  110. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/views/tasks_review_view.py +0 -0
  111. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/views/tasks_view.py +0 -0
  112. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/views/user_feedback_view.py +0 -0
  113. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit/views/verify_user_view.py +0 -0
  114. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit.egg-info/dependency_links.txt +0 -0
  115. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit.egg-info/requires.txt +0 -0
  116. {iatoolkit-0.12.0 → iatoolkit-0.14.0}/src/iatoolkit.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: iatoolkit
3
- Version: 0.12.0
3
+ Version: 0.14.0
4
4
  Summary: IAToolkit
5
5
  Author: Fernando Libedinsky
6
6
  License-Expression: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "iatoolkit"
7
- version = "0.12.0"
7
+ version = "0.14.0"
8
8
  requires-python = ">=3.11"
9
9
  description = "IAToolkit"
10
10
  readme = "readme.md"
@@ -27,7 +27,7 @@ def register_views(injector, app):
27
27
  from iatoolkit.views.tasks_review_view import TaskReviewView
28
28
  from iatoolkit.views.home_view import HomeView
29
29
  from iatoolkit.views.login_view import LoginView, InitiateLoginView
30
- from iatoolkit.views.external_chat_login_view import InitiateExternalChatView, ExternalChatLoginView
30
+ from iatoolkit.views.login_external_id_view import InitiateExternalChatView, ExternalChatLoginView
31
31
  from iatoolkit.views.signup_view import SignupView
32
32
  from iatoolkit.views.verify_user_view import VerifyAccountView
33
33
  from iatoolkit.views.forgot_password_view import ForgotPasswordView
@@ -36,21 +36,19 @@ def register_views(injector, app):
36
36
  from iatoolkit.views.user_feedback_view import UserFeedbackView
37
37
  from iatoolkit.views.prompt_view import PromptView
38
38
  from iatoolkit.views.chat_token_request_view import ChatTokenRequestView
39
- from iatoolkit.views.external_login_view import ExternalLoginView
40
39
  from iatoolkit.views.download_file_view import DownloadFileView
41
40
 
42
41
  app.add_url_rule('/', view_func=HomeView.as_view('home'))
43
42
 
44
- # front if the company internal portal
45
- app.add_url_rule('/<company_short_name>/chat_login', view_func=ExternalChatLoginView.as_view('external_chat_login'))
46
- app.add_url_rule('/<company_short_name>/external_login/<external_user_id>',
47
- view_func=ExternalLoginView.as_view('external_login'))
43
+ # login for external portals
48
44
  app.add_url_rule('/<company_short_name>/initiate_external_chat',
49
- view_func=InitiateExternalChatView.as_view('initiate_chat_login'))
45
+ view_func=InitiateExternalChatView.as_view('initiate_external_chat'))
46
+ app.add_url_rule('/<company_short_name>/external_login',
47
+ view_func=ExternalChatLoginView.as_view('external_login'))
48
+ app.add_url_rule('/auth/chat_token',
49
+ view_func=ChatTokenRequestView.as_view('chat-token'))
50
50
 
51
- app.add_url_rule('/auth/chat_token', view_func=ChatTokenRequestView.as_view('chat-token'))
52
-
53
- # main pages for the iatoolkit frontend
51
+ # login for the iatoolkit integrated frontend
54
52
  app.add_url_rule('/<company_short_name>/login', view_func=LoginView.as_view('login'))
55
53
  app.add_url_rule('/<company_short_name>/initiate_login', view_func=InitiateLoginView.as_view('initiate_login'))
56
54
 
@@ -144,8 +144,13 @@ class IAToolkit:
144
144
  is_https = self._get_config_value('USE_HTTPS', 'false').lower() == 'true'
145
145
  is_dev = self._get_config_value('FLASK_ENV') == 'development'
146
146
 
147
+ # get the iatoolkit domain
148
+ parsed_url = urlparse(os.getenv('IATOOLKIT_BASE_URL'))
149
+ domain = parsed_url.netloc
150
+
147
151
  self.app.config.update({
148
152
  'VERSION': self.version,
153
+ 'SERVER_NAME': domain,
149
154
  'SECRET_KEY': self._get_config_value('FLASK_SECRET_KEY', 'iatoolkit-default-secret'),
150
155
  'SESSION_COOKIE_SAMESITE': "None" if is_https else "Lax",
151
156
  'SESSION_COOKIE_SECURE': is_https,
@@ -156,6 +161,9 @@ class IAToolkit:
156
161
  'JWT_EXPIRATION_SECONDS_CHAT': int(self._get_config_value('JWT_EXPIRATION_SECONDS_CHAT', 3600))
157
162
  })
158
163
 
164
+ if parsed_url.scheme == 'https':
165
+ self.app.config['PREFERRED_URL_SCHEME'] = 'https'
166
+
159
167
  # Configuración para tokenizers en desarrollo
160
168
  if is_dev:
161
169
  os.environ["TOKENIZERS_PARALLELISM"] = "false"
@@ -9,9 +9,9 @@
9
9
  <link href="https://cdn.jsdelivr.net/npm/bootstrap-icons/font/bootstrap-icons.css" rel="stylesheet">
10
10
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/filepond/dist/filepond.min.css">
11
11
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/sweetalert2@11/dist/sweetalert2.min.css">
12
- <link rel="stylesheet" href="{{ url_for('static', filename='styles/chat_iatoolkit.css') }}">
13
- <link rel="stylesheet" href="{{ url_for('static', filename='styles/chat_modal.css') }}">
14
- <link rel="stylesheet" href="{{ url_for('static', filename='styles/llm_output.css') }}">
12
+ <link rel="stylesheet" href="{{ url_for('static', filename='styles/chat_iatoolkit.css', _external=True) }}">
13
+ <link rel="stylesheet" href="{{ url_for('static', filename='styles/chat_modal.css', _external=True) }}">
14
+ <link rel="stylesheet" href="{{ url_for('static', filename='styles/llm_output.css', _external=True) }}">
15
15
  </head>
16
16
  <body class="d-flex flex-column p-3" style="min-height: 100vh;">
17
17
  <main class="d-flex flex-column flex-grow-1">
@@ -44,7 +44,7 @@
44
44
 
45
45
  <!-- Icono de cerrar sesión (al final) -->
46
46
  {% if user_email %}
47
- <a href="{{ url_for('logout', company_short_name=company_short_name) }}"
47
+ <a href="{{ url_for('logout', company_short_name=company_short_name, _external=True) }}"
48
48
  class="ms-3 action-icon-style" title="Cerrar sesión" style="color: {{ branding.header_text_color }} !important;">
49
49
  <i class="bi bi-box-arrow-right"></i>
50
50
  </a>
@@ -173,10 +173,10 @@
173
173
  </script>
174
174
 
175
175
  <!-- Carga de los scripts JS externos después de definir las variables globales -->
176
- <script src="{{ url_for('static', filename='js/chat_filepond.js') }}"></script>
177
- <script src="{{ url_for('static', filename='js/chat_history.js') }}"></script>
178
- <script src="{{ url_for('static', filename='js/chat_feedback.js') }}"></script>
179
- <script src="{{ url_for('static', filename='js/chat_main.js') }}"></script>
176
+ <script src="{{ url_for('static', filename='js/chat_filepond.js', _external=True) }}"></script>
177
+ <script src="{{ url_for('static', filename='js/chat_history.js', _external=True) }}"></script>
178
+ <script src="{{ url_for('static', filename='js/chat_feedback.js', _external=True) }}"></script>
179
+ <script src="{{ url_for('static', filename='js/chat_main.js', _external=True) }}"></script>
180
180
 
181
181
  <script>
182
182
  document.addEventListener('DOMContentLoaded', function() {
@@ -156,11 +156,6 @@
156
156
  return;
157
157
  }
158
158
 
159
- const $button = $(this);
160
- const $spinner = $button.find('.spinner-border');
161
- $button.prop('disabled', true);
162
- $spinner.removeClass('d-none');
163
-
164
159
  fetch(`/${selectedCompany}/initiate_external_chat`, {
165
160
  method: 'POST',
166
161
  headers: {
@@ -188,10 +183,6 @@
188
183
  .catch(error => {
189
184
  Swal.fire({ icon: 'error', title: 'Error de Inicio de Sesión', text: error.message });
190
185
  })
191
- .finally(() => {
192
- $button.prop('disabled', false);
193
- $spinner.addClass('d-none');
194
- });
195
186
 
196
187
  });
197
188
  });
@@ -0,0 +1,185 @@
1
+ <!-- templates/iatoolkit/shell.html -->
2
+ <!DOCTYPE html>
3
+ <html lang="es">
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <title>Iniciando Maxxa IA...</title>
7
+ <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
9
+
10
+ <!-- Inyecta las variables CSS de la marca -->
11
+ {% if branding and branding.css_variables %}
12
+ <style>
13
+ {{ branding.css_variables|safe }}
14
+ </style>
15
+ {% endif %}
16
+
17
+ <style>
18
+ /* --- Estilos Generales --- */
19
+ body, html { margin: 0; padding: 0; height: 100%; overflow: hidden; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; }
20
+
21
+ #loader-wrapper {
22
+ position: fixed; top: 0; left: 0; width: 100%; height: 100%;
23
+ background-color: #f4f7f6;
24
+ z-index: 1000;
25
+ display: flex;
26
+ justify-content: center;
27
+ align-items: center;
28
+ flex-direction: column;
29
+ padding: 20px;
30
+ box-sizing: border-box;
31
+ transition: opacity 0.5s ease-in-out;
32
+ }
33
+
34
+ /* --- Estilos de Branding --- */
35
+ #brand-header {
36
+ font-size: 2.5rem;
37
+ font-weight: 700;
38
+ margin: 0 0 30px 0; /* Aumentamos el margen inferior para dar espacio */
39
+ color: var(--brand-secondary-color, #06326B);
40
+ }
41
+ #brand-header .brand-name {
42
+ color: var(--brand-primary-color, #FF5100);
43
+ }
44
+
45
+
46
+ /* --- Estilos de la Tarjeta (Sin cambios) --- */
47
+ #card-container {
48
+ background-color: #fff; border-radius: 12px; box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
49
+ padding: 30px; width: 90%; max-width: 450px; text-align: center; transition: opacity 0.3s ease-in-out;
50
+ }
51
+ #card-container .icon { font-size: 40px; color: var(--brand-primary-color, #FF5100); margin-bottom: 15px; }
52
+ #card-container h3 { font-size: 1.25rem; color: #333; margin-bottom: 10px; }
53
+ #card-container p { font-size: 0.95rem; color: #666; line-height: 1.5; min-height: 60px; }
54
+ .card-nav { display: flex; justify-content: space-between; align-items: center; margin-top: 20px; }
55
+ .card-nav button { background-color: var(--brand-secondary-color, #06326B); border: none; color: var(--brand-text-on-secondary, #FFFFFF); border-radius: 50%; width: 40px; height: 40px; cursor: pointer; transition: opacity 0.2s; }
56
+ .card-nav button:hover { opacity: 0.85; }
57
+ #progress-dots { display: flex; gap: 8px; }
58
+ .dot { width: 10px; height: 10px; border-radius: 50%; background-color: #ddd; transition: background-color 0.3s; }
59
+ .dot.active { background-color: var(--brand-primary-color, #FF5100); }
60
+
61
+ /* --- ESTILOS MEJORADOS: SPINNER DE CARGA --- */
62
+ #loading-status { margin-top: 30px; display: flex; align-items: center; gap: 15px; }
63
+ .spinner {
64
+ width: 30px; height: 30px; border: 4px solid rgba(0, 0, 0, 0.1);
65
+ border-top-color: var(--brand-primary-color, #FF5100);
66
+ border-radius: 50%;
67
+ animation: spin 1s linear infinite;
68
+ }
69
+ #loading-status p { font-size: 1rem; font-weight: 500; color: #555; margin: 0; }
70
+ @keyframes spin { to { transform: rotate(360deg); } }
71
+
72
+ /* --- Iframe (Sin cambios) --- */
73
+ #content-container { width: 100%; height: 100%; }
74
+ iframe { width: 100%; height: 100%; border: none; }
75
+ </style>
76
+ </head>
77
+ <body>
78
+ <div id="loader-wrapper">
79
+
80
+ <h1 id="brand-header">
81
+ <span class="brand-name">Maxxa</span><span>IA</span>
82
+ </h1>
83
+
84
+ <!-- ELIMINADO: El subtítulo de carga que estaba aquí -->
85
+
86
+ <div id="card-container">
87
+ <div id="card-icon" class="icon"><i class="fas fa-lightbulb"></i></div>
88
+ <h3 id="card-title">Título de la Tarjeta</h3>
89
+ <p id="card-text">Descripción de la tarjeta de capacitación.</p>
90
+ <div class="card-nav">
91
+ <button id="prev-card" aria-label="Anterior"><i class="fas fa-chevron-left"></i></button>
92
+ <div id="progress-dots"></div>
93
+ <button id="next-card" aria-label="Siguiente"><i class="fas fa-chevron-right"></i></button>
94
+ </div>
95
+ </div>
96
+
97
+ <!-- MEJORADO: Texto de estado ahora junto al spinner -->
98
+ <div id="loading-status">
99
+ <div class="spinner"></div>
100
+ <p>Inicializando el contexto de Maxxa para la IA...</p>
101
+ </div>
102
+
103
+ </div>
104
+
105
+ <div id="content-container"></div>
106
+
107
+ <script>
108
+ $(function() {
109
+ const cardsData = [
110
+ { icon: 'fas fa-users', title: 'Clientes',
111
+ text: 'Conozco en detalle a los clientes de Maxxa: antiguedad, contactos, apoderados, historial de operaciones.<br><br><strong>Ejemplo:</strong> cuantos clientes nuevos de garantia se incorporaron a mi cartera este año?' },
112
+ { icon: 'fas fa-cubes', title: 'Productos',
113
+ text: 'Productos contratados por los clientes: garantias, credito en cuotas, software.<br><br><strong>Ejemplo:</strong> Cuantos clientes de software tengo en cartera?' },
114
+ { icon: 'fas fa-exchange-alt', title: 'Operaciones',
115
+ text: 'Operaciones de garantia y créditos: tasas, comisiones, acredores, fondos, cobranza, etc.<br><br><strong>Ejemplo:</strong> Dame una tabla con los clientes de mi cartera han emitido mas de 20 garantias este año? columnas: rut, nombre, #garantias, monto, comisión' },
116
+ { icon: 'fas fa-landmark', title: 'Chilecompra',
117
+ text: 'Historial completo de la participacion en chilecompra de un cliente. <br><br><strong>Ejemplo:</strong> Que porcentaje de garantias FC adjudicadas en los últimos 12 meses por el cliente 1234567-8 las compro en Maxxa.' },
118
+ { icon: 'fas fa-comments', title: 'Equipos Comerciales',
119
+ text: 'Conozco los equipos comerciales de crédito y garantia. <br><br><strong>Ejemplo:</strong> dime las 10 licitaciones mas grandes que han ganado clientes de mi cartera este año.' },
120
+ { icon: 'fas fa-cogs', title: 'Personaliza tus Prompts',
121
+ text: 'Utiliza la varita magica y podras explorar los prompts predefinidos que he preparado para ti.' },
122
+ { icon: 'fas fa-table', title: 'Tablas y Excel',
123
+ text: 'Puedes pedirme la respuesta en formato de tablas o excel. <br><br><strong>Ejemplo:</strong> dame una tabla con los 10 certificados mas grande este año, columnas: rut, cliente, fecha, monto, tasa, comision, acreedor...' },
124
+ { icon: 'fas fa-shield-alt', title: 'Seguridad y Confidencialidad',
125
+ text: 'Toda tu información es procesada de forma segura y confidencial dentro de nuestro entorno protegido.' }
126
+ ];
127
+ let currentCardIndex = 0, autoRotateInterval;
128
+ const $cardContainer = $('#card-container'), $cardIcon = $('#card-icon'), $cardTitle = $('#card-title'), $cardText = $('#card-text'), $progressDots = $('#progress-dots');
129
+ function displayCard(index) {
130
+ $cardContainer.css('opacity', 0);
131
+ setTimeout(() => {
132
+ const card = cardsData[index];
133
+ $cardIcon.html(`<i class="${card.icon}"></i>`);
134
+ $cardTitle.text(card.title);
135
+ $cardText.html(card.text);
136
+ $progressDots.find('.dot').removeClass('active').eq(index).addClass('active');
137
+ $cardContainer.css('opacity', 1);
138
+ }, 300);
139
+ }
140
+ function startAutoRotate() { autoRotateInterval = setInterval(() => $('#next-card').click(), 5000); }
141
+ cardsData.forEach(() => $progressDots.append('<div class="dot"></div>'));
142
+ displayCard(currentCardIndex);
143
+ startAutoRotate();
144
+ $('#next-card').on('click', function() {
145
+ currentCardIndex = (currentCardIndex + 1) % cardsData.length;
146
+ displayCard(currentCardIndex);
147
+ clearInterval(autoRotateInterval); startAutoRotate();
148
+ });
149
+ $('#prev-card').on('click', function() {
150
+ currentCardIndex = (currentCardIndex - 1 + cardsData.length) % cardsData.length;
151
+ displayCard(currentCardIndex);
152
+ clearInterval(autoRotateInterval); startAutoRotate();
153
+ });
154
+
155
+ const $loader = $('#loader-wrapper');
156
+ const $container = $('#content-container');
157
+
158
+ // URL para el iframe, pasada desde la vista InitiateExternalChatView
159
+ const iframeSrc = "{{ iframe_src_url }}";
160
+
161
+ // Creamos el elemento iframe
162
+ const iframe = document.createElement('iframe');
163
+ iframe.src = iframeSrc;
164
+
165
+ // Estilos para que ocupe toda la pantalla
166
+ iframe.style.width = '100%';
167
+ iframe.style.height = '100%';
168
+ iframe.style.border = 'none';
169
+ iframe.style.display = 'none'; // Empezamos oculto
170
+
171
+ // Evento que se dispara cuando el iframe ha terminado de cargar su contenido
172
+ iframe.onload = function() {
173
+ // Mostramos el iframe
174
+ iframe.style.display = 'block';
175
+ // Ocultamos la animación de carga con una transición suave
176
+ $loader.css('opacity', 0);
177
+ setTimeout(() => $loader.hide(), 500); // Lo eliminamos del DOM después de la transición
178
+ };
179
+
180
+ // Añadimos el iframe al contenedor en el DOM
181
+ $container.append(iframe);
182
+ });
183
+ </script>
184
+ </body>
185
+ </html>
@@ -19,8 +19,12 @@ class InitiateExternalChatView(MethodView):
19
19
  @inject
20
20
  def __init__(self,
21
21
  iauthentication: IAuthentication,
22
+ branding_service: BrandingService,
23
+ profile_service: ProfileService
22
24
  ):
23
25
  self.iauthentication = iauthentication
26
+ self.branding_service = branding_service
27
+ self.profile_service = profile_service
24
28
 
25
29
  def post(self, company_short_name: str):
26
30
  data = request.get_json()
@@ -29,6 +33,10 @@ class InitiateExternalChatView(MethodView):
29
33
 
30
34
  external_user_id = data['external_user_id']
31
35
 
36
+ company = self.profile_service.get_company_by_short_name(company_short_name)
37
+ if not company:
38
+ return jsonify({"error": "Empresa no encontrada"}), 404
39
+
32
40
  # 1. verify access credentials quickly
33
41
  iaut = self.iauthentication.verify(
34
42
  company_short_name,
@@ -37,10 +45,19 @@ class InitiateExternalChatView(MethodView):
37
45
  if not iaut.get("success"):
38
46
  return jsonify(iaut), 401
39
47
 
40
- # 2. Render the shell page, passing the final data URL and user id
48
+ # 2. Get branding data for the shell page
49
+ branding_data = self.branding_service.get_company_branding(company)
50
+
51
+ # Generamos la URL para el SRC del iframe, añadiendo el usuario como un query parameter.
52
+ target_url = url_for('external_login', # Apunta a la vista del chat
53
+ company_short_name=company_short_name,
54
+ external_user_id=external_user_id, # Se añadirá como ?external_user_id=...
55
+ _external=True)
56
+
57
+ # Renderizamos el shell para un iframe.
41
58
  return render_template("login_shell.html",
42
- data_source_url=url_for('external_chat_login', company_short_name=company_short_name),
43
- external_user_id=external_user_id
59
+ iframe_src_url=target_url, # Le cambiamos el nombre para más claridad
60
+ branding=branding_data
44
61
  )
45
62
 
46
63
  class ExternalChatLoginView(MethodView):
@@ -60,15 +77,15 @@ class ExternalChatLoginView(MethodView):
60
77
  self.jwt_service = jwt_service
61
78
  self.branding_service = branding_service
62
79
 
63
- def post(self, company_short_name: str):
64
- data = request.get_json()
65
- if not data or 'external_user_id' not in data:
66
- return jsonify({"error": "Falta external_user_id"}), 400
67
-
68
- external_user_id = data['external_user_id']
80
+ def get(self, company_short_name: str):
81
+ # Leemos el user_id desde los parámetros de la URL (?external_user_id=...)
82
+ external_user_id = request.args.get('external_user_id')
83
+ if not external_user_id:
84
+ return "Falta el parámetro external_user_id en la URL", 400
69
85
 
70
86
  company = self.profile_service.get_company_by_short_name(company_short_name)
71
87
  if not company:
88
+ logging.error(f'Company {company_short_name} not found')
72
89
  return jsonify({"error": "Empresa no encontrada"}), 404
73
90
 
74
91
  try:
@@ -96,16 +113,15 @@ class ExternalChatLoginView(MethodView):
96
113
  branding_data = self.branding_service.get_company_branding(company)
97
114
 
98
115
  # 5. render the chat page with the company/user information.
99
- chat_html = render_template("chat.html",
116
+ return render_template("chat.html",
100
117
  company_short_name=company_short_name,
101
- auth_method='jwt', # login method is JWT
102
- session_jwt=token, # pass the token to the front-end
118
+ auth_method='jwt',
119
+ session_jwt=token,
103
120
  external_user_id=external_user_id,
104
121
  branding=branding_data,
105
122
  prompts=prompts,
106
123
  iatoolkit_base_url=os.getenv('IATOOLKIT_BASE_URL'),
107
- )
108
- return chat_html, 200
124
+ ), 200
109
125
 
110
126
  except Exception as e:
111
127
  logging.exception(f"Error al inicializar el chat para {company_short_name}/{external_user_id}: {e}")
@@ -13,7 +13,7 @@ from iatoolkit.services.branding_service import BrandingService
13
13
  from iatoolkit.services.query_service import QueryService
14
14
  import os
15
15
  from iatoolkit.common.session_manager import SessionManager
16
-
16
+ from iatoolkit.services.branding_service import BrandingService
17
17
 
18
18
  class InitiateLoginView(MethodView):
19
19
  """
@@ -22,8 +22,11 @@ class InitiateLoginView(MethodView):
22
22
  and immediately returns the loading shell page.
23
23
  """
24
24
  @inject
25
- def __init__(self, profile_service: ProfileService):
25
+ def __init__(self,
26
+ profile_service: ProfileService,
27
+ branding_service: BrandingService,):
26
28
  self.profile_service = profile_service
29
+ self.branding_service = branding_service
27
30
 
28
31
  def post(self, company_short_name: str):
29
32
  # get company info
@@ -35,7 +38,7 @@ class InitiateLoginView(MethodView):
35
38
  email = request.form.get('email')
36
39
  password = request.form.get('password')
37
40
 
38
- # authenticate the user
41
+ # 1. authenticate the user
39
42
  response = self.profile_service.login(
40
43
  company_short_name=company_short_name,
41
44
  email=email,
@@ -53,13 +56,18 @@ class InitiateLoginView(MethodView):
53
56
  },
54
57
  alert_message=response["error"]), 400
55
58
 
59
+ # 2. Get branding data for the shell page
60
+ branding_data = self.branding_service.get_company_branding(company)
56
61
 
57
62
  # 3. Render the shell page, passing the URL for the heavy lifting
58
63
  # The shell's AJAX call will now be authenticated via the session cookie.
59
64
  return render_template(
60
65
  "login_shell.html",
61
- data_source_url=url_for('login', company_short_name=company_short_name),
62
- external_user_id='' # Pass an empty string, the shell will handle it
66
+ data_source_url=url_for('login',
67
+ company_short_name=company_short_name,
68
+ _external=True),
69
+ external_user_id='',
70
+ branding=branding_data,
63
71
  )
64
72
 
65
73
 
@@ -91,6 +99,9 @@ class LoginView(MethodView):
91
99
  # 1. The user is already authenticated by the session cookie set by InitiateLoginView.
92
100
  # We just retrieve the user and company IDs from the session.
93
101
  user_id = SessionManager.get('user_id')
102
+ if not user_id:
103
+ return render_template('error.html', message="Usuario no encontrado"), 404
104
+
94
105
  user_email = SessionManager.get('user')['email']
95
106
 
96
107
  try:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: iatoolkit
3
- Version: 0.12.0
3
+ Version: 0.14.0
4
4
  Summary: IAToolkit
5
5
  Author: Fernando Libedinsky
6
6
  License-Expression: MIT
@@ -91,19 +91,19 @@ src/iatoolkit/templates/forgot_password.html
91
91
  src/iatoolkit/templates/header.html
92
92
  src/iatoolkit/templates/home.html
93
93
  src/iatoolkit/templates/login.html
94
+ src/iatoolkit/templates/login_shell.html
94
95
  src/iatoolkit/templates/signup.html
95
96
  src/iatoolkit/templates/test.html
96
97
  src/iatoolkit/views/__init__.py
97
98
  src/iatoolkit/views/change_password_view.py
98
99
  src/iatoolkit/views/chat_token_request_view.py
99
100
  src/iatoolkit/views/download_file_view.py
100
- src/iatoolkit/views/external_chat_login_view.py
101
- src/iatoolkit/views/external_login_view.py
102
101
  src/iatoolkit/views/file_store_view.py
103
102
  src/iatoolkit/views/forgot_password_view.py
104
103
  src/iatoolkit/views/history_view.py
105
104
  src/iatoolkit/views/home_view.py
106
105
  src/iatoolkit/views/llmquery_view.py
106
+ src/iatoolkit/views/login_external_id_view.py
107
107
  src/iatoolkit/views/login_view.py
108
108
  src/iatoolkit/views/prompt_view.py
109
109
  src/iatoolkit/views/signup_view.py
@@ -1,40 +0,0 @@
1
- # Copyright (c) 2024 Fernando Libedinsky
2
- # Product: IAToolkit
3
- #
4
- # IAToolkit is open source software.
5
-
6
- from flask.views import MethodView
7
- from injector import inject
8
- from iatoolkit.common.auth import IAuthentication
9
- from iatoolkit.services.query_service import QueryService
10
- from flask import jsonify
11
- import logging
12
-
13
- class ExternalLoginView(MethodView):
14
-
15
- @inject
16
- def __init__(self,
17
- iauthentication: IAuthentication,
18
- query_service: QueryService
19
- ):
20
- self.iauthentication = iauthentication
21
- self.query_service = query_service
22
-
23
- def get(self, company_short_name: str, external_user_id: str):
24
- # 1. get access credentials
25
- iaut = self.iauthentication.verify(company_short_name, external_user_id)
26
- if not iaut.get("success"):
27
- return jsonify(iaut), 401
28
-
29
- try:
30
- # initialize the context
31
- self.query_service.llm_init_context(
32
- company_short_name=company_short_name,
33
- external_user_id=external_user_id
34
- )
35
-
36
- return {'status': 'OK'}, 200
37
- except Exception as e:
38
- logging.exception(
39
- f"Error inesperado al inicializar el contexto durante el login para company {company_short_name}: {e}")
40
- return jsonify({"error_message": str(e)}), 500
File without changes
File without changes
File without changes