iatoolkit 2.18.7__tar.gz → 2.20.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 (245) hide show
  1. {iatoolkit-2.18.7/src/iatoolkit.egg-info → iatoolkit-2.20.0}/PKG-INFO +1 -1
  2. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/__init__.py +1 -1
  3. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/repositories/database_manager.py +25 -1
  4. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/runtime_logging.py +1 -1
  5. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/company_context_service.py +13 -11
  6. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/configuration_service.py +0 -7
  7. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/context_builder_service.py +5 -2
  8. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/sql_service.py +113 -12
  9. {iatoolkit-2.18.7 → iatoolkit-2.20.0/src/iatoolkit.egg-info}/PKG-INFO +1 -1
  10. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/LICENSE +0 -0
  11. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/LICENSE_COMMUNITY.md +0 -0
  12. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/pyproject.toml +0 -0
  13. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/readme.md +0 -0
  14. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/requirements.txt +0 -0
  15. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/setup.cfg +0 -0
  16. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/base_company.py +0 -0
  17. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/cli_commands.py +0 -0
  18. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/common/__init__.py +0 -0
  19. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/common/exceptions.py +0 -0
  20. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/common/interfaces/__init__.py +0 -0
  21. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/common/interfaces/asset_storage.py +0 -0
  22. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/common/interfaces/database_provider.py +0 -0
  23. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/common/interfaces/memory_compilation_trigger.py +0 -0
  24. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/common/interfaces/memory_lint_trigger.py +0 -0
  25. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/common/interfaces/secret_provider.py +0 -0
  26. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/common/interfaces/signup_policy_resolver.py +0 -0
  27. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/common/interfaces/web_search_provider.py +0 -0
  28. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/common/model_registry.py +0 -0
  29. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/common/routes.py +0 -0
  30. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/common/secret_resolver.py +0 -0
  31. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/common/session_manager.py +0 -0
  32. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/common/util.py +0 -0
  33. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/company_registry.py +0 -0
  34. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/config/__init__.py +0 -0
  35. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/config/llm_capabilities.yaml +0 -0
  36. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/config/system_prompts/channel_business_identity.prompt +0 -0
  37. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/config/system_prompts/channel_conversation_continuity.prompt +0 -0
  38. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/config/system_prompts/channel_response_style.prompt +0 -0
  39. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/config/system_prompts/chat_state_rules.prompt +0 -0
  40. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/config/system_prompts/chat_user_profile.prompt +0 -0
  41. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/config/system_prompts/core_identity.prompt +0 -0
  42. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/config/system_prompts/email_output.prompt +0 -0
  43. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/config/system_prompts/file_download_output.prompt +0 -0
  44. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/config/system_prompts/format_styles.prompt +0 -0
  45. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/config/system_prompts/html_structures.prompt +0 -0
  46. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/config/system_prompts/links_documents.prompt +0 -0
  47. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/config/system_prompts/memory_usage.prompt +0 -0
  48. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/config/system_prompts/multimodal_basics.prompt +0 -0
  49. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/config/system_prompts/output_basics.prompt +0 -0
  50. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/config/system_prompts/presentation_formatting.prompt +0 -0
  51. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/config/system_prompts/query_main.prompt +0 -0
  52. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/config/system_prompts/sql_aggregation_scope.prompt +0 -0
  53. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/config/system_prompts/sql_casting.prompt +0 -0
  54. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/config/system_prompts/sql_core.prompt +0 -0
  55. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/config/system_prompts/sql_jsonb.prompt +0 -0
  56. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/config/system_prompts/sql_mysql_casting.prompt +0 -0
  57. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/config/system_prompts/sql_mysql_json.prompt +0 -0
  58. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/config/system_prompts/sql_redshift_basics.prompt +0 -0
  59. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/config/system_prompts/sql_redshift_types.prompt +0 -0
  60. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/config/system_prompts/sql_rules.prompt +0 -0
  61. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/config/system_prompts/tool_html_passthrough.prompt +0 -0
  62. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/config/system_prompts_pack.yaml +0 -0
  63. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/config/system_tools_pack.yaml +0 -0
  64. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/core.py +0 -0
  65. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/infra/__init__.py +0 -0
  66. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/infra/brevo_mail_app.py +0 -0
  67. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/infra/call_service.py +0 -0
  68. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/infra/connectors/__init__.py +0 -0
  69. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/infra/connectors/file_connector.py +0 -0
  70. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/infra/connectors/file_connector_factory.py +0 -0
  71. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/infra/connectors/google_cloud_storage_connector.py +0 -0
  72. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/infra/connectors/google_drive_connector.py +0 -0
  73. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/infra/connectors/local_file_connector.py +0 -0
  74. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/infra/connectors/s3_connector.py +0 -0
  75. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/infra/google_auth_client.py +0 -0
  76. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/infra/google_chat_app.py +0 -0
  77. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/infra/inference_embeddings_client.py +0 -0
  78. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/infra/inference_handler.py +0 -0
  79. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/infra/jina_embeddings_client.py +0 -0
  80. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/infra/llm_gateway_resolver.py +0 -0
  81. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/infra/llm_providers/__init__.py +0 -0
  82. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/infra/llm_providers/anthropic_adapter.py +0 -0
  83. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/infra/llm_providers/deepseek_adapter.py +0 -0
  84. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/infra/llm_providers/gemini_adapter.py +0 -0
  85. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/infra/llm_providers/openai_adapter.py +0 -0
  86. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/infra/llm_providers/openai_compatible_chat_adapter.py +0 -0
  87. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/infra/llm_providers/openrouter_adapter.py +0 -0
  88. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/infra/llm_proxy.py +0 -0
  89. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/infra/llm_response.py +0 -0
  90. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/infra/redis_session_manager.py +0 -0
  91. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/locales/en.yaml +0 -0
  92. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/locales/es.yaml +0 -0
  93. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/repositories/__init__.py +0 -0
  94. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/repositories/api_key_repo.py +0 -0
  95. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/repositories/document_repo.py +0 -0
  96. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/repositories/env_secret_provider.py +0 -0
  97. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/repositories/filesystem_asset_repository.py +0 -0
  98. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/repositories/llm_query_repo.py +0 -0
  99. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/repositories/mcp_token_repo.py +0 -0
  100. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/repositories/memory_repo.py +0 -0
  101. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/repositories/models.py +0 -0
  102. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/repositories/profile_repo.py +0 -0
  103. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/repositories/prompt_resource_repo.py +0 -0
  104. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/repositories/sql_dataset_repo.py +0 -0
  105. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/repositories/sql_source_repo.py +0 -0
  106. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/repositories/vs_repo.py +0 -0
  107. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/__init__.py +0 -0
  108. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/api_key_service.py +0 -0
  109. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/attachment_policy_service.py +0 -0
  110. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/auth_service.py +0 -0
  111. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/benchmark_service.py +0 -0
  112. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/branding_service.py +0 -0
  113. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/dispatcher_service.py +0 -0
  114. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/embedding_service.py +0 -0
  115. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/excel_service.py +0 -0
  116. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/file_processor_service.py +0 -0
  117. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/history_manager_service.py +0 -0
  118. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/http_tool_service.py +0 -0
  119. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/i18n_service.py +0 -0
  120. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/inference_service.py +0 -0
  121. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/jwt_service.py +0 -0
  122. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/knowledge_base_service.py +0 -0
  123. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/language_service.py +0 -0
  124. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/license_service.py +0 -0
  125. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/llm_client_service.py +0 -0
  126. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/mail_service.py +0 -0
  127. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/mcp_token_service.py +0 -0
  128. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/memory_compiler_service.py +0 -0
  129. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/memory_lint_service.py +0 -0
  130. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/memory_lookup_policy_service.py +0 -0
  131. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/memory_service.py +0 -0
  132. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/memory_wiki_service.py +0 -0
  133. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/noop_memory_compilation_trigger.py +0 -0
  134. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/noop_memory_lint_trigger.py +0 -0
  135. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/parsers/__init__.py +0 -0
  136. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/parsers/contracts.py +0 -0
  137. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/parsers/image_normalizer.py +0 -0
  138. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/parsers/parsing_service.py +0 -0
  139. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/parsers/pdf_ocr_detection.py +0 -0
  140. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/parsers/provider_factory.py +0 -0
  141. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/parsers/provider_resolver.py +0 -0
  142. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/parsers/providers/__init__.py +0 -0
  143. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/parsers/providers/basic_provider.py +0 -0
  144. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/parsers/providers/docling_provider.py +0 -0
  145. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/parsers/validator.py +0 -0
  146. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/pdf_service.py +0 -0
  147. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/profile_service.py +0 -0
  148. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/prompt_resource_service.py +0 -0
  149. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/prompt_service.py +0 -0
  150. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/query_service.py +0 -0
  151. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/signup_policy_resolver.py +0 -0
  152. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/sql_dataset_service.py +0 -0
  153. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/sql_source_service.py +0 -0
  154. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/storage_service.py +0 -0
  155. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/structured_output_service.py +0 -0
  156. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/system_prompt_catalog.py +0 -0
  157. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/system_tools.py +0 -0
  158. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/telemetry_service.py +0 -0
  159. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/tool_service.py +0 -0
  160. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/user_feedback_service.py +0 -0
  161. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/user_session_context_service.py +0 -0
  162. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/visual_kb_service.py +0 -0
  163. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/visual_tool_service.py +0 -0
  164. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/warmup_service.py +0 -0
  165. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/web_search/__init__.py +0 -0
  166. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/web_search/provider_factory.py +0 -0
  167. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/web_search/providers/__init__.py +0 -0
  168. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/web_search/providers/brave_provider.py +0 -0
  169. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/services/web_search_service.py +0 -0
  170. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/static/images/fernando.jpeg +0 -0
  171. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/static/images/iatoolkit_core.png +0 -0
  172. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/static/images/iatoolkit_logo.png +0 -0
  173. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/static/js/chat_feedback_button.js +0 -0
  174. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/static/js/chat_filepond.js +0 -0
  175. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/static/js/chat_help_content.js +0 -0
  176. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/static/js/chat_history_button.js +0 -0
  177. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/static/js/chat_logout_button.js +0 -0
  178. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/static/js/chat_main.js +0 -0
  179. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/static/js/chat_memory_button.js +0 -0
  180. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/static/js/chat_model_selector.js +0 -0
  181. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/static/js/chat_onboarding_button.js +0 -0
  182. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/static/js/chat_prompt_manager.js +0 -0
  183. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/static/js/chat_reload_button.js +0 -0
  184. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/static/styles/chat_iatoolkit.css +0 -0
  185. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/static/styles/chat_modal.css +0 -0
  186. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/static/styles/chat_public.css +0 -0
  187. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/static/styles/documents.css +0 -0
  188. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/static/styles/landing_page.css +0 -0
  189. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/static/styles/llm_output.css +0 -0
  190. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/static/styles/onboarding.css +0 -0
  191. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/templates/_company_header.html +0 -0
  192. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/templates/_login_widget.html +0 -0
  193. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/templates/account.html +0 -0
  194. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/templates/base.html +0 -0
  195. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/templates/change_password.html +0 -0
  196. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/templates/chat.html +0 -0
  197. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/templates/chat_memory_modal.html +0 -0
  198. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/templates/chat_modals.html +0 -0
  199. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/templates/error.html +0 -0
  200. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/templates/forgot_password.html +0 -0
  201. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/templates/home_hosted_default.html +0 -0
  202. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/templates/memory/wiki_schema.md +0 -0
  203. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/templates/onboarding_shell.html +0 -0
  204. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/templates/pdf/base.html +0 -0
  205. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/templates/pdf/letter.html +0 -0
  206. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/templates/pdf/report.html +0 -0
  207. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/templates/pdf/simple.html +0 -0
  208. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/templates/signup.html +0 -0
  209. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/views/__init__.py +0 -0
  210. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/views/account_view.py +0 -0
  211. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/views/api_key_api_view.py +0 -0
  212. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/views/base_login_view.py +0 -0
  213. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/views/categories_api_view.py +0 -0
  214. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/views/change_password_view.py +0 -0
  215. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/views/chat_context_preview_api_view.py +0 -0
  216. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/views/chat_view.py +0 -0
  217. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/views/configuration_api_view.py +0 -0
  218. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/views/connectors_api_view.py +0 -0
  219. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/views/embedding_api_view.py +0 -0
  220. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/views/forgot_password_view.py +0 -0
  221. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/views/help_content_api_view.py +0 -0
  222. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/views/history_api_view.py +0 -0
  223. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/views/home_view.py +0 -0
  224. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/views/init_context_api_view.py +0 -0
  225. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/views/llmquery_api_view.py +0 -0
  226. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/views/load_document_api_view.py +0 -0
  227. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/views/login_view.py +0 -0
  228. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/views/logout_api_view.py +0 -0
  229. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/views/memory_api_view.py +0 -0
  230. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/views/profile_api_view.py +0 -0
  231. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/views/prompt_api_view.py +0 -0
  232. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/views/prompt_context_preview_api_view.py +0 -0
  233. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/views/prompt_resource_api_view.py +0 -0
  234. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/views/rag_api_view.py +0 -0
  235. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/views/root_redirect_view.py +0 -0
  236. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/views/signup_view.py +0 -0
  237. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/views/static_page_view.py +0 -0
  238. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/views/tool_api_view.py +0 -0
  239. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/views/user_feedback_api_view.py +0 -0
  240. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/views/users_api_view.py +0 -0
  241. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit/views/verify_user_view.py +0 -0
  242. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit.egg-info/SOURCES.txt +0 -0
  243. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit.egg-info/dependency_links.txt +0 -0
  244. {iatoolkit-2.18.7 → iatoolkit-2.20.0}/src/iatoolkit.egg-info/requires.txt +0 -0
  245. {iatoolkit-2.18.7 → iatoolkit-2.20.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: 2.18.7
3
+ Version: 2.20.0
4
4
  Summary: IAToolkit
5
5
  Author: Fernando Libedinsky
6
6
  License-Expression: MIT
@@ -3,7 +3,7 @@
3
3
  #
4
4
  # IAToolkit is open source software.
5
5
 
6
- __version__ = "2.18.7"
6
+ __version__ = "2.20.0"
7
7
 
8
8
  # Expose main classes and functions at the top level of the package
9
9
 
@@ -19,6 +19,7 @@ class DatabaseManager(DatabaseProvider):
19
19
  _POSTGRES_BOOTSTRAP_PATCHES = (
20
20
  )
21
21
  _DEFAULT_CONNECT_TIMEOUT = 60
22
+ MAX_RESULT_ROWS = 1000
22
23
 
23
24
  @inject
24
25
  def __init__(self,
@@ -42,6 +43,7 @@ class DatabaseManager(DatabaseProvider):
42
43
 
43
44
  self.url = make_url(database_url)
44
45
  self.backend = self.url.get_backend_name()
46
+ self.statement_timeout_seconds = self._resolve_statement_timeout(timeout)
45
47
  if self._is_redshift():
46
48
  self._ensure_redshift_dialect_registered()
47
49
  self.engine_url = self._build_engine_url()
@@ -114,6 +116,13 @@ class DatabaseManager(DatabaseProvider):
114
116
 
115
117
  return self.timeout
116
118
 
119
+ def _resolve_statement_timeout(self, timeout: int | str | None) -> int | None:
120
+ explicit_timeout = timeout is not None
121
+ url_timeout_present = any(self.url.query.get(key) is not None for key in ("timeout", "connect_timeout"))
122
+ if not explicit_timeout and not url_timeout_present:
123
+ return None
124
+ return self._resolve_timeout()
125
+
117
126
  def _build_engine_url(self):
118
127
  normalized_url = self.url
119
128
  if self._is_redshift():
@@ -216,6 +225,15 @@ class DatabaseManager(DatabaseProvider):
216
225
  def get_dialect(self) -> str:
217
226
  return str(self.backend or "").strip().lower()
218
227
 
228
+ def _apply_statement_timeout(self, session) -> None:
229
+ if not self._is_postgres():
230
+ return
231
+ if self.statement_timeout_seconds is None:
232
+ return
233
+
234
+ timeout_ms = max(int(self.statement_timeout_seconds * 1000), 1)
235
+ session.execute(text(f"SET LOCAL statement_timeout = {timeout_ms}"))
236
+
219
237
  def create_all(self):
220
238
  # if there is a schema defined, make sure it exists before creating tables
221
239
  if self.schema and self._is_postgres():
@@ -264,6 +282,7 @@ class DatabaseManager(DatabaseProvider):
264
282
  normalized_schema = str(self.schema or "").strip()
265
283
  if normalized_schema and normalized_schema.lower() != "public":
266
284
  session.execute(text(f"SET search_path TO {normalized_schema}, public"))
285
+ self._apply_statement_timeout(session)
267
286
 
268
287
  result = session.execute(text(query), params or {})
269
288
  if commit:
@@ -272,7 +291,12 @@ class DatabaseManager(DatabaseProvider):
272
291
  if result.returns_rows:
273
292
  # Convert SQLAlchemy rows to list of dicts immediately
274
293
  cols = result.keys()
275
- return [dict(zip(cols, row)) for row in result.fetchall()]
294
+ rows = result.fetchmany(self.MAX_RESULT_ROWS + 1)
295
+ if len(rows) > self.MAX_RESULT_ROWS:
296
+ raise ValueError(
297
+ f"Query returned more than {self.MAX_RESULT_ROWS} rows. Refine the query with filters or LIMIT."
298
+ )
299
+ return [dict(zip(cols, row)) for row in rows]
276
300
 
277
301
  return {'rowcount': result.rowcount}
278
302
 
@@ -19,7 +19,7 @@ def configure_runtime_logging() -> None:
19
19
  log_level = _runtime_log_level()
20
20
 
21
21
  _ensure_stdout_handler(logging.getLogger(), formatter, log_level)
22
- _ensure_stdout_handler(logging.getLogger(RUNTIME_LOGGER_NAME), formatter, log_level)
22
+ logging.getLogger(RUNTIME_LOGGER_NAME).propagate = True
23
23
  _preserve_stdout_handler_across_basic_config(formatter)
24
24
 
25
25
  seen_handlers: set[int] = set()
@@ -50,6 +50,7 @@ class CompanyContextService:
50
50
  company_short_name: str,
51
51
  *,
52
52
  include_sql_context: bool = True,
53
+ include_yaml_context: bool = True,
53
54
  selected_context_files: List[str] | None = None,
54
55
  ) -> dict[str, str]:
55
56
  """
@@ -83,17 +84,18 @@ class CompanyContextService:
83
84
  except Exception as e:
84
85
  logging.warning(f"Could not generate SQL context for '{company_short_name}': {e}")
85
86
 
86
- # 4. Context from residual yaml (schema/*.yaml) files
87
- try:
88
- yaml_schema_context = self._get_yaml_schema_context(
89
- company_short_name,
90
- db_tables,
91
- sql_source_table_scopes=sql_source_table_scopes,
92
- ).strip()
93
- if yaml_schema_context:
94
- yaml_context = f"## Esquemas adicionales\n\n{yaml_schema_context}"
95
- except Exception as e:
96
- logging.warning(f"Could not load Yaml context for '{company_short_name}': {e}")
87
+ # 3. Context from residual yaml (schema/*.yaml) files
88
+ if include_yaml_context:
89
+ try:
90
+ yaml_schema_context = self._get_yaml_schema_context(
91
+ company_short_name,
92
+ db_tables,
93
+ sql_source_table_scopes=sql_source_table_scopes,
94
+ ).strip()
95
+ if yaml_schema_context:
96
+ yaml_context = f"## Esquemas adicionales\n\n{yaml_schema_context}"
97
+ except Exception as e:
98
+ logging.warning(f"Could not load Yaml context for '{company_short_name}': {e}")
97
99
 
98
100
  return {
99
101
  "markdown_context": md_context,
@@ -247,10 +247,6 @@ class ConfigurationService:
247
247
  # 5. Register Knowledge base information
248
248
  self._register_knowledge_base(company_short_name, config)
249
249
 
250
- # 6. Sync SQL source catalog from YAML to DB.
251
- # Runtime registration is resolved from DB entries.
252
- self._sync_sql_sources(company_short_name, config)
253
-
254
250
  # Keep runtime cache aligned with the latest loaded configuration.
255
251
  self._loaded_configs[company_short_name] = config or {}
256
252
 
@@ -388,7 +384,6 @@ class ConfigurationService:
388
384
  config: dict = None):
389
385
  """
390
386
  Resolves runtime SQL registrations from the SQL source catalog table.
391
- YAML data_sources are synchronized into the catalog before refresh.
392
387
 
393
388
  Public method: Can be called externally after initialization (e.g. by Enterprise)
394
389
  to re-register sources once new factories (like 'bridge') are available.
@@ -402,8 +397,6 @@ class ConfigurationService:
402
397
  if not config:
403
398
  return
404
399
 
405
- self._sync_sql_sources(company_short_name, config or {})
406
-
407
400
  from iatoolkit import current_iatoolkit
408
401
  from iatoolkit.services.sql_source_service import SqlSourceService
409
402
  sql_source_service = current_iatoolkit().get_injector().get(SqlSourceService)
@@ -354,7 +354,11 @@ class ContextBuilderService:
354
354
  collection_names=rag_collections,
355
355
  )
