iatoolkit 0.7.4__py3-none-any.whl → 0.7.6__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 (57) hide show
  1. common/__init__.py +0 -0
  2. common/auth.py +200 -0
  3. common/exceptions.py +46 -0
  4. common/routes.py +86 -0
  5. common/session_manager.py +25 -0
  6. common/util.py +358 -0
  7. iatoolkit/iatoolkit.py +3 -3
  8. {iatoolkit-0.7.4.dist-info → iatoolkit-0.7.6.dist-info}/METADATA +1 -1
  9. iatoolkit-0.7.6.dist-info/RECORD +80 -0
  10. iatoolkit-0.7.6.dist-info/top_level.txt +6 -0
  11. infra/__init__.py +5 -0
  12. infra/call_service.py +140 -0
  13. infra/connectors/__init__.py +5 -0
  14. infra/connectors/file_connector.py +17 -0
  15. infra/connectors/file_connector_factory.py +57 -0
  16. infra/connectors/google_cloud_storage_connector.py +53 -0
  17. infra/connectors/google_drive_connector.py +68 -0
  18. infra/connectors/local_file_connector.py +46 -0
  19. infra/connectors/s3_connector.py +33 -0
  20. infra/gemini_adapter.py +356 -0
  21. infra/google_chat_app.py +57 -0
  22. infra/llm_client.py +430 -0
  23. infra/llm_proxy.py +139 -0
  24. infra/llm_response.py +40 -0
  25. infra/mail_app.py +145 -0
  26. infra/openai_adapter.py +90 -0
  27. infra/redis_session_manager.py +76 -0
  28. repositories/__init__.py +5 -0
  29. repositories/database_manager.py +95 -0
  30. repositories/document_repo.py +33 -0
  31. repositories/llm_query_repo.py +91 -0
  32. repositories/models.py +309 -0
  33. repositories/profile_repo.py +118 -0
  34. repositories/tasks_repo.py +52 -0
  35. repositories/vs_repo.py +139 -0
  36. views/__init__.py +5 -0
  37. views/change_password_view.py +91 -0
  38. views/chat_token_request_view.py +98 -0
  39. views/chat_view.py +51 -0
  40. views/download_file_view.py +58 -0
  41. views/external_chat_login_view.py +88 -0
  42. views/external_login_view.py +40 -0
  43. views/file_store_view.py +58 -0
  44. views/forgot_password_view.py +64 -0
  45. views/history_view.py +57 -0
  46. views/home_view.py +34 -0
  47. views/llmquery_view.py +65 -0
  48. views/login_view.py +60 -0
  49. views/prompt_view.py +37 -0
  50. views/signup_view.py +87 -0
  51. views/tasks_review_view.py +83 -0
  52. views/tasks_view.py +98 -0
  53. views/user_feedback_view.py +74 -0
  54. views/verify_user_view.py +55 -0
  55. iatoolkit-0.7.4.dist-info/RECORD +0 -30
  56. iatoolkit-0.7.4.dist-info/top_level.txt +0 -2
  57. {iatoolkit-0.7.4.dist-info → iatoolkit-0.7.6.dist-info}/WHEEL +0 -0
