iatoolkit 0.95.4__tar.gz → 1.10.0__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 (146) hide show
  1. {iatoolkit-0.95.4/src/iatoolkit.egg-info → iatoolkit-1.10.0}/PKG-INFO +1 -2
  2. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/requirements.txt +0 -1
  3. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/__init__.py +6 -4
  4. iatoolkit-1.10.0/src/iatoolkit/base_company.py +21 -0
  5. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/cli_commands.py +3 -2
  6. iatoolkit-1.10.0/src/iatoolkit/common/interfaces/asset_storage.py +34 -0
  7. iatoolkit-1.10.0/src/iatoolkit/common/interfaces/database_provider.py +43 -0
  8. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/common/model_registry.py +52 -1
  9. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/common/routes.py +64 -3
  10. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/common/util.py +32 -1
  11. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/company_registry.py +5 -0
  12. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/core.py +45 -13
  13. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/infra/connectors/file_connector_factory.py +1 -0
  14. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/infra/connectors/s3_connector.py +4 -2
  15. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/infra/llm_providers/deepseek_adapter.py +14 -15
  16. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/infra/llm_providers/openai_adapter.py +41 -3
  17. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/infra/llm_response.py +5 -0
  18. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/locales/en.yaml +199 -2
  19. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/locales/es.yaml +198 -0
  20. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/repositories/database_manager.py +52 -50
  21. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/repositories/document_repo.py +7 -0
  22. iatoolkit-1.10.0/src/iatoolkit/repositories/filesystem_asset_repository.py +36 -0
  23. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/repositories/llm_query_repo.py +31 -7
  24. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/repositories/models.py +61 -7
  25. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/repositories/profile_repo.py +59 -3
  26. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/repositories/vs_repo.py +22 -24
  27. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/services/company_context_service.py +96 -49
  28. iatoolkit-1.10.0/src/iatoolkit/services/configuration_service.py +551 -0
  29. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/services/dispatcher_service.py +15 -6
  30. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/services/file_processor_service.py +0 -5
  31. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/services/history_manager_service.py +5 -7
  32. iatoolkit-1.10.0/src/iatoolkit/services/knowledge_base_service.py +447 -0
  33. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/services/llm_client_service.py +14 -10
  34. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/services/load_documents_service.py +26 -48
  35. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/services/profile_service.py +32 -4
  36. iatoolkit-1.10.0/src/iatoolkit/services/prompt_service.py +539 -0
  37. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/services/query_service.py +6 -6
  38. iatoolkit-1.10.0/src/iatoolkit/services/sql_service.py +191 -0
  39. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/services/tool_service.py +15 -4
  40. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/services/user_session_context_service.py +1 -1
  41. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/static/js/chat_main.js +41 -3
  42. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/static/styles/chat_iatoolkit.css +38 -34
  43. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/static/styles/llm_output.css +34 -1
  44. iatoolkit-1.10.0/src/iatoolkit/system_prompts/__init__.py +0 -0
  45. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/templates/base.html +13 -0
  46. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/templates/chat.html +11 -7
  47. iatoolkit-1.10.0/src/iatoolkit/views/categories_api_view.py +111 -0
  48. iatoolkit-1.10.0/src/iatoolkit/views/chat_view.py +76 -0
  49. iatoolkit-1.10.0/src/iatoolkit/views/configuration_api_view.py +163 -0
  50. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/views/load_document_api_view.py +14 -10
  51. iatoolkit-1.10.0/src/iatoolkit/views/prompt_api_view.py +118 -0
  52. iatoolkit-1.10.0/src/iatoolkit/views/rag_api_view.py +216 -0
  53. iatoolkit-1.10.0/src/iatoolkit/views/users_api_view.py +33 -0
  54. {iatoolkit-0.95.4 → iatoolkit-1.10.0/src/iatoolkit.egg-info}/PKG-INFO +1 -2
  55. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit.egg-info/SOURCES.txt +10 -1
  56. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit.egg-info/requires.txt +0 -1
  57. iatoolkit-0.95.4/src/iatoolkit/base_company.py +0 -37
  58. iatoolkit-0.95.4/src/iatoolkit/services/configuration_service.py +0 -329
  59. iatoolkit-0.95.4/src/iatoolkit/services/prompt_service.py +0 -301
  60. iatoolkit-0.95.4/src/iatoolkit/services/search_service.py +0 -55
  61. iatoolkit-0.95.4/src/iatoolkit/services/sql_service.py +0 -159
  62. iatoolkit-0.95.4/src/iatoolkit/views/prompt_api_view.py +0 -37
  63. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/LICENSE +0 -0
  64. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/LICENSE_COMMUNITY.md +0 -0
  65. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/pyproject.toml +0 -0
  66. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/readme.md +0 -0
  67. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/setup.cfg +0 -0
  68. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/common/__init__.py +0 -0
  69. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/common/exceptions.py +0 -0
  70. {iatoolkit-0.95.4/src/iatoolkit/infra/llm_providers → iatoolkit-1.10.0/src/iatoolkit/common/interfaces}/__init__.py +0 -0
  71. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/common/session_manager.py +0 -0
  72. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/infra/__init__.py +0 -0
  73. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/infra/brevo_mail_app.py +0 -0
  74. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/infra/call_service.py +0 -0
  75. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/infra/connectors/__init__.py +0 -0
  76. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/infra/connectors/file_connector.py +0 -0
  77. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/infra/connectors/google_cloud_storage_connector.py +0 -0
  78. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/infra/connectors/google_drive_connector.py +0 -0
  79. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/infra/connectors/local_file_connector.py +0 -0
  80. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/infra/google_chat_app.py +0 -0
  81. {iatoolkit-0.95.4/src/iatoolkit/system_prompts → iatoolkit-1.10.0/src/iatoolkit/infra/llm_providers}/__init__.py +0 -0
  82. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/infra/llm_providers/gemini_adapter.py +0 -0
  83. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/infra/llm_proxy.py +0 -0
  84. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/infra/redis_session_manager.py +0 -0
  85. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/repositories/__init__.py +0 -0
  86. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/services/__init__.py +0 -0
  87. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/services/auth_service.py +0 -0
  88. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/services/benchmark_service.py +0 -0
  89. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/services/branding_service.py +0 -0
  90. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/services/document_service.py +0 -0
  91. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/services/embedding_service.py +0 -0
  92. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/services/excel_service.py +0 -0
  93. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/services/i18n_service.py +0 -0
  94. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/services/jwt_service.py +0 -0
  95. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/services/language_service.py +0 -0
  96. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/services/license_service.py +0 -0
  97. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/services/mail_service.py +0 -0
  98. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/services/user_feedback_service.py +0 -0
  99. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/static/images/fernando.jpeg +0 -0
  100. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/static/images/iatoolkit_core.png +0 -0
  101. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/static/images/iatoolkit_logo.png +0 -0
  102. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/static/js/chat_feedback_button.js +0 -0
  103. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/static/js/chat_filepond.js +0 -0
  104. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/static/js/chat_help_content.js +0 -0
  105. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/static/js/chat_history_button.js +0 -0
  106. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/static/js/chat_logout_button.js +0 -0
  107. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/static/js/chat_model_selector.js +0 -0
  108. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/static/js/chat_onboarding_button.js +0 -0
  109. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/static/js/chat_prompt_manager.js +0 -0
  110. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/static/js/chat_reload_button.js +0 -0
  111. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/static/styles/chat_modal.css +0 -0
  112. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/static/styles/chat_public.css +0 -0
  113. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/static/styles/documents.css +0 -0
  114. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/static/styles/landing_page.css +0 -0
  115. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/static/styles/onboarding.css +0 -0
  116. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/system_prompts/format_styles.prompt +0 -0
  117. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/system_prompts/query_main.prompt +0 -0
  118. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/system_prompts/sql_rules.prompt +0 -0
  119. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/templates/_company_header.html +0 -0
  120. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/templates/_login_widget.html +0 -0
  121. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/templates/change_password.html +0 -0
  122. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/templates/chat_modals.html +0 -0
  123. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/templates/error.html +0 -0
  124. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/templates/forgot_password.html +0 -0
  125. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/templates/onboarding_shell.html +0 -0
  126. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/templates/signup.html +0 -0
  127. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/views/__init__.py +0 -0
  128. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/views/base_login_view.py +0 -0
  129. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/views/change_password_view.py +0 -0
  130. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/views/embedding_api_view.py +0 -0
  131. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/views/forgot_password_view.py +0 -0
  132. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/views/help_content_api_view.py +0 -0
  133. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/views/history_api_view.py +0 -0
  134. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/views/home_view.py +0 -0
  135. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/views/init_context_api_view.py +0 -0
  136. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/views/llmquery_api_view.py +0 -0
  137. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/views/login_view.py +0 -0
  138. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/views/logout_api_view.py +0 -0
  139. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/views/profile_api_view.py +0 -0
  140. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/views/root_redirect_view.py +0 -0
  141. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/views/signup_view.py +0 -0
  142. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/views/static_page_view.py +0 -0
  143. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/views/user_feedback_api_view.py +0 -0
  144. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit/views/verify_user_view.py +0 -0
  145. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/src/iatoolkit.egg-info/dependency_links.txt +0 -0
  146. {iatoolkit-0.95.4 → iatoolkit-1.10.0}/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.95.4