356
356
 
357
- company_context_blocks = self.company_context_service.get_company_context_blocks(company_short_name)
357
+ company_context_blocks = self.company_context_service.get_company_context_blocks(
358
+ company_short_name,
359
+ include_sql_context=False,
360
+ include_yaml_context=False,
361
+ )
358
362
  final_system_context = self._join_context_sections(
359
363
  rendered_sections.get("identity"),
360
364
  rendered_sections.get("business_context"),
@@ -364,7 +368,6 @@ class ContextBuilderService:
364
368
  collection_context,
365
369
  rendered_sections.get("data_access_rules"),
366
370
  sql_context,
367
- company_context_blocks.get("yaml_context"),
368
371
  rendered_sections.get("output_contract"),
369
372
  )
370
373
 
@@ -12,6 +12,7 @@ from injector import inject, singleton
12
12
  from typing import Callable
13
13
  import json
14
14
  import logging
15
+ import re
15
16
 
16
17
 
17
18
  @singleton
@@ -20,6 +21,20 @@ class SqlService:
20
21
  Manages database connections and executes SQL statements.
21
22
  It maintains a cache of named DatabaseManager instances to avoid reconnecting.
22
23
  """
24
+ MAX_QUERY_ROWS = 1000
25
+ _ALLOWED_QUERY_PREFIXES = ("SELECT", "WITH")
26
+ _BLOCKED_SQL_PATTERN = re.compile(
27
+ r"\b(?:INSERT|UPDATE|DELETE|DROP|ALTER|CREATE|TRUNCATE|MERGE|CALL|COPY|GRANT|REVOKE|"
28
+ r"BEGIN|COMMIT|ROLLBACK|SAVEPOINT|RELEASE|VACUUM|ANALYZE|CLUSTER|REFRESH|"
29
+ r"EXEC(?:UTE)?|DO|SET|RESET|USE|PRAGMA|ATTACH|DETACH|REINDEX|LOCK|UNLOCK|INTO)\b",
30
+ re.IGNORECASE,
31
+ )
32
+ _SINGLE_QUOTED_LITERAL_RE = re.compile(r"'(?:''|[^'])*'")
33
+ _DOUBLE_QUOTED_LITERAL_RE = re.compile(r'"(?:""|[^"])*"')
34
+ _BACKTICK_LITERAL_RE = re.compile(r"`[^`]*`")
35
+ _BRACKET_LITERAL_RE = re.compile(r"\[[^\]]*\]")
36
+ _BLOCK_COMMENT_RE = re.compile(r"/\*.*?\*/", re.DOTALL)
37
+ _LINE_COMMENT_RE = re.compile(r"--[^\r\n]*")
23
38
 
24
39
  @inject
25
40
  def __init__(self,
@@ -155,6 +170,92 @@ class SqlService:
155
170
  f"Database '{db_name}' is not registered for this company."
156
171
  )
157
172
 
173
+ @classmethod
174
+ def _sanitize_sql_for_validation(cls, query: str) -> str:
175
+ sanitized = str(query or "")
176
+ for pattern in (
177
+ cls._SINGLE_QUOTED_LITERAL_RE,
178
+ cls._DOUBLE_QUOTED_LITERAL_RE,
179
+ cls._BACKTICK_LITERAL_RE,
180
+ cls._BRACKET_LITERAL_RE,
181
+ ):
182
+ sanitized = pattern.sub(" ", sanitized)
183
+ sanitized = cls._BLOCK_COMMENT_RE.sub("", sanitized)
184
+ sanitized = cls._LINE_COMMENT_RE.sub("", sanitized)
185
+ return re.sub(r"\s+", " ", sanitized).strip()
186
+
187
+ def _assert_read_only_query(self, query: str) -> str:
188
+ normalized_query = str(query or "").strip()
189
+ if not normalized_query:
190
+ raise IAToolkitException(
191
+ IAToolkitException.ErrorType.DATABASE_ERROR,
192
+ "SQL query is required.",
193
+ )
194
+
195
+ sanitized = self._sanitize_sql_for_validation(normalized_query)
196
+ if not sanitized:
197
+ raise IAToolkitException(
198
+ IAToolkitException.ErrorType.DATABASE_ERROR,
199
+ "SQL query is required.",
200
+ )
201
+ sanitized_without_trailing_semicolon = re.sub(r";+\s*$", "", sanitized).strip()
202
+ if not sanitized_without_trailing_semicolon:
203
+ raise IAToolkitException(
204
+ IAToolkitException.ErrorType.DATABASE_ERROR,
205
+ "SQL query is required.",
206
+ )
207
+ if ";" in sanitized_without_trailing_semicolon:
208
+ raise IAToolkitException(
209
+ IAToolkitException.ErrorType.DATABASE_ERROR,
210
+ "Only a single read-only SQL statement is allowed.",
211
+ )
212
+
213
+ upper_sanitized = sanitized_without_trailing_semicolon.upper()
214
+ blocked_match = self._BLOCKED_SQL_PATTERN.search(upper_sanitized)
215
+ if blocked_match:
216
+ blocked_keyword = blocked_match.group(0).upper()
217
+ raise IAToolkitException(
218
+ IAToolkitException.ErrorType.DATABASE_ERROR,
219
+ f"Blocked SQL keyword detected: {blocked_keyword}.",
220
+ )
221
+
222
+ if not upper_sanitized.startswith(self._ALLOWED_QUERY_PREFIXES):
223
+ raise IAToolkitException(
224
+ IAToolkitException.ErrorType.DATABASE_ERROR,
225
+ "Only read-only SELECT statements are allowed.",
226
+ )
227
+ if upper_sanitized.startswith("WITH") and not re.search(r"\bSELECT\b", upper_sanitized):
228
+ raise IAToolkitException(
229
+ IAToolkitException.ErrorType.DATABASE_ERROR,
230
+ "WITH queries must resolve to a read-only SELECT statement.",
231
+ )
232
+
233
+ return normalized_query
234
+
235
+ def _enforce_result_row_limit(self, result_data):
236
+ if isinstance(result_data, list) and len(result_data) > self.MAX_QUERY_ROWS:
237
+ raise IAToolkitException(
238
+ IAToolkitException.ErrorType.DATABASE_ERROR,
239
+ f"Query returned more than {self.MAX_QUERY_ROWS} rows. Refine the query with filters or LIMIT.",
240
+ )
241
+
242
+ @staticmethod
243
+ def _cleanup_provider_execution(provider: DatabaseProvider):
244
+ remove_session = getattr(provider, "remove_session", None)
245
+ if callable(remove_session):
246
+ try:
247
+ remove_session()
248
+ return
249
+ except Exception as exc:
250
+ logging.debug("Failed to remove SQL provider session: %s", exc)
251
+
252
+ rollback = getattr(provider, "rollback", None)
253
+ if callable(rollback):
254
+ try:
255
+ rollback()
256
+ except Exception as exc:
257
+ logging.debug("Failed to rollback SQL provider session: %s", exc)
258
+
158
259
  def exec_sql(self, company_short_name: str, **kwargs):
159
260
  """
