iatoolkit 0.66.2__tar.gz → 0.66.8__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (125) hide show
  1. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/PKG-INFO +1 -1
  2. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/pyproject.toml +1 -1
  3. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/common/session_manager.py +2 -0
  4. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/iatoolkit.py +1 -1
  5. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/locales/en.yaml +23 -0
  6. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/locales/es.yaml +25 -2
  7. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/repositories/database_manager.py +3 -3
  8. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/repositories/document_repo.py +1 -1
  9. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/services/auth_service.py +2 -2
  10. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/services/branding_service.py +1 -2
  11. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/services/dispatcher_service.py +8 -9
  12. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/services/document_service.py +5 -2
  13. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/services/excel_service.py +15 -11
  14. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/services/file_processor_service.py +4 -12
  15. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/services/help_content_service.py +1 -1
  16. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/services/history_service.py +8 -7
  17. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/services/i18n_service.py +4 -4
  18. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/services/jwt_service.py +7 -9
  19. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/services/language_service.py +22 -20
  20. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/services/load_documents_service.py +4 -4
  21. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/services/mail_service.py +9 -4
  22. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/services/profile_service.py +7 -7
  23. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/services/prompt_manager_service.py +20 -16
  24. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/services/query_service.py +15 -14
  25. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/services/sql_service.py +6 -2
  26. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/services/user_feedback_service.py +15 -13
  27. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/static/js/chat_history_button.js +3 -5
  28. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/static/js/chat_main.js +2 -17
  29. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/static/styles/chat_iatoolkit.css +69 -158
  30. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/static/styles/chat_modal.css +1 -37
  31. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/templates/chat.html +11 -4
  32. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/templates/chat_modals.html +3 -0
  33. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/templates/login_simulation.html +16 -5
  34. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/views/help_content_api_view.py +1 -1
  35. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/views/history_api_view.py +1 -1
  36. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/views/init_context_api_view.py +1 -1
  37. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/views/llmquery_api_view.py +1 -1
  38. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/views/login_simulation_view.py +14 -2
  39. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/views/verify_user_view.py +1 -1
  40. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit.egg-info/PKG-INFO +1 -1
  41. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/readme.md +0 -0
  42. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/requirements.txt +0 -0
  43. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/setup.cfg +0 -0
  44. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/__init__.py +0 -0
  45. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/base_company.py +0 -0
  46. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/cli_commands.py +0 -0
  47. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/common/__init__.py +0 -0
  48. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/common/exceptions.py +0 -0
  49. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/common/routes.py +0 -0
  50. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/common/util.py +0 -0
  51. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/company_registry.py +0 -0
  52. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/infra/__init__.py +0 -0
  53. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/infra/call_service.py +0 -0
  54. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/infra/connectors/__init__.py +0 -0
  55. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/infra/connectors/file_connector.py +0 -0
  56. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/infra/connectors/file_connector_factory.py +0 -0
  57. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/infra/connectors/google_cloud_storage_connector.py +0 -0
  58. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/infra/connectors/google_drive_connector.py +0 -0
  59. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/infra/connectors/local_file_connector.py +0 -0
  60. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/infra/connectors/s3_connector.py +0 -0
  61. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/infra/gemini_adapter.py +0 -0
  62. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/infra/google_chat_app.py +0 -0
  63. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/infra/llm_client.py +0 -0
  64. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/infra/llm_proxy.py +0 -0
  65. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/infra/llm_response.py +0 -0
  66. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/infra/mail_app.py +0 -0
  67. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/infra/openai_adapter.py +0 -0
  68. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/infra/redis_session_manager.py +0 -0
  69. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/repositories/__init__.py +0 -0
  70. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/repositories/llm_query_repo.py +0 -0
  71. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/repositories/models.py +0 -0
  72. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/repositories/profile_repo.py +0 -0
  73. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/repositories/tasks_repo.py +0 -0
  74. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/repositories/vs_repo.py +0 -0
  75. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/services/__init__.py +0 -0
  76. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/services/benchmark_service.py +0 -0
  77. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/services/onboarding_service.py +0 -0
  78. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/services/search_service.py +0 -0
  79. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/services/tasks_service.py +0 -0
  80. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/services/user_session_context_service.py +0 -0
  81. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/static/images/fernando.jpeg +0 -0
  82. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/static/js/chat_feedback_button.js +0 -0
  83. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/static/js/chat_filepond.js +0 -0
  84. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/static/js/chat_help_content.js +0 -0
  85. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/static/js/chat_logout_button.js +0 -0
  86. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/static/js/chat_onboarding_button.js +0 -0
  87. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/static/js/chat_prompt_manager.js +0 -0
  88. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/static/js/chat_reload_button.js +0 -0
  89. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/static/styles/chat_public.css +0 -0
  90. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/static/styles/landing_page.css +0 -0
  91. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/static/styles/llm_output.css +0 -0
  92. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/static/styles/onboarding.css +0 -0
  93. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/system_prompts/format_styles.prompt +0 -0
  94. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/system_prompts/query_main.prompt +0 -0
  95. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/system_prompts/sql_rules.prompt +0 -0
  96. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/templates/_company_header.html +0 -0
  97. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/templates/_login_widget.html +0 -0
  98. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/templates/about.html +0 -0
  99. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/templates/base.html +0 -0
  100. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/templates/change_password.html +0 -0
  101. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/templates/error.html +0 -0
  102. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/templates/forgot_password.html +0 -0
  103. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/templates/index.html +0 -0
  104. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/templates/onboarding_shell.html +0 -0
  105. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/templates/signup.html +0 -0
  106. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/views/__init__.py +0 -0
  107. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/views/base_login_view.py +0 -0
  108. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/views/change_password_view.py +0 -0
  109. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/views/external_login_view.py +0 -0
  110. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/views/file_store_api_view.py +0 -0
  111. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/views/forgot_password_view.py +0 -0
  112. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/views/home_view.py +0 -0
  113. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/views/index_view.py +0 -0
  114. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/views/login_view.py +0 -0
  115. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/views/logout_api_view.py +0 -0
  116. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/views/profile_api_view.py +0 -0
  117. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/views/prompt_api_view.py +0 -0
  118. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/views/signup_view.py +0 -0
  119. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/views/tasks_api_view.py +0 -0
  120. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/views/tasks_review_api_view.py +0 -0
  121. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit/views/user_feedback_api_view.py +0 -0
  122. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit.egg-info/SOURCES.txt +0 -0
  123. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit.egg-info/dependency_links.txt +0 -0
  124. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit.egg-info/requires.txt +0 -0
  125. {iatoolkit-0.66.2 → iatoolkit-0.66.8}/src/iatoolkit.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: iatoolkit
