iatoolkit 0.22.1__py3-none-any.whl → 0.50.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

Files changed (46) hide show
  1. iatoolkit/common/routes.py +31 -31
  2. iatoolkit/common/session_manager.py +0 -1
  3. iatoolkit/common/util.py +0 -21
  4. iatoolkit/iatoolkit.py +5 -18
  5. iatoolkit/infra/llm_client.py +3 -5
  6. iatoolkit/infra/redis_session_manager.py +48 -2
  7. iatoolkit/repositories/models.py +1 -2
  8. iatoolkit/services/auth_service.py +74 -0
  9. iatoolkit/services/dispatcher_service.py +12 -21
  10. iatoolkit/services/excel_service.py +15 -15
  11. iatoolkit/services/history_service.py +2 -11
  12. iatoolkit/services/profile_service.py +83 -25
  13. iatoolkit/services/query_service.py +132 -82
  14. iatoolkit/services/tasks_service.py +1 -1
  15. iatoolkit/services/user_feedback_service.py +3 -6
  16. iatoolkit/services/user_session_context_service.py +112 -54
  17. iatoolkit/static/js/chat_feedback.js +1 -1
  18. iatoolkit/static/js/chat_history.js +1 -5
  19. iatoolkit/static/js/chat_main.js +1 -1
  20. iatoolkit/static/styles/landing_page.css +62 -2
  21. iatoolkit/system_prompts/query_main.prompt +3 -12
  22. iatoolkit/templates/_login_widget.html +6 -8
  23. iatoolkit/templates/chat.html +78 -4
  24. iatoolkit/templates/error.html +1 -1
  25. iatoolkit/templates/index.html +38 -11
  26. iatoolkit/templates/{home.html → login_test.html} +11 -51
  27. iatoolkit/views/external_login_view.py +50 -111
  28. iatoolkit/views/{file_store_view.py → file_store_api_view.py} +4 -4
  29. iatoolkit/views/history_api_view.py +52 -0
  30. iatoolkit/views/init_context_api_view.py +62 -0
  31. iatoolkit/views/llmquery_api_view.py +50 -0
  32. iatoolkit/views/llmquery_web_view.py +38 -0
  33. iatoolkit/views/{home_view.py → login_test_view.py} +2 -5
  34. iatoolkit/views/login_view.py +79 -56
  35. iatoolkit/views/{prompt_view.py → prompt_api_view.py} +4 -4
  36. iatoolkit/views/{user_feedback_view.py → user_feedback_api_view.py} +16 -19
  37. {iatoolkit-0.22.1.dist-info → iatoolkit-0.50.0.dist-info}/METADATA +2 -2
  38. {iatoolkit-0.22.1.dist-info → iatoolkit-0.50.0.dist-info}/RECORD +40 -41
  39. iatoolkit/common/auth.py +0 -200
  40. iatoolkit/templates/login.html +0 -43
  41. iatoolkit/views/download_file_view.py +0 -58
  42. iatoolkit/views/history_view.py +0 -57
  43. iatoolkit/views/init_context_view.py +0 -35
  44. iatoolkit/views/llmquery_view.py +0 -65
  45. {iatoolkit-0.22.1.dist-info → iatoolkit-0.50.0.dist-info}/WHEEL +0 -0
  46. {iatoolkit-0.22.1.dist-info → iatoolkit-0.50.0.dist-info}/top_level.txt +0 -0
@@ -7,60 +7,20 @@
7
7
  <!-- Contenido principal con espaciado adicional respecto al header -->
8
8
  <div class="row flex-fill mt-5 flex-wrap">
9
9
 
10
- {% if not user or user_company != company_short_name %}
11
- <!-- Sección de login (se coloca primero en el HTML para mobile) -->
12
- <div class="col-12 col-lg-5 offset-lg-1">
13
- <div class="border rounded p-4 shadow-sm bg-light">
14
- <h4 class="text-muted fw-semibold text-start mb-3">login integrado (IAToolkit)</h4>
15
- <form id="login-form"
16
- action="{{ url_for('chat', company_short_name=company_short_name, external_login=True) }}"
17
- method="post">
18
- <div class="mb-3">
19
- <label for="company_short_name" class="form-label d-block text-muted">Empresa</label>
20
- <select id="company_short_name" name="company_short_name" class="form-select" required>
21
- <option value="" disabled selected>Selecciona una empresa</option>
22
- {% for company in companies %}
23
- <option value="{{ company.short_name }}"
24
- {% if company.short_name == company_short_name %}selected{% endif %}>
25
- {{ company.short_name }}
26
- </option>
27
- {% endfor %}
28
- </select>
29
- </div>
30
10
 