3
+ Version: 1.10.0
4
4
  Summary: IAToolkit
5
5
  Author: Fernando Libedinsky
6
6
  License-Expression: MIT
@@ -14,7 +14,6 @@ Requires-Dist: botocore==1.36.22
14
14
  Requires-Dist: build==1.2.2.post1
15
15
  Requires-Dist: click==8.1.8
16
16
  Requires-Dist: cryptography==44.0.3
17
- Requires-Dist: deepseek==1.0.0
18
17
  Requires-Dist: Flask==3.1.0
19
18
  Requires-Dist: Flask-Bcrypt==1.0.1
20
19
  Requires-Dist: flask-cors==6.0.0
@@ -4,7 +4,6 @@ botocore==1.36.22
4
4
  build==1.2.2.post1
5
5
  click==8.1.8
6
6
  cryptography==44.0.3
7
- deepseek==1.0.0
8
7
  Flask==3.1.0
9
8
  Flask-Bcrypt==1.0.1
10
9
  flask-cors==6.0.0
@@ -3,7 +3,7 @@
3
3
  #
4
4
  # IAToolkit is open source software.
5
5
 
6
- __version__ = "0.95.4"
6
+ __version__ = "1.10.0"
7
7
 
8
8
  # Expose main classes and functions at the top level of the package
