iatoolkit 0.50.2__tar.gz → 0.51.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 (125) hide show
  1. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/PKG-INFO +1 -1
  2. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/pyproject.toml +1 -1
  3. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/common/routes.py +5 -5
  4. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/iatoolkit.py +7 -1
  5. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/templates/_login_widget.html +1 -1
  6. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/templates/login_test.html +2 -2
  7. iatoolkit-0.51.0/src/iatoolkit/views/base_login_view.py +63 -0
  8. iatoolkit-0.51.0/src/iatoolkit/views/external_login_view.py +70 -0
  9. iatoolkit-0.51.0/src/iatoolkit/views/login_view.py +111 -0
  10. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit.egg-info/PKG-INFO +1 -1
  11. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit.egg-info/SOURCES.txt +1 -0
  12. iatoolkit-0.50.2/src/iatoolkit/views/external_login_view.py +0 -93
  13. iatoolkit-0.50.2/src/iatoolkit/views/login_view.py +0 -159
  14. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/readme.md +0 -0
  15. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/requirements.txt +0 -0
  16. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/setup.cfg +0 -0
  17. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/__init__.py +0 -0
  18. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/base_company.py +0 -0
  19. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/cli_commands.py +0 -0
  20. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/common/__init__.py +0 -0
  21. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/common/exceptions.py +0 -0
  22. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/common/session_manager.py +0 -0
  23. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/common/util.py +0 -0
  24. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/company_registry.py +0 -0
  25. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/infra/__init__.py +0 -0
  26. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/infra/call_service.py +0 -0
  27. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/infra/connectors/__init__.py +0 -0
  28. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/infra/connectors/file_connector.py +0 -0
  29. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/infra/connectors/file_connector_factory.py +0 -0
  30. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/infra/connectors/google_cloud_storage_connector.py +0 -0
  31. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/infra/connectors/google_drive_connector.py +0 -0
  32. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/infra/connectors/local_file_connector.py +0 -0
  33. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/infra/connectors/s3_connector.py +0 -0
  34. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/infra/gemini_adapter.py +0 -0
  35. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/infra/google_chat_app.py +0 -0
  36. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/infra/llm_client.py +0 -0
  37. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/infra/llm_proxy.py +0 -0
  38. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/infra/llm_response.py +0 -0
  39. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/infra/mail_app.py +0 -0
  40. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/infra/openai_adapter.py +0 -0
  41. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/infra/redis_session_manager.py +0 -0
  42. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/repositories/__init__.py +0 -0
  43. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/repositories/database_manager.py +0 -0
  44. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/repositories/document_repo.py +0 -0
  45. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/repositories/llm_query_repo.py +0 -0
  46. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/repositories/models.py +0 -0
  47. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/repositories/profile_repo.py +0 -0
  48. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/repositories/tasks_repo.py +0 -0
  49. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/repositories/vs_repo.py +0 -0
  50. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/services/__init__.py +0 -0
  51. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/services/auth_service.py +0 -0
  52. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/services/benchmark_service.py +0 -0
  53. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/services/branding_service.py +0 -0
  54. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/services/dispatcher_service.py +0 -0
  55. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/services/document_service.py +0 -0
  56. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/services/excel_service.py +0 -0
  57. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/services/file_processor_service.py +0 -0
  58. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/services/history_service.py +0 -0
  59. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/services/jwt_service.py +0 -0
  60. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/services/load_documents_service.py +0 -0
  61. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/services/mail_service.py +0 -0
  62. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/services/onboarding_service.py +0 -0
  63. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/services/profile_service.py +0 -0
  64. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/services/prompt_manager_service.py +0 -0
  65. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/services/query_service.py +0 -0
  66. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/services/search_service.py +0 -0
  67. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/services/sql_service.py +0 -0
  68. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/services/tasks_service.py +0 -0
  69. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/services/user_feedback_service.py +0 -0
  70. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/services/user_session_context_service.py +0 -0
  71. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/static/images/arrow_up.png +0 -0
  72. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/static/images/diagrama_iatoolkit.jpg +0 -0
  73. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/static/images/logo_clinica.png +0 -0
  74. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/static/images/logo_iatoolkit.png +0 -0
  75. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/static/images/logo_maxxa.png +0 -0
  76. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/static/images/logo_notaria.png +0 -0
  77. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/static/images/logo_tarjeta.png +0 -0
  78. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/static/images/logo_umayor.png +0 -0
  79. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/static/images/upload.png +0 -0
  80. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/static/js/chat_feedback.js +0 -0
  81. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/static/js/chat_filepond.js +0 -0
  82. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/static/js/chat_history.js +0 -0
  83. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/static/js/chat_main.js +0 -0
  84. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/static/styles/chat_iatoolkit.css +0 -0
  85. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/static/styles/chat_info.css +0 -0
  86. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/static/styles/chat_modal.css +0 -0
  87. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/static/styles/landing_page.css +0 -0
  88. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/static/styles/llm_output.css +0 -0
  89. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/system_prompts/format_styles.prompt +0 -0
  90. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/system_prompts/query_main.prompt +0 -0
  91. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/system_prompts/sql_rules.prompt +0 -0
  92. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/templates/_branding_styles.html +0 -0
  93. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/templates/_navbar.html +0 -0
  94. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/templates/about.html +0 -0
  95. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/templates/base.html +0 -0
  96. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/templates/change_password.html +0 -0
  97. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/templates/chat.html +0 -0
  98. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/templates/chat_modals.html +0 -0
  99. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/templates/error.html +0 -0
  100. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/templates/forgot_password.html +0 -0
  101. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/templates/header.html +0 -0
  102. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/templates/index.html +0 -0
  103. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/templates/onboarding_shell.html +0 -0
  104. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/templates/signup.html +0 -0
  105. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/templates/test.html +0 -0
  106. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/views/__init__.py +0 -0
  107. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/views/change_password_view.py +0 -0
  108. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/views/chat_token_request_view.py +0 -0
  109. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/views/file_store_api_view.py +0 -0
  110. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/views/forgot_password_view.py +0 -0
  111. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/views/history_api_view.py +0 -0
  112. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/views/index_view.py +0 -0
  113. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/views/init_context_api_view.py +0 -0
  114. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/views/llmquery_api_view.py +0 -0
  115. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/views/llmquery_web_view.py +0 -0
  116. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/views/login_test_view.py +0 -0
  117. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/views/prompt_api_view.py +0 -0
  118. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/views/signup_view.py +0 -0
  119. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/views/tasks_review_view.py +0 -0
  120. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/views/tasks_view.py +0 -0
  121. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/views/user_feedback_api_view.py +0 -0
  122. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit/views/verify_user_view.py +0 -0
  123. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit.egg-info/dependency_links.txt +0 -0
  124. {iatoolkit-0.50.2 → iatoolkit-0.51.0}/src/iatoolkit.egg-info/requires.txt +0 -0
  125. {iatoolkit-0.50.2 → iatoolkit-0.51.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.50.2
3
+ Version: 0.51.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.50.2"
7
+ version = "0.51.0"
8
8
  requires-python = ">=3.12"
9
9
  description = "IAToolkit"
10
10
  readme = "readme.md"
@@ -26,8 +26,8 @@ def register_views(injector, app):
26
26
  from iatoolkit.views.tasks_view import TaskView
27
27
  from iatoolkit.views.tasks_review_view import TaskReviewView
28
28
  from iatoolkit.views.login_test_view import LoginTest
29
- from iatoolkit.views.login_view import LoginView, InitiateLoginView
30
- from iatoolkit.views.external_login_view import InitiateExternalChatView
29
+ from iatoolkit.views.login_view import LoginView, FinalizeContextView
30
+ from iatoolkit.views.external_login_view import ExternalLoginView
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
@@ -46,8 +46,8 @@ def register_views(injector, app):
46
46
 
47
47
  # this functions are for login external users (with api-key)
48
48
  # only the first one should be used from an external app
49
- app.add_url_rule('/<company_short_name>/initiate_external_chat',
50
- view_func=InitiateExternalChatView.as_view('initiate_external_chat'))
49
+ app.add_url_rule('/<company_short_name>/external_login',
50
+ view_func=ExternalLoginView.as_view('external_login'))
51
51
 
52
52
  # this endpoint is for requesting a chat token for external users
53
53
  app.add_url_rule('/auth/chat_token',
@@ -55,8 +55,8 @@ def register_views(injector, app):
55
55
 
56
56
  # login for the iatoolkit integrated frontend
57
57
  # this is the main login endpoint for the frontend
58
- app.add_url_rule('/<company_short_name>/chat', view_func=InitiateLoginView.as_view('chat'))
59
58
  app.add_url_rule('/<company_short_name>/login', view_func=LoginView.as_view('login'))
59
+ app.add_url_rule('/<company_short_name>/finalize_context_load', view_func=FinalizeContextView.as_view('finalize_context_load'))
60
60
 
61
61
  # register new user, account verification and forgot password
62
62
  app.add_url_rule('/<company_short_name>/signup',view_func=SignupView.as_view('signup'))
@@ -19,7 +19,7 @@ from werkzeug.middleware.proxy_fix import ProxyFix
19
19
  from injector import Binder, singleton, Injector
20
20
  from importlib.metadata import version as _pkg_version, PackageNotFoundError
21
21
 
22
- IATOOLKIT_VERSION = "0.21.0"
22
+ IATOOLKIT_VERSION = "0.50.2"
23
23
 
24
24
  # global variable for the unique instance of IAToolkit
25
25
  _iatoolkit_instance: Optional['IAToolkit'] = None
@@ -360,6 +360,10 @@ class IAToolkit:
360
360
  @self.app.context_processor
361
361
  def inject_globals():
362
362
  from iatoolkit.common.session_manager import SessionManager
363
+ from iatoolkit.services.profile_service import ProfileService
364
+
365
+ profile_service = self._injector.get(ProfileService)
366
+ user_profile = profile_service.get_current_session_info().get('profile', {})
363
367
 
364
368
  return {
365
369
  'url_for': url_for,
@@ -367,6 +371,8 @@ class IAToolkit:
367
371
  'app_name': 'IAToolkit',
368
372
  'user_identifier': SessionManager.get('user_identifier'),
369
373
  'company_short_name': SessionManager.get('company_short_name'),
374
+ 'user_is_local': user_profile.get('user_is_local'),
375
+ 'user_email': user_profile.get('user_email'),
370
376
  'iatoolkit_base_url': os.environ.get('IATOOLKIT_BASE_URL', ''),
371
377
  }
372
378
 
@@ -10,7 +10,7 @@
10
10
 
11
11
  <!-- 2. Formulario de Inicio de Sesión -->
12
12
  <form id="login-form"
13
- action="{{ url_for('chat', company_short_name=company_short_name) }}"
13
+ action="{{ url_for('login', company_short_name=company_short_name) }}"
14
14
  method="post">
15
15
  <div class="mb-3">
16
16
  <label for="email" class="form-label d-block">Correo Electrónico</label>
@@ -72,7 +72,7 @@
72
72
 
73
73
  // Actualizar action del formulario "Iniciar Sesión"
74
74
  if (selectedCompany && selectedCompany.trim() !== '') {
75
- const loginAction = '/' + selectedCompany + '/chat';
75
+ const loginAction = '/' + selectedCompany + '/external_login';
76
76
  $('#login-form').attr('action', loginAction); // Actualizamos la URL del form
77
77
  } else {
78
78
  $('#login-form').attr('action', '#'); // URL genérica si no hay selección
@@ -116,7 +116,7 @@
116
116
  return;
117
117
  }
118
118
 
119
- fetch(`/${selectedCompany}/initiate_external_chat`, {
119
+ fetch(`/${selectedCompany}/external_login`, {
120
120
  method: 'POST',
121
121
  headers: {
122
122
  'Content-Type': 'application/json',
@@ -0,0 +1,63 @@
1
+ # iatoolkit/views/base_login_view.py
2
+ # Copyright (c) 2024 Fernando Libedinsky
3
+ # Product: IAToolkit
4
+ #
5
+ # IAToolkit is open source software.
6
+
7
+ from flask.views import MethodView
8
+ from flask import render_template, url_for
9
+ from injector import inject
10
+ from iatoolkit.services.profile_service import ProfileService
11
+ from iatoolkit.services.query_service import QueryService
12
+ from iatoolkit.services.branding_service import BrandingService
13
+ from iatoolkit.services.onboarding_service import OnboardingService
14
+ from iatoolkit.services.prompt_manager_service import PromptService
15
+
16
+
17
+ class BaseLoginView(MethodView):
18
+ """
19
+ Base class for views that initiate a session and decide the context
20
+ loading path (fast or slow).
21
+ """
22
+ @inject
23
+ def __init__(self,
24
+ profile_service: ProfileService,
25
+ branding_service: BrandingService,
26
+ prompt_service: PromptService,
27
+ onboarding_service: OnboardingService,
28
+ query_service: QueryService):
29
+ self.profile_service = profile_service
30
+ self.branding_service = branding_service
31
+ self.prompt_service = prompt_service
32
+ self.onboarding_service = onboarding_service
33
+ self.query_service = query_service
34
+
35
+ def _handle_login_path(self, company_short_name: str, user_identifier: str, company):
36
+ """
37
+ Centralized logic to decide between the fast path and the slow path.
38
+ """
39
+ prep_result = self.query_service.prepare_context(
40
+ company_short_name=company_short_name, user_identifier=user_identifier
41
+ )
42
+
43
+ branding_data = self.branding_service.get_company_branding(company)
44
+
45
+ if prep_result.get('rebuild_needed'):
46
+ # --- SLOW PATH: Render the loading shell ---
47
+ onboarding_cards = self.onboarding_service.get_onboarding_cards(company)
48
+ target_url = url_for('finalize_context_load', company_short_name=company_short_name, _external=True)
49
+
50
+ return render_template(
51
+ "onboarding_shell.html",
52
+ iframe_src_url=target_url,
53
+ branding=branding_data,
54
+ onboarding_cards=onboarding_cards
55
+ )
56
+ else:
57
+ # --- FAST PATH: Render the chat page directly ---
58
+ prompts = self.prompt_service.get_user_prompts(company_short_name)
59
+ return render_template(
60
+ "chat.html",
61
+ branding=branding_data,
62
+ prompts=prompts,
63
+ )
@@ -0,0 +1,70 @@
1
+ # Copyright (c) 2024 Fernando Libedinsky
2
+ # Product: IAToolkit
3
+ #
4
+ # IAToolkit is open source software.
5
+
6
+ import os
7
+ import logging
8
+ from flask import request, jsonify
9
+ from injector import inject
10
+ from iatoolkit.services.auth_service import AuthService
11
+ from iatoolkit.views.base_login_view import BaseLoginView
12
+
13
+ # Importar los servicios que necesita la clase base
14
+ from iatoolkit.services.profile_service import ProfileService
15
+ from iatoolkit.services.branding_service import BrandingService
16
+ from iatoolkit.services.onboarding_service import OnboardingService
17
+ from iatoolkit.services.query_service import QueryService
18
+ from iatoolkit.services.prompt_manager_service import PromptService
19
+
20
+ class ExternalLoginView(BaseLoginView):
21
+ """
22
+ Handles login for external users via API.
23
+ Authenticates and then delegates the path decision (fast/slow) to the base class.
24
+ """
25
+ @inject
26
+ def __init__(self,
27
+ iauthentication: AuthService,
28
+ profile_service: ProfileService,
29
+ branding_service: BrandingService,
30
+ prompt_service: PromptService,
31
+ onboarding_service: OnboardingService,
32
+ query_service: QueryService):
33
+ # Pass the dependencies for the base class to its __init__
34
+ super().__init__(
35
+ profile_service=profile_service,
36
+ branding_service=branding_service,
37
+ onboarding_service=onboarding_service,
38
+ query_service=query_service,
39
+ prompt_service=prompt_service
40
+ )
41
+ # Handle the dependency specific to this child class
42
+ self.iauthentication = iauthentication
43
+
44
+ def post(self, company_short_name: str):
45
+ data = request.get_json()
46
+ if not data or 'external_user_id' not in data:
47
+ return jsonify({"error": "Falta external_user_id"}), 400
48
+
49
+ company = self.profile_service.get_company_by_short_name(company_short_name)
50
+ if not company:
51
+ return jsonify({"error": "Empresa no encontrada"}), 404
52
+
53
+ external_user_id = data['external_user_id']
54
+ if not external_user_id:
55
+ return jsonify({"error": "missing external_user_id"}), 404
56
+
57
+ # 1. Authenticate the API call.
58
+ iaut = self.iauthentication.verify()
59
+ if not iaut.get("success"):
60
+ return jsonify(iaut), 401
61
+
62
+ # 2. Create the external user session.
63
+ self.profile_service.create_external_user_session(company, external_user_id)
64
+
65
+ # 3. Delegate the path decision to the centralized logic.
66
+ try:
67
+ return self._handle_login_path(company_short_name, external_user_id, company)
68
+ except Exception as e:
69
+ logging.exception(f"Error processing external login path for {company_short_name}/{external_user_id}: {e}")
70
+ return jsonify({"error": f"Internal server error while starting chat. {str(e)}"}), 500
@@ -0,0 +1,111 @@
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 flask import request, redirect, render_template, url_for
8
+ from injector import inject
9
+ from iatoolkit.services.profile_service import ProfileService
10
+ from iatoolkit.services.query_service import QueryService
11
+ from iatoolkit.services.prompt_manager_service import PromptService
12
+ from iatoolkit.services.branding_service import BrandingService
13
+ from iatoolkit.views.base_login_view import BaseLoginView
14
+
15
+
16
+ class LoginView(BaseLoginView):
17
+ """
18
+ Handles login for local users.
19
+ Authenticates and then delegates the path decision (fast/slow) to the base class.
20
+ """
21
+
22
+ def post(self, company_short_name: str):
23
+ company = self.profile_service.get_company_by_short_name(company_short_name)
24
+ if not company:
25
+ return render_template('error.html', message="Empresa no encontrada"), 404
26
+
27
+ email = request.form.get('email')
28
+ password = request.form.get('password')
29
+
30
+ # 1. Authenticate user and create the unified session.
31
+ auth_response = self.profile_service.login(
32
+ company_short_name=company_short_name,
33
+ email=email,
34
+ password=password
35
+ )
36
+
37
+ if not auth_response['success']:
38
+ branding_data = self.branding_service.get_company_branding(company)
39
+
40
+ return render_template(
41
+ 'index.html',
42
+ company_short_name=company_short_name,
43
+ company=company,
44
+ branding=branding_data,
45
+ form_data={"email": email},
46
+ alert_message=auth_response["message"]
47
+ ), 400
48
+
49
+ user_identifier = auth_response['user_identifier']
50
+
51
+ # 2. Delegate the path decision to the centralized logic.
52
+ try:
53
+ return self._handle_login_path(company_short_name, user_identifier, company)
54
+ except Exception as e:
55
+ return render_template("error.html", company=company, company_short_name=company_short_name,
56
+ message=f"Error processing login path: {str(e)}"), 500
57
+
58
+
59
+ class FinalizeContextView(MethodView):
60
+ """
61
+ Finalizes context loading in the slow path.
62
+ This view is invoked by the iframe inside onboarding_shell.html.
63
+ """
64
+
65
+ @inject
66
+ def __init__(self,
67
+ profile_service: ProfileService,
68
+ query_service: QueryService,
69
+ prompt_service: PromptService,
70
+ branding_service: BrandingService
71
+ ):
72
+ self.profile_service = profile_service
73
+ self.query_service = query_service
74
+ self.prompt_service = prompt_service
75
+ self.branding_service = branding_service
76
+
77
+ def get(self, company_short_name: str):
78
+ # 1. Use the centralized method to get session info.
79
+ session_info = self.profile_service.get_current_session_info()
80
+ user_identifier = session_info.get('user_identifier')
81
+
82
+ if not user_identifier:
83
+ # This can happen if the session expires or is invalid.
84
+ return redirect(url_for('login_page', company_short_name=company_short_name))
85
+
86
+ company = self.profile_service.get_company_by_short_name(company_short_name)
87
+ if not company:
88
+ return render_template('error.html', message="Empresa no encontrada"), 404
89
+
90
+ try:
91
+ # 2. Finalize the context rebuild (the heavy task).
92
+ self.query_service.finalize_context_rebuild(
93
+ company_short_name=company_short_name,
94
+ user_identifier=user_identifier
95
+ )
96
+
97
+ # 3. render the chat page.
98
+ prompts = self.prompt_service.get_user_prompts(company_short_name)
99
+ branding_data = self.branding_service.get_company_branding(company)
100
+
101
+ return render_template(
102
+ "chat.html",
103
+ branding=branding_data,
104
+ prompts=prompts,
105
+ )
106
+
107
+ except Exception as e:
108
+ return render_template("error.html",
109
+ company=company,
110
+ company_short_name=company_short_name,
111
+ message=f"An unexpected error occurred during context loading: {str(e)}"), 500
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: iatoolkit
3
- Version: 0.50.2
3
+ Version: 0.51.0
4
4
  Summary: IAToolkit
5
5
  Author: Fernando Libedinsky
6
6
  License-Expression: MIT
@@ -100,6 +100,7 @@ src/iatoolkit/templates/onboarding_shell.html
100
100
  src/iatoolkit/templates/signup.html
101
101
  src/iatoolkit/templates/test.html
102
102
  src/iatoolkit/views/__init__.py
103
+ src/iatoolkit/views/base_login_view.py
103
104
  src/iatoolkit/views/change_password_view.py
104
105
  src/iatoolkit/views/chat_token_request_view.py
105
106
  src/iatoolkit/views/external_login_view.py
@@ -1,93 +0,0 @@
1
- # Copyright (c) 2024 Fernando Libedinsky
2
- # Product: IAToolkit
3
- #
4
- # IAToolkit is open source software.
5
-
6
- import os
7
- import logging
8
- from flask import request, jsonify, render_template, url_for
9
- from flask.views import MethodView
10
- from injector import inject
11
- from iatoolkit.services.auth_service import AuthService
12
- from iatoolkit.services.profile_service import ProfileService
13
- from iatoolkit.services.query_service import QueryService
14
- from iatoolkit.services.prompt_manager_service import PromptService
15
- from iatoolkit.services.branding_service import BrandingService
16
- from iatoolkit.services.onboarding_service import OnboardingService
17
-
18
-
19
- class InitiateExternalChatView(MethodView):
20
- @inject
21
- def __init__(self,
22
- iauthentication: AuthService,
23
- branding_service: BrandingService,
24
- profile_service: ProfileService,
25
- onboarding_service: OnboardingService,
26
- query_service: QueryService,
27
- prompt_service: PromptService
28
- ):
29
- self.iauthentication = iauthentication
30
- self.branding_service = branding_service
31
- self.profile_service = profile_service
32
- self.onboarding_service = onboarding_service
33
- self.query_service = query_service
34
- self.prompt_service = prompt_service
35
-
36
- def post(self, company_short_name: str):
37
- data = request.get_json()
38
- if not data or 'external_user_id' not in data:
39
- return jsonify({"error": "Falta external_user_id"}), 400
40
-
41
- company = self.profile_service.get_company_by_short_name(company_short_name)
42
- if not company:
43
- return jsonify({"error": "Empresa no encontrada"}), 404
44
-
45
- external_user_id = data['external_user_id']
46
- if not external_user_id:
47
- return jsonify({"error": "missing external_user_id"}), 404
48
-
49
- # 1. Authenticate the API call.
50
- iaut = self.iauthentication.verify()
51
- if not iaut.get("success"):
52
- return jsonify(iaut), 401
53
-
54
- # 2. Delegate session creation to ProfileService.
55
- self.profile_service.create_external_user_session(company, external_user_id)
56
-
57
- # 3. prepare and decide the path
58
- prep_result = self.query_service.prepare_context(
59
- company_short_name=company_short_name, user_identifier=external_user_id
60
- )
61
-
62
- if prep_result.get('rebuild_needed'):
63
- branding_data = self.branding_service.get_company_branding(company)
64
- onboarding_cards = self.onboarding_service.get_onboarding_cards(company)
65
- target_url = url_for('login', company_short_name=company_short_name,
66
- _external=True)
67
-
68
- return render_template(
69
- "onboarding_shell.html",
70
- iframe_src_url=target_url,
71
- branding=branding_data,
72
- onboarding_cards=onboarding_cards
73
- )
74
- else:
75
- # fast path, the context is already on the cache, render the chat directly
76
- try:
77
- session_info = self.profile_service.get_current_session_info()
78
- user_profile = session_info.get('profile', {})
79
-
80
- prompts = self.prompt_service.get_user_prompts(company_short_name)
81
- branding_data = self.branding_service.get_company_branding(company)
82
-
83
- return render_template("chat.html",
84
- company_short_name=company_short_name,
85
- user_is_local=user_profile.get('user_is_local'),
86
- user_email=user_profile.get('user_email'),
87
- branding=branding_data,
88
- prompts=prompts,
89
- iatoolkit_base_url=os.getenv('IATOOLKIT_BASE_URL'),
90
- ), 200
91
- except Exception as e:
92
- logging.exception(f"Error en el camino rápido para {company_short_name}/{external_user_id}: {e}")
93
- return jsonify({"error": f"Error interno al iniciar el chat. {str(e)}"}), 500
@@ -1,159 +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 flask import request, redirect, render_template, url_for
8
- from injector import inject
9
- from iatoolkit.services.profile_service import ProfileService
10
- from iatoolkit.services.prompt_manager_service import PromptService
11
- from iatoolkit.services.query_service import QueryService
12
- import os
13
- from iatoolkit.services.branding_service import BrandingService
14
- from iatoolkit.services.onboarding_service import OnboardingService
15
-
16
-
17
- class InitiateLoginView(MethodView):
18
- """
19
- Handles the initial part of the login process.
20
- Authenticates, decides the login path (fast or slow), and renders
21
- either the chat page directly or the loading shell.
22
- """
23
-
24
- @inject
25
- def __init__(self,
26
- profile_service: ProfileService,
27
- branding_service: BrandingService,
28
- onboarding_service: OnboardingService,
29
- query_service: QueryService,
30
- prompt_service: PromptService):
31
- self.profile_service = profile_service
32
- self.branding_service = branding_service
33
- self.onboarding_service = onboarding_service
34
- self.query_service = query_service
35
- self.prompt_service = prompt_service
36
-
37
- def post(self, company_short_name: str):
38
- company = self.profile_service.get_company_by_short_name(company_short_name)
39
- if not company:
40
- return render_template('error.html', message="Empresa no encontrada"), 404
41
-
42
- email = request.form.get('email')
43
- password = request.form.get('password')
44
-
45
- # 1. Authenticate user and create the unified session.
46
- auth_response = self.profile_service.login(
47
- company_short_name=company_short_name,
48
- email=email,
49
- password=password
50
- )
51
-
52
- if not auth_response['success']:
53
- return render_template(
54
- 'index.html',
55
- company_short_name=company_short_name,
56
- company=company,
57
- form_data={"email": email},
58
- alert_message=auth_response["message"]
59
- ), 400
60
-
61
- user_identifier = auth_response['user_identifier']
62
-
63
- # 2. PREPARE and DECIDE: Call prepare_context to determine the path.
64
- prep_result = self.query_service.prepare_context(
65
- company_short_name=company_short_name, user_identifier=user_identifier
66
- )
67
-
68
- if prep_result.get('rebuild_needed'):
69
- # --- SLOW PATH: Context rebuild is needed ---
70
- # Render the shell, which will call LoginView for the heavy lifting.
71
- branding_data = self.branding_service.get_company_branding(company)
72
- onboarding_cards = self.onboarding_service.get_onboarding_cards(company)
73
- target_url = url_for('login', company_short_name=company_short_name, _external=True)
74
-
75
- return render_template(
76
- "onboarding_shell.html",
77
- iframe_src_url=target_url,
78
- branding=branding_data,
79
- onboarding_cards=onboarding_cards
80
- )
81
- else:
82
- # --- FAST PATH: Context is already cached ---
83
- # Render chat.html directly.
84
- try:
85
- session_info = self.profile_service.get_current_session_info()
86
- user_profile = session_info.get('profile', {})
87
-
88
- prompts = self.prompt_service.get_user_prompts(company_short_name)
89
- branding_data = self.branding_service.get_company_branding(company)
90
-
91
- return render_template("chat.html",
92
- user_is_local=user_profile.get('user_is_local'),
93
- user_email=user_profile.get('user_email'),
94
- branding=branding_data,
95
- prompts=prompts,
96
- iatoolkit_base_url=os.getenv('IATOOLKIT_BASE_URL'),
97
- ), 200
98
- except Exception as e:
99
- return render_template("error.html", company=company, company_short_name=company_short_name,
100
- message=f"Error in fast path: {str(e)}"), 500
101
-
102
-
103
- class LoginView(MethodView):
104
- """
105
- Handles the heavy-lifting part of the login, ONLY triggered by the iframe
106
- in the slow path (when context rebuild is needed).
107
- """
108
-
109
- @inject
110
- def __init__(self,
111
- profile_service: ProfileService,
112
- query_service: QueryService,
113
- prompt_service: PromptService,
114
- branding_service: BrandingService):
115
- self.profile_service = profile_service
116
- self.query_service = query_service
117
- self.prompt_service = prompt_service
118
- self.branding_service = branding_service
119
-
120
- def get(self, company_short_name: str):
121
- # 1. Use the new centralized method to get session info.
122
- session_info = self.profile_service.get_current_session_info()
123
- user_identifier = session_info.get('user_identifier')
124
- user_profile = session_info.get('profile', {})
125
-
126
- if not user_identifier:
127
- # This can happen if the session expires or is invalid.
128
- return redirect(url_for('login_page', company_short_name=company_short_name))
129
-
130
- company = self.profile_service.get_company_by_short_name(company_short_name)
131
- if not company:
132
- return render_template('error.html', message="Empresa no encontrada"), 404
133
-
134
- try:
135
- # 2. Finalize the context rebuild (the potentially long-running task).
136
- # We pass the identifier, and the service resolves if it's local or external.
137
- self.query_service.finalize_context_rebuild(
138
- company_short_name=company_short_name,
139
- user_identifier=user_identifier
140
- )
141
-
142
- # 3. Get the necessary data for the chat page.
143
- prompts = self.prompt_service.get_user_prompts(company_short_name)
144
- branding_data = self.branding_service.get_company_branding(company)
145
-
146
- # 4. Render the final chat page.
147
- return render_template("chat.html",
148
- user_is_local=user_profile.get('user_is_local'),
149
- user_email=user_profile.get('user_email'),
150
- branding=branding_data,
151
- prompts=prompts,
152
- iatoolkit_base_url=os.getenv('IATOOLKIT_BASE_URL'),
153
- ), 200
154
-
155
- except Exception as e:
156
- return render_template("error.html",
157
- company=company,
158
- company_short_name=company_short_name,
159
- message=f"An unexpected error occurred during context loading: {str(e)}"), 500
File without changes
File without changes
File without changes