iatoolkit 0.11.0__py3-none-any.whl → 0.71.2__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.
Files changed (122) hide show
  1. iatoolkit/__init__.py +2 -6
  2. iatoolkit/base_company.py +9 -29
  3. iatoolkit/cli_commands.py +1 -1
  4. iatoolkit/common/routes.py +96 -52
  5. iatoolkit/common/session_manager.py +2 -1
  6. iatoolkit/common/util.py +17 -27
  7. iatoolkit/company_registry.py +1 -2
  8. iatoolkit/iatoolkit.py +97 -53
  9. iatoolkit/infra/llm_client.py +15 -20
  10. iatoolkit/infra/llm_proxy.py +38 -10
  11. iatoolkit/infra/openai_adapter.py +1 -1
  12. iatoolkit/infra/redis_session_manager.py +48 -2
  13. iatoolkit/locales/en.yaml +167 -0
  14. iatoolkit/locales/es.yaml +163 -0
  15. iatoolkit/repositories/database_manager.py +23 -3
  16. iatoolkit/repositories/document_repo.py +1 -1
  17. iatoolkit/repositories/models.py +35 -10
  18. iatoolkit/repositories/profile_repo.py +3 -2
  19. iatoolkit/repositories/vs_repo.py +26 -20
  20. iatoolkit/services/auth_service.py +193 -0
  21. iatoolkit/services/branding_service.py +70 -25
  22. iatoolkit/services/company_context_service.py +155 -0
  23. iatoolkit/services/configuration_service.py +133 -0
  24. iatoolkit/services/dispatcher_service.py +80 -105
  25. iatoolkit/services/document_service.py +5 -2
  26. iatoolkit/services/embedding_service.py +146 -0
  27. iatoolkit/services/excel_service.py +30 -26
  28. iatoolkit/services/file_processor_service.py +4 -12
  29. iatoolkit/services/history_service.py +7 -16
  30. iatoolkit/services/i18n_service.py +104 -0
  31. iatoolkit/services/jwt_service.py +18 -29
  32. iatoolkit/services/language_service.py +83 -0
  33. iatoolkit/services/load_documents_service.py +100 -113
  34. iatoolkit/services/mail_service.py +9 -4
  35. iatoolkit/services/profile_service.py +152 -76
  36. iatoolkit/services/prompt_manager_service.py +20 -16
  37. iatoolkit/services/query_service.py +208 -96
  38. iatoolkit/services/search_service.py +11 -4
  39. iatoolkit/services/sql_service.py +57 -25
  40. iatoolkit/services/tasks_service.py +1 -1
  41. iatoolkit/services/user_feedback_service.py +72 -34
  42. iatoolkit/services/user_session_context_service.py +112 -54
  43. iatoolkit/static/images/fernando.jpeg +0 -0
  44. iatoolkit/static/js/chat_feedback_button.js +80 -0
  45. iatoolkit/static/js/chat_help_content.js +124 -0
  46. iatoolkit/static/js/chat_history_button.js +110 -0
  47. iatoolkit/static/js/chat_logout_button.js +36 -0
  48. iatoolkit/static/js/chat_main.js +135 -222
  49. iatoolkit/static/js/chat_onboarding_button.js +103 -0
  50. iatoolkit/static/js/chat_prompt_manager.js +94 -0
  51. iatoolkit/static/js/chat_reload_button.js +35 -0
  52. iatoolkit/static/styles/chat_iatoolkit.css +289 -210
  53. iatoolkit/static/styles/chat_modal.css +63 -77
  54. iatoolkit/static/styles/chat_public.css +107 -0
  55. iatoolkit/static/styles/landing_page.css +182 -0
  56. iatoolkit/static/styles/onboarding.css +176 -0
  57. iatoolkit/system_prompts/query_main.prompt +5 -22
  58. iatoolkit/templates/_company_header.html +20 -0
  59. iatoolkit/templates/_login_widget.html +42 -0
  60. iatoolkit/templates/base.html +40 -20
  61. iatoolkit/templates/change_password.html +57 -36
  62. iatoolkit/templates/chat.html +180 -86
  63. iatoolkit/templates/chat_modals.html +138 -68
  64. iatoolkit/templates/error.html +44 -8
  65. iatoolkit/templates/forgot_password.html +40 -23
  66. iatoolkit/templates/index.html +145 -0
  67. iatoolkit/templates/login_simulation.html +45 -0
  68. iatoolkit/templates/onboarding_shell.html +107 -0
  69. iatoolkit/templates/signup.html +63 -65
  70. iatoolkit/views/base_login_view.py +91 -0
  71. iatoolkit/views/change_password_view.py +56 -31
  72. iatoolkit/views/embedding_api_view.py +65 -0
  73. iatoolkit/views/external_login_view.py +61 -28
  74. iatoolkit/views/{file_store_view.py → file_store_api_view.py} +10 -3
  75. iatoolkit/views/forgot_password_view.py +27 -21
  76. iatoolkit/views/help_content_api_view.py +54 -0
  77. iatoolkit/views/history_api_view.py +56 -0
  78. iatoolkit/views/home_view.py +50 -23
  79. iatoolkit/views/index_view.py +14 -0
  80. iatoolkit/views/init_context_api_view.py +74 -0
  81. iatoolkit/views/llmquery_api_view.py +58 -0
  82. iatoolkit/views/login_simulation_view.py +93 -0
  83. iatoolkit/views/login_view.py +130 -37
  84. iatoolkit/views/logout_api_view.py +49 -0
  85. iatoolkit/views/profile_api_view.py +46 -0
  86. iatoolkit/views/{prompt_view.py → prompt_api_view.py} +10 -10
  87. iatoolkit/views/signup_view.py +41 -36
  88. iatoolkit/views/{tasks_view.py → tasks_api_view.py} +10 -36
  89. iatoolkit/views/tasks_review_api_view.py +55 -0
  90. iatoolkit/views/user_feedback_api_view.py +60 -0
  91. iatoolkit/views/verify_user_view.py +34 -29
  92. {iatoolkit-0.11.0.dist-info → iatoolkit-0.71.2.dist-info}/METADATA +41 -23
  93. iatoolkit-0.71.2.dist-info/RECORD +122 -0
  94. iatoolkit-0.71.2.dist-info/licenses/LICENSE +21 -0
  95. iatoolkit/common/auth.py +0 -200
  96. iatoolkit/static/images/arrow_up.png +0 -0
  97. iatoolkit/static/images/diagrama_iatoolkit.jpg +0 -0
  98. iatoolkit/static/images/logo_clinica.png +0 -0
  99. iatoolkit/static/images/logo_iatoolkit.png +0 -0
  100. iatoolkit/static/images/logo_maxxa.png +0 -0
  101. iatoolkit/static/images/logo_notaria.png +0 -0
  102. iatoolkit/static/images/logo_tarjeta.png +0 -0
  103. iatoolkit/static/images/logo_umayor.png +0 -0
  104. iatoolkit/static/images/upload.png +0 -0
  105. iatoolkit/static/js/chat_feedback.js +0 -115
  106. iatoolkit/static/js/chat_history.js +0 -117
  107. iatoolkit/static/styles/chat_info.css +0 -53
  108. iatoolkit/templates/header.html +0 -31
  109. iatoolkit/templates/home.html +0 -199
  110. iatoolkit/templates/login.html +0 -43
  111. iatoolkit/templates/test.html +0 -9
  112. iatoolkit/views/chat_token_request_view.py +0 -98
  113. iatoolkit/views/chat_view.py +0 -58
  114. iatoolkit/views/download_file_view.py +0 -58
  115. iatoolkit/views/external_chat_login_view.py +0 -95
  116. iatoolkit/views/history_view.py +0 -57
  117. iatoolkit/views/llmquery_view.py +0 -65
  118. iatoolkit/views/tasks_review_view.py +0 -83
  119. iatoolkit/views/user_feedback_view.py +0 -74
  120. iatoolkit-0.11.0.dist-info/RECORD +0 -110
  121. {iatoolkit-0.11.0.dist-info → iatoolkit-0.71.2.dist-info}/WHEEL +0 -0
  122. {iatoolkit-0.11.0.dist-info → iatoolkit-0.71.2.dist-info}/top_level.txt +0 -0