160
261
  Executes a raw SQL statement against a registered database provider.
@@ -163,27 +264,32 @@ class SqlService:
163
264
  database_name = kwargs.get('database_key')
164
265
  query = kwargs.get('query')
165
266
  format = kwargs.get('format', 'json')
166
- commit = kwargs.get('commit')
167
267
  params = kwargs.get('params')
268
+ provider = None
269
+ cleanup_required = False
168
270
 
169
271
  if not database_name:
170
272
  raise IAToolkitException(IAToolkitException.ErrorType.DATABASE_ERROR,
171
273
  'missing database_name in call to exec_sql')
274
+ if kwargs.get('commit'):
275
+ logging.warning("Ignoring commit=True for read-only SQL execution against '%s'.", database_name)
172
276
 
173
277
  try:
174
278
  # 1. Get the abstract provider (could be Direct or Bridge)
175
279
  provider = self.get_database_provider(company_short_name, database_name)
176
- db_schema = self._db_schemas[(company_short_name, database_name)]
280
+ safe_query = self._assert_read_only_query(query)
177
281
 
178
282
  # 2. Delegate execution
179
283
  # The provider returns a clean List[Dict] or Dict result
180
284
  execute_kwargs = {
181
- "query": query,
182
- "commit": commit,
285
+ "query": safe_query,
286
+ "commit": False,
183
287
  }