9
9
 
@@ -17,13 +17,14 @@ from .base_company import BaseCompany
17
17
  # --- Services ---
18
18
  from iatoolkit.services.query_service import QueryService
19
19
  from iatoolkit.services.document_service import DocumentService
20
- from iatoolkit.services.search_service import SearchService
20
+ from iatoolkit.services.knowledge_base_service import KnowledgeBaseService
21
21
  from iatoolkit.services.sql_service import SqlService
22
22
  from iatoolkit.services.load_documents_service import LoadDocumentsService
23
23
  from iatoolkit.infra.call_service import CallServiceClient
24
24
  from iatoolkit.services.profile_service import ProfileService
25
25
  from iatoolkit.services.mail_service import MailService
26
26
  from iatoolkit.repositories.models import Base as OrmModel
27
+ from iatoolkit.base_company import BaseCompany
27
28
 
28
29
  __all__ = [
29
30
  'IAToolkit',
@@ -35,10 +36,11 @@ __all__ = [
35
36
  'QueryService',
36
37
  'SqlService',
37
38
  'DocumentService',
38
- 'SearchService',
39
+ 'KnowledgeBaseService',
39
40
  'LoadDocumentsService',
40
41
  'CallServiceClient',
41
42
  'ProfileService',
42
43
  'MailService',
43
- 'OrmModel'
44
+ 'OrmModel',
45
+ 'BaseCompany',
44
46
  ]
@@ -0,0 +1,21 @@
1
+ # Copyright (c) 2024 Fernando Libedinsky
2
+ # Product: IAToolkit
3
+ #
4
+ # IAToolkit is open source software.
5
+
6
+ # companies/base_company.py
7
+ from abc import ABC, abstractmethod
8
+
9
+ class BaseCompany(ABC):
10
+
11
+ @abstractmethod
12
+ # execute the specific action configured in the intent table
13
+ def handle_request(self, tag: str, params: dict) -> dict:
14
+ raise NotImplementedError("La subclase debe implementar el método handle_request()")
15
+
16
+ @abstractmethod
17
+ def register_cli_commands(self, app):
18
+ pass
19
+
20
+ def unsupported_operation(self, tag):
21
+ raise NotImplementedError(f"La operación '{tag}' no está soportada por esta empresa.")
@@ -14,12 +14,13 @@ def register_core_commands(app):
14
14
 
15
15
  @app.cli.command("api-key")
16
16
  @click.argument("company_short_name")
17
- def api_key(company_short_name: str):
17
+ @click.argument("key_name")
18
+ def api_key(company_short_name: str, key_name: str):
18
19
  """⚙️ Genera una nueva API key para una compañía ya registrada."""
19
20
  try:
20
21
  profile_service = IAToolkit.get_instance().get_injector().get(ProfileService)
21
22
  click.echo(f"🔑 Generating API-KEY for company: '{company_short_name}'...")
22
- result = profile_service.new_api_key(company_short_name)
23
+ result = profile_service.new_api_key(company_short_name, key_name)
23
24
 
24
25
  if 'error' in result:
25
26
  click.echo(f"❌ Error: {result['error']}")
@@ -0,0 +1,34 @@
1
+ from enum import Enum
2
+ from typing import List
3
+ import abc
4
+
5
+
6
+ class AssetType(Enum):
7
+ CONFIG = "config"
8
+ PROMPT = "prompts"
9
+ SCHEMA = "schema"
10
+ CONTEXT = "context"
11
+
12
+
13
+ class AssetRepository(abc.ABC):
14
+ @abc.abstractmethod
15
+ def exists(self, company_short_name: str, asset_type: AssetType, filename: str) -> bool:
16
+ pass
17
+
18
+ @abc.abstractmethod
19
+ def read_text(self, company_short_name: str, asset_type: AssetType, filename: str) -> str:
20
+ pass
21
+
22
+ @abc.abstractmethod
23
+ def list_files(self, company_short_name: str, asset_type: AssetType, extension: str = None) -> List[str]:
24
+ pass
25
+
26
+ @abc.abstractmethod
27
+ def write_text(self, company_short_name: str, asset_type: AssetType, filename: str, content: str) -> None:
28
+ """Creates or updates a text asset."""
29
+ pass
30
+
31
+ @abc.abstractmethod
32
+ def delete(self, company_short_name: str, asset_type: AssetType, filename: str) -> None:
33
+ """Deletes an asset if it exists."""
34
+ pass
@@ -0,0 +1,43 @@
1
+ import abc
2
+ from typing import Any, List, Dict, Union
3
+
4
+ class DatabaseProvider(abc.ABC):
5
+ """
6
+ Abstract interface for interacting with a database source.
7
+ Handles both metadata introspection and query execution.
8
+ """
9
+
10
+ # --- Schema Methods ---
11
+ @abc.abstractmethod
12
+ def get_database_structure(self) -> dict:
13
+ """
14
+ Returns the structure of the database (tables, columns, types)
15
+ Format:
16
+ {
17
+ "table_name": {
18
+ "columns": [
19
+ {"name": "col1", "type": "VARCHAR", "nullable": True, "pk": True},
20
+ ...
21
+ ]
22
+ }
23
+ }
24
+ """
25
+ pass
26
+
27
+ # --- Execution Methods ---
28
+ @abc.abstractmethod
29
+ def execute_query(self, query: str, commit: bool = False) -> Union[List[Dict[str, Any]], Dict[str, int]]:
30
+ """
31
+ Executes a query and returns:
32
+ - A list of dicts for SELECT (rows).
33
+ - A dict {'rowcount': N} for INSERT/UPDATE/DELETE.
34
+ """
35
+ pass
36
+
37
+ @abc.abstractmethod
38
+ def commit(self) -> None:
39
+ pass
40
+
41
+ @abc.abstractmethod
42
+ def rollback(self) -> None:
43
+ pass
@@ -42,7 +42,7 @@ class ModelRegistry:
42
42
  # Hardcoded rules for now; can be extended or loaded from config later.
43
43
  # The order of patterns matters: first match wins.
44
44
  self._provider_patterns: dict[ProviderType, tuple[str, ...]] = {
45
- "openai": ("gpt", "gpt-5"),
45
+ "openai": ("gpt", "gpt-5", "gpt-5-mini", "gpt-5.1"),
46
46
  "gemini": ("gemini", "gemini-3"),
47
47
  "deepseek": ("deepseek",),
48
48
  "xai": ("grok", "grok-1", "grok-beta"),
@@ -72,6 +72,57 @@ class ModelRegistry:
72
72
 
73
73
  return "unknown"
74
74
 
75
+ def get_request_defaults(self, model: str) -> dict:
76
+ """
77
+ Return per-model request defaults to keep model-specific policy centralized.
78
+
79
+ Notes:
80
+ - This should only include keys that are supported by the target provider.
81
+ - Callers should merge these defaults with user-provided params (do not mutate inputs).
82
+ """
83
+ model_lower = (model or "").lower()
84
+ provider = self.get_provider(model_lower)
85
+
86
+ # Conservative defaults: do not send provider-specific knobs unless we know they are supported.
87
+ defaults = {"text": {}, "reasoning": {}}
88
+
89
+ # OpenAI/xAI (OpenAI-compatible) support 'text.verbosity' and 'reasoning.effort' in our current integration.
90
+ if provider in ("openai", "xai"):
91
+ defaults["text"] = {"verbosity": "low"}
92
+
93
+ # Fine-grained per-model tuning.
94
+ if model_lower in ("gpt-5", "gpt-5-mini"):
95
+ defaults["reasoning"] = {"effort": "minimal"}
96
+ elif model_lower == "gpt-5.1":
97
+ defaults["reasoning"] = {"effort": "low", "summary": "auto"}
98
+
99
+ # Gemini/DeepSeek/unknown: keep defaults empty to avoid sending unsupported parameters.
100
+ return defaults
101
+
102
+ def resolve_request_params(self, model: str, text: dict | None = None, reasoning: dict | None = None) -> dict:
103
+ """
104
+ Resolve provider/model defaults and merge them with caller-provided overrides.
105
+
106
+ Rules:
107
+ - Defaults come from get_request_defaults(model).
108
+ - Caller overrides win over defaults.
109
+ - Input dictionaries are never mutated.
110
+ """
111
+ defaults = self.get_request_defaults(model)
112
+
113
+ merged_text: dict = {}
114
+ merged_text.update(defaults.get("text") or {})
115
+ merged_text.update(text or {})
116
+
117
+ merged_reasoning: dict = {}
118
+ merged_reasoning.update(defaults.get("reasoning") or {})
119
+ merged_reasoning.update(reasoning or {})
120
+
121
+ return {
122
+ "text": merged_text,
123
+ "reasoning": merged_reasoning,
124
+ }
125
+
75
126
  def get_history_type(self, model: str) -> HistoryType:
76
127
  """
77
128
  Returns the history strategy for a given model.
@@ -24,10 +24,15 @@ def register_views(app):
24
24
  from iatoolkit.views.profile_api_view import UserLanguageApiView
25
25
  from iatoolkit.views.embedding_api_view import EmbeddingApiView
26
26
  from iatoolkit.views.login_view import LoginView, FinalizeContextView
27
+ from iatoolkit.views.configuration_api_view import ConfigurationApiView, ValidateConfigurationApiView
27
28
  from iatoolkit.views.logout_api_view import LogoutApiView
28
29
  from iatoolkit.views.home_view import HomeView
30
+ from iatoolkit.views.chat_view import ChatView
29
31
  from iatoolkit.views.static_page_view import StaticPageView
30
32
  from iatoolkit.views.root_redirect_view import RootRedirectView
33
+ from iatoolkit.views.users_api_view import UsersApiView
34
+ from iatoolkit.views.rag_api_view import RagApiView
35
+ from iatoolkit.views.categories_api_view import CategoriesApiView
31
36
 
32
37
  # assign root '/' to our new redirect logic
33
38
  app.add_url_rule('/home', view_func=RootRedirectView.as_view('root_redirect'))
@@ -38,6 +43,10 @@ def register_views(app):
38
43
  # login for the iatoolkit integrated frontend
39
44
  app.add_url_rule('/<company_short_name>/login', view_func=LoginView.as_view('login'))
40
45
 
46
+ # Chat Route (Direct Access)
47
+ app.add_url_rule('/<company_short_name>/chat',
48
+ view_func=ChatView.as_view('chat'))
49
+
41
50
  # this endpoint is called when onboarding_shell finish the context load
42
51
  app.add_url_rule(
43
52
  '/<company_short_name>/finalize',
@@ -68,19 +77,62 @@ def register_views(app):
68
77
  app.add_url_rule('/<company_short_name>/verify/<token>', view_func=VerifyAccountView.as_view('verify_account'))
69
78
  app.add_url_rule('/<company_short_name>/forgot-password', view_func=ForgotPasswordView.as_view('forgot_password'))
70
79
  app.add_url_rule('/<company_short_name>/change-password/<token>', view_func=ChangePasswordView.as_view('change_password'))
80
+ app.add_url_rule(
81
+ '/<string:company_short_name>/api/company-users',
82
+ view_func=UsersApiView.as_view('company-users')
83
+ )
71
84
 
72
85
  # main chat query, used by the JS in the browser (with credentials)
73
86
  # can be used also for executing iatoolkit prompts
74
87
  app.add_url_rule('/<company_short_name>/api/llm_query', view_func=LLMQueryApiView.as_view('llm_query_api'))
75
88
 
76
- # open the promt directory
77
- app.add_url_rule('/<company_short_name>/api/prompts', view_func=PromptApiView.as_view('prompt'))
78
-
89
+ # Categories Endpoint
90
+ app.add_url_rule('/<company_short_name>/api/categories',
91
+ view_func=CategoriesApiView.as_view('categories_api'),
92
+ methods=['GET', 'POST'])
93
+
94
+ # open the promt directory and specific prompt management
95
+ prompt_view = PromptApiView.as_view('prompt')
96
+ app.add_url_rule('/<company_short_name>/api/prompts',
97
+ view_func=prompt_view,
98
+ methods=['GET', 'POST'],
99
+ defaults={'prompt_name': None})
100
+
101
+ app.add_url_rule('/<company_short_name>/api/prompts/<prompt_name>',
102
+ view_func=prompt_view,
103
+ methods=['GET', 'POST','PUT', 'DELETE'])
79
104
  # toolbar buttons
80
105
  app.add_url_rule('/<company_short_name>/api/feedback', view_func=UserFeedbackApiView.as_view('feedback'))
81
106
  app.add_url_rule('/<company_short_name>/api/history', view_func=HistoryApiView.as_view('history'))
82
107
  app.add_url_rule('/<company_short_name>/api/help-content', view_func=HelpContentApiView.as_view('help-content'))
83
108
 
109
+ # --- RAG API Routes ---
110
+ rag_view = RagApiView.as_view('rag_api')
111
+
112
+ # 1. List Files (POST for filters)
113
+ app.add_url_rule('/api/rag/<company_short_name>/files',
114
+ view_func=rag_view,
115
+ methods=['POST'],
116
+ defaults={'action': 'list_files'})
117
+
118
+ # 2. Delete File
119
+ app.add_url_rule('/api/rag/<company_short_name>/files/<int:document_id>',
120
+ view_func=rag_view,
121
+ methods=['DELETE'],
122
+ defaults={'action': 'delete_file'})
123
+
124
+ # 3. Search Lab
125
+ app.add_url_rule('/api/rag/<company_short_name>/search',
126
+ view_func=rag_view,
127
+ methods=['POST'],
128
+ defaults={'action': 'search'})
129
+
130
+ # 4. Get File Content (View/Download)
131
+ app.add_url_rule('/api/rag/<company_short_name>/files/<int:document_id>/content',
132
+ view_func=rag_view,
133
+ methods=['GET'],
134
+ defaults={'action': 'get_file_content'})
135
+
84
136
  # this endpoint is for upload documents into the vector store (api-key)
85
137
  app.add_url_rule('/api/load-document', view_func=LoadDocumentApiView.as_view('load-document'), methods=['POST'])
86
138
 
@@ -88,6 +140,15 @@ def register_views(app):
88
140
  app.add_url_rule('/<company_short_name>/api/embedding',
89
141
  view_func=EmbeddingApiView.as_view('embedding_api'))
90
142
 
143
+ # company configuration
144
+ app.add_url_rule('/<company_short_name>/api/configuration',
145
+ view_func=ConfigurationApiView.as_view('configuration'),
146
+ methods=['GET', 'POST', 'PATCH'],)
147
+
148
+ app.add_url_rule('/<company_short_name>/api/configuration/validate',
149
+ view_func=ValidateConfigurationApiView.as_view('configuration-validate'),
150
+ methods=['GET'])
151
+
91
152
  # static pages
92
153
  # url: /pages/foundation o /pages/implementation_plan
93
154
  static_view = StaticPageView.as_view('static_pages')
@@ -157,6 +157,31 @@ class Utility:
157
157
  schema = yaml.safe_load(f)
158
158
  return schema
159
159
 
160
+ def load_yaml_from_string(self, yaml_content: str) -> dict:
161
+ """
162
+ Parses a YAML string into a dictionary securely.
163
+ """
164
+ try:
165
+ yaml_content = yaml_content.replace('\t', ' ')
166
+ return yaml.safe_load(yaml_content) or {}
167
+ except yaml.YAMLError as e:
168
+ logging.error(f"Error parsing YAML string: {e}")
169
+ return {}
170
+
171
+ def dump_yaml_to_string(self, config: dict) -> str:
172
+ """
173
+ Dumps a dictionary into a YAML formatted string.
174
+ It uses default flow style False to ensure block format (readable YAML).
175
+ """
176
+ try:
177
+ # default_flow_style=False ensures lists and dicts are expanded (not inline like JSON)
178
+ # allow_unicode=True ensures characters like accents are preserved
179
+ return yaml.safe_dump(config, default_flow_style=False, allow_unicode=True, sort_keys=False)
180
+ except yaml.YAMLError as e:
181
+ logging.error(f"Error dumping YAML to string: {e}")
182
+ raise IAToolkitException(IAToolkitException.ErrorType.FILE_IO_ERROR,
183
+ f"Failed to generate YAML: {e}")
184
+
160
185
  def generate_context_for_schema(self, entity_name: str, schema_file: str = None, schema: dict = {}) -> str:
161
186
  if not schema_file and not schema:
162
187
  raise IAToolkitException(IAToolkitException.ErrorType.FILE_IO_ERROR,
@@ -186,9 +211,13 @@ class Utility:
186
211
  root_name = list(schema.keys())[0]
187
212
  root_details = schema[root_name]
188
213
 
214
+ # support this format
215
+ if root_details.get('columns'):
216
+ root_details = root_details['columns']
217
+
189
218
  if isinstance(root_details, dict):
190
219
  # Las claves de metadatos describen el objeto en sí, no sus propiedades hijas.
191
- METADATA_KEYS = ['description', 'type', 'format', 'items', 'properties']
220
+ METADATA_KEYS = ['description', 'type', 'format', 'items', 'properties', 'pk']
192
221
 
193
222
  # Las propiedades son las claves restantes en el diccionario.
194
223
  properties = {
@@ -231,6 +260,8 @@ class Utility:
231
260
  description = details.get('description', '')
232
261
  data_type = details.get('type', 'any')
233
262
  output.append(f"{indent_str}- **`{name.lower()}`** ({data_type}): {description}")
263
+ # if 'pk' in details and details['pk']:
264
+ # output.append(f"{indent_str}- **Primary Key**: {details['pk']}")
234
265
 
235
266
  child_indent_str = ' ' * (indent_level + 1)
236
267
 
@@ -6,6 +6,7 @@
6
6
  from typing import Dict, Type, Any, Optional
7
7
  from .base_company import BaseCompany
8
8
  import logging
9
+ from injector import inject
9
10
 
10
11
 
11
12
  class CompanyRegistry:
@@ -14,6 +15,7 @@ class CompanyRegistry:
14
15
  Allow the client to register companies and instantiate them with dependency injection.
15
16
  """
16
17
 
18
+ @inject
17
19
  def __init__(self):
18
20
  self._company_classes: Dict[str, Type[BaseCompany]] = {}
19
21
  self._company_instances: Dict[str, BaseCompany] = {}
@@ -85,6 +87,9 @@ def get_company_registry() -> CompanyRegistry:
85
87
  """Get the global company registry instance."""
86
88
  return _company_registry
87
89
 
90
+ def get_registered_companies() -> Dict[str, Type[BaseCompany]]:
91
+ return _company_registry.get_registered_companies()
92
+
88
93
 
89
94
  def set_company_registry(registry: CompanyRegistry) -> None:
90
95
  """
@@ -9,20 +9,26 @@ from flask_injector import FlaskInjector
9
9
  from flask_bcrypt import Bcrypt
10
10
  from flask_cors import CORS
11
11
  from iatoolkit.common.exceptions import IAToolkitException
12
- from typing import Optional, Dict, Any
13
12
  from iatoolkit.repositories.database_manager import DatabaseManager
13
+ from iatoolkit.common.interfaces.asset_storage import AssetRepository
14
+ from iatoolkit.company_registry import get_registered_companies
14
15
  from werkzeug.middleware.proxy_fix import ProxyFix
15
16
  from injector import Binder, Injector, singleton
17
+ from typing import Optional, Dict, Any
16
18
  from urllib.parse import urlparse
17
19
  import redis
18
20
  import logging
19
21
  import os
20
22
 
21
23
  from iatoolkit import __version__ as IATOOLKIT_VERSION
24
+ from iatoolkit.services.configuration_service import ConfigurationService
22
25
 
23
26
  # global variable for the unique instance of IAToolkit
24
27
  _iatoolkit_instance: Optional['IAToolkit'] = None
25
28
 
29
+ def is_bound(injector: Injector, cls) -> bool:
30
+ return cls in injector.binder._bindings
31
+
26
32
  class IAToolkit:
27
33
  """
28
34
  IAToolkit main class
@@ -49,8 +55,8 @@ class IAToolkit:
49
55
  self.config = config or {}
50
56
  self.app = None
51
57
  self.db_manager = None
52
- self._injector = None
53
- self.version = IATOOLKIT_VERSION # default version
58
+ self._injector = Injector() # init empty injector
59
+ self.version = IATOOLKIT_VERSION
54
60
  self.license = "Community Edition"
55
61
 
56
62
  @classmethod
@@ -61,7 +67,7 @@ class IAToolkit:
61
67
  _iatoolkit_instance = cls()
62
68
  return _iatoolkit_instance
63
69
 
64
- def create_iatoolkit(self):
70
+ def create_iatoolkit(self, start: bool = True):
65
71
  """
66
72
  Creates, configures, and returns the Flask application instance.
67
73
  this is the main entry point for the application factory.
@@ -77,8 +83,8 @@ class IAToolkit:
77
83
  # Step 2: Set up the core components that DI depends on
78
84
  self._setup_database()
79
85
 
80
- # Step 3: Create the Injector and configure all dependencies in one place
81
- self._injector = Injector(self._configure_core_dependencies)
86
+ # Step 3: Configure dependencies using the existing injector
87
+ self._configure_core_dependencies(self._injector)
82
88
 
83
89
  # Step 4: Register routes using the fully configured injector
84
90
  self._register_routes()
@@ -98,6 +104,7 @@ class IAToolkit:
98
104
 
99
105
  # Step 8: Finalize setup within the application context
100
106
  self._setup_redis_sessions()
107
+
101
108
  self._setup_cors()
102
109
  self._setup_additional_services()
103
110
  self._setup_cli_commands()
@@ -107,11 +114,21 @@ class IAToolkit:
107
114
  # Step 9: define the download_dir
108
115
  self._setup_download_dir()
109
116
 
117
+ # register data source
118
+ if start:
119
+ self.register_data_sources()
120
+
110
121
  logging.info(f"🎉 IAToolkit {self.license} version {self.version} correctly initialized.")
111
122
  self._initialized = True
112
123
 
113
124
  return self.app
114
125
 
126
+ def register_data_sources(self):
127
+ # load the company configurations
128
+ configuration_service = self._injector.get(ConfigurationService)
129
+ for company in get_registered_companies():
130
+ configuration_service.register_data_sources(company)
131
+
115
132
  def _get_config_value(self, key: str, default=None):
116
133
  # get a value from the config dict or the environment variable
117
134
  return self.config.get(key, os.getenv(key, default))
@@ -181,11 +198,11 @@ class IAToolkit:
181
198
  os.environ["TOKENIZERS_PARALLELISM"] = "false"
182
199
 
183
200
  def _setup_database(self):
184
- database_uri = self._get_config_value('DATABASE_URI')
201
+ database_uri = self._get_config_value('DATABASE_URI') or self._get_config_value('DATABASE_URL')
185
202
  if not database_uri:
186
203
  raise IAToolkitException(
187
204
  IAToolkitException.ErrorType.CONFIG_ERROR,
188
- "DATABASE_URI is requires (config dict or env. variable)"
205
+ "DATABASE_URI is required (config dict or env. variable)"
189
206
  )
190
207
 
191
208
  self.db_manager = DatabaseManager(database_url=database_uri, schema='iatoolkit')
@@ -240,8 +257,9 @@ class IAToolkit:
240
257
  extra_origins = []
241
258
  all_company_instances = get_company_registry().get_all_company_instances()
242
259
  for company_name, company_instance in all_company_instances.items():
243
- cors_origin = company_instance.company.parameters.get('cors_origin', [])
244
- extra_origins += cors_origin
260
+ if company_instance.company:
261
+ cors_origin = company_instance.company.parameters.get('cors_origin', [])
262
+ extra_origins += cors_origin
245
263
 
246
264
  all_origins = default_origins + extra_origins
247
265
 
@@ -256,8 +274,11 @@ class IAToolkit:
256
274
 
257
275
  logging.info(f"✅ CORS configured for: {all_origins}")
258
276
 
259
- def _configure_core_dependencies(self, binder: Binder):
277
+ def _configure_core_dependencies(self, injector: Injector):
260
278
  """⚙️ Configures all system dependencies."""
279
+
280
+ # get the binder from injector
281
+ binder = injector.binder
261
282
  try:
262
283
  # Core dependencies
263
284
  binder.bind(Flask, to=self.app)
@@ -282,12 +303,17 @@ class IAToolkit:
282
303
  from iatoolkit.repositories.profile_repo import ProfileRepo
283
304
  from iatoolkit.repositories.llm_query_repo import LLMQueryRepo
284
305
  from iatoolkit.repositories.vs_repo import VSRepo
306
+ from iatoolkit.repositories.filesystem_asset_repository import FileSystemAssetRepository
285
307
 
286
308
  binder.bind(DocumentRepo, to=DocumentRepo)
287
309
  binder.bind(ProfileRepo, to=ProfileRepo)
288
310
  binder.bind(LLMQueryRepo, to=LLMQueryRepo)
289
311
  binder.bind(VSRepo, to=VSRepo)
290
312
 
313
+ # this class can be setup befor by iatoolkit enterprise
314
+ if not is_bound(self._injector, AssetRepository):
315
+ binder.bind(AssetRepository, to=FileSystemAssetRepository)
316
+
291
317
  def _bind_services(self, binder: Binder):
292
318
  from iatoolkit.services.query_service import QueryService
293
319
  from iatoolkit.services.benchmark_service import BenchmarkService
@@ -308,7 +334,8 @@ class IAToolkit:
308
334
  from iatoolkit.services.tool_service import ToolService
309
335
  from iatoolkit.services.llm_client_service import llmClient
310
336
  from iatoolkit.services.auth_service import AuthService
311
-
337
+ from iatoolkit.services.sql_service import SqlService
338
+ from iatoolkit.services.knowledge_base_service import KnowledgeBaseService
312
339
 
313
340
  binder.bind(QueryService, to=QueryService)
314
341
  binder.bind(BenchmarkService, to=BenchmarkService)
@@ -329,6 +356,8 @@ class IAToolkit:
329
356
  binder.bind(ToolService, to=ToolService)
330
357
  binder.bind(llmClient, to=llmClient)
331
358
  binder.bind(AuthService, to=AuthService)
359
+ binder.bind(SqlService, to=SqlService)
360
+ binder.bind(KnowledgeBaseService, to=KnowledgeBaseService)
332
361
 
333
362
  def _bind_infrastructure(self, binder: Binder):
334
363
  from iatoolkit.infra.llm_proxy import LLMProxy
@@ -405,11 +434,13 @@ class IAToolkit:
405
434
  'app_name': 'IAToolkit',
406
435
  'user_identifier': SessionManager.get('user_identifier'),
407
436
  'company_short_name': SessionManager.get('company_short_name'),
437
+ 'user_role': user_profile.get('user_role'),
408
438
  'user_is_local': user_profile.get('user_is_local'),
409
439
  'user_email': user_profile.get('user_email'),
410
440
  'iatoolkit_base_url': request.url_root,
411
441
  'flashed_messages': get_flashed_messages(with_categories=True),
412
- 't': translate_for_template
442
+ 't': translate_for_template,
443
+ 'google_analytics_id': self._get_config_value('GOOGLE_ANALYTICS_ID', ''),
413
444
  }
414
445
 
415
446
  def _get_default_static_folder(self) -> str:
@@ -473,6 +504,7 @@ class IAToolkit:
473
504
  logging.info(f"✅ download dir created in: {download_dir}")
474
505
 
475
506
 
507
+
476
508
  def current_iatoolkit() -> IAToolkit:
477
509
  return IAToolkit.get_instance()
478
510
 
@@ -40,6 +40,7 @@ class FileConnectorFactory:
40
40
  return S3Connector(
41
41
  bucket=config['bucket'],
42
42
  prefix=config.get('prefix', ''),
43
+ folder=config.get('folder', ''),
43
44
  auth=auth
44
45
  )
45
46
 
@@ -9,14 +9,16 @@ from typing import List
9
9
 
10
10
 
11
11
  class S3Connector(FileConnector):
12
- def __init__(self, bucket: str, prefix: str, auth: dict):
12
+ def __init__(self, bucket: str, prefix: str, folder: str, auth: dict):
13
13
  self.bucket = bucket
14
14
  self.prefix = prefix
15
+ self.folder = folder
15
16
  self.s3 = boto3.client('s3', **auth)
16
17
 
17
18
  def list_files(self) -> List[dict]:
18
19
  # list all the files as dictionaries, with keys: 'path', 'name' y 'metadata'.
19
- response = self.s3.list_objects_v2(Bucket=self.bucket, Prefix=self.prefix)
20
+ prefix = f'{self.prefix}/{self.folder}/'
21
+ response = self.s3.list_objects_v2(Bucket=self.bucket, Prefix=prefix)
20
22
  files = response.get('Contents', [])
21
23
 
22
24
  return [