31
- <div class="mb-3">
32
- <label for="email" class="form-label d-block text-muted">Correo Electrónico</label>
33
- <input type="email" id="email" name="email" class="form-control" required>
34
- </div>
35
- <div class="mb-3">
36
- <label for="password" class="form-label d-block text-muted">Contraseña</label>
37
- <input type="password" id="password" name="password" class="form-control" required>
38
- </div>
39
- <button type="submit" class="btn btn-primary w-100">
40
- Iniciar Sesión</button>
41
- </form>
42
-
43
- <div class="text-center mt-3">
44
- <a href="{% if company_short_name %}{{ url_for('signup', company_short_name=company_short_name) }}{% else %}#{% endif %}"
45
- id="signup-link"
46
- class="btn btn-outline-primary w-100">Registrarse</a>
47
- </div>
48
- <div class="text-center mt-3">
49
- <a href="{{ url_for('forgot_password', company_short_name=company_short_name) }}" class="text-decoration-none text-muted fw-semibold">
50
- ¿Olvidaste tu contraseña?
51
- </a>
52
- </div>
53
- </div>
54
- </div>
55
- {% endif %}
56
-
57
- <!-- Sección de JWT -->
11
+ <!-- login desde sistema externo -->
58
12
  <div class="col-12 col-lg-5 offset-lg-1">
59
13
  <div class="border rounded p-4 shadow-sm bg-light">
60
- <h4 class="text-muted fw-semibold text-start mb-3">login externo (api-key)</h4>
14
+ <h3 class="text-muted fw-semibold text-start mb-3">login externo (api-key)</h3>
15
+ <div class="text-center mb-4">
16
+ <p class="text-muted widget-intro-text">
17
+ Este formulario permite testear el acceso a IAToolkit desde un portal externo utilizando una api-key.
18
+ El external user ID es el nombre del usuario ya autentificado en algún portal interno de la empresa.
19
+ </p>
20
+ </div>
61
21
  <form id="jwt-form" method="post">
62
22
  <div class="mb-3">
63
- <label for="company_name" class="form-label d-block text-muted">Empresa</label>
23
+ <label for="company_name" class="form-label d-block">Empresa</label>
64
24
  <select id="company_name" name="company_short_name" class="form-select" required>
65
25
  <option value="" disabled selected>Selecciona una empresa</option>
66
26
  {% for company in companies %}
@@ -73,7 +33,7 @@
73
33
  </div>
74
34
 
75
35
  <div class="mb-3">
76
- <label for="external_user_id" class="form-label d-block text-muted">External user ID</label>
36
+ <label for="external_user_id" class="form-label d-block">External user ID</label>
77
37
  <input type="text" id="external_user_id" name="external_user_id" class="form-control" required>
78
38
  </div>
79
39
 
@@ -81,7 +41,7 @@
81
41
  id="initiateJwtChatButton"
82
42
  class="ml-5 btn btn-primary">
83
43
  <span class="spinner-border spinner-border-sm d-none" role="status" aria-hidden="true"></span>
84
- Iniciar Sesión JWT
44
+ Iniciar Sesión
85
45
  </button>
86
46
  </form>
87
47
  </div>
@@ -5,150 +5,89 @@
5
5
 
6
6
  import os
7
7
  import logging
8
- from flask import request, jsonify, render_template, url_for, session
8
+ from flask import request, jsonify, render_template, url_for
9
9
  from flask.views import MethodView
10
10
  from injector import inject
11
- from iatoolkit.common.auth import IAuthentication
11
+ from iatoolkit.services.auth_service import AuthService
12
12
  from iatoolkit.services.profile_service import ProfileService
13
13
  from iatoolkit.services.query_service import QueryService
14
14
  from iatoolkit.services.prompt_manager_service import PromptService
15
- from iatoolkit.services.jwt_service import JWTService
16
15
  from iatoolkit.services.branding_service import BrandingService