3
- Version: 0.66.2
3
+ Version: 0.66.8
4
4
  Summary: IAToolkit
5
5
  Author: Fernando Libedinsky
6
6
  License-Expression: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "iatoolkit"
7
- version = "0.66.2"
7
+ version = "0.66.8"
8
8
  requires-python = ">=3.12"
9
9
  description = "IAToolkit"
10
10
  readme = "readme.md"
@@ -3,6 +3,8 @@
3
3
  #
4
4
  # IAToolkit is open source software.
5
5
 
6
+ # This is the Flask connected session manager for IAToolkit
7
+
6
8
  from flask import session
7
9
 
8
10
  class SessionManager:
@@ -19,7 +19,7 @@ from werkzeug.middleware.proxy_fix import ProxyFix
19
19
  from injector import Binder, Injector, singleton
20
20
  from importlib.metadata import version as _pkg_version, PackageNotFoundError
21
21
 
22
- IATOOLKIT_VERSION = "0.66.2"
22
+ IATOOLKIT_VERSION = "0.66.8"
23
23
 
24
24
  # global variable for the unique instance of IAToolkit
25
25
  _iatoolkit_instance: Optional['IAToolkit'] = None
@@ -77,6 +77,8 @@ ui:
77
77
  stop: "Stop"
78
78
 
79
79
  errors:
80
+ company_not_found: "The company {company_short_name} does not exist."
81
+ timeout: "timeout expired."
80
82
  auth:
81
83
  invalid_password: "The provided password is incorrect."
82
84
  user_not_found: "A user with that email address was not found."
@@ -115,9 +117,29 @@ errors:
115
117
  password_no_digit: "Password must contain at least one number."
116
118
  password_no_special_char: "Password must contain at least one special character."
117
119
 
120
+ services:
121
+ no_text_file: "The file is not text or the encoding is not UTF-8"
122
+ no_output_file: "Missing output file name"
123
+ no_data_for_excel: "Missing data or it is not a list of dictionaries"
124
+ no_download_directory: "Temporary directory for saving Excel files is not configured"
125
+ cannot_create_excel: "Could not create the Excel file"
126
+ invalid_filename: "Invalid filename"
127
+ file_not_exist: "File not found"
128
+ path_is_not_a_file: "The path does not correspond to a file"
129
+ file_validation_error: "Error validating file"
130
+ user_not_authorized: "user is not authorized for this company"
131
+ account_not_verified: "Your account has not been verified. Please check your email."
132
+ missing_response_id: "Can not found 'previous_response_id' for '{company_short_name}/{user_identifier}'. Reinit context"
133
+
134
+
118
135
  api_responses:
119
136
  context_reloaded_success: "The context has been successfully reloaded."
120
137
 
138
+ services:
139
+ mail_sent: "Email sent successfully."
140
+ start_query: "Hello, what can I help you with today?"
141
+
142
+
121
143
  flash_messages:
122
144
  password_changed_success: "Your password has been successfully reset. You can now log in."
123
145
  login_required: "Please log in to continue."
@@ -142,3 +164,4 @@ js_messages:
142
164
  unknown_server_error: "Unknown server error."
143
165
  loading: "Loading..."
144
166
  reload_init: "init reloading context in background..."
167
+ no_history_found: "No query history found."
@@ -73,6 +73,10 @@
73
73
  stop: "Detener"
74
74
 
75
75
  errors:
76
+ company_not_found: "La empresa {company_short_name} no existe."
77
+ timeout: "El tiempo de espera ha expirado."
78
+
79
+
76
80
  auth:
77
81
  invalid_password: "La contraseña proporcionada es incorrecta."
78
82
  user_not_found: "No se encontró un usuario con ese correo."
@@ -84,11 +88,11 @@
84
88
  templates:
85
89
  company_not_found: "Empresa no encontrada."
86
90
  home_template_not_found: "La plantilla de la página de inicio para la empresa '{company_name}' no está configurada."
91
+ processing_error: "Error al procesar el template: {error}"
87
92
  template_not_found: "No se encontro el template: '{template_name}'."
88
- processing_error: "Ocurrió un error al procesar la plantilla personalizada de la página de inicio: {error}"
89
93
 
90
94
  general:
91
- unexpected_error: "Ha ocurrido un error inesperado. Por favor, contacta a soporte."
95
+ unexpected_error: "Ha ocurrido un error inesperado: {error}."
92
96
  unsupported_language: "El idioma seleccionado no es válido."
93
97
  signup:
94
98
  company_not_found: "La empresa {company_name} no existe."
@@ -111,9 +115,27 @@
111
115
  password_no_digit: "La contraseña debe tener al menos un número."
112
116
  password_no_special_char: "La contraseña debe tener al menos un carácter especial."
113
117
 
118
+ services:
119
+ no_text_file: "El archivo no es texto o la codificación no es UTF-8"
120
+ no_output_file: "falta el nombre del archivo de salida"
121
+ no_data_for_excel: "faltan los datos o no es una lista de diccionarios"
122
+ no_download_directory: "no esta configurado el directorio temporal para guardar excels"
123
+ cannot_create_excel: "no se pudo crear el archivo excel"
124
+ invalid_filename: "Nombre de archivo inválido"
125
+ file_not_exist : "Archivo no encontrado"
126
+ path_is_not_a_file : "La ruta no corresponde a un archivo"
127
+ file_validation_error : "Error validando archivo"
128
+ user_not_authorized: "Usuario no esta autorizado para esta empresa"
129
+ account_not_verified: "Tu cuenta no ha sido verificada. Por favor, revisa tu correo."
130
+ missing_response_id: "No se encontró 'previous_response_id' para '{company_short_name}/{user_identifier}'. Reinicia el contexto."
131
+
114
132
  api_responses:
115
133
  context_reloaded_success: "El contexto se ha recargado con éxito."
116
134
 
135
+ services:
136
+ mail_sent: "mail enviado exitosamente."
137
+ start_query: "Hola, cual es tu pregunta?"
138
+
117
139
  flash_messages:
118
140
  password_changed_success: "Tu contraseña ha sido restablecida exitosamente. Ahora puedes iniciar sesión."
119
141
  signup_success: "Registro exitoso. Por favor, revisa tu correo para verificar tu cuenta."
@@ -137,4 +159,5 @@
137
159
  unknown_server_error: "Error desconocido del servidor."
138
160
  loading: "Cargando..."
139
161
  reload_init: "Iniciando recarga de contexto en segundo plano..."
162
+ no_history_found: "No existe historial de consultas."
140
163
 