views/llmquery_view.py ADDED
@@ -0,0 +1,65 @@
1
+ # Copyright (c) 2024 Fernando Libedinsky
2
+ # Product: IAToolkit
3
+ #
4
+ # IAToolkit is open source software.
5
+
6
+ from flask import request, jsonify, render_template
7
+ from flask.views import MethodView
8
+ from services.query_service import QueryService
9
+ from common.auth import IAuthentication
10
+ from injector import inject
11
+ import logging
12
+
13
+
14
+ class LLMQueryView(MethodView):
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 post(self, company_short_name):
24
+ data = request.get_json()
25
+ if not data:
26
+ return jsonify({"error_message": "Cuerpo de la solicitud JSON inválido o faltante"}), 400
27
+
28
+ # get access credentials
29
+ iaut = self.iauthentication.verify(company_short_name, data.get("external_user_id"))
30
+ if not iaut.get("success"):
31
+ return jsonify(iaut), 401
32
+
33
+ company_id = iaut.get("company_id")
34
+ external_user_id = iaut.get("external_user_id")
35
+ local_user_id = iaut.get("local_user_id")
36
+
37
+ # now check the form
38
+ question = data.get("question")
39
+ files = data.get("files", [])
40
+ client_data = data.get("client_data", {})
41
+ prompt_name = data.get("prompt_name")
42
+ if not question and not prompt_name:
43
+ return jsonify({"error_message": "Falta la consulta o el prompt_name"}), 400
44
+
45
+ try:
46
+ response = self.query_service.llm_query(
47
+ company_short_name=company_short_name,
48
+ external_user_id=external_user_id,
49
+ local_user_id=local_user_id,
50
+ question=question,
51
+ prompt_name=prompt_name,
52
+ client_data=client_data,
53
+ files=files)
54
+ if "error" in response:
55
+ return {'error_message': response.get("error_message", '')}, 401
56
+
57
+ return response, 200
58
+ except Exception as e:
59
+ logging.exception(
60
+ f"Error inesperado al procesar llm_query para company {company_short_name}: {e}")
61
+ if local_user_id:
62
+ return render_template("error.html",
63
+ message="Ha ocurrido un error inesperado."), 500
64
+ else:
65
+ return jsonify({"error_message": str(e)}), 500
views/login_view.py ADDED
@@ -0,0 +1,60 @@
1
+ # Copyright (c) 2024 Fernando Libedinsky
2
+ # Product: IAToolkit
3
+ #
4
+ # IAToolkit is open source software.
5
+
6
+ from flask.views import MethodView
7
+ from flask import request, redirect, render_template, url_for
8
+ from injector import inject
9
+ from services.profile_service import ProfileService
10
+
11
+ class LoginView(MethodView):
12
+ @inject
13
+ def __init__(self, profile_service: ProfileService):
14
+ self.profile_service = profile_service
15
+
16
+ def get(self, company_short_name: str):
17
+ # get company info
18
+ company = self.profile_service.get_company_by_short_name(company_short_name)
19
+ if not company:
20
+ return render_template('error.html', message="Empresa no encontrada"), 404
21
+
22
+ return render_template('login.html',
23
+ company=company,
24
+ company_short_name=company_short_name)
25
+
26
+ def post(self, company_short_name: str):
27
+ # get company info
28
+ 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
+
32
+ email = request.form.get('email')
33
+ try:
34
+ password = request.form.get('password')
35
+
36
+ response = self.profile_service.login(
37
+ company_short_name=company_short_name,
38
+ email=email,
39
+ password=password
40
+ )
41
+
42
+ if "error" in response:
43
+ return render_template(
44
+ 'login.html',
45
+ company_short_name=company_short_name,
46
+ company=company,
47
+ form_data={
48
+ "email": email,
49
+ "password": password,
50
+ },
51
+ alert_message=response["error"]), 400
52
+
53
+ return redirect(url_for('chat', company_short_name=company_short_name))
54
+
55
+ except Exception as e:
56
+ return render_template("error.html",
57
+ company=company,
58
+ company_short_name=company_short_name,
59
+ message="Ha ocurrido un error inesperado."), 500
60
+
views/prompt_view.py ADDED
@@ -0,0 +1,37 @@
1
+ # Copyright (c) 2024 Fernando Libedinsky
2
+ # Product: IAToolkit
3
+ #
4
+ # IAToolkit is open source software.
5
+
6
+ from flask import jsonify
7
+ from flask.views import MethodView
8
+ from services.prompt_manager_service import PromptService
9
+ from common.auth import IAuthentication
10
+ from injector import inject
11
+ import logging
12
+
13
+
14
+ class PromptView(MethodView):
15
+ @inject
16
+ def __init__(self,
17
+ iauthentication: IAuthentication,
18
+ prompt_service: PromptService ):
19
+ self.iauthentication = iauthentication
20
+ self.prompt_service = prompt_service
21
+
22
+ def get(self, company_short_name):
23
+ # get access credentials
24
+ iaut = self.iauthentication.verify(company_short_name)
25
+ if not iaut.get("success"):
26
+ return jsonify(iaut), 401
27
+
28
+ try:
29
+ response = self.prompt_service.get_user_prompts(company_short_name)
30
+ if "error" in response:
31
+ return {'error_message': response["error"]}, 402
32
+
33
+ return response, 200
34
+ except Exception as e:
35
+ logging.exception(
36
+ f"Error inesperado al obtener el historial de consultas para company {company_short_name}: {e}")
37
+ return jsonify({"error_message": str(e)}), 500
views/signup_view.py ADDED
@@ -0,0 +1,87 @@
1
+ # Copyright (c) 2024 Fernando Libedinsky
2
+ # Product: IAToolkit
3
+ #
4
+ # IAToolkit is open source software.
5
+
6
+ from flask.views import MethodView
7
+ from flask import render_template
8
+ from services.profile_service import ProfileService
9
+ from injector import inject
10
+ from itsdangerous import URLSafeTimedSerializer
11
+ from flask import url_for, request
12
+ import os
13
+
14
+
15
+ class SignupView(MethodView):
16
+ @inject
17
+ def __init__(self, profile_service: ProfileService):
18
+ self.profile_service = profile_service
19
+ self.serializer = URLSafeTimedSerializer(os.getenv("USER_VERIF_KEY"))
20
+
21
+
22
+ def get(self, company_short_name: str):
23
+ # get company info
24
+ company = self.profile_service.get_company_by_short_name(company_short_name)
25
+ if not company:
26
+ return render_template('error.html', message="Empresa no encontrada"), 404
27
+
28
+ user_agent = request.user_agent
29
+ is_mobile = user_agent.platform in ["android", "iphone", "ipad"] or "mobile" in user_agent.string.lower()
30
+ return render_template('signup.html',
31
+ company=company,
32
+ company_short_name=company_short_name,
33
+ is_mobile=is_mobile)
34
+
35
+ def post(self, company_short_name: str):
36
+ # get company info
37
+ company = self.profile_service.get_company_by_short_name(company_short_name)
38
+ if not company:
39
+ return render_template('error.html', message="Empresa no encontrada"), 404
40
+
41
+ try:
42
+ first_name = request.form.get('first_name')
43
+ last_name = request.form.get('last_name')
44
+ email = request.form.get('email')
45
+ password = request.form.get('password')
46
+ confirm_password = request.form.get('confirm_password')
47
+
48
+ # create verification token and url for verification
49
+ token = self.serializer.dumps(email, salt='email-confirm')
50
+ verification_url = url_for('verify_account',
51
+ company_short_name=company_short_name,
52
+ token=token, _external=True)
53
+
54
+ response = self.profile_service.signup(
55
+ company_short_name=company_short_name,
56
+ email=email,
57
+ first_name=first_name, last_name=last_name,
58
+ password=password, confirm_password=confirm_password,
59
+ verification_url=verification_url)
60
+
61
+ if "error" in response:
62
+ return render_template(
63
+ 'signup.html',
64
+ company=company,
65
+ company_short_name=company_short_name,
66
+ form_data={
67
+ "first_name": first_name,
68
+ "last_name": last_name,
69
+ "email": email,
70
+ "password": password,
71
+ "confirm_password": confirm_password
72
+ },
73
+ alert_message=response["error"]), 400
74
+
75
+ # all is OK
76
+ return render_template(
77
+ 'login.html',
78
+ company=company,
79
+ company_short_name=company_short_name,
80
+ alert_icon='success',
81
+ alert_message=response["message"]), 200
82
+ except Exception as e:
83
+ return render_template("error.html",
84
+ company=company,
85
+ company_short_name=company_short_name,
86
+ message="Ha ocurrido un error inesperado."), 500
87
+
@@ -0,0 +1,83 @@
1
+ # Copyright (c) 2024 Fernando Libedinsky
2
+ # Product: IAToolkit
3
+ #
4
+ # IAToolkit is open source software.
5
+
6
+ from flask.views import MethodView
7
+ from flask import request, jsonify
8
+ from services.tasks_service import TaskService
9
+ from repositories.profile_repo import ProfileRepo
10
+ from injector import inject
11
+ import logging
12
+ from typing import Optional
13
+
14
+
15
+ class TaskReviewView(MethodView):
16
+ @inject
17
+ def __init__(self, task_service: TaskService, profile_repo: ProfileRepo):
18
+ self.task_service = task_service
19
+ self.profile_repo = profile_repo
20
+
21
+
22
+ def _authenticate_requesting_company_via_api_key(self) -> tuple[
23
+ Optional[int], Optional[str], Optional[tuple[dict, int]]]:
24
+ """
25
+ Autentica a la compañía usando su API Key.
26
+ Retorna (company_id, company_short_name, None) en éxito.
27
+ Retorna (None, None, (error_json, status_code)) en fallo.
28
+ """
29
+ api_key_header = request.headers.get('Authorization')
30
+ if not api_key_header or not api_key_header.startswith('Bearer '):
31
+ return None, None, ({"error": "API Key faltante o mal formada en el header Authorization"}, 401)
32
+
33
+ api_key_value = api_key_header.split('Bearer ')[1]
34
+ try:
35
+ api_key_entry = self.profile_repo.get_active_api_key_entry(api_key_value)
36
+ if not api_key_entry:
37
+ return None, None, ({"error": "API Key inválida o inactiva"}, 401)
38
+
39
+ # api_key_entry.company ya está cargado por joinedload en get_active_api_key_entry
40
+ if not api_key_entry.company: # Sanity check
41
+ logging.error(
42
+ f"ChatTokenRequest: API Key {api_key_value[:5]}... no tiene compañía asociada a pesar de ser válida.")
43
+ return None, None, ({"error": "Error interno del servidor al verificar API Key"}, 500)
44
+
45
+ return api_key_entry.company_id, api_key_entry.company.short_name, None
46
+
47
+ except Exception as e:
48
+ logging.exception(f"ChatTokenRequest: Error interno durante validación de API Key: {e}")
49
+ return None, None, ({"error": "Error interno del servidor al validar API Key"}, 500)
50
+
51
+
52
+ def post(self, task_id: int):
53
+ try:
54
+ # only requests with valid api-key are allowed
55
+ auth_company_id, auth_company_short_name, error = self._authenticate_requesting_company_via_api_key()
56
+ if error:
57
+ return jsonify(error[0]), error[1]
58
+
59
+ req_data = request.get_json()
60
+
61
+ required_fields = ['review_user', 'approved']
62
+ for field in required_fields:
63
+ if field not in req_data:
64
+ return jsonify({"error": f"El campo {field} es requerido"}), 400
65
+
66
+ review_user = req_data.get('review_user', '')
67
+ approved = req_data.get('approved', False)
68
+ comment = req_data.get('comment', '')
69
+
70
+ new_task = self.task_service.review_task(
71
+ task_id=task_id,
72
+ review_user=review_user,
73
+ approved=approved,
74
+ comment=comment)
75
+
76
+ return jsonify({
77
+ "task_id": new_task.id,
78
+ "status": new_task.status.name
79
+ }), 200
80
+
81
+ except Exception as e:
82
+ logging.exception("Error al revisar la tarea: %s", str(e))
83
+ return jsonify({"error": str(e)}), 500
views/tasks_view.py ADDED
@@ -0,0 +1,98 @@
1
+ # Copyright (c) 2024 Fernando Libedinsky
2
+ # Product: IAToolkit
3
+ #
4
+ # IAToolkit is open source software.
5
+
6
+ from flask.views import MethodView
7
+ from flask import request, jsonify
8
+ from services.tasks_service import TaskService
9
+ from repositories.profile_repo import ProfileRepo
10
+ from injector import inject
11
+ from datetime import datetime
12
+ import logging
13
+ from typing import Optional
14
+
15
+
16
+ class TaskView(MethodView):
17
+ @inject
18
+ def __init__(self, task_service: TaskService, profile_repo: ProfileRepo):
19
+ self.task_service = task_service
20
+ self.profile_repo = profile_repo
21
+
22
+ def _authenticate_requesting_company_via_api_key(self) -> tuple[
23
+ Optional[int], Optional[str], Optional[tuple[dict, int]]]:
24
+ """
25
+ Autentica a la compañía usando su API Key.
26
+ Retorna (company_id, company_short_name, None) en éxito.
27
+ Retorna (None, None, (error_json, status_code)) en fallo.
28
+ """
29
+ api_key_header = request.headers.get('Authorization')
30
+ if not api_key_header or not api_key_header.startswith('Bearer '):
31
+ return None, None, ({"error": "API Key faltante o mal formada en el header Authorization"}, 401)
32
+
33
+ api_key_value = api_key_header.split('Bearer ')[1]
34
+ try:
35
+ api_key_entry = self.profile_repo.get_active_api_key_entry(api_key_value)
36
+ if not api_key_entry:
37
+ return None, None, ({"error": "API Key inválida o inactiva"}, 401)
38
+
39
+ # api_key_entry.company ya está cargado por joinedload en get_active_api_key_entry
40
+ if not api_key_entry.company: # Sanity check
41
+ logging.error(
42
+ f"ChatTokenRequest: API Key {api_key_value[:5]}... no tiene compañía asociada a pesar de ser válida.")
43
+ return None, None, ({"error": "Error interno del servidor al verificar API Key"}, 500)
44
+
45
+ return api_key_entry.company_id, api_key_entry.company.short_name, None
46
+
47
+ except Exception as e:
48
+ logging.exception(f"ChatTokenRequest: Error interno durante validación de API Key: {e}")
49
+ return None, None, ({"error": "Error interno del servidor al validar API Key"}, 500)
50
+
51
+
52
+ def post(self):
53
+ try:
54
+ # only requests with valid api-key are allowed
55
+ auth_company_id, auth_company_short_name, error = self._authenticate_requesting_company_via_api_key()
56
+ if error:
57
+ return jsonify(error[0]), error[1]
58
+
59
+ req_data = request.get_json()
60
+ files = request.files.getlist('files')
61
+
62
+ required_fields = ['company', 'task_type', 'client_data']
63
+ for field in required_fields:
64
+ if field not in req_data:
65
+ return jsonify({"error": f"El campo {field} es requerido"}), 400
66
+
67
+ company_short_name = req_data.get('company', '')
68
+ task_type = req_data.get('task_type', '')
69
+ client_data = req_data.get('client_data', {})
70
+ company_task_id = req_data.get('company_task_id', 0)
71
+ execute_at = req_data.get('execute_at', None)
72
+
73
+ # validate date format is parameter is present
74
+ if execute_at:
75
+ try:
76
+ # date in iso format
77
+ execute_at = datetime.fromisoformat(execute_at)
78
+ except ValueError:
79
+ return jsonify({
80
+ "error": "El formato de execute_at debe ser YYYY-MM-DD HH:MM:SS"
81
+ }), 400
82
+
83
+ new_task = self.task_service.create_task(
84
+ company_short_name=company_short_name,
85
+ task_type_name=task_type,
86
+ client_data=client_data,
87
+ company_task_id=company_task_id,
88
+ execute_at=execute_at,
89
+ files=files)
90
+
91
+ return jsonify({
92
+ "task_id": new_task.id,
93
+ "status": new_task.status.name
94
+ }), 201
95
+
96
+ except Exception as e:
97
+ logging.exception("Error al crear la tarea: %s", str(e))
98
+ return jsonify({"error": str(e)}), 500
@@ -0,0 +1,74 @@
1
+ # Copyright (c) 2024 Fernando Libedinsky
2
+ # Product: IAToolkit
3
+ #
4
+ # IAToolkit is open source software.
5
+
6
+ from flask import request, jsonify, render_template
7
+ from flask.views import MethodView
8
+ from services.user_feedback_service import UserFeedbackService
9
+ from common.auth import IAuthentication
10
+ from injector import inject
11
+ import logging
12
+
13
+
14
+ class UserFeedbackView(MethodView):
15
+ @inject
16
+ def __init__(self,
17
+ iauthentication: IAuthentication,
18
+ user_feedback_service: UserFeedbackService ):
19
+ self.iauthentication = iauthentication
20
+ self.user_feedback_service = user_feedback_service
21
+
22
+ def post(self, company_short_name):
23
+ data = request.get_json()
24
+ if not data:
25
+ return jsonify({"error_message": "Cuerpo de la solicitud JSON inválido o faltante"}), 400
26
+
27
+ # get access credentials
28
+ iaut = self.iauthentication.verify(company_short_name, data.get("external_user_id"))
29
+ if not iaut.get("success"):
30
+ return jsonify(iaut), 401
31
+
32
+ message = data.get("message")
33
+ if not message:
34
+ return jsonify({"error_message": "Falta el mensaje de feedback"}), 400
35
+
36
+ space = data.get("space")
37
+ if not space:
38
+ return jsonify({"error_message": "Falta el espacio de Google Chat"}), 400
39
+
40
+ type = data.get("type")
41
+ if not type:
42
+ return jsonify({"error_message": "Falta el tipo de feedback"}), 400
43
+
44
+ rating = data.get("rating")
45
+ if not rating:
46
+ return jsonify({"error_message": "Falta la calificación"}), 400
47
+
48
+ external_user_id = data.get("external_user_id")
49
+ local_user_id = data.get("local_user_id", 0)
50
+
51
+ try:
52
+ response = self.user_feedback_service.new_feedback(
53
+ company_short_name=company_short_name,
54
+ message=message,
55
+ external_user_id=external_user_id,
56
+ local_user_id=local_user_id,
57
+ space=space,
58
+ type=type,
59
+ rating=rating
60
+ )
61
+
62
+ if "error" in response:
63
+ return {'error_message': response["error"]}, 402
64
+
65
+ return response, 200
66
+ except Exception as e:
67
+ logging.exception(
68
+ f"Error inesperado al procesar feedback para company {company_short_name}: {e}")
69
+ if local_user_id:
70
+ return render_template("error.html",
71
+ message="Ha ocurrido un error inesperado."), 500
72
+ else:
73
+ return jsonify({"error_message": str(e)}), 500
74
+
@@ -0,0 +1,55 @@
1
+ # Copyright (c) 2024 Fernando Libedinsky
2
+ # Product: IAToolkit
3
+ #
4
+ # IAToolkit is open source software.
5
+
6
+ from flask.views import MethodView
7
+ from flask import render_template
8
+ from services.profile_service import ProfileService
9
+ from itsdangerous import URLSafeTimedSerializer, SignatureExpired
10
+ from injector import inject
11
+ import os
12
+
13
+
14
+ class VerifyAccountView(MethodView):
15
+ @inject
16
+ def __init__(self, profile_service: ProfileService):
17
+ self.profile_service = profile_service
18
+ self.serializer = URLSafeTimedSerializer(os.getenv("USER_VERIF_KEY"))
19
+
20
+ def get(self, company_short_name: str, token: str):
21
+ # get company info
22
+ company = self.profile_service.get_company_by_short_name(company_short_name)
23
+ if not company:
24
+ return render_template('error.html', message="Empresa no encontrada"), 404
25
+
26
+ try:
27
+ # decode the token from the URL
28
+ email = self.serializer.loads(token, salt='email-confirm', max_age=3600*5)
29
+ except SignatureExpired:
30
+ return render_template('signup.html',
31
+ company=company,
32
+ company_short_name=company_short_name,
33
+ token=token,
34
+ alert_message="El enlace de verificación ha expirado. Por favor, solicita uno nuevo."), 400
35
+
36
+ try:
37
+ response = self.profile_service.verify_account(email)
38
+ if "error" in response:
39
+ return render_template(
40
+ 'signup.html',
41
+ company=company,
42
+ company_short_name=company_short_name,
43
+ token=token,
44
+ alert_message=response["error"]), 400
45
+
46
+ return render_template('login.html',
47
+ company=company,
48
+ company_short_name=company_short_name,
49
+ alert_icon='success',
50
+ alert_message=response['message'])
51
+ except Exception as e:
52
+ return render_template("error.html",
53
+ company=company,
54
+ company_short_name=company_short_name,
55
+ message="Ha ocurrido un error inesperado."), 500
@@ -1,30 +0,0 @@
1
- iatoolkit/__init__.py,sha256=GkFxAQHKPifz4Kd8M73Rc8TWRVIxjxkl1N0nsPvb_sU,1743
2
- iatoolkit/base_company.py,sha256=WmD4o0qFC1n5DW5eRsRsuNfaGot9nxGFcJe3LmibSuE,4259
3
- iatoolkit/cli_commands.py,sha256=BGuThg19eoSssrBJIqzBNaWpMmyy7u4yRUz0JA7d-vc,2270
4
- iatoolkit/company_registry.py,sha256=tduqt3oV8iDX_IB1eA7KIgvIxE4edTcy-3qZIXh3Lzw,2549
5
- iatoolkit/iatoolkit.py,sha256=0q6P0QHDHD_d_KEqvcKpbDXRGIoWLZgBhHTD0zdFRJY,15748
6
- iatoolkit/system_prompts/format_styles.prompt,sha256=MSMe1qvR3cF_0IbFshn8R0z6Wx6VCHQq1p37rpu5wwk,3576
7
- iatoolkit/system_prompts/query_main.prompt,sha256=w_9ybgWgiQH4V_RbAXqsvz0M7oOuiyhxcwf-D0CgfA4,3017
8
- iatoolkit/system_prompts/sql_rules.prompt,sha256=y4nURVnb9AyFwt-lrbMNBHHtZlhk6kC9grYoOhRnrJo,59174
9
- services/__init__.py,sha256=5JqK9sZ6jBuK83zDQokUhxQ0wuJJJ9DXB8pYCLkX7X4,102
10
- services/benchmark_service.py,sha256=_ruKh9YzrTLtR0ZKrRNxqJQW0HdbwWuFz1gfLzJ9owA,5850
11
- services/dispatcher_service.py,sha256=y2J-TfrkoCcsOESr3E6E3q5bleJfRibT4ONxs9AxUSg,13959
12
- services/document_service.py,sha256=8MsJz0pihM9E9Z92PrPqDgQnpMAmpFrbogXr5HscMWM,5926
13
- services/excel_service.py,sha256=ATPaeAvkLwQAkPZ3AKIUpO73RVyRg0D8c6i37_mcql0,3559
14
- services/file_processor_service.py,sha256=98yWYF7nIq1nm7nh6IzMmTKaOMTIeqCFWYwXVtV-ZJI,4102
15
- services/history_service.py,sha256=j0QCqcIIyw7DBy3GrZrEZNk0I4m-uuRoG5g0Z2RCcOE,1586
16
- services/jwt_service.py,sha256=YoZ9h7_o9xBko-arNQv4MbcwnxoSWVNj4VbZmMo_QGY,3908
17
- services/load_documents_service.py,sha256=UGfomYz7seWFXawbDuk2t6CyoEr1vggR8vmrCUAeLBg,7190
18
- services/mail_service.py,sha256=_67pctxZO46DHnWBip51ayuYtWd4bEoS1kg29ACO7_I,2162
19
- services/profile_service.py,sha256=vTK9TvH_2AFdqgL3sGjhck9LyLGIbvdC2USoaRx82G8,17561
20
- services/prompt_manager_service.py,sha256=7SMC6N_T4BP4m5-ZNYAL3Y2YWHwl1bytXSgnEqu5bWI,8301
21
- services/query_service.py,sha256=gvUnq0Vpn4gv5ycQk8-fklh7NDFIXpO1Vt1lT2ugO6Q,15283
22
- services/search_service.py,sha256=bB3FWFxJi1iYsOdBxyu9tzIO406nQxcyeQzEowpmpjY,1803
23
- services/sql_service.py,sha256=s84K1ADlvMtum949wgMh8jsmqlOUeL-m_SWfAM4Wsv4,2141
24
- services/tasks_service.py,sha256=1DdbERlAxIkCpGEylnHDKC-KAsXRJugbaRSzRbPfL58,6790
25
- services/user_feedback_service.py,sha256=_LeNBYz4hHFapXfYTQVfkkD34gE8j2UeKnyOZ8H0nWo,2442
26
- services/user_session_context_service.py,sha256=GluNSgqP6W_hFke4oslSnfGnU_b-ph28BHH6jf3EIm0,3797
27
- iatoolkit-0.7.4.dist-info/METADATA,sha256=TCwvfWjnFKTqpAjPbIXF0Q4haWHAORKU0ecnVjMxG54,9300
28
- iatoolkit-0.7.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
29
- iatoolkit-0.7.4.dist-info/top_level.txt,sha256=dqlBbmgo9okD9d_WMR9uYzdup7Rxgj26yFF85jRGeu4,19
30
- iatoolkit-0.7.4.dist-info/RECORD,,
@@ -1,2 +0,0 @@
1
- iatoolkit
2
- services