iatoolkit 0.56.0__py3-none-any.whl → 0.57.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/iatoolkit.py +1 -1
- iatoolkit/repositories/models.py +26 -1
- iatoolkit/services/auth_service.py +109 -5
- iatoolkit/views/base_login_view.py +3 -0
- iatoolkit/views/external_login_view.py +12 -55
- iatoolkit/views/login_view.py +4 -3
- {iatoolkit-0.56.0.dist-info → iatoolkit-0.57.0.dist-info}/METADATA +1 -1
- {iatoolkit-0.56.0.dist-info → iatoolkit-0.57.0.dist-info}/RECORD +10 -10
- {iatoolkit-0.56.0.dist-info → iatoolkit-0.57.0.dist-info}/WHEEL +0 -0
- {iatoolkit-0.56.0.dist-info → iatoolkit-0.57.0.dist-info}/top_level.txt +0 -0
iatoolkit/iatoolkit.py
CHANGED
|
@@ -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.
|
|
22
|
+
IATOOLKIT_VERSION = "0.57.0"
|
|
23
23
|
|
|
24
24
|
# global variable for the unique instance of IAToolkit
|
|
25
25
|
_iatoolkit_instance: Optional['IAToolkit'] = None
|
iatoolkit/repositories/models.py
CHANGED
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
#
|
|
4
4
|
# IAToolkit is open source software.
|
|
5
5
|
|
|
6
|
-
from sqlalchemy import Column, Integer, String, DateTime, Enum, Text, JSON, Boolean, ForeignKey, Table
|
|
6
|
+
from sqlalchemy import Column, Integer, BigInteger, String, DateTime, Enum, Text, JSON, Boolean, ForeignKey, Table
|
|
7
7
|
from sqlalchemy.orm import DeclarativeBase
|
|
8
8
|
from sqlalchemy.orm import relationship, class_mapper, declarative_base
|
|
9
|
+
from sqlalchemy.sql import func
|
|
9
10
|
from datetime import datetime
|
|
10
11
|
from pgvector.sqlalchemy import Vector
|
|
11
12
|
from enum import Enum as PyEnum
|
|
@@ -307,3 +308,27 @@ class Prompt(Base):
|
|
|
307
308
|
|
|
308
309
|
company = relationship("Company", back_populates="prompts")
|
|
309
310
|
category = relationship("PromptCategory", back_populates="prompts")
|
|
311
|
+
|
|
312
|
+
class AccessLog(Base):
|
|
313
|
+
# Modelo ORM para registrar cada intento de acceso a la plataforma.
|
|
314
|
+
__tablename__ = 'iat_access_log'
|
|
315
|
+
|
|
316
|
+
id = Column(BigInteger, primary_key=True)
|
|
317
|
+
|
|
318
|
+
timestamp = Column(DateTime(timezone=True), server_default=func.now(), nullable=False, index=True)
|
|
319
|
+
company_short_name = Column(String(100), nullable=False, index=True)
|
|
320
|
+
user_identifier = Column(String(255), index=True)
|
|
321
|
+
|
|
322
|
+
# Cómo y el Resultado
|
|
323
|
+
auth_type = Column(String(20), nullable=False) # 'local', 'external_api', 'redeem_token', etc.
|
|
324
|
+
outcome = Column(String(10), nullable=False) # 'success' o 'failure'
|
|
325
|
+
reason_code = Column(String(50)) # Causa de fallo, ej: 'INVALID_CREDENTIALS'
|
|
326
|
+
|
|
327
|
+
# Contexto de la Petición
|
|
328
|
+
source_ip = Column(String(45), nullable=False)
|
|
329
|
+
user_agent_hash = Column(String(16)) # Hash corto del User-Agent
|
|
330
|
+
request_path = Column(String(255), nullable=False)
|
|
331
|
+
|
|
332
|
+
def __repr__(self):
|
|
333
|
+
return (f"<AccessLog(id={self.id}, company='{self.company_short_name}', "
|
|
334
|
+
f"user='{self.user_identifier}', outcome='{self.outcome}')>")
|
|
@@ -6,8 +6,12 @@
|
|
|
6
6
|
from flask import request
|
|
7
7
|
from injector import inject
|
|
8
8
|
from iatoolkit.services.profile_service import ProfileService
|
|
9
|
+
from iatoolkit.services.jwt_service import JWTService
|
|
10
|
+
from iatoolkit.repositories.database_manager import DatabaseManager
|
|
11
|
+
from iatoolkit.repositories.models import AccessLog
|
|
9
12
|
from flask import request
|
|
10
13
|
import logging
|
|
14
|
+
import hashlib
|
|
11
15
|
|
|
12
16
|
|
|
13
17
|
class AuthService:
|
|
@@ -17,11 +21,75 @@ class AuthService:
|
|
|
17
21
|
"""
|
|
18
22
|
|
|
19
23
|
@inject
|
|
20
|
-
def __init__(self, profile_service: ProfileService
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
+
def __init__(self, profile_service: ProfileService,
|
|
25
|
+
jwt_service: JWTService,
|
|
26
|
+
db_manager: DatabaseManager
|
|
27
|
+
):
|
|
24
28
|
self.profile_service = profile_service
|
|
29
|
+
self.jwt_service = jwt_service
|
|
30
|
+
self.db_manager = db_manager
|
|
31
|
+
|
|
32
|
+
def login_local_user(self, company_short_name: str, email: str, password: str) -> dict:
|
|
33
|
+
# try to autenticate a local user, register the event and return the result
|
|
34
|
+
auth_response = self.profile_service.login(
|
|
35
|
+
company_short_name=company_short_name,
|
|
36
|
+
email=email,
|
|
37
|
+
password=password
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
if not auth_response.get('success'):
|
|
41
|
+
self.log_access(
|
|
42
|
+
company_short_name=company_short_name,
|
|
43
|
+
user_identifier=email,
|
|
44
|
+
auth_type='local',
|
|
45
|
+
outcome='failure',
|
|
46
|
+
reason_code='INVALID_CREDENTIALS',
|
|
47
|
+
)
|
|
48
|
+
else:
|
|
49
|
+
self.log_access(
|
|
50
|
+
company_short_name=company_short_name,
|
|
51
|
+
auth_type='local',
|
|
52
|
+
outcome='success',
|
|
53
|
+
user_identifier=auth_response.get('user_identifier')
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
return auth_response
|
|
57
|
+
|
|
58
|
+
def redeem_token_for_session(self, company_short_name: str, token: str) -> dict:
|
|
59
|
+
# redeem a token for a session, register the event and return the result
|
|
60
|
+
payload = self.jwt_service.validate_chat_jwt(token)
|
|
61
|
+
|
|
62
|
+
if not payload:
|
|
63
|
+
self.log_access(
|
|
64
|
+
company_short_name=company_short_name,
|
|
65
|
+
auth_type='redeem_token',
|
|
66
|
+
outcome='failure',
|
|
67
|
+
reason_code='JWT_INVALID'
|
|
68
|
+
)
|
|
69
|
+
return {'success': False, 'error': 'Token inválido o expirado'}
|
|
70
|
+
|
|
71
|
+
# 2. if token is valid, extract the user_identifier
|
|
72
|
+
user_identifier = payload.get('user_identifier')
|
|
73
|
+
try:
|
|
74
|
+
# create the Flask session
|
|
75
|
+
self.profile_service.set_session_for_user(company_short_name, user_identifier)
|
|
76
|
+
self.log_access(
|
|
77
|
+
company_short_name=company_short_name,
|
|
78
|
+
auth_type='redeem_token',
|
|
79
|
+
outcome='success',
|
|
80
|
+
user_identifier=user_identifier
|
|
81
|
+
)
|
|
82
|
+
return {'success': True, 'user_identifier': user_identifier}
|
|
83
|
+
except Exception as e:
|
|
84
|
+
logging.error(f"Error al crear la sesión desde token para {user_identifier}: {e}")
|
|
85
|
+
self.log_access(
|
|
86
|
+
company_short_name=company_short_name,
|
|
87
|
+
auth_type='redeem_token',
|
|
88
|
+
outcome='failure',
|
|
89
|
+
reason_code='SESSION_CREATION_FAILED',
|
|
90
|
+
user_identifier=user_identifier
|
|
91
|
+
)
|
|
92
|
+
return {'success': False, 'error': 'No se pudo crear la sesión del usuario'}
|
|
25
93
|
|
|
26
94
|
def verify(self) -> dict:
|
|
27
95
|
"""
|
|
@@ -74,4 +142,40 @@ class AuthService:
|
|
|
74
142
|
# --- Failure: No valid credentials found ---
|
|
75
143
|
logging.info(f"Authentication required. No session cookie or API Key provided.")
|
|
76
144
|
return {"success": False, "error": "Authentication required. No session cookie or API Key provided.",
|
|
77
|
-
"status_code": 402}
|
|
145
|
+
"status_code": 402}
|
|
146
|
+
|
|
147
|
+
def log_access(self,
|
|
148
|
+
company_short_name: str,
|
|
149
|
+
auth_type: str,
|
|
150
|
+
outcome: str,
|
|
151
|
+
user_identifier: str = None,
|
|
152
|
+
reason_code: str = None):
|
|
153
|
+
"""
|
|
154
|
+
Registra un intento de acceso en la base de datos.
|
|
155
|
+
Es "best-effort" y no debe interrumpir el flujo de autenticación.
|
|
156
|
+
"""
|
|
157
|
+
session = self.db_manager.scoped_session()
|
|
158
|
+
try:
|
|
159
|
+
# Capturar datos del contexto de la petición de Flask
|
|
160
|
+
source_ip = request.headers.get('X-Forwarded-For', request.remote_addr)
|
|
161
|
+
path = request.path
|
|
162
|
+
ua = request.headers.get('User-Agent', '')
|
|
163
|
+
ua_hash = hashlib.sha256(ua.encode()).hexdigest()[:16] if ua else None
|
|
164
|
+
|
|
165
|
+
# Crear la entrada de log
|
|
166
|
+
log_entry = AccessLog(
|
|
167
|
+
company_short_name=company_short_name,
|
|
168
|
+
user_identifier=user_identifier,
|
|
169
|
+
auth_type=auth_type,
|
|
170
|
+
outcome=outcome,
|
|
171
|
+
reason_code=reason_code,
|
|
172
|
+
source_ip=source_ip,
|
|
173
|
+
user_agent_hash=ua_hash,
|
|
174
|
+
request_path=path,
|
|
175
|
+
)
|
|
176
|
+
session.add(log_entry)
|
|
177
|
+
session.commit()
|
|
178
|
+
|
|
179
|
+
except Exception as e:
|
|
180
|
+
logging.error(f"Fallo al escribir en AccessLog: {e}", exc_info=False)
|
|
181
|
+
session.rollback()
|
|
@@ -8,6 +8,7 @@ from flask.views import MethodView
|
|
|
8
8
|
from flask import render_template, url_for
|
|
9
9
|
from injector import inject
|
|
10
10
|
from iatoolkit.services.profile_service import ProfileService
|
|
11
|
+
from iatoolkit.services.auth_service import AuthService
|
|
11
12
|
from iatoolkit.services.query_service import QueryService
|
|
12
13
|
from iatoolkit.services.branding_service import BrandingService
|
|
13
14
|
from iatoolkit.services.onboarding_service import OnboardingService
|
|
@@ -23,6 +24,7 @@ class BaseLoginView(MethodView):
|
|
|
23
24
|
@inject
|
|
24
25
|
def __init__(self,
|
|
25
26
|
profile_service: ProfileService,
|
|
27
|
+
auth_service: AuthService,
|
|
26
28
|
jwt_service: JWTService,
|
|
27
29
|
branding_service: BrandingService,
|
|
28
30
|
prompt_service: PromptService,
|
|
@@ -30,6 +32,7 @@ class BaseLoginView(MethodView):
|
|
|
30
32
|
query_service: QueryService
|
|
31
33
|
):
|
|
32
34
|
self.profile_service = profile_service
|
|
35
|
+
self.auth_service = auth_service
|
|
33
36
|
self.jwt_service = jwt_service
|
|
34
37
|
self.branding_service = branding_service
|
|
35
38
|
self.prompt_service = prompt_service
|
|
@@ -6,45 +6,18 @@
|
|
|
6
6
|
import os
|
|
7
7
|
import logging
|
|
8
8
|
from flask import request, jsonify
|
|
9
|
-
from flask.views import MethodView
|
|
10
9
|
from injector import inject
|
|
11
|
-
from iatoolkit.services.auth_service import AuthService
|
|
12
10
|
from iatoolkit.views.base_login_view import BaseLoginView
|
|
13
11
|
|
|
14
12
|
# Importar los servicios que necesita la clase base
|
|
15
13
|
from iatoolkit.services.profile_service import ProfileService
|
|
16
14
|
from iatoolkit.services.jwt_service import JWTService
|
|
17
|
-
from iatoolkit.services.branding_service import BrandingService
|
|
18
|
-
from iatoolkit.services.onboarding_service import OnboardingService
|
|
19
|
-
from iatoolkit.services.query_service import QueryService
|
|
20
|
-
from iatoolkit.services.prompt_manager_service import PromptService
|
|
21
15
|
|
|
22
16
|
class ExternalLoginView(BaseLoginView):
|
|
23
17
|
"""
|
|
24
18
|
Handles login for external users via API.
|
|
25
19
|
Authenticates and then delegates the path decision (fast/slow) to the base class.
|
|
26
20
|
"""
|
|
27
|
-
@inject
|
|
28
|
-
def __init__(self,
|
|
29
|
-
iauthentication: AuthService,
|
|
30
|
-
jwt_service: JWTService,
|
|
31
|
-
profile_service: ProfileService,
|
|
32
|
-
branding_service: BrandingService,
|
|
33
|
-
prompt_service: PromptService,
|
|
34
|
-
onboarding_service: OnboardingService,
|
|
35
|
-
query_service: QueryService):
|
|
36
|
-
# Pass the dependencies for the base class to its __init__
|
|
37
|
-
super().__init__(
|
|
38
|
-
profile_service=profile_service,
|
|
39
|
-
jwt_service=jwt_service,
|
|
40
|
-
branding_service=branding_service,
|
|
41
|
-
onboarding_service=onboarding_service,
|
|
42
|
-
query_service=query_service,
|
|
43
|
-
prompt_service=prompt_service,
|
|
44
|
-
)
|
|
45
|
-
# Handle the dependency specific to this child class
|
|
46
|
-
self.iauthentication = iauthentication
|
|
47
|
-
|
|
48
21
|
def post(self, company_short_name: str):
|
|
49
22
|
data = request.get_json()
|
|
50
23
|
if not data or 'user_identifier' not in data:
|
|
@@ -59,9 +32,9 @@ class ExternalLoginView(BaseLoginView):
|
|
|
59
32
|
return jsonify({"error": "missing user_identifier"}), 404
|
|
60
33
|
|
|
61
34
|
# 1. Authenticate the API call.
|
|
62
|
-
|
|
63
|
-
if not
|
|
64
|
-
return jsonify(
|
|
35
|
+
auth_response = self.auth_service.verify()
|
|
36
|
+
if not auth_response.get("success"):
|
|
37
|
+
return jsonify(auth_response), 401
|
|
65
38
|
|
|
66
39
|
# 2. Create the external user session.
|
|
67
40
|
self.profile_service.create_external_user_session(company, user_identifier)
|
|
@@ -74,37 +47,21 @@ class ExternalLoginView(BaseLoginView):
|
|
|
74
47
|
return jsonify({"error": f"Internal server error while starting chat. {str(e)}"}), 500
|
|
75
48
|
|
|
76
49
|
|
|
77
|
-
class RedeemTokenApiView(
|
|
50
|
+
class RedeemTokenApiView(BaseLoginView):
|
|
78
51
|
# this endpoint is only used ONLY by chat_main.js to redeem a chat token
|
|
79
|
-
@inject
|
|
80
|
-
def __init__(self,
|
|
81
|
-
profile_service: ProfileService,
|
|
82
|
-
jwt_service: JWTService):
|
|
83
|
-
self.profile_service = profile_service
|
|
84
|
-
self.jwt_service = jwt_service
|
|
85
|
-
|
|
86
52
|
def post(self, company_short_name: str):
|
|
87
53
|
data = request.get_json()
|
|
88
54
|
if not data or 'token' not in data:
|
|
89
55
|
return jsonify({"error": "Falta token de validación"}), 400
|
|
90
56
|
|
|
91
|
-
#
|
|
57
|
+
# get the token and validate with auth service
|
|
92
58
|
token = data.get('token')
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
# 2. if token is valid, extract the user_identifier
|
|
99
|
-
user_identifier = payload.get('user_identifier')
|
|
100
|
-
|
|
101
|
-
try:
|
|
102
|
-
# 3. create the Flask session
|
|
103
|
-
self.profile_service.set_session_for_user(company_short_name, user_identifier)
|
|
104
|
-
logging.info(f"Token de sesión canjeado exitosamente para {user_identifier}.")
|
|
59
|
+
redeem_result = self.auth_service.redeem_token_for_session(
|
|
60
|
+
company_short_name=company_short_name,
|
|
61
|
+
token=token
|
|
62
|
+
)
|
|
105
63
|
|
|
106
|
-
|
|
64
|
+
if not redeem_result['success']:
|
|
65
|
+
return {"error": redeem_result['error']}, 401
|
|
107
66
|
|
|
108
|
-
|
|
109
|
-
logging.error(f"Error al crear la sesión desde token para {user_identifier}: {e}")
|
|
110
|
-
return {"error": "No se pudo crear la sesión del usuario."}, 500
|
|
67
|
+
return {"status": "ok"}, 200
|
iatoolkit/views/login_view.py
CHANGED
|
@@ -7,6 +7,7 @@ from flask.views import MethodView
|
|
|
7
7
|
from flask import request, redirect, render_template, url_for
|
|
8
8
|
from injector import inject
|
|
9
9
|
from iatoolkit.services.profile_service import ProfileService
|
|
10
|
+
from iatoolkit.services.auth_service import AuthService
|
|
10
11
|
from iatoolkit.services.jwt_service import JWTService
|
|
11
12
|
from iatoolkit.services.query_service import QueryService
|
|
12
13
|
from iatoolkit.services.prompt_manager_service import PromptService
|
|
@@ -21,7 +22,6 @@ class LoginView(BaseLoginView):
|
|
|
21
22
|
Handles login for local users.
|
|
22
23
|
Authenticates and then delegates the path decision (fast/slow) to the base class.
|
|
23
24
|
"""
|
|
24
|
-
|
|
25
25
|
def post(self, company_short_name: str):
|
|
26
26
|
company = self.profile_service.get_company_by_short_name(company_short_name)
|
|
27
27
|
if not company:
|
|
@@ -30,8 +30,8 @@ class LoginView(BaseLoginView):
|
|
|
30
30
|
email = request.form.get('email')
|
|
31
31
|
password = request.form.get('password')
|
|
32
32
|
|
|
33
|
-
# 1. Authenticate
|
|
34
|
-
auth_response = self.
|
|
33
|
+
# 1. Authenticate internal user
|
|
34
|
+
auth_response = self.auth_service.login_local_user(
|
|
35
35
|
company_short_name=company_short_name,
|
|
36
36
|
email=email,
|
|
37
37
|
password=password
|
|
@@ -67,6 +67,7 @@ class FinalizeContextView(MethodView):
|
|
|
67
67
|
@inject
|
|
68
68
|
def __init__(self,
|
|
69
69
|
profile_service: ProfileService,
|
|
70
|
+
auth_service: AuthService,
|
|
70
71
|
query_service: QueryService,
|
|
71
72
|
prompt_service: PromptService,
|
|
72
73
|
branding_service: BrandingService,
|
|
@@ -2,7 +2,7 @@ iatoolkit/__init__.py,sha256=4PWjMJjktixtrxF6BY405qyA50Sv967kEP2x-oil6qk,1120
|
|
|
2
2
|
iatoolkit/base_company.py,sha256=nfF-G0h63jy3Qh9kCnvx8Ozx76IjG2p7a34HpweWhOk,4608
|
|
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=tFx-D1Q0usCdOc3vSNdtz94mTCWhUGcyRkDISI2QMMs,17583
|
|
6
6
|
iatoolkit/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
7
|
iatoolkit/common/exceptions.py,sha256=EXx40n5htp7UiOM6P1xfJ9U6NMcADqm62dlFaKz7ICU,1154
|
|
8
8
|
iatoolkit/common/routes.py,sha256=c8kRk8pEK_nV-2P1LiYXRERmW_QoW21Hk6CZkkizv6Y,6419
|
|
@@ -29,12 +29,12 @@ iatoolkit/repositories/__init__.py,sha256=5JqK9sZ6jBuK83zDQokUhxQ0wuJJJ9DXB8pYCL
|
|
|
29
29
|
iatoolkit/repositories/database_manager.py,sha256=QgV8hNnVv9RmeOvUdomdj_mfk0bf3Rl8Ti41a-5zIAY,3700
|
|
30
30
|
iatoolkit/repositories/document_repo.py,sha256=Y7bF1kZB1HWJsAGjWdF7P2aVYeTYNufq9ngQXp7mDkY,1124
|
|
31
31
|
iatoolkit/repositories/llm_query_repo.py,sha256=YT_t7cYGQk8rwzH_17-28aTzO-e2jUfa2rvXy8tugvA,3612
|
|
32
|
-
iatoolkit/repositories/models.py,sha256=
|
|
32
|
+
iatoolkit/repositories/models.py,sha256=qM95kiKm_92JoPNXiwMT4HTjr5BjalnrDiatG3Rte-M,14300
|
|
33
33
|
iatoolkit/repositories/profile_repo.py,sha256=21am3GP7XCG0nq6i3pArQ7mfGsrRn8rdcWT98fsdwlU,4397
|
|
34
34
|
iatoolkit/repositories/tasks_repo.py,sha256=icVO_r2oPagGnnBhwVFzznnvEEU2EAx-2dlWuWvoDC4,1745
|
|
35
35
|
iatoolkit/repositories/vs_repo.py,sha256=UkpmQQiocgM5IwRBmmWhw3HHzHP6zK1nN3J3TcQgjhc,5300
|
|
36
36
|
iatoolkit/services/__init__.py,sha256=5JqK9sZ6jBuK83zDQokUhxQ0wuJJJ9DXB8pYCLkX7X4,102
|
|
37
|
-
iatoolkit/services/auth_service.py,sha256=
|
|
37
|
+
iatoolkit/services/auth_service.py,sha256=vBVKkFJWsaPhhR-LvfLXfIrR-mmR-P5Y8Ya_5p1pgC8,7126
|
|
38
38
|
iatoolkit/services/benchmark_service.py,sha256=CdbFYyS3FHFhNzWQEa9ZNjUlmON10DT1nKNbZQ1EUi8,5880
|
|
39
39
|
iatoolkit/services/branding_service.py,sha256=gXj9Lj6EIFNIHT6wAHia5lr4_2a2sD-ExMbewno5YD8,7505
|
|
40
40
|
iatoolkit/services/dispatcher_service.py,sha256=Qdn2x4cozpgpKg2448sUxkhO6tuplzb8xPWUxdTTFBE,12772
|
|
@@ -86,10 +86,10 @@ iatoolkit/templates/onboarding_shell.html,sha256=r1ivSR2ci8GrDSm1uaD-cf78rfO1bKT
|
|
|
86
86
|
iatoolkit/templates/signup.html,sha256=9ArDvcNQgHFR2dwxy-37AXzGUOeOsT7Nz5u0y6fAB3U,4385
|
|
87
87
|
iatoolkit/templates/test.html,sha256=rwNtxC83tbCl5COZFXYvmRBxxmgFJtPNuVBd_nq9KWY,133
|
|
88
88
|
iatoolkit/views/__init__.py,sha256=5JqK9sZ6jBuK83zDQokUhxQ0wuJJJ9DXB8pYCLkX7X4,102
|
|
89
|
-
iatoolkit/views/base_login_view.py,sha256=
|
|
89
|
+
iatoolkit/views/base_login_view.py,sha256=_JM-SMFlftxhpIRV7KyHsTAnAJN_ThY2j1WaYP-HneI,4111
|
|
90
90
|
iatoolkit/views/change_password_view.py,sha256=tM0woZyKdhY4XYjS_YXg2sKq3RYkXGfcq_eVAKrNvNM,4498
|
|
91
91
|
iatoolkit/views/chat_token_request_view.py,sha256=wf32_A2Sq8NHYWshCwL10Tovd1znLoD0jQjzutR3sVE,4408
|
|
92
|
-
iatoolkit/views/external_login_view.py,sha256=
|
|
92
|
+
iatoolkit/views/external_login_view.py,sha256=ZFd2Qm_B7ecLxFfu9vL4YjIfkRP6M18slGZszQzpB2g,2572
|
|
93
93
|
iatoolkit/views/file_store_api_view.py,sha256=Uz9f6sey3_F5K8zuyQz6SwYRKAalCjD1ekf-Mkl_Kfo,2326
|
|
94
94
|
iatoolkit/views/forgot_password_view.py,sha256=-qKJeeOBqJFdvDUk7rCNg1E1cDQnJQkozPpb0T0FgwA,3159
|
|
95
95
|
iatoolkit/views/history_api_view.py,sha256=x-tZhB8UzqrD2n-WDIfmHK9iVhGZ9f0yncsGs9mxwt0,1953
|
|
@@ -98,14 +98,14 @@ iatoolkit/views/init_context_api_view.py,sha256=1j8NKfODfPrffbA5YO8TPMHh-ildlLNz
|
|
|
98
98
|
iatoolkit/views/llmquery_api_view.py,sha256=Rh-y-VENwwtNsDrYAD_SWKwjK16fW-pFRWlEvI-OYwY,2120
|
|
99
99
|
iatoolkit/views/llmquery_web_view.py,sha256=WhjlA1mfsoL8hL9tlKQfjCUcaTzT43odlp_uQKmT314,1500
|
|
100
100
|
iatoolkit/views/login_simulation_view.py,sha256=0Qt-puRnltI2HZxlfdyJmOf26-hQp3xjknGV_jkwV7E,3484
|
|
101
|
-
iatoolkit/views/login_view.py,sha256=
|
|
101
|
+
iatoolkit/views/login_view.py,sha256=VmW5oDOBqbxLcHx7-LcLyGoI9WMwyg-UbMedV7vap8g,5448
|
|
102
102
|
iatoolkit/views/prompt_api_view.py,sha256=MP0r-MiswwKcbNc_5KY7aVbHkrR218I8XCiCX1D0yTA,1244
|
|
103
103
|
iatoolkit/views/signup_view.py,sha256=BCjhM2lMiDPwYrlW_eEwPl-ZLupblbFfsonWtq0E4vU,3922
|
|
104
104
|
iatoolkit/views/tasks_review_view.py,sha256=keLsLCyOTTlcoIapnB_lbuSvLwrPVZVpBiFC_7ChbLg,3388
|
|
105
105
|
iatoolkit/views/tasks_view.py,sha256=a3anTXrJTTvbQuc6PSpOzidLKQFL4hWa7PI2Cppcz8w,4110
|
|
106
106
|
iatoolkit/views/user_feedback_api_view.py,sha256=59XB9uQLHI4Q6QA4_XhK787HzfXb-c6EY7k1Ccyr4hI,2424
|
|
107
107
|
iatoolkit/views/verify_user_view.py,sha256=7XLSaxvs8LjBr3cYOUDa9B8DqW_50IGlq0IvmOQcD0Y,2340
|
|
108
|
-
iatoolkit-0.
|
|
109
|
-
iatoolkit-0.
|
|
110
|
-
iatoolkit-0.
|
|
111
|
-
iatoolkit-0.
|
|
108
|
+
iatoolkit-0.57.0.dist-info/METADATA,sha256=zrwlhrbdyUpcYe4x6e3-1nexr7_p8-b2aEcDzuv4Vzs,9301
|
|
109
|
+
iatoolkit-0.57.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
110
|
+
iatoolkit-0.57.0.dist-info/top_level.txt,sha256=V_w4QvDx0b1RXiy8zTCrD1Bp7AZkFe3_O0-9fMiwogg,10
|
|
111
|
+
iatoolkit-0.57.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|