@@ -27,8 +27,8 @@ class DatabaseManager:
27
27
  self._engine = create_engine(
28
28
  database_url,
29
29
  echo=False,
30
- pool_size=2, # per worker
31
- max_overflow=3,
30
+ pool_size=10, # per worker
31
+ max_overflow=20,
32
32
  pool_timeout=30,
33
33
  pool_recycle=1800,
34
34
  pool_pre_ping=True,
@@ -77,7 +77,7 @@ class DatabaseManager:
77
77
  inspector = inspect(self._engine)
78
78
 
79
79
  if table_name not in inspector.get_table_names():
80
- raise RuntimeError(f"La tabla '{table_name}' no existe en la BD.")
80
+ raise RuntimeError(f"Table '{table_name}' does not exist.")
81
81
 
82
82
  if exclude_columns is None:
83
83
  exclude_columns = []
@@ -22,7 +22,7 @@ class DocumentRepo:
22
22
  def get(self, company_id, filename: str ) -> Document:
23
23
  if not company_id or not filename:
24
24
  raise IAToolkitException(IAToolkitException.ErrorType.PARAM_NOT_FILLED,
25
- 'Falta empresa o filename')
25
+ 'missing company_id or filename')
26
26
 
27
27
  return self.session.query(Document).filter_by(company_id=company_id, filename=filename).first()
28
28
 
@@ -84,7 +84,7 @@ class AuthService:
84
84
  )
85
85
  return {'success': True, 'user_identifier': user_identifier}
86
86
  except Exception as e:
87
- logging.error(f"Error al crear la sesión desde token para {user_identifier}: {e}")
87
+ logging.error(f"error creeating session for Token of {user_identifier}: {e}")
88
88
  self.log_access(
89
89
  company_short_name=company_short_name,
90
90
  auth_type='redeem_token',
@@ -189,5 +189,5 @@ class AuthService:
189
189
  session.commit()
190
190
 
191
191
  except Exception as e:
192
- logging.error(f"Fallo al escribir en AccessLog: {e}", exc_info=False)
192
+ logging.error(f"error writting to AccessLog: {e}", exc_info=False)
193
193
  session.rollback()
@@ -9,9 +9,8 @@ from injector import inject
9
9
 
10
10
  class BrandingService:
11
11
  """
12
- Servicio centralizado que gestiona la configuración de branding.
12
+ Branding configuration for IAToolkit
13
13
  """
14
-
15
14
  @inject
16
15
  def __init__(self):
17
16
  """
@@ -149,7 +149,7 @@ class Dispatcher:
149
149
  except Exception as e:
150
150
  logging.exception(e)
151
151
  raise IAToolkitException(IAToolkitException.ErrorType.EXTERNAL_SOURCE_ERROR,
152
- f"Error en get_company_context de {company_name}: {str(e)}") from e
152
+ f"Error getting company context of: {company_name}: {str(e)}") from e
153
153
 
154
154
  def get_company_services(self, company: Company) -> list[dict]:
155
155
  # create the syntax with openai response syntax, for the company function list
@@ -173,7 +173,7 @@ class Dispatcher:
173
173
  def get_user_info(self, company_name: str, user_identifier: str) -> dict:
174
174
  if company_name not in self.company_instances:
175
175
  raise IAToolkitException(IAToolkitException.ErrorType.EXTERNAL_SOURCE_ERROR,
176
- f"Empresa no configurada: {company_name}")
176
+ f"company not configured: {company_name}")
177
177
 
178
178
  # source 2: external company user
179
179
  company_instance = self.company_instances[company_name]
@@ -182,14 +182,14 @@ class Dispatcher:
182
182
  except Exception as e:
183
183
  logging.exception(e)
184
184
  raise IAToolkitException(IAToolkitException.ErrorType.EXTERNAL_SOURCE_ERROR,
185
- f"Error en get_user_info de {company_name}: {str(e)}") from e
185
+ f"Error in get_user_info: {company_name}: {str(e)}") from e
186
186
 
187
187
  return external_user_profile
188
188
 
189
189
  def get_metadata_from_filename(self, company_name: str, filename: str) -> dict:
190
190
  if company_name not in self.company_instances:
191
191
  raise IAToolkitException(IAToolkitException.ErrorType.EXTERNAL_SOURCE_ERROR,
192
- f"Empresa no configurada: {company_name}")
192
+ f"company not configured: {company_name}")
193
193
 
194
194
  company_instance = self.company_instances[company_name]
195
195
  try:
@@ -197,7 +197,7 @@ class Dispatcher:
197
197
  except Exception as e:
198
198
  logging.exception(e)
199
199
  raise IAToolkitException(IAToolkitException.ErrorType.EXTERNAL_SOURCE_ERROR,
200
- f"Error en get_metadata_from_filename de {company_name}: {str(e)}") from e
200
+ f"Error in get_metadata_from_filename: {company_name}: {str(e)}") from e
201
201
 
202
202
  def get_company_instance(self, company_name: str):
203
203
  """Returns the instance for a given company name."""
@@ -207,12 +207,11 @@ class Dispatcher:
207
207
 
208
208
  # iatoolkit system prompts
209
209
  _SYSTEM_PROMPT = [
210
- {'name': 'query_main', 'description':'main prompt de iatoolkit'},
211
- {'name': 'format_styles', 'description':'formatos y estilos de salida'},
212
- {'name': 'sql_rules', 'description':'instrucciones para generar sql'}
210
+ {'name': 'query_main', 'description':'iatoolkit main prompt'},
211
+ {'name': 'format_styles', 'description':'output format styles'},
212
+ {'name': 'sql_rules', 'description':'instructions for SQL queries'}
213
213
  ]
214
214
 
215
-
216
215
  # iatoolkit function calls
217
216
  _FUNCTION_LIST = [
218
217
  {
@@ -11,10 +11,13 @@ import os
11
11
  import pytesseract
12
12
  from injector import inject
13
13
  from iatoolkit.common.exceptions import IAToolkitException
14
+ from iatoolkit.services.i18n_service import I18nService
14
15
 
15
16
  class DocumentService:
16
17
  @inject
17
- def __init__(self):
18
+ def __init__(self, i18n_service: I18nService):
19
+ self.i18n_service = i18n_service
20
+
18
21
  # max number of pages to load
19
22
  self.max_doc_pages = int(os.getenv("MAX_DOC_PAGES", "200"))
20
23
 
@@ -29,7 +32,7 @@ class DocumentService:
29
32
  file_content = file_content.decode('utf-8')
30
33
  except UnicodeDecodeError:
31
34
  raise IAToolkitException(IAToolkitException.ErrorType.FILE_FORMAT_ERROR,
32
- "El archivo no es texto o la codificación no es UTF-8")
35
+ self.i18n_service.t('errors.services.no_text_file'))
33
36
 
34
37
  return file_content
35
38
  elif filename.lower().endswith('.pdf'):
@@ -8,6 +8,7 @@ import pandas as pd
8
8
  from uuid import uuid4
9
9
  from pathlib import Path
10
10
  from iatoolkit.common.exceptions import IAToolkitException
11
+ from iatoolkit.services.i18n_service import I18nService
11
12
  from injector import inject
12
13
  import os
13
14
  import logging
@@ -18,8 +19,11 @@ EXCEL_MIME = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
18
19
 
19
20
  class ExcelService:
20
21
  @inject
21
- def __init__(self,util: Utility):
22
+ def __init__(self,
23
+ util: Utility,
24
+ i18n_service: I18nService):
22
25
  self.util = util
26
+ self.i18n_service = i18n_service
23
27
 
24
28
  def excel_generator(self, **kwargs) -> str:
25
29
  """
@@ -42,11 +46,11 @@ class ExcelService:
42
46
  # get the parameters
43
47
  fname = kwargs.get('filename')
44
48
  if not fname:
45
- return 'falta el nombre del archivo de salida'
49
+ return self.i18n_service.t('errors.services.no_output_file')
46
50
 
47
51
  data = kwargs.get('data')
48
52
  if not data or not isinstance(data, list):
49
- return 'faltan los datos o no es una lista de diccionarios'
53
+ return self.i18n_service.t('errors.services.no_data_for_excel')
50
54
 
51
55
  sheet_name = kwargs.get('sheet_name', 'hoja 1')
52
56
 
@@ -58,7 +62,7 @@ class ExcelService:
58
62
 
59
63
  # 4. check that download directory is configured
60
64
  if 'IATOOLKIT_DOWNLOAD_DIR' not in current_app.config:
61
- return 'no esta configurado el directorio temporal para guardar excels'
65
+ return self.i18n_service.t('errors.services.no_download_directory')
62
66
 
63
67
  download_dir = current_app.config['IATOOLKIT_DOWNLOAD_DIR']
64
68
  filepath = Path(download_dir) / token
@@ -77,28 +81,28 @@ class ExcelService:
77
81
 
78
82
  except Exception as e:
79
83
  raise IAToolkitException(IAToolkitException.ErrorType.CALL_ERROR,
80
- 'error generating excel file') from e
84
+ self.i18n_service.t('errors.services.cannot_create_excel')) from e
81
85
 
