iatoolkit 0.11.1__py3-none-any.whl → 0.14.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.
- iatoolkit/common/routes.py +12 -12
- iatoolkit/iatoolkit.py +8 -4
- iatoolkit/services/profile_service.py +12 -20
- iatoolkit/templates/base.html +3 -3
- iatoolkit/templates/chat.html +7 -7
- iatoolkit/templates/home.html +3 -12
- iatoolkit/templates/login_shell.html +185 -0
- iatoolkit/views/history_view.py +1 -1
- iatoolkit/views/{external_chat_login_view.py → login_external_id_view.py} +56 -23
- iatoolkit/views/login_view.py +97 -22
- {iatoolkit-0.11.1.dist-info → iatoolkit-0.14.0.dist-info}/METADATA +1 -1
- {iatoolkit-0.11.1.dist-info → iatoolkit-0.14.0.dist-info}/RECORD +14 -15
- iatoolkit/views/chat_view.py +0 -58
- iatoolkit/views/external_login_view.py +0 -40
- {iatoolkit-0.11.1.dist-info → iatoolkit-0.14.0.dist-info}/WHEEL +0 -0
- {iatoolkit-0.11.1.dist-info → iatoolkit-0.14.0.dist-info}/top_level.txt +0 -0
iatoolkit/common/routes.py
CHANGED
|
@@ -26,9 +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.home_view import HomeView
|
|
29
|
-
from iatoolkit.views.
|
|
30
|
-
from iatoolkit.views.
|
|
31
|
-
from iatoolkit.views.external_chat_login_view import ExternalChatLoginView
|
|
29
|
+
from iatoolkit.views.login_view import LoginView, InitiateLoginView
|
|
30
|
+
from iatoolkit.views.login_external_id_view import InitiateExternalChatView, ExternalChatLoginView
|
|
32
31
|
from iatoolkit.views.signup_view import SignupView
|
|
33
32
|
from iatoolkit.views.verify_user_view import VerifyAccountView
|
|
34
33
|
from iatoolkit.views.forgot_password_view import ForgotPasswordView
|
|
@@ -37,21 +36,22 @@ def register_views(injector, app):
|
|
|
37
36
|
from iatoolkit.views.user_feedback_view import UserFeedbackView
|
|
38
37
|
from iatoolkit.views.prompt_view import PromptView
|
|
39
38
|
from iatoolkit.views.chat_token_request_view import ChatTokenRequestView
|
|
40
|
-
from iatoolkit.views.external_login_view import ExternalLoginView
|
|
41
39
|
from iatoolkit.views.download_file_view import DownloadFileView
|
|
42
40
|
|
|
43
41
|
app.add_url_rule('/', view_func=HomeView.as_view('home'))
|
|
44
42
|
|
|
45
|
-
#
|
|
46
|
-
app.add_url_rule('/<company_short_name>/
|
|
43
|
+
# login for external portals
|
|
44
|
+
app.add_url_rule('/<company_short_name>/initiate_external_chat',
|
|
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'))
|
|
47
50
|
|
|
48
|
-
#
|
|
49
|
-
app.add_url_rule('/<company_short_name>/chat_login', view_func=ExternalChatLoginView.as_view('external_chat_login'))
|
|
50
|
-
app.add_url_rule('/<company_short_name>/external_login/<external_user_id>', view_func=ExternalLoginView.as_view('external_login'))
|
|
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'))
|
|
53
|
+
app.add_url_rule('/<company_short_name>/initiate_login', view_func=InitiateLoginView.as_view('initiate_login'))
|
|
54
|
+
|
|
55
55
|
app.add_url_rule('/<company_short_name>/signup',view_func=SignupView.as_view('signup'))
|
|
56
56
|
app.add_url_rule('/<company_short_name>/logout', 'logout', logout)
|
|
57
57
|
app.add_url_rule('/logout', 'logout', logout)
|
iatoolkit/iatoolkit.py
CHANGED
|
@@ -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"
|
|
@@ -315,12 +323,8 @@ class IAToolkit:
|
|
|
315
323
|
"""Vincula las vistas después de que el injector ha sido creado"""
|
|
316
324
|
from iatoolkit.views.llmquery_view import LLMQueryView
|
|
317
325
|
from iatoolkit.views.home_view import HomeView
|
|
318
|
-
from iatoolkit.views.chat_view import ChatView
|
|
319
|
-
from iatoolkit.views.change_password_view import ChangePasswordView
|
|
320
326
|
|
|
321
327
|
binder.bind(HomeView, to=HomeView)
|
|
322
|
-
binder.bind(ChatView, to=ChatView)
|
|
323
|
-
binder.bind(ChangePasswordView, to=ChangePasswordView)
|
|
324
328
|
binder.bind(LLMQueryView, to=LLMQueryView)
|
|
325
329
|
|
|
326
330
|
logging.info("✅ Views configuradas correctamente")
|
|
@@ -17,7 +17,6 @@ import secrets
|
|
|
17
17
|
import string
|
|
18
18
|
from datetime import datetime, timezone
|
|
19
19
|
from iatoolkit.services.user_session_context_service import UserSessionContextService
|
|
20
|
-
from iatoolkit.services.query_service import QueryService
|
|
21
20
|
|
|
22
21
|
|
|
23
22
|
class ProfileService:
|
|
@@ -25,50 +24,43 @@ class ProfileService:
|
|
|
25
24
|
def __init__(self,
|
|
26
25
|
profile_repo: ProfileRepo,
|
|
27
26
|
session_context_service: UserSessionContextService,
|
|
28
|
-
query_service: QueryService,
|
|
29
27
|
mail_app: MailApp):
|
|
30
28
|
self.profile_repo = profile_repo
|
|
31
29
|
self.session_context = session_context_service
|
|
32
|
-
self.query_service = query_service
|
|
33
30
|
self.mail_app = mail_app
|
|
34
31
|
self.bcrypt = Bcrypt()
|
|
35
32
|
|
|
36
33
|
|
|
37
34
|
def login(self, company_short_name: str, email: str, password: str) -> dict:
|
|
38
35
|
try:
|
|
39
|
-
# check if
|
|
36
|
+
# check if user exists
|
|
40
37
|
user = self.profile_repo.get_user_by_email(email)
|
|
41
38
|
if not user:
|
|
42
|
-
return {"
|
|
39
|
+
return {'success': False, "message": "Usuario no encontrado"}
|
|
43
40
|
|
|
44
41
|
# check the encrypted password
|
|
45
42
|
if not check_password_hash(user.password, password):
|
|
46
|
-
return {"
|
|
43
|
+
return {'success': False, "message": "Contraseña inválida"}
|
|
47
44
|
|
|
48
45
|
company = self.get_company_by_short_name(company_short_name)
|
|
49
46
|
if not company:
|
|
50
|
-
return {"
|
|
47
|
+
return {'success': False, "message": "Empresa no encontrada"}
|
|
51
48
|
|
|
52
|
-
# check that user belongs to
|
|
49
|
+
# check that user belongs to company
|
|
53
50
|
if company not in user.companies:
|
|
54
|
-
return {"
|
|
51
|
+
return {'success': False, "message": "Usuario no esta autorizado para esta empresa"}
|
|
55
52
|
|
|
56
53
|
if not user.verified:
|
|
57
|
-
return {
|
|
54
|
+
return {'success': False,
|
|
55
|
+
"message": "Tu cuenta no ha sido verificada. Por favor, revisa tu correo."}
|
|
58
56
|
|
|
59
|
-
#
|
|
57
|
+
# save user data into session manager
|
|
60
58
|
self.set_user_session(user=user, company=company)
|
|
61
59
|
|
|
62
|
-
|
|
63
|
-
self.query_service.llm_init_context(
|
|
64
|
-
company_short_name=company_short_name,
|
|
65
|
-
local_user_id=user.id
|
|
66
|
-
)
|
|
67
|
-
|
|
68
|
-
return {"message": "Login exitoso"}
|
|
60
|
+
return {'success': True, "user": user, "message": "Login exitoso"}
|
|
69
61
|
except Exception as e:
|
|
70
|
-
|
|
71
|
-
|
|
62
|
+
return {'success': False, "message": str(e)}
|
|
63
|
+
|
|
72
64
|
|
|
73
65
|
def set_user_session(self, user: User, company: Company):
|
|
74
66
|
SessionManager.set('user_id', user.id)
|
iatoolkit/templates/base.html
CHANGED
|
@@ -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">
|
iatoolkit/templates/chat.html
CHANGED
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
<div class="d-flex align-items-center">
|
|
27
27
|
<!-- 1. ID de Usuario -->
|
|
28
28
|
<span style="{{ branding.secondary_text_style }}">
|
|
29
|
-
{{ external_user_id or
|
|
29
|
+
{{ external_user_id or user_email }}
|
|
30
30
|
</span>
|
|
31
31
|
|
|
32
32
|
<!-- 2. Separador Vertical -->
|
|
@@ -43,8 +43,8 @@
|
|
|
43
43
|
</a>
|
|
44
44
|
|
|
45
45
|
<!-- Icono de cerrar sesión (al final) -->
|
|
46
|
-
{% if
|
|
47
|
-
<a href="{{ url_for('logout', company_short_name=company_short_name) }}"
|
|
46
|
+
{% if user_email %}
|
|
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() {
|
iatoolkit/templates/home.html
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
<div class="border rounded p-4 shadow-sm bg-light">
|
|
14
14
|
<h4 class="text-muted fw-semibold text-start mb-3">login integrado (IAToolkit)</h4>
|
|
15
15
|
<form id="login-form"
|
|
16
|
-
action="{{ url_for('
|
|
16
|
+
action="{{ url_for('initiate_login', company_short_name=company_short_name) }}"
|
|
17
17
|
method="post">
|
|
18
18
|
<div class="mb-3">
|
|
19
19
|
<label for="company_short_name" class="form-label d-block text-muted">Empresa</label>
|
|
@@ -112,7 +112,7 @@
|
|
|
112
112
|
|
|
113
113
|
// Actualizar action del formulario "Iniciar Sesión"
|
|
114
114
|
if (selectedCompany && selectedCompany.trim() !== '') {
|
|
115
|
-
const loginAction = '/' + selectedCompany + '/
|
|
115
|
+
const loginAction = '/' + selectedCompany + '/initiate_login';
|
|
116
116
|
$('#login-form').attr('action', loginAction); // Actualizamos la URL del form
|
|
117
117
|
} else {
|
|
118
118
|
$('#login-form').attr('action', '#'); // URL genérica si no hay selección
|
|
@@ -156,12 +156,7 @@
|
|
|
156
156
|
return;
|
|
157
157
|
}
|
|
158
158
|
|
|
159
|
-
|
|
160
|
-
const $spinner = $button.find('.spinner-border');
|
|
161
|
-
$button.prop('disabled', true);
|
|
162
|
-
$spinner.removeClass('d-none');
|
|
163
|
-
|
|
164
|
-
fetch(`/${selectedCompany}/chat_login`, {
|
|
159
|
+
fetch(`/${selectedCompany}/initiate_external_chat`, {
|
|
165
160
|
method: 'POST',
|
|
166
161
|
headers: {
|
|
167
162
|
'Content-Type': 'application/json',
|
|
@@ -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>
|
iatoolkit/views/history_view.py
CHANGED
|
@@ -34,7 +34,7 @@ class HistoryView(MethodView):
|
|
|
34
34
|
return jsonify(iaut), 401
|
|
35
35
|
|
|
36
36
|
external_user_id = data.get("external_user_id")
|
|
37
|
-
local_user_id =
|
|
37
|
+
local_user_id = iaut.get("local_user_id", 0)
|
|
38
38
|
|
|
39
39
|
try:
|
|
40
40
|
response = self.history_service.get_history(
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import os
|
|
7
7
|
import logging
|
|
8
|
-
from flask import request, jsonify, render_template
|
|
8
|
+
from flask import request, jsonify, render_template, url_for, session
|
|
9
9
|
from flask.views import MethodView
|
|
10
10
|
from injector import inject
|
|
11
11
|
from iatoolkit.common.auth import IAuthentication
|
|
@@ -15,22 +15,16 @@ from iatoolkit.services.prompt_manager_service import PromptService
|
|
|
15
15
|
from iatoolkit.services.jwt_service import JWTService
|
|
16
16
|
from iatoolkit.services.branding_service import BrandingService
|
|
17
17
|
|
|
18
|
-
class
|
|
18
|
+
class InitiateExternalChatView(MethodView):
|
|
19
19
|
@inject
|
|
20
20
|
def __init__(self,
|
|
21
|
-
profile_service: ProfileService,
|
|
22
|
-
query_service: QueryService,
|
|
23
|
-
prompt_service: PromptService,
|
|
24
21
|
iauthentication: IAuthentication,
|
|
25
|
-
|
|
26
|
-
|
|
22
|
+
branding_service: BrandingService,
|
|
23
|
+
profile_service: ProfileService
|
|
27
24
|
):
|
|
28
|
-
self.profile_service = profile_service
|
|
29
|
-
self.query_service = query_service
|
|
30
|
-
self.prompt_service = prompt_service
|
|
31
25
|
self.iauthentication = iauthentication
|
|
32
|
-
self.jwt_service = jwt_service
|
|
33
26
|
self.branding_service = branding_service
|
|
27
|
+
self.profile_service = profile_service
|
|
34
28
|
|
|
35
29
|
def post(self, company_short_name: str):
|
|
36
30
|
data = request.get_json()
|
|
@@ -39,7 +33,11 @@ class ExternalChatLoginView(MethodView):
|
|
|
39
33
|
|
|
40
34
|
external_user_id = data['external_user_id']
|
|
41
35
|
|
|
42
|
-
|
|
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
|
+
|
|
40
|
+
# 1. verify access credentials quickly
|
|
43
41
|
iaut = self.iauthentication.verify(
|
|
44
42
|
company_short_name,
|
|
45
43
|
body_external_user_id=external_user_id
|
|
@@ -47,11 +45,51 @@ class ExternalChatLoginView(MethodView):
|
|
|
47
45
|
if not iaut.get("success"):
|
|
48
46
|
return jsonify(iaut), 401
|
|
49
47
|
|
|
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.
|
|
58
|
+
return render_template("login_shell.html",
|
|
59
|
+
iframe_src_url=target_url, # Le cambiamos el nombre para más claridad
|
|
60
|
+
branding=branding_data
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
class ExternalChatLoginView(MethodView):
|
|
64
|
+
@inject
|
|
65
|
+
def __init__(self,
|
|
66
|
+
profile_service: ProfileService,
|
|
67
|
+
query_service: QueryService,
|
|
68
|
+
prompt_service: PromptService,
|
|
69
|
+
iauthentication: IAuthentication,
|
|
70
|
+
jwt_service: JWTService,
|
|
71
|
+
branding_service: BrandingService
|
|
72
|
+
):
|
|
73
|
+
self.profile_service = profile_service
|
|
74
|
+
self.query_service = query_service
|
|
75
|
+
self.prompt_service = prompt_service
|
|
76
|
+
self.iauthentication = iauthentication
|
|
77
|
+
self.jwt_service = jwt_service
|
|
78
|
+
self.branding_service = branding_service
|
|
79
|
+
|
|
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
|
|
85
|
+
|
|
50
86
|
company = self.profile_service.get_company_by_short_name(company_short_name)
|
|
51
87
|
if not company:
|
|
88
|
+
logging.error(f'Company {company_short_name} not found')
|
|
52
89
|
return jsonify({"error": "Empresa no encontrada"}), 404
|
|
53
90
|
|
|
54
91
|
try:
|
|
92
|
+
|
|
55
93
|
# 1. generate a new JWT, our secure access token.
|
|
56
94
|
token = self.jwt_service.generate_chat_jwt(
|
|
57
95
|
company_id=company.id,
|
|
@@ -75,20 +113,15 @@ class ExternalChatLoginView(MethodView):
|
|
|
75
113
|
branding_data = self.branding_service.get_company_branding(company)
|
|
76
114
|
|
|
77
115
|
# 5. render the chat page with the company/user information.
|
|
78
|
-
|
|
79
|
-
is_mobile = user_agent.platform in ["android", "iphone", "ipad"] or "mobile" in user_agent.string.lower()
|
|
80
|
-
|
|
81
|
-
chat_html = render_template("chat.html",
|
|
116
|
+
return render_template("chat.html",
|
|
82
117
|
company_short_name=company_short_name,
|
|
83
|
-
|
|
118
|
+
auth_method='jwt',
|
|
119
|
+
session_jwt=token,
|
|
84
120
|
external_user_id=external_user_id,
|
|
85
|
-
|
|
86
|
-
auth_method='jwt', # login method is JWT
|
|
87
|
-
session_jwt=token, # pass the token to the front-end
|
|
88
|
-
iatoolkit_base_url=os.getenv('IATOOLKIT_BASE_URL'),
|
|
121
|
+
branding=branding_data,
|
|
89
122
|
prompts=prompts,
|
|
90
|
-
|
|
91
|
-
|
|
123
|
+
iatoolkit_base_url=os.getenv('IATOOLKIT_BASE_URL'),
|
|
124
|
+
), 200
|
|
92
125
|
|
|
93
126
|
except Exception as e:
|
|
94
127
|
logging.exception(f"Error al inicializar el chat para {company_short_name}/{external_user_id}: {e}")
|
iatoolkit/views/login_view.py
CHANGED
|
@@ -6,12 +6,82 @@
|
|
|
6
6
|
from flask.views import MethodView
|
|
7
7
|
from flask import request, redirect, render_template, url_for
|
|
8
8
|
from injector import inject
|
|
9
|
+
from iatoolkit.repositories.models import User
|
|
9
10
|
from iatoolkit.services.profile_service import ProfileService
|
|
11
|
+
from iatoolkit.services.prompt_manager_service import PromptService
|
|
12
|
+
from iatoolkit.services.branding_service import BrandingService
|
|
13
|
+
from iatoolkit.services.query_service import QueryService
|
|
14
|
+
import os
|
|
15
|
+
from iatoolkit.common.session_manager import SessionManager
|
|
16
|
+
from iatoolkit.services.branding_service import BrandingService
|
|
17
|
+
|
|
18
|
+
class InitiateLoginView(MethodView):
|
|
19
|
+
"""
|
|
20
|
+
Handles the initial, fast part of the standard login process.
|
|
21
|
+
Authenticates user credentials, sets up the server-side session,
|
|
22
|
+
and immediately returns the loading shell page.
|
|
23
|
+
"""
|
|
24
|
+
@inject
|
|
25
|
+
def __init__(self,
|
|
26
|
+
profile_service: ProfileService,
|
|
27
|
+
branding_service: BrandingService,):
|
|
28
|
+
self.profile_service = profile_service
|
|
29
|
+
self.branding_service = branding_service
|
|
30
|
+
|
|
31
|
+
def post(self, company_short_name: str):
|
|
32
|
+
# get company info
|
|
33
|
+
company = self.profile_service.get_company_by_short_name(company_short_name)
|
|
34
|
+
if not company:
|
|
35
|
+
return render_template('error.html',
|
|
36
|
+
message="Empresa no encontrada"), 404
|
|
37
|
+
|
|
38
|
+
email = request.form.get('email')
|
|
39
|
+
password = request.form.get('password')
|
|
40
|
+
|
|
41
|
+
# 1. authenticate the user
|
|
42
|
+
response = self.profile_service.login(
|
|
43
|
+
company_short_name=company_short_name,
|
|
44
|
+
email=email,
|
|
45
|
+
password=password
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
if not response['success']:
|
|
49
|
+
return render_template(
|
|
50
|
+
'login.html',
|
|
51
|
+
company_short_name=company_short_name,
|
|
52
|
+
company=company,
|
|
53
|
+
form_data={
|
|
54
|
+
"email": email,
|
|
55
|
+
"password": password,
|
|
56
|
+
},
|
|
57
|
+
alert_message=response["error"]), 400
|
|
58
|
+
|
|
59
|
+
# 2. Get branding data for the shell page
|
|
60
|
+
branding_data = self.branding_service.get_company_branding(company)
|
|
61
|
+
|
|
62
|
+
# 3. Render the shell page, passing the URL for the heavy lifting
|
|
63
|
+
# The shell's AJAX call will now be authenticated via the session cookie.
|
|
64
|
+
return render_template(
|
|
65
|
+
"login_shell.html",
|
|
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,
|
|
71
|
+
)
|
|
72
|
+
|
|
10
73
|
|
|
11
74
|
class LoginView(MethodView):
|
|
12
75
|
@inject
|
|
13
|
-
def __init__(self,
|
|
76
|
+
def __init__(self,
|
|
77
|
+
profile_service: ProfileService,
|
|
78
|
+
query_service: QueryService,
|
|
79
|
+
prompt_service: PromptService,
|
|
80
|
+
branding_service: BrandingService):
|
|
14
81
|
self.profile_service = profile_service
|
|
82
|
+
self.query_service = query_service
|
|
83
|
+
self.prompt_service = prompt_service
|
|
84
|
+
self.branding_service = branding_service
|
|
15
85
|
|
|
16
86
|
def get(self, company_short_name: str):
|
|
17
87
|
# get company info
|
|
@@ -24,33 +94,38 @@ class LoginView(MethodView):
|
|
|
24
94
|
company_short_name=company_short_name)
|
|
25
95
|
|
|
26
96
|
def post(self, company_short_name: str):
|
|
27
|
-
# get company info
|
|
28
97
|
company = self.profile_service.get_company_by_short_name(company_short_name)
|
|
29
|
-
if not company:
|
|
30
|
-
return render_template('error.html', message="Empresa no encontrada"), 404
|
|
31
98
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
99
|
+
# 1. The user is already authenticated by the session cookie set by InitiateLoginView.
|
|
100
|
+
# We just retrieve the user and company IDs from the session.
|
|
101
|
+
user_id = SessionManager.get('user_id')
|
|
102
|
+
if not user_id:
|
|
103
|
+
return render_template('error.html', message="Usuario no encontrado"), 404
|
|
104
|
+
|
|
105
|
+
user_email = SessionManager.get('user')['email']
|
|
35
106
|
|
|
36
|
-
|
|
107
|
+
try:
|
|
108
|
+
# 2. init the company/user LLM context.
|
|
109
|
+
self.query_service.llm_init_context(
|
|
37
110
|
company_short_name=company_short_name,
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
)
|
|
111
|
+
local_user_id=user_id
|
|
112
|
+
)
|
|
41
113
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
114
|
+
# 3. get the prompt list from backend
|
|
115
|
+
prompts = self.prompt_service.get_user_prompts(company_short_name)
|
|
116
|
+
|
|
117
|
+
# 4. get the branding data
|
|
118
|
+
branding_data = self.branding_service.get_company_branding(company)
|
|
119
|
+
|
|
120
|
+
return render_template("chat.html",
|
|
45
121
|
company_short_name=company_short_name,
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
return redirect(url_for('chat', company_short_name=company_short_name))
|
|
122
|
+
auth_method="Session",
|
|
123
|
+
session_jwt=None, # No JWT in this flow
|
|
124
|
+
user_email=user_email,
|
|
125
|
+
branding=branding_data,
|
|
126
|
+
prompts=prompts,
|
|
127
|
+
iatoolkit_base_url=os.getenv('IATOOLKIT_BASE_URL'),
|
|
128
|
+
), 200
|
|
54
129
|
|
|
55
130
|
except Exception as e:
|
|
56
131
|
return render_template("error.html",
|
|
@@ -2,11 +2,11 @@ iatoolkit/__init__.py,sha256=4PWjMJjktixtrxF6BY405qyA50Sv967kEP2x-oil6qk,1120
|
|
|
2
2
|
iatoolkit/base_company.py,sha256=4usUdOC57Nk1XsawAEyC7mlzb0jROadu64YcYf6poiM,4371
|
|
3
3
|
iatoolkit/cli_commands.py,sha256=G5L9xQXZ0lVFXQWBaE_KEZHyfuiT6PL1nTQRoSdnBzc,2302
|
|
4
4
|
iatoolkit/company_registry.py,sha256=tduqt3oV8iDX_IB1eA7KIgvIxE4edTcy-3qZIXh3Lzw,2549
|
|
5
|
-
iatoolkit/iatoolkit.py,sha256=
|
|
5
|
+
iatoolkit/iatoolkit.py,sha256=9OIBCsHGAQGGIzExP95KFxND1bxaRuYQ08oHkbxv8WM,16996
|
|
6
6
|
iatoolkit/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
7
|
iatoolkit/common/auth.py,sha256=8NH6MQXfddLQd1GxrO2op3IYrrP4SMQKoKzj1o1jZmc,8486
|
|
8
8
|
iatoolkit/common/exceptions.py,sha256=EXx40n5htp7UiOM6P1xfJ9U6NMcADqm62dlFaKz7ICU,1154
|
|
9
|
-
iatoolkit/common/routes.py,sha256=
|
|
9
|
+
iatoolkit/common/routes.py,sha256=mzbljACSZeJmJ6S9BZvTTRujTRnrEU-VKTqNdmfW3hs,4904
|
|
10
10
|
iatoolkit/common/session_manager.py,sha256=7D_RuJs60w-1zDr3fOGEz9JW7IZlSXuUHgUT87CzaUo,472
|
|
11
11
|
iatoolkit/common/util.py,sha256=08js3KLJTXICOd5sgwDp2u_kDaZO_0xG4BIuzWZnLo8,15535
|
|
12
12
|
iatoolkit/infra/__init__.py,sha256=5JqK9sZ6jBuK83zDQokUhxQ0wuJJJ9DXB8pYCLkX7X4,102
|
|
@@ -45,7 +45,7 @@ iatoolkit/services/history_service.py,sha256=ZlYfaSHOcCxxc6ICTnqflaGBlzctpJdNUwX
|
|
|
45
45
|
iatoolkit/services/jwt_service.py,sha256=YoZ9h7_o9xBko-arNQv4MbcwnxoSWVNj4VbZmMo_QGY,3908
|
|
46
46
|
iatoolkit/services/load_documents_service.py,sha256=ZpB0BZ3qX1fGJGBtZtMLbFdWWx0hkPoeCS3OqJKwCTs,7291
|
|
47
47
|
iatoolkit/services/mail_service.py,sha256=2h-fcF3swZDya_o7IpgXkmuj3iEVHVCiHi7oVxU99sQ,2182
|
|
48
|
-
iatoolkit/services/profile_service.py,sha256=
|
|
48
|
+
iatoolkit/services/profile_service.py,sha256=Mxt_Hdz-SyYDuwWVu10hZnb00dKaOeONX8zp1TzpQt4,17387
|
|
49
49
|
iatoolkit/services/prompt_manager_service.py,sha256=U-XmSpkeXvv1KRN4dytdMxSYBMRSB7y-UHcb18mk0nA,8342
|
|
50
50
|
iatoolkit/services/query_service.py,sha256=CI_LUBdqolvsuh7TjY23oaQcc8s6rmmr4LqnjE81ZJc,15394
|
|
51
51
|
iatoolkit/services/search_service.py,sha256=i1xGWu7ORKIIDH0aAQBkF86dVVbLQ0Yrooz5TiZ6aGo,1823
|
|
@@ -74,37 +74,36 @@ iatoolkit/system_prompts/format_styles.prompt,sha256=MSMe1qvR3cF_0IbFshn8R0z6Wx6
|
|
|
74
74
|
iatoolkit/system_prompts/query_main.prompt,sha256=w_9ybgWgiQH4V_RbAXqsvz0M7oOuiyhxcwf-D0CgfA4,3017
|
|
75
75
|
iatoolkit/system_prompts/sql_rules.prompt,sha256=y4nURVnb9AyFwt-lrbMNBHHtZlhk6kC9grYoOhRnrJo,59174
|
|
76
76
|
iatoolkit/templates/about.html,sha256=ciC08grUVz5qLzdzDDqDX31xirg5PrJIRYabWpV9oA8,294
|
|
77
|
-
iatoolkit/templates/base.html,sha256=
|
|
77
|
+
iatoolkit/templates/base.html,sha256=TojvSnVvXkTe7Kpt_BBWoXFfZN6dveKD0VqQjUOXdgU,2212
|
|
78
78
|
iatoolkit/templates/change_password.html,sha256=DFfQSFcZ2YJZNFis2IXfzEKStxTf4i9f4eQ_6GiyNs8,2342
|
|
79
|
-
iatoolkit/templates/chat.html,sha256=
|
|
79
|
+
iatoolkit/templates/chat.html,sha256=pQm1vDikaSsvleJK0LglL1BAeoLbwPLe4FYtLIsW4T8,9451
|
|
80
80
|
iatoolkit/templates/chat_modals.html,sha256=3CQ430bwhebq6rAJ6Bk12PQDjt9YenqNXm5thC5WP2Y,5771
|
|
81
81
|
iatoolkit/templates/error.html,sha256=BNF-7z8AYL5vF4ZMUFMrOBt8c85kCFrm9qSHn9EiHWg,540
|
|
82
82
|
iatoolkit/templates/forgot_password.html,sha256=1lUbKg9CKnQdnySplceY_pibwYne1-mOlM38fqI1kW8,1563
|
|
83
83
|
iatoolkit/templates/header.html,sha256=179agI7rnYwP_rvJNXIiVde5E8Ec5649_XKq6eew2Hk,1263
|
|
84
|
-
iatoolkit/templates/home.html,sha256=
|
|
84
|
+
iatoolkit/templates/home.html,sha256=UWtAn19_S-k6e8_UoWBFeeELbMhJRxXLwxNH7AC4Lf0,7921
|
|
85
85
|
iatoolkit/templates/login.html,sha256=r4hy7MsQkfDqi6pBRNkkRiFr3GPSoHCT89R5lQLUWZc,1991
|
|
86
|
+
iatoolkit/templates/login_shell.html,sha256=d_dAgbZ2JqCc96FDX_kA6sRofAZ_qc7D1N6Zyto9ZJ8,9727
|
|
86
87
|
iatoolkit/templates/signup.html,sha256=J8wOjUhUe_KozyThDTWHjXpSJ1ubR2IDVobThtkSRuo,3819
|
|
87
88
|
iatoolkit/templates/test.html,sha256=rwNtxC83tbCl5COZFXYvmRBxxmgFJtPNuVBd_nq9KWY,133
|
|
88
89
|
iatoolkit/views/__init__.py,sha256=5JqK9sZ6jBuK83zDQokUhxQ0wuJJJ9DXB8pYCLkX7X4,102
|
|
89
90
|
iatoolkit/views/change_password_view.py,sha256=rSebwecI1zwBgR2yvAhcfMwWpGDa4QbVAIllgtSOo9k,3940
|
|
90
91
|
iatoolkit/views/chat_token_request_view.py,sha256=wf32_A2Sq8NHYWshCwL10Tovd1znLoD0jQjzutR3sVE,4408
|
|
91
|
-
iatoolkit/views/chat_view.py,sha256=BD1N-Jo9IOoS6baX1bzdM7DKa2zepVHZnJIxiF0vNc8,2381
|
|
92
92
|
iatoolkit/views/download_file_view.py,sha256=1gZ0ipqeCn39sTrJFo1-tlewlcSF7s_YNTvE4qd0HOw,2010
|
|
93
|
-
iatoolkit/views/external_chat_login_view.py,sha256=h-Xr7UkQM7QxLZIDQ0fXb-BUfPbABQ1gjiP--FrXnpc,4075
|
|
94
|
-
iatoolkit/views/external_login_view.py,sha256=EHxN2omqTDkWyMp0FVCNDFt-JJ2hpg8LvprKanGR1gY,1355
|
|
95
93
|
iatoolkit/views/file_store_view.py,sha256=hUm5wX4E5oqJJEPEAObEj-nPiRp5EJIICULSfAWmHCs,1933
|
|
96
94
|
iatoolkit/views/forgot_password_view.py,sha256=Rk8Qbe9Fz7Wlgje1rt29I15gFM-a089EBi2at4FT7kA,2715
|
|
97
|
-
iatoolkit/views/history_view.py,sha256=
|
|
95
|
+
iatoolkit/views/history_view.py,sha256=fzZrnC-RySa7ngcPe2Hmf9_s3imx6VB6MKROMcNpjoU,2064
|
|
98
96
|
iatoolkit/views/home_view.py,sha256=TihO2flkelJa9j6a0FKCMVhD-2X7BhemonB7LTne4x8,1248
|
|
99
97
|
iatoolkit/views/llmquery_view.py,sha256=rv2i3oeXlNc3Sv7Qu3DZGf37r-bMSa4N25FzG7_kPAI,2432
|
|
100
|
-
iatoolkit/views/
|
|
98
|
+
iatoolkit/views/login_external_id_view.py,sha256=bkpsGFLxg9MPhRyLdvtfzlOIQFZgQVzNKPIJbnsHTPY,5524
|
|
99
|
+
iatoolkit/views/login_view.py,sha256=mmJ-VMnT_VvQy5GkTGM8dDdG7yNjqpW-7YQgzkQmhQI,5396
|
|
101
100
|
iatoolkit/views/prompt_view.py,sha256=l8KHlLmkSgSLK43VbhwKED7mCN9YyfeHHh4zvx0pT0E,1257
|
|
102
101
|
iatoolkit/views/signup_view.py,sha256=NTx_2w8F6Np88FKEpDvBvJXU-bISKpDMdhhT4XFAVfk,3805
|
|
103
102
|
iatoolkit/views/tasks_review_view.py,sha256=keLsLCyOTTlcoIapnB_lbuSvLwrPVZVpBiFC_7ChbLg,3388
|
|
104
103
|
iatoolkit/views/tasks_view.py,sha256=a3anTXrJTTvbQuc6PSpOzidLKQFL4hWa7PI2Cppcz8w,4110
|
|
105
104
|
iatoolkit/views/user_feedback_view.py,sha256=G37zmP8P4LvZrSymNJ5iFXhLZg1A3BEwRfTpH1Iam5w,2652
|
|
106
105
|
iatoolkit/views/verify_user_view.py,sha256=a3q4wHJ8mKAEmgbNTOcnX4rMikROjOR3mHvCr30qGGA,2351
|
|
107
|
-
iatoolkit-0.
|
|
108
|
-
iatoolkit-0.
|
|
109
|
-
iatoolkit-0.
|
|
110
|
-
iatoolkit-0.
|
|
106
|
+
iatoolkit-0.14.0.dist-info/METADATA,sha256=VYEM96_CE62ebzB8ScujIwbcjnC5T6qEzzr8hQep0Xw,9301
|
|
107
|
+
iatoolkit-0.14.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
108
|
+
iatoolkit-0.14.0.dist-info/top_level.txt,sha256=V_w4QvDx0b1RXiy8zTCrD1Bp7AZkFe3_O0-9fMiwogg,10
|
|
109
|
+
iatoolkit-0.14.0.dist-info/RECORD,,
|
iatoolkit/views/chat_view.py
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
# Copyright (c) 2024 Fernando Libedinsky
|
|
2
|
-
# Product: IAToolkit
|
|
3
|
-
#
|
|
4
|
-
# IAToolkit is open source software.
|
|
5
|
-
|
|
6
|
-
from flask import render_template, request, jsonify
|
|
7
|
-
from iatoolkit.services.profile_service import ProfileService
|
|
8
|
-
from flask.views import MethodView
|
|
9
|
-
from injector import inject
|
|
10
|
-
import os
|
|
11
|
-
from iatoolkit.common.auth import IAuthentication
|
|
12
|
-
from iatoolkit.services.prompt_manager_service import PromptService
|
|
13
|
-
from iatoolkit.services.branding_service import BrandingService
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
class ChatView(MethodView):
|
|
17
|
-
@inject
|
|
18
|
-
def __init__(self,
|
|
19
|
-
iauthentication: IAuthentication,
|
|
20
|
-
prompt_service: PromptService,
|
|
21
|
-
profile_service: ProfileService,
|
|
22
|
-
branding_service: BrandingService
|
|
23
|
-
):
|
|
24
|
-
self.iauthentication = iauthentication
|
|
25
|
-
self.profile_service = profile_service
|
|
26
|
-
self.prompt_service = prompt_service
|
|
27
|
-
self.branding_service = branding_service
|
|
28
|
-
|
|
29
|
-
def get(self, company_short_name: str):
|
|
30
|
-
# get access credentials
|
|
31
|
-
iaut = self.iauthentication.verify(company_short_name)
|
|
32
|
-
if not iaut.get("success"):
|
|
33
|
-
return jsonify(iaut), 401
|
|
34
|
-
|
|
35
|
-
user_agent = request.user_agent
|
|
36
|
-
is_mobile = user_agent.platform in ["android", "iphone", "ipad"] or "mobile" in user_agent.string.lower()
|
|
37
|
-
alert_message = request.args.get('alert_message', None)
|
|
38
|
-
|
|
39
|
-
# 1. get company info
|
|
40
|
-
company = self.profile_service.get_company_by_short_name(company_short_name)
|
|
41
|
-
if not company:
|
|
42
|
-
return render_template('error.html', message="Empresa no encontrada"), 404
|
|
43
|
-
|
|
44
|
-
# 2. get the company prompts
|
|
45
|
-
prompts = self.prompt_service.get_user_prompts(company_short_name)
|
|
46
|
-
|
|
47
|
-
# 3. get the branding data
|
|
48
|
-
branding_data = self.branding_service.get_company_branding(company)
|
|
49
|
-
|
|
50
|
-
return render_template("chat.html",
|
|
51
|
-
branding=branding_data,
|
|
52
|
-
company_short_name=company_short_name,
|
|
53
|
-
is_mobile=is_mobile,
|
|
54
|
-
alert_message=alert_message,
|
|
55
|
-
alert_icon='success' if alert_message else None,
|
|
56
|
-
iatoolkit_base_url=os.getenv('IATOOLKIT_BASE_URL', 'http://localhost:5000'),
|
|
57
|
-
prompts=prompts
|
|
58
|
-
)
|
|
@@ -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
|