17
16
  from iatoolkit.services.onboarding_service import OnboardingService
18
- from iatoolkit.services.jwt_service import JWTService
19
17
 
20
18
 
21
19
  class InitiateExternalChatView(MethodView):
22
20
  @inject
23
21
  def __init__(self,
24
- iauthentication: IAuthentication,
22
+ iauthentication: AuthService,
25
23
  branding_service: BrandingService,
26
24
  profile_service: ProfileService,
27
25
  onboarding_service: OnboardingService,
28
- jwt_service: JWTService
26
+ query_service: QueryService,
27
+ prompt_service: PromptService
29
28
  ):
30
29
  self.iauthentication = iauthentication
31
30
  self.branding_service = branding_service
32
31
  self.profile_service = profile_service
33
32
  self.onboarding_service = onboarding_service
34
- self.jwt_service = jwt_service
33
+ self.query_service = query_service
34
+ self.prompt_service = prompt_service
35
35
 
36
36
  def post(self, company_short_name: str):
37
37
  data = request.get_json()
38
38
  if not data or 'external_user_id' not in data:
39
39
  return jsonify({"error": "Falta external_user_id"}), 400
40
40
 
41
- external_user_id = data['external_user_id']
42
-
43
41
  company = self.profile_service.get_company_by_short_name(company_short_name)
44
42
  if not company:
45
43
  return jsonify({"error": "Empresa no encontrada"}), 404
46
44
 
47
- # 1. verify access credentials quickly
48
- iaut = self.iauthentication.verify(
49
- company_short_name,
50
- body_external_user_id=external_user_id
51
- )
52
- if not iaut.get("success"):
53
- return jsonify(iaut), 401
54
-
55
- # 2. Generate a short-lived initiation token.
56
- initiation_token = self.jwt_service.generate_chat_jwt(
57
- company_id=company.id,
58
- company_short_name=company.short_name,
59
- external_user_id=external_user_id,
60
- expires_delta_seconds=180
61
- )
62
-
63
- # 2. Get branding and onboarding data for the shell page
64
- branding_data = self.branding_service.get_company_branding(company)
65
- onboarding_cards = self.onboarding_service.get_onboarding_cards(company)
66
-
67
- # 4. Generate the URL for the iframe's SRC, now with the secure token.
68
- target_url = url_for('external_login',
69
- company_short_name=company_short_name,
70
- init_token=initiation_token,
71
- _external=True)
72
-
73
- # 5. Render the shell.
74
- return render_template("onboarding_shell.html",
75
- iframe_src_url=target_url,
76
- branding=branding_data,
77
- onboarding_cards=onboarding_cards
78
- )
79
-
80
- class ExternalChatLoginView(MethodView):
81
- @inject
82
- def __init__(self,
83
- profile_service: ProfileService,
84
- query_service: QueryService,
85
- prompt_service: PromptService,
86
- iauthentication: IAuthentication,
87
- jwt_service: JWTService,
88
- branding_service: BrandingService
89
- ):
90
- self.profile_service = profile_service
91
- self.query_service = query_service
92
- self.prompt_service = prompt_service
93
- self.iauthentication = iauthentication
94
- self.jwt_service = jwt_service
95
- self.branding_service = branding_service
96
-
97
- def get(self, company_short_name: str):
98
- # 1. Validate the initiation token from the URL
99
- init_token = request.args.get('init_token')
100
- if not init_token:
101
- return "Falta el token de iniciación.", 401
102
-
103
- # Reutilizamos el validador de JWT, ya que el token tiene la misma estructura
104
- payload = self.jwt_service.validate_chat_jwt(init_token, company_short_name)
105
- if not payload:
106
- return "Token de iniciación inválido o expirado.", 401
107
-
108
- # 2. Extract user ID securely from the validated token
109
- external_user_id = payload.get('external_user_id')
45
+ external_user_id = data['external_user_id']
110
46
  if not external_user_id:
111
- return "Token con formato incorrecto.", 400
112
-
113
- company = self.profile_service.get_company_by_short_name(company_short_name)
114
- if not company:
115
- logging.error(f'Company {company_short_name} not found')
116
- return jsonify({"error": "Empresa no encontrada"}), 404
47
+ return jsonify({"error": "missing external_user_id"}), 404
117
48
 