82
86
  def validate_file_access(self, filename):
83
87
  try:
84
88
  if not filename:
85
- return jsonify({"error": "Nombre de archivo inválido"})
89
+ return jsonify({"error": self.i18n_service.t('errors.services.invalid_filename')})
86
90
  # Prevent path traversal attacks
87
91
  if '..' in filename or filename.startswith('/') or '\\' in filename:
88
- return jsonify({"error": "Nombre de archivo inválido"})
92
+ return jsonify({"error": self.i18n_service.t('errors.services.invalid_filename')})
89
93
 
90
94
  temp_dir = os.path.join(current_app.root_path, 'static', 'temp')
91
95
  file_path = os.path.join(temp_dir, filename)
92
96
 
93
97
  if not os.path.exists(file_path):
94
- return jsonify({"error": "Archivo no encontrado"})
98
+ return jsonify({"error": self.i18n_service.t('errors.services.file_not_exist')})
95
99
 
96
100
  if not os.path.isfile(file_path):
97
- return jsonify({"error": "La ruta no corresponde a un archivo"})
101
+ return jsonify({"error": self.i18n_service.t('errors.services.path_is_not_a_file')})
98
102
 
99
103
  return None
100
104
 
101
105
  except Exception as e:
102
- error_msg = f"Error validando acceso al archivo {filename}: {str(e)}"
106
+ error_msg = f"File validation error {filename}: {str(e)}"
103
107
  logging.error(error_msg)
104
- return jsonify({"error": "Error validando archivo"})
108
+ return jsonify({"error": self.i18n_service.t('errors.services.file_validation_error')})
@@ -52,27 +52,19 @@ class FileProcessor:
52
52
  logger: Optional[logging.Logger] = None):
53
53
  self.connector = connector
54
54
  self.config = config
55
- self.logger = logger or self._setup_logger()
56
55
  self.processed_files = 0
57
56
 
58
- def _setup_logger(self):
59
- logging.basicConfig(
60
- filename=self.config.log_file,
61
- level=logging.INFO,
62
- format='%(asctime)s - %(levelname)s - %(message)s'
63
- )
64
- return logging.getLogger(__name__)
65
57
 
66
58
  def process_files(self):
67
59
  # Fetches files from the connector, filters them, and processes them.
68
60
  try:
69
61
  files = self.connector.list_files()
70
62
  except Exception as e:
71
- self.logger.error(f"Error fetching files: {e}")
63
+ logging.error(f"Error fetching files: {e}")
72
64
  return False
73
65
 
74
66
  if self.config.echo:
75
- print(f'cargando un total de {len(files)} archivos')
67
+ print(f'loading {len(files)} files')
76
68
 
77
69
  for file_info in files:
78
70
  file_path = file_info['path']
@@ -95,10 +87,10 @@ class FileProcessor:
95
87
  context=self.config.context)
96
88
  self.processed_files += 1
97
89
 
98
- self.logger.info(f"Successfully processed file: {file_path}")
90
+ logging.info(f"Successfully processed file: {file_path}")
99
91
 
100
92
  except Exception as e:
101
- self.logger.error(f"Error processing {file_path}: {e}")
93
+ logging.error(f"Error processing {file_path}: {e}")
102
94
  if not self.config.continue_on_error:
103
95
  raise e
104
96
 
@@ -27,4 +27,4 @@ class HelpContentService:
27
27
  except Exception as e:
28
28
  logging.exception(e)
29
29
  raise IAToolkitException(IAToolkitException.ErrorType.CONFIG_ERROR,
30
- f"Error obteniendo help de {company_short_name}: {str(e)}") from e
30
+ f"Error getting help file for {company_short_name}: {str(e)}") from e
@@ -6,32 +6,33 @@
6
6
  from injector import inject
7
7
  from iatoolkit.repositories.llm_query_repo import LLMQueryRepo
8
8
  from iatoolkit.repositories.profile_repo import ProfileRepo
9
+ from iatoolkit.services.i18n_service import I18nService
10
+
9
11
 
10
12
 
11
13
  class HistoryService:
12
14
  @inject
13
15
  def __init__(self, llm_query_repo: LLMQueryRepo,
14
- profile_repo: ProfileRepo):
16
+ profile_repo: ProfileRepo,
17
+ i18n_service: I18nService):
15
18
  self.llm_query_repo = llm_query_repo
16
19
  self.profile_repo = profile_repo
20
+ self.i18n_service = i18n_service
17
21
 
