iatoolkit 2.74.3__tar.gz → 2.75.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 (283) hide show
  1. {iatoolkit-2.74.3/src/iatoolkit.egg-info → iatoolkit-2.75.0}/PKG-INFO +1 -1
  2. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/__init__.py +1 -1
  3. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/config/system_prompts/sql_core.prompt +6 -3
  4. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/config/system_tools_pack.yaml +33 -0
  5. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/company_context_service.py +24 -118
  6. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/dispatcher_service.py +2 -0
  7. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/llm_client_service.py +3 -2
  8. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/resource_access_scope.py +11 -2
  9. iatoolkit-2.75.0/src/iatoolkit/services/sql_catalog_service.py +260 -0
  10. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/tool_service.py +30 -1
  11. {iatoolkit-2.74.3 → iatoolkit-2.75.0/src/iatoolkit.egg-info}/PKG-INFO +1 -1
  12. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit.egg-info/SOURCES.txt +1 -0
  13. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/LICENSE +0 -0
  14. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/LICENSE_COMMUNITY.md +0 -0
  15. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/pyproject.toml +0 -0
  16. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/readme.md +0 -0
  17. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/setup.cfg +0 -0
  18. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/base_company.py +0 -0
  19. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/cli_commands.py +0 -0
  20. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/common/__init__.py +0 -0
  21. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/common/access.py +0 -0
  22. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/common/bridge_validation.py +0 -0
  23. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/common/company_paths.py +0 -0
  24. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/common/exceptions.py +0 -0
  25. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/common/interfaces/__init__.py +0 -0
  26. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/common/interfaces/asset_storage.py +0 -0
  27. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/common/interfaces/database_provider.py +0 -0
  28. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/common/interfaces/history_compaction_trigger.py +0 -0
  29. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/common/interfaces/memory_compilation_trigger.py +0 -0
  30. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/common/interfaces/secret_provider.py +0 -0
  31. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/common/interfaces/signup_policy_resolver.py +0 -0
  32. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/common/interfaces/web_search_provider.py +0 -0
  33. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/common/memory_tools.py +0 -0
  34. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/common/model_registry.py +0 -0
  35. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/common/routes.py +0 -0
  36. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/common/search_terms.py +0 -0
  37. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/common/secret_resolver.py +0 -0
  38. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/common/session_manager.py +0 -0
  39. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/common/text_splitter.py +0 -0
  40. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/common/url_safety.py +0 -0
  41. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/common/util.py +0 -0
  42. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/company_registry.py +0 -0
  43. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/config/__init__.py +0 -0
  44. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/config/llm_capabilities.yaml +0 -0
  45. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/config/system_agents/history_compaction.prompt +0 -0
  46. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/config/system_agents/memory_compiler.prompt +0 -0
  47. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/config/system_agents/memory_correction.prompt +0 -0
  48. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/config/system_agents/memory_document_ingest.prompt +0 -0
  49. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/config/system_agents/memory_image_ingest.prompt +0 -0
  50. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/config/system_agents/memory_meeting_ingest.prompt +0 -0
  51. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/config/system_agents/memory_question_review.prompt +0 -0
  52. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/config/system_agents_pack.yaml +0 -0
  53. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/config/system_prompts/channel_business_identity.prompt +0 -0
  54. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/config/system_prompts/channel_conversation_continuity.prompt +0 -0
  55. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/config/system_prompts/channel_response_style.prompt +0 -0
  56. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/config/system_prompts/chat_state_rules.prompt +0 -0
  57. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/config/system_prompts/chat_user_profile.prompt +0 -0
  58. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/config/system_prompts/core_identity.prompt +0 -0
  59. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/config/system_prompts/email_output.prompt +0 -0
  60. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/config/system_prompts/file_download_output.prompt +0 -0
  61. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/config/system_prompts/format_styles.prompt +0 -0
  62. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/config/system_prompts/html_structures.prompt +0 -0
  63. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/config/system_prompts/links_documents.prompt +0 -0
  64. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/config/system_prompts/memory_usage.prompt +0 -0
  65. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/config/system_prompts/multimodal_basics.prompt +0 -0
  66. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/config/system_prompts/output_basics.prompt +0 -0
  67. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/config/system_prompts/presentation_formatting.prompt +0 -0
  68. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/config/system_prompts/query_main.prompt +0 -0
  69. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/config/system_prompts/sql_aggregation_scope.prompt +0 -0
  70. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/config/system_prompts/sql_casting.prompt +0 -0
  71. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/config/system_prompts/sql_jsonb.prompt +0 -0
  72. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/config/system_prompts/sql_mysql_casting.prompt +0 -0
  73. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/config/system_prompts/sql_mysql_json.prompt +0 -0
  74. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/config/system_prompts/sql_redshift_basics.prompt +0 -0
  75. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/config/system_prompts/sql_redshift_types.prompt +0 -0
  76. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/config/system_prompts/sql_rules.prompt +0 -0
  77. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/config/system_prompts/tool_html_passthrough.prompt +0 -0
  78. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/config/system_prompts_pack.yaml +0 -0
  79. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/core.py +0 -0
  80. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/infra/__init__.py +0 -0
  81. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/infra/brevo_mail_app.py +0 -0
  82. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/infra/call_service.py +0 -0
  83. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/infra/connectors/__init__.py +0 -0
  84. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/infra/connectors/file_connector.py +0 -0
  85. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/infra/connectors/file_connector_factory.py +0 -0
  86. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/infra/connectors/google_cloud_storage_connector.py +0 -0
  87. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/infra/connectors/google_drive_connector.py +0 -0
  88. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/infra/connectors/local_file_connector.py +0 -0
  89. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/infra/connectors/s3_connector.py +0 -0
  90. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/infra/google_auth_client.py +0 -0
  91. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/infra/google_chat_app.py +0 -0
  92. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/infra/inference_embeddings_client.py +0 -0
  93. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/infra/inference_handler.py +0 -0
  94. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/infra/jina_embeddings_client.py +0 -0
  95. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/infra/llm_gateway_resolver.py +0 -0
  96. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/infra/llm_providers/__init__.py +0 -0
  97. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/infra/llm_providers/anthropic_adapter.py +0 -0
  98. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/infra/llm_providers/deepseek_adapter.py +0 -0
  99. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/infra/llm_providers/gemini_adapter.py +0 -0
  100. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/infra/llm_providers/openai_adapter.py +0 -0
  101. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/infra/llm_providers/openai_compatible_chat_adapter.py +0 -0
  102. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/infra/llm_providers/openrouter_adapter.py +0 -0
  103. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/infra/llm_proxy.py +0 -0
  104. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/infra/llm_response.py +0 -0
  105. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/infra/redis_session_manager.py +0 -0
  106. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/locales/en.yaml +0 -0
  107. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/locales/es.yaml +0 -0
  108. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/repositories/__init__.py +0 -0
  109. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/repositories/advisory_lock.py +0 -0
  110. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/repositories/api_key_repo.py +0 -0
  111. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/repositories/bridge_repo.py +0 -0
  112. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/repositories/database_manager.py +0 -0
  113. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/repositories/document_repo.py +0 -0
  114. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/repositories/env_secret_provider.py +0 -0
  115. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/repositories/filesystem_asset_repository.py +0 -0
  116. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/repositories/knowledge_wiki_repo.py +0 -0
  117. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/repositories/llm_query_repo.py +0 -0
  118. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/repositories/mcp_token_repo.py +0 -0
  119. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/repositories/memory_question_repo.py +0 -0
  120. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/repositories/memory_repo.py +0 -0
  121. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/repositories/memory_usage_repo.py +0 -0
  122. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/repositories/models.py +0 -0
  123. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/repositories/profile_repo.py +0 -0
  124. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/repositories/prompt_resource_repo.py +0 -0
  125. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/repositories/sql_dataset_repo.py +0 -0
  126. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/repositories/sql_source_repo.py +0 -0
  127. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/repositories/vs_repo.py +0 -0
  128. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/runtime_logging.py +0 -0
  129. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/__init__.py +0 -0
  130. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/api_key_service.py +0 -0
  131. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/attachment_policy_service.py +0 -0
  132. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/auth_service.py +0 -0
  133. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/branding_service.py +0 -0
  134. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/configuration_service.py +0 -0
  135. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/context_builder_service.py +0 -0
  136. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/embedding_service.py +0 -0
  137. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/excel_service.py +0 -0
  138. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/file_processor_service.py +0 -0
  139. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/history_compaction_service.py +0 -0
  140. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/history_manager_service.py +0 -0
  141. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/http_tool_service.py +0 -0
  142. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/i18n_service.py +0 -0
  143. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/inference_service.py +0 -0
  144. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/jwt_service.py +0 -0
  145. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/knowledge_base_service.py +0 -0
  146. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/language_service.py +0 -0
  147. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/license_service.py +0 -0
  148. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/mail_service.py +0 -0
  149. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/markdown_wiki_service.py +0 -0
  150. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/mcp_token_service.py +0 -0
  151. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/memory_compiler_service.py +0 -0
  152. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/memory_lookup_policy_service.py +0 -0
  153. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/memory_question_service.py +0 -0
  154. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/memory_service.py +0 -0
  155. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/memory_sources.py +0 -0
  156. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/memory_usage_service.py +0 -0
  157. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/memory_wiki_service.py +0 -0
  158. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/noop_history_compaction_trigger.py +0 -0
  159. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/noop_memory_compilation_trigger.py +0 -0
  160. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/operator_identity_service.py +0 -0
  161. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/parsers/__init__.py +0 -0
  162. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/parsers/contracts.py +0 -0
  163. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/parsers/image_normalizer.py +0 -0
  164. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/parsers/parsing_service.py +0 -0
  165. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/parsers/pdf_ocr_detection.py +0 -0
  166. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/parsers/provider_factory.py +0 -0
  167. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/parsers/provider_resolver.py +0 -0
  168. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/parsers/providers/__init__.py +0 -0
  169. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/parsers/providers/basic_provider.py +0 -0
  170. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/parsers/providers/docling_provider.py +0 -0
  171. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/parsers/validator.py +0 -0
  172. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/pdf_service.py +0 -0
  173. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/profile_service.py +0 -0
  174. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/prompt_resource_service.py +0 -0
  175. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/prompt_service.py +0 -0
  176. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/query_service.py +0 -0
  177. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/signup_policy_resolver.py +0 -0
  178. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/sql_dataset_service.py +0 -0
  179. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/sql_service.py +0 -0
  180. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/sql_source_service.py +0 -0
  181. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/storage_service.py +0 -0
  182. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/structured_output_service.py +0 -0
  183. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/system_agent_catalog.py +0 -0
  184. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/system_agent_runner.py +0 -0
  185. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/system_prompt_catalog.py +0 -0
  186. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/system_tools.py +0 -0
  187. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/telemetry_service.py +0 -0
  188. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/tenant_wiki_service.py +0 -0
  189. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/tool_output_contract.py +0 -0
  190. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/user_feedback_service.py +0 -0
  191. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/user_session_context_service.py +0 -0
  192. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/visual_kb_service.py +0 -0
  193. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/visual_tool_service.py +0 -0
  194. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/warmup_service.py +0 -0
  195. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/web_search/__init__.py +0 -0
  196. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/web_search/provider_factory.py +0 -0
  197. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/web_search/providers/__init__.py +0 -0
  198. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/web_search/providers/brave_provider.py +0 -0
  199. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/web_search_service.py +0 -0
  200. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/services/wiki_page_index_service.py +0 -0
  201. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/static/images/favicon.ico +0 -0
  202. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/static/images/favicon.png +0 -0
  203. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/static/images/fernando.jpeg +0 -0
  204. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/static/images/iatoolkit_core.png +0 -0
  205. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/static/images/iatoolkit_logo.png +0 -0
  206. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/static/js/chat_feedback_button.js +0 -0
  207. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/static/js/chat_filepond.js +0 -0
  208. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/static/js/chat_header_navigation.js +0 -0
  209. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/static/js/chat_help_content.js +0 -0
  210. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/static/js/chat_history_button.js +0 -0
  211. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/static/js/chat_logout_button.js +0 -0
  212. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/static/js/chat_main.js +0 -0
  213. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/static/js/chat_memory_button.js +0 -0
  214. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/static/js/chat_model_selector.js +0 -0
  215. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/static/js/chat_onboarding_button.js +0 -0
  216. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/static/js/chat_prompt_manager.js +0 -0
  217. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/static/styles/account.css +0 -0
  218. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/static/styles/chat_iatoolkit.css +0 -0
  219. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/static/styles/chat_modal.css +0 -0
  220. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/static/styles/chat_public.css +0 -0
  221. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/static/styles/documents.css +0 -0
  222. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/static/styles/landing_page.css +0 -0
  223. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/static/styles/llm_output.css +0 -0
  224. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/static/styles/onboarding.css +0 -0
  225. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/static/styles/wiki_page.css +0 -0
  226. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/templates/_chat_header.html +0 -0
  227. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/templates/_company_header.html +0 -0
  228. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/templates/_login_widget.html +0 -0
  229. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/templates/account.html +0 -0
  230. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/templates/base.html +0 -0
  231. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/templates/change_password.html +0 -0
  232. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/templates/chat.html +0 -0
  233. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/templates/chat_memory_modal.html +0 -0
  234. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/templates/chat_modals.html +0 -0
  235. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/templates/error.html +0 -0
  236. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/templates/forgot_password.html +0 -0
  237. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/templates/home_hosted_default.html +0 -0
  238. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/templates/login_global.html +0 -0
  239. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/templates/memory/wiki_schema.md +0 -0
  240. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/templates/onboarding_shell.html +0 -0
  241. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/templates/pdf/base.html +0 -0
  242. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/templates/pdf/letter.html +0 -0
  243. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/templates/pdf/report.html +0 -0
  244. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/templates/pdf/simple.html +0 -0
  245. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/templates/signup.html +0 -0
  246. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/templates/wiki_page.html +0 -0
  247. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/views/__init__.py +0 -0
  248. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/views/account_view.py +0 -0
  249. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/views/api_key_api_view.py +0 -0
  250. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/views/base_login_view.py +0 -0
  251. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/views/categories_api_view.py +0 -0
  252. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/views/change_password_view.py +0 -0
  253. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/views/chat_context_preview_api_view.py +0 -0
  254. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/views/chat_view.py +0 -0
  255. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/views/configuration_api_view.py +0 -0
  256. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/views/connectors_api_view.py +0 -0
  257. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/views/embedding_api_view.py +0 -0
  258. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/views/forgot_password_view.py +0 -0
  259. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/views/help_content_api_view.py +0 -0
  260. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/views/history_api_view.py +0 -0
  261. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/views/home_view.py +0 -0
  262. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/views/init_context_api_view.py +0 -0
  263. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/views/llmquery_api_view.py +0 -0
  264. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/views/load_document_api_view.py +0 -0
  265. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/views/login_view.py +0 -0
  266. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/views/logout_api_view.py +0 -0
  267. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/views/memory_api_view.py +0 -0
  268. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/views/profile_api_view.py +0 -0
  269. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/views/prompt_api_view.py +0 -0
  270. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/views/prompt_context_preview_api_view.py +0 -0
  271. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/views/prompt_resource_api_view.py +0 -0
  272. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/views/rag_api_view.py +0 -0
  273. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/views/root_redirect_view.py +0 -0
  274. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/views/signup_view.py +0 -0
  275. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/views/static_page_view.py +0 -0
  276. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/views/tool_api_view.py +0 -0
  277. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/views/user_feedback_api_view.py +0 -0
  278. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/views/users_api_view.py +0 -0
  279. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/views/verify_user_view.py +0 -0
  280. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit/views/wiki_page_view.py +0 -0
  281. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit.egg-info/dependency_links.txt +0 -0
  282. {iatoolkit-2.74.3 → iatoolkit-2.75.0}/src/iatoolkit.egg-info/requires.txt +0 -0
  283. {iatoolkit-2.74.3 → iatoolkit-2.75.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.74.3
3
+ Version: 2.75.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.74.3"
6
+ __version__ = "2.75.0"
7
7
 
8
8
  # Expose main classes and functions at the top level of the package
9
9
 
@@ -3,10 +3,13 @@
3
3
  - Trabaja siempre con el dialecto SQL indicado para la base seleccionada.
4
4
  - Antes de escribir la consulta, revisa el contexto de la base y respeta su marcador
5
5
  `dialect=...` (por ejemplo `postgresql` o `mysql`).
6
- - Usa solo tablas, columnas y relaciones presentes en el schema provisto.
6
+ - El contexto lista las bases y sus tablas, sin columnas. Antes de escribir la
7
+ consulta, pide con `iat_sql_schema` las columnas de las tablas que vas a usar,
8
+ todas en una sola llamada. Si una columna no aparece, pide la tabla que la tiene
9
+ en vez de suponerla.
10
+ - Usa solo tablas de la lista y columnas que `iat_sql_schema` te haya mostrado.
7
11
  No inventes columnas ni supongas nombres parecidos.
8
- - Si la consulta requiere una base especifica, usa `iat_sql_query` con el
9
- `database_key` correcto.
12
+ - Ejecuta la consulta con `iat_sql_query` y el `database_key` correcto.
10
13
  - Si hay mas de una tabla, subconsulta o CTE, califica las columnas con alias
11
14
  en `SELECT`, `JOIN`, `ON`, `WHERE`, `GROUP BY`, `HAVING` y `ORDER BY`.
12
15
  - No mezcles sintaxis de distintos dialectos en la misma consulta.
@@ -220,6 +220,39 @@ tools:
220
220
  required:
221
221
  - database_key
222
222
  - query
223
+ - function_name: iat_sql_schema
224
+ description: "Columnas de tablas SQL: antes de escribir una consulta para iat_sql_query, pide aquí las columnas de las tablas que vas a usar. El contexto trae la lista de bases y tablas; esta herramienta trae sus columnas, tipos y descripciones. Pide varias tablas en una sola llamada."
225
+ routing:
226
+ force_include_capability: has_sql_sources
227
+ routing_profile:
228
+ tags:
229
+ - sql
230
+ - database
231
+ - schema
232
+ - columns
233
+ intents:
234
+ - Get the columns of SQL tables before writing a query.
235
+ - Inspect the structure of a configured SQL database.
236
+ examples:
237
+ - iat_sql_schema(database_key="erp", table_names=["customers", "orders"])
238
+ cost:
239
+ penalty: 0.05
240
+ latency_class: low
241
+ expensive: false
242
+ parameters:
243
+ type: object
244
+ properties:
245
+ database_key:
246
+ type: string
247
+ description: "Nombre exacto de la base, como aparece en el contexto."
248
+ table_names:
249
+ type: array
250
+ items:
251
+ type: string
252
+ description: "Tablas de esa base cuyas columnas necesitas (hasta 10)."
253
+ required:
254
+ - database_key
255
+ - table_names
223
256
  - function_name: iat_document_search
224
257
  description: Búsqueda semántica sobre documentos internos de la empresa para traer contexto adicional cuando haga falta. No usar si el usuario pide trabajar exclusivamente con un archivo ya adjunto en el turno actual. Usa metadata_filter solo cuando el usuario o el contexto indiquen un filtro de metadata concreto y necesario; si no hace falta, envía null.
225
258
  routing:
@@ -181,129 +181,35 @@ class CompanyContextService:
181
181
  return False
182
182
  return bool(cls._table_name_candidates(table_name) & allowed_tables)
183
183
 
184
+ @property
185
+ def sql_catalog(self):
186
+ """What of each SQL source a person sees (BL-017); built here, it reads this service's schema."""
187
+ if getattr(self, "_sql_catalog", None) is None:
188
+ from iatoolkit.services.sql_catalog_service import SqlCatalogService
189
+
190
+ self._sql_catalog = SqlCatalogService(self, self.sql_source_service, self.sql_service)
191
+ return self._sql_catalog
192
+
184
193
  def _get_sql_enriched_context(self, company_short_name: str, allowed_databases: List[str] | None = None,
185
194
  table_filter=None):
186
195
  """
187
- Generates the SQL context for the LLM using the enriched schema logic.
188
- It iterates over configured databases, fetches their enriched structure,
189
- and formats it into a prompt-friendly string.
190
- """
191
- sql_sources = self.sql_source_service.list_sources(company_short_name, include_inactive=False)
192
- if not sql_sources:
193
- return '', []
194
-
195
- allowed_database_set = {
196
- str(database or "").strip()
197
- for database in (allowed_databases or [])
198
- if str(database or "").strip()
199
- }
200
- if allowed_databases is not None and not allowed_database_set:
201
- return "", []
202
-
203
- context_output = []
204
- db_tables=[]
196
+ The SQL block of the base context: a map of each source the person may
197
+ query, its tables with a one-line description and no columns (BL-017).
205
198
 
206
- for source in sql_sources:
207
- db_name = source.get('database')
208
- if not db_name:
209
- continue
210
- if allowed_database_set and db_name not in allowed_database_set:
211
- continue
212
-
213
- allowed_tables = self._resolve_allowed_tables_for_source(source)
214
-
215
- try:
216
- # 1. Get the Enriched Schema (Physical + YAML)
217
- enriched_structure = self.get_enriched_database_schema(company_short_name, db_name)
218
- if not enriched_structure:
219
- continue
220
-
221
- if allowed_tables is not None:
222
- enriched_structure = {
223
- table_name: table_data
224
- for table_name, table_data in enriched_structure.items()
225
- if self._table_is_allowed(table_name, allowed_tables)
226
- }
227
- if not enriched_structure:
228
- continue
229
- if table_filter is not None:
230
- # Tables the person may not query (enterprise's knowledge tables, BL-010).
231
- enriched_structure = {
232
- table_name: table_data
233
- for table_name, table_data in enriched_structure.items()
234
- if table_filter(db_name, table_name)
235
- }
236
- if not enriched_structure:
237
- continue
238
-
239
- # 2. Build Header for this Database
240
- dialect = self.sql_service.get_database_dialect(company_short_name, db_name)
241
- dialect_suffix = f" [dialect={dialect}]" if dialect else ""
242
- db_context = f"### Base SQL (`database_key`): {db_name}{dialect_suffix}\n"
243
-
244
- # Optional: Add DB description from config if available (useful context)
245
- db_desc = source.get('description', '')
246
- if db_desc:
247
- db_context += f"- Descripcion: {db_desc}\n"
248
-
249
- db_context += (
250
- f"- Usa `iat_sql_query` con `database_key='{db_name}'` para consultar esta base.\n"
251
- )
252
-
253
- # 3. Format Tables
254
- for table_name, table_data in enriched_structure.items():
255
- table_desc = table_data.get('description', '')
256
- columns = table_data.get('columns', [])
257
-
258
- # Table Header
259
- table_str = f"\n\n#### Tabla: `{table_name}`"
260
- if table_desc:
261
- table_str += f"\n- Descripcion: {table_desc}"
262
-
263
- table_str += "\n- Columnas:"
264
-
265
- # Format Columns
266
- for col in columns:
267
- col_name = col.get('name')
268
- col_type = col.get('type', 'unknown')
269
- col_desc = col.get('description', '')
270
- col_props = col.get('properties') # Nested JSONB structure
271
-
272
- col_line = f"\n - `{col_name}` ({col_type})"
273
- if col_desc:
274
- col_line += f": {col_desc}"
275
-
276
- table_str += col_line
277
-
278
- # If it has nested properties (JSONB enriched from YAML), format them
279
- if col_props:
280
- table_str += "\n"
281
- table_str += self._format_json_schema(col_props, 2) # Indent level 2
282
-
283
- db_context += table_str
284
-
285
- # collect the table names for later use
286
- db_tables.append(
287
- {'db_name': db_name,
288
- 'table_name': table_name,
289
- }
290
- )
291
-
292
- context_output.append(db_context)
293
-
294
- except Exception as e:
295
- logging.warning(f"Could not generate enriched SQL context for '{db_name}': {e}")
296
-
297
- if not context_output:
298
- return "", []
299
-
300
- header = (
301
- "## Bases de datos SQL disponibles\n\n"
302
- "Estas son las bases SQL que puedes consultar usando `iat_sql_query`. "
303
- "El schema a continuacion incluye metadata enriquecida.\n"
199
+ The columns travel only when a question needs them, through
200
+ `iat_sql_schema`: the whole schema in the base context was resent on
201
+ every model call and never compacted (~33k tokens at Maxxa).
202
+ Returns the block and the (db_name, table_name) pairs it covers.
203
+ """
204
+ sources = self.sql_catalog.sources(
205
+ company_short_name, allowed_databases=allowed_databases, table_filter=table_filter,
304
206
  )
305
- return header + "\n\n---\n\n".join(context_output), db_tables
306
-
207
+ db_tables = [
208
+ {"db_name": source["database_key"], "table_name": table["name"]}
209
+ for source in sources
210
+ for table in source["tables"]
211
+ ]
212
+ return self.sql_catalog.render_map(sources), db_tables
307
213
 
308
214
  def _get_yaml_schema_context(
309
215
  self,
@@ -33,6 +33,8 @@ class Dispatcher:
33
33
  "iat_memory_answer_question",
34
34
  "iat_wiki_search",
35
35
  "iat_wiki_get_page",
36
+ # The schema shown is the person's: their sources and tables (BL-017).
37
+ "iat_sql_schema",
36
38
  }
37
39
  _tool_execution_hook = None
38
40
  # Tool types this module executes itself; an extension cannot take them over.
@@ -1606,8 +1606,9 @@ class llmClient:
1606
1606
  sql {sql_query}
1607
1607
 
1608
1608
  **INSTRUCCIÓN OBLIGATORIA:**
1609
- 1. Analiza el error y corrige la sintaxis de la consulta SQL anterior.
1610
- 2. Llama a la herramienta `{function_name}` **OTRA VEZ**, inmediatamente, con la consulta corregida.
1609
+ 1. Analiza el error y corrige la consulta SQL anterior. Si dice que una columna o una tabla
1610
+ no existe, pide primero sus columnas reales con `iat_sql_schema`; no adivines otro nombre.
1611
+ 2. Llama a la herramienta `{function_name}` **OTRA VEZ** con la consulta corregida.
1611
1612
  3. **NO** respondas al usuario con este mensaje de error. Tu ÚNICA acción debe ser volver a llamar a la herramienta con la solución.
1612
1613
  """
1613
1614
 
@@ -32,7 +32,16 @@ from iatoolkit.common.exceptions import IAToolkitException
32
32
  from iatoolkit.repositories.database_manager import DatabaseManager
33
33
  from iatoolkit.repositories.models import CollectionType, Company, Document, KnowledgeWiki
34
34
 
35
- SQL_TOOLS = frozenset({"iat_sql_query"})
35
+ SQL_TOOLS = frozenset({"iat_sql_query", "iat_sql_schema"})
36
+ #: Tools whose access follows another tool's (BL-017): whoever may query may read
37
+ #: the schema of what they query, and nobody else. Without this a new tool falls
38
+ #: to the type default and can end up wider or narrower than the one it serves.
39
+ TOOL_ACCESS_ALIASES = {"iat_sql_schema": "iat_sql_query"}
40
+
41
+
42
+ def tool_access_key(function_name: str) -> str:
43
+ """The tool name whose access list decides this tool's access."""
44
+ return TOOL_ACCESS_ALIASES.get(function_name, function_name)
36
45
  COLLECTION_TOOLS = frozenset({"iat_document_search", "iat_document_list", "iat_image_search", "iat_visual_search"})
37
46
  DOCUMENT_READ_TOOLS = frozenset({"iat_document_read"})
38
47
  WIKI_TOOLS = frozenset({"iat_wiki_search", "iat_wiki_get_page"})
@@ -55,7 +64,7 @@ class ResourceAccessScope:
55
64
  """The call's arguments, narrowed to what the person may reach; raises PERMISSION otherwise."""
56
65
  if not user_identifier:
57
66
  return arguments
58
- if not access.can(company_short_name, user_identifier, USE, "tool", function_name):
67
+ if not access.can(company_short_name, user_identifier, USE, "tool", tool_access_key(function_name)):
59
68
  raise _denied(f"No access to the tool '{function_name}'.")
60
69
 
61
70
  scoped = dict(arguments)
@@ -0,0 +1,260 @@
1
+ # Copyright (c) 2024 Fernando Libedinsky
2
+ # Product: IAToolkit
3
+ #
4
+ # IAToolkit is open source software.
5
+
6
+ """
7
+ The SQL schema a person can see, in one place (BL-017).
8
+
9
+ Two levels, as the MCP always worked: a map of each source (its tables, without
10
+ columns) that is cheap enough to travel in every model call, and the columns of
11
+ the tables a question needs, asked for when it needs them (`iat_sql_schema` in
12
+ the chat, `get_sql_schema` over MCP).
13
+
14
+ Every filter lives here, so the chat and the MCP cannot show different tables to
15
+ the same person: the source must be active, the person must be allowed the
16
+ source (BL-010), the table must be one of the source's `included_tables`, and
17
+ tables holding resources of their own (enterprise's knowledge tables) must pass
18
+ `access.sql_table_filter`.
19
+ """
20
+
21
+ from __future__ import annotations
22
+
23
+ import logging
24
+ from typing import Any, Callable, Optional
25
+
26
+ from iatoolkit.common import access
27
+
28
+ TableFilter = Optional[Callable[[str, str], bool]]
29
+
30
+
31
+ class SqlCatalogService:
32
+ #: Tables one call to `iat_sql_schema` may describe: the columns of a whole
33
+ #: database in one answer is the cost this service exists to avoid.
34
+ MAX_TABLES_PER_REQUEST = 10
35
+ #: One line per table in the map.
36
+ MAP_DESCRIPTION_MAX_CHARS = 200
37
+ SCHEMA_TOOL_NAME = "iat_sql_schema"
38
+ QUERY_TOOL_NAME = "iat_sql_query"
39
+
40
+ def __init__(self, company_context_service, sql_source_service, sql_service):
41
+ # Built by CompanyContextService itself (it owns the enriched schema and
42
+ # this owns what of it a person sees), so no injector cycle between them.
43
+ self.company_context_service = company_context_service
44
+ self.sql_source_service = sql_source_service
45
+ self.sql_service = sql_service
46
+
47
+ # ------------------------------------------------------------------
48
+ # Scope of a person
49
+ # ------------------------------------------------------------------
50
+
51
+ def person_scope(self, company_short_name: str, user_identifier: str | None) -> tuple[list[str] | None, TableFilter]:
52
+ """(allowed databases, table filter) for this person; (None, None) when nothing is restricted."""
53
+ if not user_identifier or not access.Access.registered():
54
+ return None, None
55
+ databases = [str(s.get("database") or "") for s in self._active_sources(company_short_name) if s.get("database")]
56
+ allowed = [d for d in databases
57
+ if access.can(company_short_name, user_identifier, access.USE, "sql_source", d)]
58
+ table_filter = access.sql_table_filter(company_short_name, user_identifier)
59
+ return (None if len(allowed) == len(databases) else allowed), table_filter
60
+
61
+ # ------------------------------------------------------------------
62
+ # The two levels
63
+ # ------------------------------------------------------------------
64
+
65
+ def sources(self, company_short_name: str, *, allowed_databases: list[str] | None = None,
66
+ table_filter: TableFilter = None) -> list[dict]:
67
+ """Each visible source with its visible tables (name, kind, description), no columns."""
68
+ allowed = self._allowed_set(allowed_databases)
69
+ if allowed is not None and not allowed:
70
+ return []
71
+ items = []
72
+ for source in self._active_sources(company_short_name):
73
+ database_key = str(source.get("database") or "").strip()
74
+ if not database_key or (allowed is not None and database_key not in allowed):
75
+ continue
76
+ try:
77
+ tables = self.visible_schema(company_short_name, database_key, source=source, table_filter=table_filter)
78
+ except Exception as e:
79
+ logging.warning(f"Could not read the schema of '{database_key}' for '{company_short_name}': {e}")
80
+ continue
81
+ if not tables:
82
+ continue
83
+ items.append({
84
+ "database_key": database_key,
85
+ "dialect": self._dialect(company_short_name, database_key),
86
+ "description": str(source.get("description") or "").strip(),
87
+ "tables": [
88
+ {
89
+ "name": name,
90
+ "object_type": data.get("object_type") or "table",
91
+ "description": self._one_line(data.get("description")),
92
+ }
93
+ for name, data in tables.items()
94
+ ],
95
+ })
96
+ return items
97
+
98
+ def describe(self, company_short_name: str, database_key: str, table_names: list[str] | None, *,
99
+ allowed_databases: list[str] | None = None, table_filter: TableFilter = None) -> dict:
100
+ """The columns of the requested tables of one source, or why they cannot be given."""
101
+ database_key = str(database_key or "").strip()
102
+ source = self._source(company_short_name, database_key)
103
+ allowed = self._allowed_set(allowed_databases)
104
+ if source is None or (allowed is not None and database_key not in allowed):
105
+ return {"database_key": database_key, "error": "unknown_database",
106
+ "available_databases": [s["database_key"] for s in self.sources(
107
+ company_short_name, allowed_databases=allowed_databases, table_filter=table_filter)]}
108
+
109
+ visible = self.visible_schema(company_short_name, database_key, source=source, table_filter=table_filter)
110
+ requested = [str(name or "").strip() for name in (table_names or []) if str(name or "").strip()]
111
+ if not requested:
112
+ return {"database_key": database_key, "error": "table_names_required",
113
+ "available_tables": list(visible.keys())}
114
+
115
+ index = {}
116
+ for name in visible:
117
+ for candidate in self.company_context_service._table_name_candidates(name):
118
+ index.setdefault(candidate, name)
119
+ found: dict[str, dict] = {}
120
+ unknown: list[str] = []
121
+ for name in requested:
122
+ match = next((index[c] for c in self.company_context_service._table_name_candidates(name) if c in index), None)
123
+ if match is None:
124
+ unknown.append(name)
125
+ elif match not in found:
126
+ found[match] = visible[match]
127
+
128
+ omitted = list(found)[self.MAX_TABLES_PER_REQUEST:]
129
+ for name in omitted:
130
+ found.pop(name)
131
+ result = {
132
+ "database_key": database_key,
133
+ "dialect": self._dialect(company_short_name, database_key),
134
+ "tables": found,
135
+ }
136
+ if unknown:
137
+ result["unknown_tables"] = unknown
138
+ result["available_tables"] = list(visible.keys())
139
+ if omitted:
140
+ result["omitted_tables"] = omitted
141
+ return result
142
+
143
+ def visible_schema(self, company_short_name: str, database_key: str, *, source: dict | None = None,
144
+ table_filter: TableFilter = None) -> dict:
145
+ """The enriched schema of one source, narrowed to the tables a person may see."""
146
+ source = source if source is not None else self._source(company_short_name, database_key)
147
+ if source is None:
148
+ return {}
149
+ ccs = self.company_context_service
150
+ schema = ccs.get_enriched_database_schema(company_short_name, database_key) or {}
151
+ included = ccs._resolve_allowed_tables_for_source(source)
152
+ return {
153
+ name: data
154
+ for name, data in schema.items()
155
+ if ccs._table_is_allowed(name, included)
156
+ and (table_filter is None or table_filter(database_key, name))
157
+ }
158
+
159
+ # ------------------------------------------------------------------
160
+ # What the model reads
161
+ # ------------------------------------------------------------------
162
+
163
+ def render_map(self, sources: list[dict]) -> str:
164
+ if not sources:
165
+ return ""
166
+ parts = []
167
+ for source in sources:
168
+ dialect = f" [dialect={source['dialect']}]" if source.get("dialect") else ""
169
+ lines = [f"### Base SQL (`database_key`): {source['database_key']}{dialect}"]
170
+ if source.get("description"):
171
+ lines.append(f"- Descripcion: {source['description']}")
172
+ lines.append("- Tablas:")
173
+ for table in source.get("tables") or []:
174
+ kind = " (vista)" if table.get("object_type") == "view" else ""
175
+ description = f": {table['description']}" if table.get("description") else ""
176
+ lines.append(f" - `{table['name']}`{kind}{description}")
177
+ parts.append("\n".join(lines))
178
+ header = (
179
+ "## Bases de datos SQL disponibles\n\n"
180
+ f"Estas son las bases SQL que puedes consultar, con sus tablas. Antes de escribir una consulta, "
181
+ f"pide con `{self.SCHEMA_TOOL_NAME}` las columnas de las tablas que vas a usar (varias en una sola "
182
+ f"llamada); luego consulta con `{self.QUERY_TOOL_NAME}`. Usa solo tablas de esta lista y columnas "
183
+ f"que `{self.SCHEMA_TOOL_NAME}` te haya mostrado.\n"
184
+ )
185
+ return header + "\n\n---\n\n".join(parts)
186
+
187
+ def render_tables(self, description: dict) -> str:
188
+ """`describe`'s answer as the model reads it: the columns of each table, or what to do instead."""
189
+ database_key = description.get("database_key") or ""
190
+ error = description.get("error")
191
+ if error == "unknown_database":
192
+ available = ", ".join(f"`{d}`" for d in description.get("available_databases") or []) or "(ninguna)"
193
+ return f"La base `{database_key}` no existe o no tienes acceso. Bases disponibles: {available}."
194
+ if error == "table_names_required":
195
+ return (f"Indica en `table_names` las tablas de `{database_key}` que necesitas (hasta "
196
+ f"{self.MAX_TABLES_PER_REQUEST}). Tablas: {self._names(description.get('available_tables'))}.")
197
+
198
+ dialect = f" [dialect={description['dialect']}]" if description.get("dialect") else ""
199
+ out = [f"### Base SQL (`database_key`): {database_key}{dialect}"]
200
+ for table_name, table_data in (description.get("tables") or {}).items():
201
+ out.append(self._render_table(table_name, table_data))
202
+ if description.get("unknown_tables"):
203
+ out.append(
204
+ f"\nNo existen o no tienes acceso: {self._names(description['unknown_tables'])}. "
205
+ f"Tablas de `{database_key}`: {self._names(description.get('available_tables'))}."
206
+ )
207
+ if description.get("omitted_tables"):
208
+ out.append(
209
+ f"\nSe describen hasta {self.MAX_TABLES_PER_REQUEST} tablas por llamada; pide en otra: "
210
+ f"{self._names(description['omitted_tables'])}."
211
+ )
212
+ return "\n".join(out)
213
+
214
+ def _render_table(self, table_name: str, table_data: dict) -> str:
215
+ text = f"\n#### Tabla: `{table_name}`"
216
+ if table_data.get("description"):
217
+ text += f"\n- Descripcion: {table_data['description']}"
218
+ text += "\n- Columnas:"
219
+ for column in table_data.get("columns") or []:
220
+ line = f"\n - `{column.get('name')}` ({column.get('type', 'unknown')})"
221
+ if column.get("description"):
222
+ line += f": {column['description']}"
223
+ text += line
224
+ if column.get("properties"):
225
+ text += "\n" + self.company_context_service._format_json_schema(column["properties"], 2)
226
+ return text
227
+
228
+ # ------------------------------------------------------------------
229
+ # Helpers
230
+ # ------------------------------------------------------------------
231
+
232
+ def _active_sources(self, company_short_name: str) -> list[dict]:
233
+ return self.sql_source_service.list_sources(company_short_name, include_inactive=False) or []
234
+
235
+ def _source(self, company_short_name: str, database_key: str) -> dict | None:
236
+ return next((s for s in self._active_sources(company_short_name)
237
+ if str(s.get("database") or "").strip() == database_key), None)
238
+
239
+ def _dialect(self, company_short_name: str, database_key: str) -> str:
240
+ try:
241
+ return self.sql_service.get_database_dialect(company_short_name, database_key) or ""
242
+ except Exception:
243
+ return ""
244
+
245
+ @staticmethod
246
+ def _allowed_set(allowed_databases: list[str] | None) -> set[str] | None:
247
+ if allowed_databases is None:
248
+ return None
249
+ return {str(d or "").strip() for d in allowed_databases if str(d or "").strip()}
250
+
251
+ @classmethod
252
+ def _one_line(cls, description: Any) -> str:
253
+ text = " ".join(str(description or "").split())
254
+ if len(text) <= cls.MAP_DESCRIPTION_MAX_CHARS:
255
+ return text
256
+ return text[:cls.MAP_DESCRIPTION_MAX_CHARS].rstrip() + "…"
257
+
258
+ @staticmethod
259
+ def _names(names: list[str] | None) -> str:
260
+ return ", ".join(f"`{n}`" for n in names or []) or "(ninguna)"
@@ -110,6 +110,7 @@ class ToolService:
110
110
  "iat_generate_pdf": self.pdf_service.pdf_generator,
111
111
  "iat_send_email": self.mail_service.send_mail,
112
112
  "iat_sql_query": self.sql_service.exec_sql,
113
+ "iat_sql_schema": self._handle_sql_schema_tool,
113
114
  "iat_image_search": self._handle_image_search_tool,
114
115
  "iat_visual_search": self._handle_visual_search_tool,
115
116
  "iat_document_search": self._handle_document_search_tool,
@@ -489,6 +490,31 @@ class ToolService:
489
490
  user_identifier=user_identifier,
490
491
  )
491
492
 
493
+ def _handle_sql_schema_tool(
494
+ self,
495
+ company_short_name: str,
496
+ database_key: str,
497
+ table_names: list[str] | None = None,
498
+ user_identifier: str | None = None,
499
+ **kwargs,
500
+ ) -> str:
501
+ """The columns of the tables a question needs (BL-017): the base context carries only the map."""
502
+ catalog = self.company_context_service.sql_catalog
503
+ allowed_databases, table_filter = catalog.person_scope(company_short_name, user_identifier)
504
+ description = catalog.describe(
505
+ company_short_name, database_key, table_names,
506
+ allowed_databases=allowed_databases, table_filter=table_filter,
507
+ )
508
+ return catalog.render_tables(description)
509
+
510
+ @property
511
+ def company_context_service(self):
512
+ if getattr(self, "_company_context_service", None) is None:
513
+ from iatoolkit.services.company_context_service import CompanyContextService
514
+
515
+ self._company_context_service = current_iatoolkit().get_injector().get(CompanyContextService)
516
+ return self._company_context_service
517
+
492
518
  def _handle_wiki_get_page_tool(
493
519
  self,
494
520
  company_short_name: str,
@@ -1541,8 +1567,11 @@ class ToolService:
1541
1567
  tools.append(ai_tool)
1542
1568
 
1543
1569
  if user_identifier and access.Access.registered():
1570
+ from iatoolkit.services.resource_access_scope import tool_access_key
1571
+
1544
1572
  tools = [tool for tool in tools
1545
- if access.can(company.short_name, user_identifier, access.USE, "tool", tool["name"])]
1573
+ if access.can(company.short_name, user_identifier, access.USE, "tool",
1574
+ tool_access_key(tool["name"]))]
1546
1575
  return tools
1547
1576
 
1548
1577
  def get_always_include_tool_names(self, company_short_name: str, tools: list[dict]) -> list[str]:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: iatoolkit
3
- Version: 2.74.3
3
+ Version: 2.75.0
4
4
  Summary: IAToolkit
5
5
  Author: Fernando Libedinsky
6
6
  License-Expression: MIT
@@ -163,6 +163,7 @@ src/iatoolkit/services/prompt_service.py
163
163
  src/iatoolkit/services/query_service.py
164
164
  src/iatoolkit/services/resource_access_scope.py
165
165
  src/iatoolkit/services/signup_policy_resolver.py
166
+ src/iatoolkit/services/sql_catalog_service.py
166
167
  src/iatoolkit/services/sql_dataset_service.py
167
168
  src/iatoolkit/services/sql_service.py
168
169
  src/iatoolkit/services/sql_source_service.py
File without changes
File without changes
File without changes
File without changes