118
- try:
119
- # 3. Generate a new long-lived session JWT.
120
- token = self.jwt_service.generate_chat_jwt(
121
- company_id=company.id,
122
- company_short_name=company.short_name,
123
- external_user_id=external_user_id,
124
- expires_delta_seconds=3600 * 8 # 8 horas
125
- )
126
- if not token:
127
- raise Exception("No se pudo generar el token de sesión (JWT).")
49
+ # 1. Authenticate the API call.
50
+ iaut = self.iauthentication.verify()
51
+ if not iaut.get("success"):
52
+ return jsonify(iaut), 401
128
53
 
129
- # 4. Init the company/user LLM context.
130
- self.query_service.llm_init_context(
131
- company_short_name=company_short_name,
132
- external_user_id=external_user_id
133
- )
54
+ # 2. Delegate session creation to ProfileService.
55
+ self.profile_service.create_external_user_session(company, external_user_id)
134
56
 
135
- # 5. get the prompt list from backend
136
- prompts = self.prompt_service.get_user_prompts(company_short_name)
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
+ )
137
61
 
138
- # 6. get the branding data
62
+ if prep_result.get('rebuild_needed'):
139
63
  branding_data = self.branding_service.get_company_branding(company)
140
-
141
- # 7. render the chat page with the company/user information.
142
- return render_template("chat.html",
143
- company_short_name=company_short_name,
144
- auth_method='jwt',
145
- session_jwt=token,
146
- external_user_id=external_user_id,
147
- branding=branding_data,
148
- prompts=prompts,
149
- iatoolkit_base_url=os.getenv('IATOOLKIT_BASE_URL'),
150
- ), 200
151
-
152
- except Exception as e:
153
- logging.exception(f"Error al inicializar el chat para {company_short_name}/{external_user_id}: {e}")
154
- return jsonify({"error": f"Error interno al iniciar el chat. {str(e)}"}), 500
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
@@ -6,16 +6,16 @@
6
6
  from flask.views import MethodView
7
7
  from flask import request, jsonify
8
8
  from iatoolkit.services.load_documents_service import LoadDocumentsService
9
- from iatoolkit.common.auth import IAuthentication
9
+ from iatoolkit.services.auth_service import AuthService
10
10
  from iatoolkit.repositories.profile_repo import ProfileRepo
11
11
  from injector import inject
12
12
  import base64
13
13
 
14
14
 
15
- class FileStoreView(MethodView):
15
+ class FileStoreApiView(MethodView):
16
16
  @inject
17
17
  def __init__(self,
18
- iauthentication: IAuthentication,
18
+ iauthentication: AuthService,
19
19
  doc_service: LoadDocumentsService,
20
20
  profile_repo: ProfileRepo,):
21
21
  self.iauthentication = iauthentication
@@ -43,7 +43,7 @@ class FileStoreView(MethodView):
43
43
  return jsonify({"error": f"La empresa {company_short_name} no existe"}), 400
44
44
 
45
45
  # get access credentials
46
- iaut = self.iauthentication.verify(company_short_name, requested_name)
46
+ iaut = self.iauthentication.verify()
47
47
  if not iaut.get("success"):
48
48
  return jsonify(iaut), 401
49
49
 