@@ -4,52 +4,57 @@
4
4
  # IAToolkit is open source software.
5
5
 
6
6
  from flask.views import MethodView
7
- from flask import render_template
7
+ from flask import render_template, url_for, redirect, session, flash
8
8
  from iatoolkit.services.profile_service import ProfileService
9
9
  from itsdangerous import URLSafeTimedSerializer, SignatureExpired
10
+ from iatoolkit.services.branding_service import BrandingService
11
+ from iatoolkit.services.i18n_service import I18nService
10
12
  from injector import inject
11
13
  import os
12
14
 
13
15
 
14
16
  class VerifyAccountView(MethodView):
15
17
  @inject
16
- def __init__(self, profile_service: ProfileService):
18
+ def __init__(self,
19
+ profile_service: ProfileService,
20
+ branding_service: BrandingService,
21
+ i18n_service: I18nService):
17
22
  self.profile_service = profile_service
23
+ self.branding_service = branding_service
24
+ self.i18n_service = i18n_service
18
25
  self.serializer = URLSafeTimedSerializer(os.getenv("USER_VERIF_KEY"))
19
26
 
20
27
  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
28
  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
29
+ # get company info
30
+ company = self.profile_service.get_company_by_short_name(company_short_name)
31
+ if not company:
32
+ return render_template('error.html',
33
+ message=self.i18n_service.t('errors.templates.company_not_found')), 404
34
+
35
+ branding_data = self.branding_service.get_company_branding(company_short_name)
36
+ try:
37
+ # decode the token from the URL
38
+ email = self.serializer.loads(token, salt='email-confirm', max_age=3600*5)
39
+ except SignatureExpired:
40
+ flash(self.i18n_service.t('errors.verification.token_expired'), 'error')
41
+ return render_template('signup.html',
42
+ company_short_name=company_short_name,
43
+ branding=branding_data,
44
+ token=token), 400
35
45
 
36
- try:
37
46
  response = self.profile_service.verify_account(email)
38
47
  if "error" in response:
48
+ flash(response["error"], 'error')
39
49
  return render_template(
40
50
  'signup.html',
41
- company=company,
42
51
  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'])
52
+ branding=branding_data,
53
+ token=token), 400
54
+
55
+ flash(response['message'], 'success')
56
+ return redirect(url_for('home', company_short_name=company_short_name))
57
+
51
58
  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
59
+ flash(self.i18n_service.t('errors.general.unexpected_error', error=str(e)), 'error')
60
+ return redirect(url_for('home', company_short_name=company_short_name))
@@ -1,11 +1,12 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: iatoolkit
3
- Version: 0.11.0
3
+ Version: 0.71.2
4
4
  Summary: IAToolkit
5
5
  Author: Fernando Libedinsky
6
6
  License-Expression: MIT
7
- Requires-Python: >=3.11
7
+ Requires-Python: >=3.12
8
8
  Description-Content-Type: text/markdown
9
+ License-File: LICENSE
9
10
  Requires-Dist: aiohappyeyeballs==2.4.4
10
11
  Requires-Dist: aiohttp==3.11.9
11
12
  Requires-Dist: aiosignal==1.3.1
@@ -206,47 +207,64 @@ Requires-Dist: wrapt==1.17.0
206
207
  Requires-Dist: yarl==1.18.3