184
288
  if params is not None:
185
289
  execute_kwargs["params"] = params
290
+ cleanup_required = True
186
291
  result_data = provider.execute_query(**execute_kwargs)
292
+ self._enforce_result_row_limit(result_data)
187
293
 
188
294
  # 3. Handle Formatting (Service layer responsibility)
189
295
  if format == 'dict':
@@ -195,14 +301,6 @@ class SqlService:
195
301
  except IAToolkitException:
196
302
  raise
197
303
  except Exception as e:
198
- # Attempt rollback if supported/needed
199
- try:
200
- provider = self.get_database_provider(company_short_name, database_name)
201
- if provider:
202
- provider.rollback()
203
- except Exception:
204
- pass
205
-
206
304
  error_message = str(e)
207
305
  if 'timed out' in str(e):
208
306
  error_message = self.i18n_service.t('errors.timeout')
@@ -210,6 +308,9 @@ class SqlService:
210
308
  logging.error(f"Error executing SQL statement: {error_message}")
211
309
  raise IAToolkitException(IAToolkitException.ErrorType.DATABASE_ERROR,
212
310
  error_message) from e
311
+ finally:
312
+ if provider is not None and cleanup_required:
313
+ self._cleanup_provider_execution(provider)
213
314
 
214
315
  def commit(self, company_short_name: str, database_name: str):
215
316
  """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: iatoolkit
3
- Version: 2.18.7
3
+ Version: 2.20.0
4
4
  Summary: IAToolkit
5
5
  Author: Fernando Libedinsky
6
6
  License-Expression: MIT
File without changes
File without changes
File without changes
File without changes
File without changes