18
22
  def get_history(self,
19
23
  company_short_name: str,
20
24
  user_identifier: str) -> dict:
21
25
  try:
22
- # validate company
23
26
  company = self.profile_repo.get_company_by_short_name(company_short_name)
24
27
  if not company:
25
- return {'error': f'No existe la empresa: {company_short_name}'}
28
+ return {"error": self.i18n_service.t('errors.company_not_found', company_short_name=company_short_name)}
26
29
 
27
30
  history = self.llm_query_repo.get_history(company, user_identifier)
28
-
29
31
  if not history:
30
- return {'message': 'Historial vacio actualmente', 'history': []}
32
+ return {'message': 'empty history', 'history': []}
31
33
 
32
34
  history_list = [query.to_dict() for query in history]
33
-
34
- return {'message': 'Historial obtenido correctamente', 'history': history_list}
35
+ return {'message': 'history loaded ok', 'history': history_list}
35
36
 
36
37
  except Exception as e:
37
38
  return {'error': str(e)}
@@ -1,11 +1,11 @@
1
1
  # iatoolkit/services/i18n_service.py
2
2
  import os
3
3
  import logging
4
- from injector import inject
4
+ from injector import inject, singleton
5
5
  from iatoolkit.common.util import Utility
6
6
  from iatoolkit.services.language_service import LanguageService
7
7
 
8
-
8
+ @singleton
9
9
  class I18nService:
10
10
  """
11
11
  Servicio centralizado para manejar la internacionalización (i18n).
@@ -27,7 +27,7 @@ class I18nService:
27
27
  """
28
28
  locales_dir = os.path.join(os.path.dirname(__file__), '..', 'locales')
29
29
  if not os.path.exists(locales_dir):
30
- logging.error("El directorio 'locales' no fue encontrado.")
30
+ logging.error("Directory 'locales' not found.")
31
31
  return
32
32
 
33
33
  for filename in os.listdir(locales_dir):
@@ -37,7 +37,7 @@ class I18nService:
37
37
  try:
38
38
  self.translations[lang_code] = self.util.load_schema_from_yaml(filepath)
39
39
  except Exception as e:
40
- logging.error(f"Fallo al cargar el archivo de traducción {filepath}: {e}")
40
+ logging.error(f"Error while loading the translation file {filepath}: {e}")
41
41
 
42
42
  def _get_nested_key(self, lang: str, key: str):
43
43
  """
@@ -20,8 +20,8 @@ class JWTService:
20
20
  self.secret_key = app.config['JWT_SECRET_KEY']
21
21
  self.algorithm = app.config['JWT_ALGORITHM']
22
22
  except KeyError as e:
23
- logging.error(f"Configuración JWT faltante en app.config: {e}. JWTService no funcionará correctamente.")
24
- raise RuntimeError(f"Configuración JWT esencial faltante: {e}")
23
+ logging.error(f"missing JWT configuration: {e}.")
24
+ raise RuntimeError(f"missing JWT configuration variables: {e}")
25
25
 
26
26
  def generate_chat_jwt(self,
27
27
  company_short_name: str,
@@ -58,25 +58,23 @@ class JWTService:
58
58
 
59
59
  # Validaciones adicionales
60
60
  if payload.get('type') != 'chat_session':
61
- logging.warning(f"Validación JWT fallida: tipo incorrecto '{payload.get('type')}'")
61
+ logging.warning(f"Invalid JWT type '{payload.get('type')}'")
62
62
  return None
63
63
 
64
64
  # user_identifier debe estar presente
65
65
  if not payload.get('user_identifier'):
66
- logging.warning(f"Validación JWT fallida: user_identifier ausente o vacío.")
66
+ logging.warning(f"missing user_identifier in JWT payload.")
67
67
  return None
68
68
 
69
69
  if not payload.get('company_short_name'):
70
- logging.warning(f"Validación JWT fallida: company_short_name ausente.")
70
+ logging.warning(f"missing company_short_name in JWT payload.")
71
71
  return None
72
72
 
73
- logging.debug(
74
- f"JWT validado exitosamente para company: {payload.get('company_short_name')}, user: {payload.get('external_user_id')}")
75
73
  return payload
76
74
 
77
75
  except jwt.InvalidTokenError as e:
78
- logging.warning(f"Validación JWT fallida: token inválido . Error: {e}")
76
+ logging.warning(f"Invalid JWT token:: {e}")
79
77
  return None
80
78
  except Exception as e:
81
- logging.error(f"Error inesperado durante validación de JWT : {e}")
79
+ logging.error(f"unexpected error during JWT validation: {e}")
82
80
  return None
@@ -1,12 +1,12 @@
1
1
  # iatoolkit/services/language_service.py
2
2
 
3
3
  import logging
4
- from injector import inject
4
+ from injector import inject, singleton
5
5
  from flask import g, request
6
6
  from iatoolkit.repositories.profile_repo import ProfileRepo
7
7
  from iatoolkit.common.session_manager import SessionManager
8
8
 
9
-
9
+ @singleton
10
10
  class LanguageService:
11
11
  """