207
208
  Requires-Dist: zipp==3.21.0
208
209
  Requires-Dist: zstandard==0.23.0
210
+ Dynamic: license-file
209
211
 
210
212
 
211
213
  <div align="center">
212
- <h1>IAToolkit</h1>
214
+ <h1>
215
+ IAToolkit
216
+ </h1>
217
+
213
218
  <p><strong>The Open-Source Framework for Building AI Chatbots on Your Private Data.</strong></p>
219
+ <h4>
220
+ <a href="https://www.iatoolkit.com" target="_blank" style="text-decoration: none; color: inherit;">
221
+ www.iatoolkit.com
222
+ </a>
223
+ </h4>
214
224
  </div>
215
225
 
216
- IAToolkit is a comprehensive, open-source framework designed for building enterprise-grade
217
- AI chatbots and conversational applications.
226
+ IAToolkit is a comprehensive, Python open-source framework designed for building enterprise-grade
227
+ AI chatbots and conversational applications. It bridges the gap between the power of
228
+ Large Language Models (LLMs) and the valuable,
229
+ private data locked within your organization's databases and documents.
230
+
218
231
  With IAToolkit, you can build production-ready, context-aware chatbots and agents that
219
232
  can query relational databases, perform semantic searches on documents,
220
233
  and connect to your internal APIs in minutes.
221
234
 
222
- IAToolkit bridges the gap between powerful LLMs and your company's data.
235
+ Create secure, branded chat interfaces that can reason over your data, answer questions, and execute custom business logic,
236
+ all powered by leading models from OpenAI, Google Gemini, and more.
223
237
 
224
238
 
225
239
  ## 🚀 Key Features
226
240
 
227
- * **🔗 Unified Data Connection**:
228
- * **Natural Language to SQL**: Let your chatbot query relational databases (PostgreSQL, MySQL, SQLite) using everyday language.
229
- * **Semantic Document Search**: Automatically chunk, embed, and search across your private documents (PDFs, Word, etc.) to provide contextually accurate answers.
241
+ * **🔗 Unified Data Connection**
242
+ * **Natural Language to SQL**: Let your chatbot query relational databases (PostgreSQL, MySQL, SQLite) using everyday language.
243
+ * **Semantic Document Search**: Automatically chunk, embed, and search across your private documents (PDFs, Word, etc.) to provide contextually accurate answers.
230
244
 
231
- * **🏢 Enterprise-Ready Multi-Tenancy**:
232
- * Deploy isolated "Company" modules, each with its own data, tools, and context. Perfect for SaaS products or internal departmental agents.
245
+ * **🏢 Enterprise-Ready Multi-Tenancy**
246
+ * Deploy isolated "Company" modules, each with its own data, tools, and context.
247
+ * Perfect for SaaS products or internal departmental agents.
233
248
 
234
- * **🧠 LLM Agnostic**:
235
- * Switch between **OpenAI (GPT-*)** and **Google (Gemini-*)** with a single line change in your configuration. No code refactoring needed.
249
+ * **🎨 Fully Brandable UI**
250
+ * Customize the look and feel for each "Company" with its own logos, colors, and even language settings (i18n).
251
+ * Provides a white-labeled experience for your users.
236
252
 
237
- * **🛠️ Developer-First Experience**:
238
- * Built with a clean, **Dependency Injection** architecture.
239
- * High-quality code base with **90%+ test coverage**.
240
- * Powerful Flask-based **CLI** for database setup, API key generation, and more.
253
+ * **🧠 LLM Agnostic**
254
+ * Switch between **OpenAI (GPT-*)** and **Google (Gemini-*)** with a single line change in your configuration.
255
+ * No code refactoring needed.
241
256
 
242
- * **🔒 Security & Observability Built-In**:
243
- * Comes with JWT-based authentication, user management, and secure session handling out of the box.
244
- * Full traceability with detailed logging of all queries, function calls, token usage, and costs.
257
+ * **🛠️ Developer-First Experience**
258
+ * Built with a clean **Dependency Injection** architecture.
259
+ * High-quality code base with **90%+ test coverage**.
245
260
 
246
- ## Quick Start: Create a Custom Tool in 30 Seconds
261
+ * **🔒 Security & Observability Built-In**
262
+ * Comes with integrated user authentication, API keys, and secure session handling out of the box.
263
+ * Full traceability with detailed logging of all queries, function calls, token usage, and costs.
264
+ ## ⚡ Quick Start: Try our 'hello world' example
247
265
 
248
- See how easy it is to give your AI a new skill. Just define a method inside your Company class and describe it.
249
- IAToolkit handles the rest.
266
+ Ready to see it in action? Our Quickstart Guide will walk you through downloading, configuring, and launching your first AI assistant in just a few minutes.
267
+ It's the best way to experience the toolkit's capabilities firsthand.
250
268
 
251
269
  ## 🤝 Contributing
252
270
 