@@ -0,0 +1,52 @@
1
+ # Copyright (c) 2024 Fernando Libedinsky
2
+ # Product: IAToolkit
3
+ #
4
+ # IAToolkit is open source software.
5
+
6
+ from flask import request, jsonify
7
+ from flask.views import MethodView
8
+ from iatoolkit.services.history_service import HistoryService
9
+ from iatoolkit.services.profile_service import ProfileService
10
+ from injector import inject
11
+ import logging
12
+
13
+
14
+ class HistoryApiView(MethodView):
15
+ """
16
+ Handles requests from the web UI to fetch a user's query history.
17
+ Authentication is based on the active Flask session.
18
+ """
19
+
20
+ @inject
21
+ def __init__(self,
22
+ profile_service: ProfileService,
23
+ history_service: HistoryService):
24
+ self.profile_service = profile_service
25
+ self.history_service = history_service
26
+
27
+ def post(self, company_short_name: str):
28
+ # 1. Get the authenticated user's info from the unified session.
29
+ session_info = self.profile_service.get_current_session_info()
30
+ user_identifier = session_info.get("user_identifier")
31
+
32
+ if not user_identifier:
33
+ return jsonify({'error_message': 'Usuario no autenticado o sesión inválida'}), 401
34
+
35
+ try:
36
+ # 2. Call the history service with the unified identifier.
37
+ # The service's signature should now only expect user_identifier.
38
+ response = self.history_service.get_history(
39
+ company_short_name=company_short_name,
40
+ user_identifier=user_identifier
41
+ )
42
+
43
+ if "error" in response:
44
+ # Handle errors reported by the service itself.
45
+ return jsonify({'error_message': response["error"]}), 400
46
+
47
+ return jsonify(response), 200
48
+
49
+ except Exception as e:
50
+ logging.exception(
51
+ f"Unexpected error fetching history for {company_short_name}/{user_identifier}: {e}")
52
+ return jsonify({"error_message": "Ha ocurrido un error inesperado en el servidor."}), 500
@@ -0,0 +1,62 @@
1
+ from flask.views import MethodView
2
+ from injector import inject
3
+ from iatoolkit.services.query_service import QueryService
4
+ from iatoolkit.services.profile_service import ProfileService
5
+ from iatoolkit.services.auth_service import AuthService
6
+ from flask import jsonify, request
7
+ import logging
8
+
9
+
10
+ class InitContextApiView(MethodView):
11
+ """
12
+ API endpoint to force a full context rebuild for a user.
13
+ Handles both web users (via session) and API users (via API Key).
14
+ """
15
+
16
+ @inject
17
+ def __init__(self,
18
+ auth_service: AuthService,
19
+ query_service: QueryService,
20
+ profile_service: ProfileService):
21
+ self.auth_service = auth_service
22
+ self.query_service = query_service
23
+ self.profile_service = profile_service
24
+
25
+ def post(self, company_short_name: str):
26
+ """
27
+ Cleans and rebuilds the context. The user is identified either by
28
+ an active web session or by the external_user_id in the JSON payload
29
+ for API calls.
30
+ """
31
+ # 1. Authenticate the request. This handles both session and API Key.
32
+ auth_result = self.auth_service.verify()
33
+ if not auth_result.get("success"):
34
+ return jsonify({"error": auth_result.get("error_message")}), auth_result.get("status_code", 401)
35
+
36
+ user_identifier = auth_result.get('user_identifier')
37
+ if not user_identifier:
38
+ return jsonify({"error": "Could not identify user from session or payload"}), 400
39
+
40
+ try:
41
+ # 2. Execute the forced rebuild sequence using the unified identifier.
42
+ self.query_service.session_context.clear_all_context(company_short_name, user_identifier)
43
+ logging.info(f"Context for {company_short_name}/{user_identifier} has been cleared.")
44
+
45
+ self.query_service.prepare_context(
46
+ company_short_name=company_short_name,
47
+ user_identifier=user_identifier
48
+ )
49
+
50
+ self.query_service.finalize_context_rebuild(
51
+ company_short_name=company_short_name,
52
+ user_identifier=user_identifier
53
+ )
54
+
55
+ logging.info(f"Context for {company_short_name}/{user_identifier} rebuilt successfully.")
56
+
57
+ # 3. Respond with JSON, as this is an API endpoint.
58
+ return jsonify({'status': 'OK', 'message': 'Context has been reloaded successfully.'}), 200
59
+
60
+ except Exception as e:
61
+ logging.exception(f"Error forcing context rebuild for {user_identifier}: {e}")
62
+ return jsonify({"error_message": str(e)}), 500
@@ -0,0 +1,50 @@
1
+ from flask.views import MethodView
2
+ from flask import request, jsonify
3
+ from injector import inject
4
+ from iatoolkit.services.query_service import QueryService
5
+ from iatoolkit.services.auth_service import AuthService
6
+ from iatoolkit.services.profile_service import ProfileService
7
+ import logging
8
+
9
+ class LLMQueryApiView(MethodView):
10
+ """
11
+ API-only endpoint for submitting queries. Authenticates via API Key.
12
+ """
13
+
14
+ @inject
15
+ def __init__(self, auth_service: AuthService, query_service: QueryService, profile_service: ProfileService):
16
+ self.auth_service = auth_service
17
+ self.query_service = query_service
18
+ self.profile_service = profile_service
19
+
20
+ def post(self, company_short_name: str):
21
+ # 1. Authenticate the API request.
22
+ auth_result = self.auth_service.verify()
23
+ if not auth_result.get("success"):
24
+ return jsonify({"error": auth_result.get("error_message")}), auth_result.get("status_code", 401)
25
+
26
+ # 2. Get the user identifier from the payload.
27
+ user_identifier = auth_result.get('user_identifier')
28
+ if not user_identifier:
29
+ return jsonify({"error": "Payload must include 'user_identifier'"}), 400
30
+
31
+ data = request.get_json()
32
+ if not data:
33
+ return jsonify({"error": "Invalid JSON body"}), 400
34
+
35
+ # 3. Ensure session state exists for this API user (lazy creation).
36
+ profile = self.profile_service.get_profile_by_identifier(company_short_name, user_identifier)
37
+ if not profile:
38
+ company = self.profile_service.get_company_by_short_name(company_short_name)
39
+ self.profile_service.create_external_user_session(company, user_identifier)
40
+
41
+ # 4. Call the unified query service method.
42
+ result = self.query_service.llm_query(
43
+ company_short_name=company_short_name,
44
+ user_identifier=user_identifier,
45
+ question=data.get('question', ''),
46
+ prompt_name=data.get('prompt_name'),
47
+ client_data=data.get('client_data', {}),
48
+ files=data.get('files', [])
49
+ )
50
+ return jsonify(result)
@@ -0,0 +1,38 @@
1
+ from flask.views import MethodView
2
+ from flask import request, jsonify
3
+ from injector import inject
4
+ from iatoolkit.services.query_service import QueryService
5
+ from iatoolkit.services.auth_service import AuthService # Use AuthService for session check
6
+
7
+
8
+ class LLMQueryWebView(MethodView): # Renamed for clarity
9
+ """
10
+ Web-only endpoint for submitting queries from the chat UI.
11
+ Authenticates via Flask session cookie.
12
+ """
13
+
14
+ @inject
15
+ def __init__(self, auth_service: AuthService, query_service: QueryService):
16
+ self.auth_service = auth_service
17
+ self.query_service = query_service
18
+
19
+ def post(self, company_short_name: str):
20
+ # 1. Authenticate the web session request.
21
+ auth_result = self.auth_service.verify()
22
+ if not auth_result.get("success"):
23
+ return jsonify({"error": auth_result.get("error_message")}), auth_result.get("status_code", 401)
24
+
25
+ # 2. Get the guaranteed user_identifier from the auth result.
26
+ user_identifier = auth_result['user_identifier']
27
+ data = request.get_json() or {}
28
+
29
+ # 3. Call the unified query service method.
30
+ result = self.query_service.llm_query(
31
+ company_short_name=company_short_name,
32
+ user_identifier=user_identifier,
33
+ question=data.get('question', ''),
34
+ prompt_name=data.get('prompt_name'),
35
+ client_data=data.get('client_data', {}),
36
+ files=data.get('files', [])
37
+ )
38
+ return jsonify(result)
@@ -10,24 +10,21 @@ from iatoolkit.services.profile_service import ProfileService
10
10
  import os
11
11
 
12
12
 
13
- class HomeView(MethodView):
13
+ class LoginTest(MethodView):
14
14
  @inject
15
15
  def __init__(self,
16
16
  profile_service: ProfileService):
17
17
  self.profile_service = profile_service
18
18
 
19
19
  def get(self):
20
- user_agent = request.user_agent
21
- is_mobile = user_agent.platform in ["android", "iphone", "ipad"] or "mobile" in user_agent.string.lower()
22
20
  alert_message = request.args.get('alert_message', None)
23
21
  companies = self.profile_service.get_companies()
24
22
 
25
23
  # Esta API_KEY para el login
26
24
  api_key_for_login = os.getenv("IATOOLKIT_API_KEY", "tu_api_key_por_defecto_o_error")
27
25
 
28
- return render_template('home.html',
26
+ return render_template('login_test.html',
29
27
  companies=companies,
30
- is_mobile=is_mobile,
31
28
  alert_message=alert_message,
32
29
  alert_icon='success' if alert_message else None,
33
30
  api_key=api_key_for_login