12
12
  Determines the correct language for the current request
@@ -14,6 +14,8 @@ class LanguageService:
14
14
  and caches it in the Flask 'g' object for the request's lifecycle.
15
15
  """
16
16
 
17
+ FALLBACK_LANGUAGE = 'es'
18
+
17
19
  @inject
18
20
  def __init__(self, profile_repo: ProfileRepo):
19
21
  self.profile_repo = profile_repo
@@ -49,29 +51,29 @@ class LanguageService:
49
51
  if 'lang' in g:
50
52
  return g.lang
51
53
 
52
- from iatoolkit.services.i18n_service import I18nService
53
- lang = I18nService.FALLBACK_LANGUAGE
54
-
55
54
  try:
55
+ # Priority 1: User's preferred language
56
+ user_identifier = SessionManager.get('user_identifier')
57
+ if user_identifier:
58
+ user = self.profile_repo.get_user_by_email(user_identifier)
59
+ if user and user.preferred_language:
60
+ logging.debug(f"Language determined by user preference: {user.preferred_language}")
61
+ g.lang = user.preferred_language
62
+ return g.lang
63
+
64
+ # Priority 2: Company's default language
56
65
  company_short_name = self._get_company_short_name()
57
66
  if company_short_name:
58
- # Prioridad 1: Preferencia del Usuario
59
- user_identifier = SessionManager.get('user_identifier')
60
- if user_identifier:
61
- # Usamos el repositorio para obtener el objeto User
62
- user = self.profile_repo.get_user_by_email(
63
- user_identifier) # Asumiendo que el email es el identificador
64
- if user and user.preferred_language:
65
- g.lang = user.preferred_language
66
- return g.lang
67
-
68
- # Prioridad 2: Idioma por defecto de la Compañía (si no se encontró preferencia de usuario)
69
67
  company = self.profile_repo.get_company_by_short_name(company_short_name)
70
68
  if company and company.default_language:
71
- lang = company.default_language
69
+ logging.debug(f"Language determined by company default: {company.default_language}")
70
+ g.lang = company.default_language
71
+ return g.lang
72
72
  except Exception as e:
73
- logging.debug(f"Could not determine language, falling back to default. Reason: {e}")
73
+ logging.info(f"Could not determine language, falling back to default. Reason: {e}")
74
74
  pass
75
75
 
76
- g.lang = lang
77
- return lang
76
+ # Priority 3: System-wide fallback
77
+ logging.info(f"Language determined by system fallback: {self.FALLBACK_LANGUAGE}")
78
+ g.lang = self.FALLBACK_LANGUAGE
79
+ return g.lang
@@ -72,7 +72,7 @@ class LoadDocumentsService:
72
72
  """
73
73
  if not connector_config:
74
74
  raise IAToolkitException(IAToolkitException.ErrorType.MISSING_PARAMETER,
75
- f"Falta configurar conector")
75
+ f"Missing connector config")
76
76
 
77
77
  try:
78
78
  if not filters:
@@ -123,7 +123,7 @@ class LoadDocumentsService:
123
123
 
124
124
  if not company:
125
125
  raise IAToolkitException(IAToolkitException.ErrorType.MISSING_PARAMETER,
126
- f"Falta configurar empresa")
126
+ f"missing company")
127
127
 
128
128
  # check if file exist in repositories
129
129
  if self.doc_repo.get(company_id=company.id,filename=filename):
@@ -182,6 +182,6 @@ class LoadDocumentsService:
182
182
  self.doc_repo.session.rollback()
183
183
 
184
184
  # if something fails, throw exception
185
- logging.exception("Error procesando el archivo %s: %s", filename, str(e))
185
+ logging.exception("Error processing file %s: %s", filename, str(e))
186
186
  raise IAToolkitException(IAToolkitException.ErrorType.LOAD_DOCUMENT_ERROR,
187
- f"Error al procesar el archivo {filename}")
187
+ f"Error while processing file: {filename}")