@@ -0,0 +1,122 @@
1
+ iatoolkit/__init__.py,sha256=lWMmZiXzVqOAD2cnLZTjoX5_EMoDljjU7oAZTQbKu5c,951
2
+ iatoolkit/base_company.py,sha256=U0KWZf7zLrJCw87NrEt2MCCHfd78HS22D7ht_BLeoL0,3522
3
+ iatoolkit/cli_commands.py,sha256=bTn4iXiDM4P2Nyn6oPT2wCL4pUQy34hVTL6c4fyEQdY,2303
4
+ iatoolkit/company_registry.py,sha256=NAsrCJyvgkdG8yGfqA7EdPUTHDzzcPzKu0PKXniub50,2490
5
+ iatoolkit/iatoolkit.py,sha256=Z5aPSnKlepfqWqsChSju4aQVZttDI-hxUy1p0Eo1WIc,19439
6
+ iatoolkit/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
+ iatoolkit/common/exceptions.py,sha256=EXx40n5htp7UiOM6P1xfJ9U6NMcADqm62dlFaKz7ICU,1154
8
+ iatoolkit/common/routes.py,sha256=oFL8ivzenGpNgiDjV0pda_NRZ5XrlEHSIHPWW53zj8k,6529
9
+ iatoolkit/common/session_manager.py,sha256=OUYMzT8hN1U-NCUidR5tUAXB1drd8nYTOpo60rUNYeY,532
10
+ iatoolkit/common/util.py,sha256=lwMhQ2gT1DPzJ3mmL9xw3uobWJFIapAw50ks6mCvV60,15028
11
+ iatoolkit/infra/__init__.py,sha256=5JqK9sZ6jBuK83zDQokUhxQ0wuJJJ9DXB8pYCLkX7X4,102
12
+ iatoolkit/infra/call_service.py,sha256=iRk9VxbXaAwlLIl8fUzGDWIAdzwfsbs1MtP84YeENxg,4929
13
+ iatoolkit/infra/gemini_adapter.py,sha256=kXV-t5i9GmWBafUPX2kAyiqvcT7GPoxHylcCUWG_c_U,15051
14
+ iatoolkit/infra/google_chat_app.py,sha256=_uKWxeacHH6C5a4FVx0YZjBn1tL-x_MIQV9gqgWGAjo,1937
15
+ iatoolkit/infra/llm_client.py,sha256=Jt7CWX-RlBANvwnAuIIQscHPQVuWrxC8Jn7YjUuYs5A,18297
16
+ iatoolkit/infra/llm_proxy.py,sha256=TJti_mkdeFfsl4oGd5gTB7gaxF6bNG_rwqchkDiubw0,6933
17
+ iatoolkit/infra/llm_response.py,sha256=YUUQPBHzmP3Ce6-t0kKMRIpowvh7de1odSoefEByIvI,904
18
+ iatoolkit/infra/mail_app.py,sha256=PLGZdEs7LQ_9bmMRRxz0iqQdNa4xToAFyf9tg75wK8U,6103
19
+ iatoolkit/infra/openai_adapter.py,sha256=tbzd8aPAH5cQOJT-sD4ypqq2fWB6WiEIGuGesUDnQNk,3550
20
+ iatoolkit/infra/redis_session_manager.py,sha256=EPr3E_g7LHxn6U4SV5lT_L8WQsAwg8VzA_WIEZ3TwOw,3667
21
+ iatoolkit/infra/connectors/__init__.py,sha256=5JqK9sZ6jBuK83zDQokUhxQ0wuJJJ9DXB8pYCLkX7X4,102
22
+ iatoolkit/infra/connectors/file_connector.py,sha256=HOjRTFd-WfDOcFyvHncAhnGNZuFgChIwC-P6osPo9ZM,352
23
+ iatoolkit/infra/connectors/file_connector_factory.py,sha256=3qvyfH4ZHKuiMxJFkawOxhW2-TGKKtsBYHgoPpZMuKU,2118
24
+ iatoolkit/infra/connectors/google_cloud_storage_connector.py,sha256=IXpL3HTo7Ft4EQsYiQq5wXRRQK854jzOEB7ZdWjLa4U,2050
25
+ iatoolkit/infra/connectors/google_drive_connector.py,sha256=WR1AlO5-Bl3W89opdja0kKgHTJzVOjTsy3H4SlIvwVg,2537
26
+ iatoolkit/infra/connectors/local_file_connector.py,sha256=hrzIgpMJOTuwTqzlQeTIU_50ZbZ6yl8lcWPv6hMnoqI,1739
27
+ iatoolkit/infra/connectors/s3_connector.py,sha256=Nj4_YaLobjfcnbZewJf21_K2EXohgcc3mJll1Pzn4zg,1123
28
+ iatoolkit/locales/en.yaml,sha256=uEwOksWcaXyluj9aYW_yYSCbwqd84Kio2Z4lHaWyi_s,7674
29
+ iatoolkit/locales/es.yaml,sha256=HbszlQ2Xqx82hpcbMYtgWtSw3KUdMpUEIjl__BYIX8I,8690
30
+ iatoolkit/repositories/__init__.py,sha256=5JqK9sZ6jBuK83zDQokUhxQ0wuJJJ9DXB8pYCLkX7X4,102
31
+ iatoolkit/repositories/database_manager.py,sha256=IyqokOXhYydTGC859wDvu6jvJAK_Rgs16YdpDTuaF3k,3889
32
+ iatoolkit/repositories/document_repo.py,sha256=vhFc0hu9GK6yoKJHs2dLaAoQ9ZJaf9GEOsD2yWuVuNw,1130
33
+ iatoolkit/repositories/llm_query_repo.py,sha256=YT_t7cYGQk8rwzH_17-28aTzO-e2jUfa2rvXy8tugvA,3612
34
+ iatoolkit/repositories/models.py,sha256=9UijNdpZnX6yzHOj5ReYJckRz01gIXmIetBJ7nBOES0,14287
35
+ iatoolkit/repositories/profile_repo.py,sha256=zM68DvI3J3aSFt8yMuOpqy3v9_xJ2j86cmspD87gLK8,4139
36
+ iatoolkit/repositories/tasks_repo.py,sha256=icVO_r2oPagGnnBhwVFzznnvEEU2EAx-2dlWuWvoDC4,1745
37
+ iatoolkit/repositories/vs_repo.py,sha256=Iwbx9G-N05NEYTkZD2GP5mKWHcp_3D7h8VAhS0XGSv0,5824
38
+ iatoolkit/services/__init__.py,sha256=5JqK9sZ6jBuK83zDQokUhxQ0wuJJJ9DXB8pYCLkX7X4,102
39
+ iatoolkit/services/auth_service.py,sha256=ErP0CC2MpGJthIOMuYBbRdFsQQKpEQQ0Uu9_wT90yJI,7744
40
+ iatoolkit/services/benchmark_service.py,sha256=CdbFYyS3FHFhNzWQEa9ZNjUlmON10DT1nKNbZQ1EUi8,5880
41
+ iatoolkit/services/branding_service.py,sha256=GCUxchW6cAbYogCRVw3KGF-Zmi8v99yHiiDUYBxaD5Q,8141
42
+ iatoolkit/services/company_context_service.py,sha256=ME9dshCY1J1L6Kz_anrvoSfWy2Zutk4PtnMkyjbq_d4,6986
43
+ iatoolkit/services/configuration_service.py,sha256=TmWRqne9M9vf06c9_Hlfc8VMB--s99iK39hf8JSyO3k,5746
44
+ iatoolkit/services/dispatcher_service.py,sha256=wHZV4AU4okYKuFwH5afB3ktYDE2Ej4XVvxmUlL-IsmM,12635
45
+ iatoolkit/services/document_service.py,sha256=whW3B9g7lCaNOqezYmoHkSAov0K7EH90u-KVANO0mPg,6057
46
+ iatoolkit/services/embedding_service.py,sha256=AxcNVEhUeUXXYU80kafS70D-kFBlnN2_EnR6doae-cE,6110
47
+ iatoolkit/services/excel_service.py,sha256=MGVFjSo1NOL8PL7_hVgEEFzvXfA4NmF-JFEr8FBSjOA,4090
48
+ iatoolkit/services/file_processor_service.py,sha256=h8Tg2Xwvjv_HOIUo51Rnu5H4tUmkJ8W9tKvmFfgKPms,3792
49
+ iatoolkit/services/history_service.py,sha256=HoJs5CRpXturrdycznlalL6TOPbzC2npziTs86mOIkg,1375
50
+ iatoolkit/services/i18n_service.py,sha256=mR4pS0z56NgZLeSnEvDXiMvVBeOCl5CkUWdYBTVEhyM,3941
51
+ iatoolkit/services/jwt_service.py,sha256=EXpc1cZAak2nQ3cXIopm5nFTqevzINToWRYk22gJNjo,2933
52
+ iatoolkit/services/language_service.py,sha256=6l5ooiFXXRIF2gdKySR_7sj5IkJg-PYmwTMhdBcJHBM,3245
53
+ iatoolkit/services/load_documents_service.py,sha256=04XZmn6AWOK0wiRU7QDu2VYRekOK7fD19H-mC4FiMjA,7908
54
+ iatoolkit/services/mail_service.py,sha256=R_5zOSXMGOdn3pSCyUFCOUmQumXoiKEgmg78H_rxcP8,2366
55
+ iatoolkit/services/profile_service.py,sha256=sjE9cFz8fDRClYTXs1LLkPGfDlbzrV6TYx_DYJM6VW8,21969
56
+ iatoolkit/services/prompt_manager_service.py,sha256=o0SBO3k_VHaPxPcaM5oeq7Y2rOlFr7FCp_cIcpcU8qY,8415
57
+ iatoolkit/services/query_service.py,sha256=4g_rzRmAh-X4_6FsJgBoM7RQ0CV7FOWfGoxILDBk-8U,20704
58
+ iatoolkit/services/search_service.py,sha256=Omx7tXit5V9o_HdIEFs24Hmaz382CxuphfFzvige4Uo,2188
59
+ iatoolkit/services/sql_service.py,sha256=Eyyi1uY4o3szSO06nxURHUGTWp2N631kdWXZSEOho2E,3455
60
+ iatoolkit/services/tasks_service.py,sha256=itREO5rDnUIgsqtyCOBKDtH30QL5v1egs4qPTiBK8xU,6865
61
+ iatoolkit/services/user_feedback_service.py,sha256=4hftNzE69kiaJYjhxgPmiDAVu3399DiIgCbzg6DQ7Rc,4966
62
+ iatoolkit/services/user_session_context_service.py,sha256=vYF_vWM37tPB_ZyPBJ6f6WTJVjT2j-4L8JfZbqbI93k,6775
63
+ iatoolkit/static/images/fernando.jpeg,sha256=W68TYMuo5hZVpbP-evwH6Nu4xWFv2bc8pJzSKDoLTeQ,100612
64
+ iatoolkit/static/js/chat_feedback_button.js,sha256=Wzb2l3jmpZNwY2KYQQDuBmFKS4oU9WteB9s4U-bEqb4,2429
65
+ iatoolkit/static/js/chat_filepond.js,sha256=mzXafm7a506EpM37KATTK3zvAswO1E0KSUY1vKbwuRc,3163
66
+ iatoolkit/static/js/chat_help_content.js,sha256=N9APsdNoPWWyC1aMLjfq-xFfFYZ5g8ZefUGTkYt75DY,5211
67
+ iatoolkit/static/js/chat_history_button.js,sha256=i9EBAWWW2XyQnAuj1b-c8102EG_gDkQ2ElbA8_Nu0yo,3491
68
+ iatoolkit/static/js/chat_logout_button.js,sha256=Of9H6IbAboSBmeqRaurEVW6_dL752L0UeDcDLNBD5Z0,1335
69
+ iatoolkit/static/js/chat_main.js,sha256=MmoagngCFqzjWVUewq9ZOE2RgATKoyuy351aQ0ezVco,12504
70
+ iatoolkit/static/js/chat_onboarding_button.js,sha256=MyNpqqc4BGPZL5MMJTqi6OLFjQKKrJ9eNT1nOsTbvIw,3353
71
+ iatoolkit/static/js/chat_prompt_manager.js,sha256=QYki28CpyM2Chn82dnOP2eH6FObxH8eChGFyUxukv1M,3319
72
+ iatoolkit/static/js/chat_reload_button.js,sha256=FHMm5sLdn2HuWDq66wphNuRcltjLG-aADp0yTwEbnQw,1256
73
+ iatoolkit/static/styles/chat_iatoolkit.css,sha256=b25ahyuEKRLQArOhyIgnMxWAxy2vATk8-iVlebl6PrY,13808
74
+ iatoolkit/static/styles/chat_modal.css,sha256=9rwWrzL4Vq7AsdiGb3qczyOUf2PJEgLjSLCkSns8dQA,3031
75
+ iatoolkit/static/styles/chat_public.css,sha256=4EHN_VvURQYlooCmNB-UHIhvMsn4GFm7tKtr4VKpCNE,3830
76
+ iatoolkit/static/styles/landing_page.css,sha256=E6VRI5dko_naloH_FmNAHpjzxz4NZbrbzKwYLw4fYJA,4297
77
+ iatoolkit/static/styles/llm_output.css,sha256=AlxgRSOleeCk2dLAqFWVaQ-jwZiJjcpC5rHuUv3T6VU,2312
78
+ iatoolkit/static/styles/onboarding.css,sha256=fNiqT_MMJ6gGhNzfbSZhJwvcCZ_8gibL-MWZwxyAgAs,3749
79
+ iatoolkit/system_prompts/format_styles.prompt,sha256=MSMe1qvR3cF_0IbFshn8R0z6Wx6VCHQq1p37rpu5wwk,3576
80
+ iatoolkit/system_prompts/query_main.prompt,sha256=zcXM8nNyxvtbWevNkFAgBbSdLkzvLPxKQx9kj8NvfFA,2077
81
+ iatoolkit/system_prompts/sql_rules.prompt,sha256=y4nURVnb9AyFwt-lrbMNBHHtZlhk6kC9grYoOhRnrJo,59174
82
+ iatoolkit/templates/_company_header.html,sha256=wrwDftsSVu1uMPchsweAPLupsPkmLIPQBQ0xpIIyxjA,747
83
+ iatoolkit/templates/_login_widget.html,sha256=mheHpa_mcGK7UYSYdzxyD_n97MnJXJE19IcFxxUQYTY,1952
84
+ iatoolkit/templates/about.html,sha256=ciC08grUVz5qLzdzDDqDX31xirg5PrJIRYabWpV9oA8,294
85
+ iatoolkit/templates/base.html,sha256=xOox6JJEd6dHBlw6DBrFDJTXtAKCaXZc3Ffrufa-GDk,3042
86
+ iatoolkit/templates/change_password.html,sha256=p0GWZ9gldluYQM8OPSz2Q4CYhU8UJmb-72iz_Sl_6Ho,3485
87
+ iatoolkit/templates/chat.html,sha256=fT85IZMJZwWrhmI_5rTpdTCmyda19SwK8inMZmtDA44,13283
88
+ iatoolkit/templates/chat_modals.html,sha256=x0Do7I7X9cfgZFHSAwWreIN55nYPCpZK7PTBxGXjrYY,8501
89
+ iatoolkit/templates/error.html,sha256=4aT6cIYQUILciekAceHEiUuZxcAqkmNPUMnB9CD4BNA,1778
90
+ iatoolkit/templates/forgot_password.html,sha256=RPV_fDCzEdSQpA0qM8RNSCsNlhUhgp9sRGUHpMMBQ10,2247
91
+ iatoolkit/templates/index.html,sha256=mOuHePAmQ5PaMwqkJf7HU5oIL_lh8iKBKFng6d-QVzA,8017
92
+ iatoolkit/templates/login_simulation.html,sha256=2_f-rTEf3yuCaTFwrQlY3XxHljbp34KHPffHRuUkCyY,1459
93
+ iatoolkit/templates/onboarding_shell.html,sha256=ozjzzHfu63Ovgk295rE-sRvI4Z9Ecpk-SuDcV8Gs7lA,4678
94
+ iatoolkit/templates/signup.html,sha256=u2wiahk_d_BfooknSCcgcgAaQqIfas2aj6fe0cG3jzE,4174
95
+ iatoolkit/views/__init__.py,sha256=5JqK9sZ6jBuK83zDQokUhxQ0wuJJJ9DXB8pYCLkX7X4,102
96
+ iatoolkit/views/base_login_view.py,sha256=yu3dzY3CSA13voplE2AJ6uUz0X51diRuHSjvIEx2_pw,3691
97
+ iatoolkit/views/change_password_view.py,sha256=sTtjvLsGrZPt38gVzqABSB9EUEWIx3o4lFKYYGK79fc,4951
98
+ iatoolkit/views/embedding_api_view.py,sha256=9n5utihq8zHiG0V2sVCOYQ72wOKa4denqE951gqaJWo,2371
99
+ iatoolkit/views/external_login_view.py,sha256=H83jtiHXQCL0yP0ULBF0O_fxh-WU6XMz-YMJXEcSuDY,2864
100
+ iatoolkit/views/file_store_api_view.py,sha256=pkGYtSKaIH0S9qGEMYvELoJmNKmlVnyDZfJEqYYAWYA,2307
101
+ iatoolkit/views/forgot_password_view.py,sha256=M4w2UpEU3DFQXMOvyp3HqIKHs0PUPWzFZtVezmlhr14,3121
102
+ iatoolkit/views/help_content_api_view.py,sha256=8EUw2iSE6X-Lm2dGlYZxSp-29HzaAGwD3CpL4Otqp5k,2011
103
+ iatoolkit/views/history_api_view.py,sha256=CrfHmdIx4pB41KC_mbvEpv33zkPeKuBmlfGI2kc1ZvM,1988
104
+ iatoolkit/views/home_view.py,sha256=f3KLPr5Pv4utVSDK5ImjMIovDi5J0cta8ZQ_hjGpJpc,2579
105
+ iatoolkit/views/index_view.py,sha256=OsykSlXLB-TpFAPkDlsMna6bi3Ie5PXL303Hsg3WwUM,329
106
+ iatoolkit/views/init_context_api_view.py,sha256=SZ71RkMirbzvnSF0upUznwmn9id8W82PA1SuYYkynxo,2948
107
+ iatoolkit/views/llmquery_api_view.py,sha256=zjNVAvFI62xj4fBDaTWY6uqtlkoopCwizCX7KtvX_c8,2233
108
+ iatoolkit/views/login_simulation_view.py,sha256=xZ6GH7AfqNAK-0Cpf0RRD5Bdm3SsWkfNyx2PohV3_Uk,4034
109
+ iatoolkit/views/login_view.py,sha256=zdqwljOl4xGYoUbDYR-ucxBUF6nROTyvVFW8OGGE6Bw,6443
110
+ iatoolkit/views/logout_api_view.py,sha256=tvk4sCCXOFsk6qfGsrwY-pDKHL4ET30tL7ncTG-PT8A,1733
111
+ iatoolkit/views/profile_api_view.py,sha256=qhlmhyygIs5h-OyNDwq1uGUS8S-GxB2zOYY51Hs5prY,1645
112
+ iatoolkit/views/prompt_api_view.py,sha256=zumYnC_LWq_IeLraoL24YrY87U6a7iC6maY1PN-IP6U,1263
113
+ iatoolkit/views/signup_view.py,sha256=UIRsiZ_rCJprWy58UAsiVTUcPWnIdU7UyayJwoWaq28,3917
114
+ iatoolkit/views/tasks_api_view.py,sha256=wGnuwuuL83ByQ1Yre6ytRVztA0OGQjGrwMjB1_G830U,2630
115
+ iatoolkit/views/tasks_review_api_view.py,sha256=wsCpzqyRyUdCXWAhyGlBe3eNZZ6A1DQG7TblN_GZNfM,1894
116
+ iatoolkit/views/user_feedback_api_view.py,sha256=QOTBtpNqYAmewXDgVAoaIprnVjvf1xM0ExWxSFp3ICI,2098
117
+ iatoolkit/views/verify_user_view.py,sha256=TTC9BNjyjT8ZT5KnQ2f5-8UF1Y_sJII2wJ501xWSFvY,2653
118
+ iatoolkit-0.71.2.dist-info/licenses/LICENSE,sha256=5tOLQdjoCvSXEx_7Lr4bSab3ha4NSwzamvua0fwCXi8,1075
119
+ iatoolkit-0.71.2.dist-info/METADATA,sha256=en0VLL6vKIP1H7lXkakyLlzXotm7FNDJZqStOOHfvt0,9963
120
+ iatoolkit-0.71.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
121
+ iatoolkit-0.71.2.dist-info/top_level.txt,sha256=V_w4QvDx0b1RXiy8zTCrD1Bp7AZkFe3_O0-9fMiwogg,10
122
+ iatoolkit-0.71.2.dist-info/RECORD,,
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Fernando Libedinsky
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
iatoolkit/common/auth.py DELETED
@@ -1,200 +0,0 @@
1
- # Copyright (c) 2024 Fernando Libedinsky
2
- # Product: IAToolkit
3
- #
4
- # IAToolkit is open source software.
5
-
6
- from flask import redirect, url_for
7
- from iatoolkit.common.session_manager import SessionManager
8
- from datetime import datetime, timezone
9
- from injector import inject
10
- from iatoolkit.repositories.profile_repo import ProfileRepo
11
- from iatoolkit.services.jwt_service import JWTService
12
- import logging
13
- from flask import request
14
- from typing import Optional
15
-
16
- MAX_INACTIVITY_SECONDS = 60*30
17
-
18
- class IAuthentication:
19
- @inject
20
-
21
- def __init__(self,
22
- profile_repo: ProfileRepo,
23
- jwt_service: JWTService):
24
- self.profile_repo = profile_repo
25
- self.jwt_service = jwt_service
26
-
27
- def verify(self, company_short_name: str, body_external_user_id: str = None) -> dict:
28
- # authentication is in this orden: JWT, API Key, Sesión
29
- local_user_id = None
30
- company_id = None
31
- auth_method = None
32
- external_user_id = None # for JWT or API Key
33
-
34
- # 1. try auth via JWT
35
- jwt_company_id, jwt_external_user_id, jwt_error_info = self._authenticate_via_chat_jwt(company_short_name)
36
-
37
- if jwt_company_id is not None and jwt_external_user_id is not None:
38
- auth_method = "JWT"
39
- company_id = jwt_company_id
40
- external_user_id = jwt_external_user_id
41
- local_user_id = 0
42
- elif jwt_error_info is not None:
43
- # explicit error in JWT (inválido, expirado, etc.)
44
- logging.warning(f"Fallo de autenticación JWT: {jwt_error_info}")
45
- return {"error_message": "Fallo de autenticación JWT"}
46
- else:
47
- # 2. JWT not apply, try by API Key
48
- api_key_company_id, api_key_error_info = self._authenticate_via_api_key(company_short_name)
49
-
50
- if api_key_company_id is not None:
51
- auth_method = "API Key"
52
- company_id = api_key_company_id
53
- external_user_id = body_external_user_id # API Key usa external_user_id del body
54
- local_user_id = 0
55
- elif api_key_error_info is not None:
56
- # explicit error in API Key (inválida, incorrecta, error interno)
57
- logging.warning(f"Fallo de autenticación API Key: {api_key_error_info}")
58
- return {"error_message": "Fallo de autenticación API Key"}
59
- else:
60
- # 3. no JWT and API Key auth, try by Session
61
- self.check_if_user_is_logged_in(company_short_name) # raise exception or redirect if not logged in
62
-
63
- # In case not logged in check_if_user_is_logged_in redirects to login page
64
- auth_method = "Session"
65
- local_user_id = SessionManager.get('user_id')
66
- company_id = SessionManager.get('company_id')
67
- external_user_id = ""
68
-
69
- if not company_id or not local_user_id:
70
- logging.error(
71
- f"Sesión válida para {company_short_name} pero falta company_id o user_id en SessionManager.")
72
- return {"error_message": "Fallo interno en la autenticación o no autenticado"}
73
-
74
- # last verification of authentication
75
- if company_id is None or auth_method is None or local_user_id is None:
76
- # this condition should never happen,
77
- logging.error(
78
- f"Fallo inesperado en la lógica de autenticación para {company_short_name}. Ningún método tuvo éxito o devolvió error.")
79
- return {"error_message": "Fallo interno en la autenticación o no autenticado"}
80
-
81
- return {
82
- 'success': True,
83
- "auth_method": auth_method,
84
- "company_id": company_id,
85
- "auth_method": auth_method,
86
- "local_user_id": local_user_id,
87
- "external_user_id": external_user_id
88
- }
89
-
90
- def _authenticate_via_api_key(self, company_short_name_from_url: str):
91
- """
92
- try to authenticate using an API Key from the header 'Authorization'.
93
- Retorna (company_id, None) en éxito.
94
- Retorna (None, error_message) en fallo.
95
- """
96
- api_key_header = request.headers.get('Authorization')
97
- api_key_value = None
98
-
99
- # extract the key
100
- if api_key_header and api_key_header.startswith('Bearer '):
101
- api_key_value = api_key_header.split('Bearer ')[1]
102
- else:
103
- # there is no key in the headers expected
104
- return None, None
105
-
106
- # validate the api-key using ProfileRepo
107
- try:
108
- api_key_entry = self.profile_repo.get_active_api_key_entry(api_key_value)
109
- if not api_key_entry:
110
- logging.warning(f"Intento de acceso con API Key inválida o inactiva: {api_key_value[:5]}...")
111
- return None, "API Key inválida o inactiva"
112
-
113
- # check that the key belongs to the company
114
- # api_key_entry.company already loaded by joinedload
115
- if not api_key_entry.company or api_key_entry.company.short_name != company_short_name_from_url:
116
- return None, f"API Key no es válida para la compañía {company_short_name_from_url}"
117
-
118
- # successfull auth by API Key
119
- company_id = api_key_entry.company_id
120
-
121
- return company_id, None
122
-
123
- except Exception as e:
124
- logging.exception(f"Error interno durante validación de API Key: {e}")
125
- return None, "Error interno del servidor al validar API Key"
126
-
127
- def _authenticate_via_chat_jwt(self, company_short_name_from_url: str) -> tuple[
128
- Optional[int], Optional[str], Optional[str]]:
129
- """
130
- authenticate using an JWT chat session in the del header 'X-Chat-Token'.
131
- Return (company_id, external_user_id, None) on exit
132
- Returns (None, None, error_message) on fail.
133
- """
134
- chat_jwt = request.headers.get('X-Chat-Token')
135
- if not chat_jwt:
136
- return None, None, None
137
-
138
- # open the jwt token and retrieve the payload
139
- jwt_payload = self.jwt_service.validate_chat_jwt(chat_jwt, company_short_name_from_url)
140
- if not jwt_payload:
141
- # validation fails (token expired, incorrect signature, company , etc.)
142
- # validate_chat_jwt logs the specific failure
143
- return None, None, "Token de chat expirado, debes reingresar al chat"
144
-
145
- # JWT is validated: extract the company_id and external_user_id
146
- company_id = jwt_payload.get('company_id')
147
- external_user_id = jwt_payload.get('external_user_id')
148
-
149
- # Sanity check aditional, should never happen
150
- if not isinstance(company_id, int) or not external_user_id:
151
- logging.error(
152
- f"LLMQuery: JWT payload incompleto tras validación exitosa. CompanyID: {company_id}, UserID: {external_user_id}")
153
- return None, None, "Token de chat con formato interno incorrecto"
154
-
155
- return company_id, external_user_id, None
156
-
157
- def check_if_user_is_logged_in(self, company_short_name: str):
158
- if not SessionManager.get('user'):
159
- if company_short_name:
160
- return redirect(url_for('login', company_short_name=company_short_name))
161
- else:
162
- return redirect(url_for('home'))
163
-
164
- if company_short_name != SessionManager.get('company_short_name'):
165
- return redirect(url_for('login', company_short_name=company_short_name))
166
-
167
- # check session timeout
168
- if not self.check_session_timeout():
169
- SessionManager.clear()
170
- return redirect(url_for('login', company_short_name=company_short_name))
171
-
172
- # update last_activity
173
- SessionManager.set('last_activity', datetime.now(timezone.utc).timestamp())
174
-
175
- def check_session_timeout(self):
176
- # get last activity from session manager
177
- last_activity = SessionManager.get('last_activity')
178
- if not last_activity:
179
- return False
180
-
181
- # Tiempo actual en timestamp
182
- current_time = datetime.now(timezone.utc).timestamp()
183
-
184
- # get inactivity duration
185
- inactivity_duration = current_time - last_activity
186
-
187
- # verify if inactivity duration is greater than MAX_INACTIVITY_SECONDS
188
- if inactivity_duration > MAX_INACTIVITY_SECONDS:
189
- # close session
190
- return False
191
-
192
- # update last activity timestamp
193
- SessionManager.set('last_activity', current_time)
194
-
195
- return True # session is active
196
-
197
-
198
-
199
-
200
-
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file