iatoolkit 2.4.0__tar.gz → 2.4.1__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 (232) hide show
  1. {iatoolkit-2.4.0/src/iatoolkit.egg-info → iatoolkit-2.4.1}/PKG-INFO +1 -1
  2. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/__init__.py +1 -1
  3. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/config/system_prompts_pack.yaml +0 -1
  4. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/infra/llm_proxy.py +35 -0
  5. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/locales/en.yaml +3 -0
  6. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/locales/es.yaml +3 -0
  7. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/configuration_service.py +114 -0
  8. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/knowledge_base_service.py +17 -1
  9. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/system_prompts/html_structures.prompt +1 -1
  10. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/views/rag_api_view.py +73 -1
  11. {iatoolkit-2.4.0 → iatoolkit-2.4.1/src/iatoolkit.egg-info}/PKG-INFO +1 -1
  12. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/LICENSE +0 -0
  13. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/LICENSE_COMMUNITY.md +0 -0
  14. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/pyproject.toml +0 -0
  15. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/readme.md +0 -0
  16. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/requirements.txt +0 -0
  17. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/setup.cfg +0 -0
  18. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/base_company.py +0 -0
  19. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/cli_commands.py +0 -0
  20. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/common/__init__.py +0 -0
  21. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/common/exceptions.py +0 -0
  22. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/common/interfaces/__init__.py +0 -0
  23. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/common/interfaces/asset_storage.py +0 -0
  24. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/common/interfaces/database_provider.py +0 -0
  25. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/common/interfaces/memory_compilation_trigger.py +0 -0
  26. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/common/interfaces/memory_lint_trigger.py +0 -0
  27. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/common/interfaces/secret_provider.py +0 -0
  28. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/common/interfaces/signup_policy_resolver.py +0 -0
  29. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/common/interfaces/web_search_provider.py +0 -0
  30. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/common/model_registry.py +0 -0
  31. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/common/routes.py +0 -0
  32. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/common/secret_resolver.py +0 -0
  33. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/common/session_manager.py +0 -0
  34. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/common/util.py +0 -0
  35. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/company_registry.py +0 -0
  36. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/config/__init__.py +0 -0
  37. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/config/llm_capabilities.yaml +0 -0
  38. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/config/system_tools_pack.yaml +0 -0
  39. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/core.py +0 -0
  40. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/infra/__init__.py +0 -0
  41. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/infra/brevo_mail_app.py +0 -0
  42. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/infra/call_service.py +0 -0
  43. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/infra/connectors/__init__.py +0 -0
  44. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/infra/connectors/file_connector.py +0 -0
  45. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/infra/connectors/file_connector_factory.py +0 -0
  46. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/infra/connectors/google_cloud_storage_connector.py +0 -0
  47. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/infra/connectors/google_drive_connector.py +0 -0
  48. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/infra/connectors/local_file_connector.py +0 -0
  49. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/infra/connectors/s3_connector.py +0 -0
  50. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/infra/google_auth_client.py +0 -0
  51. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/infra/google_chat_app.py +0 -0
  52. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/infra/inference_embeddings_client.py +0 -0
  53. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/infra/inference_handler.py +0 -0
  54. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/infra/jina_embeddings_client.py +0 -0
  55. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/infra/llm_providers/__init__.py +0 -0
  56. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/infra/llm_providers/anthropic_adapter.py +0 -0
  57. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/infra/llm_providers/deepseek_adapter.py +0 -0
  58. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/infra/llm_providers/gemini_adapter.py +0 -0
  59. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/infra/llm_providers/openai_adapter.py +0 -0
  60. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/infra/llm_providers/openai_compatible_chat_adapter.py +0 -0
  61. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/infra/llm_providers/openrouter_adapter.py +0 -0
  62. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/infra/llm_response.py +0 -0
  63. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/infra/redis_session_manager.py +0 -0
  64. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/repositories/__init__.py +0 -0
  65. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/repositories/api_key_repo.py +0 -0
  66. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/repositories/database_manager.py +0 -0
  67. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/repositories/document_repo.py +0 -0
  68. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/repositories/env_secret_provider.py +0 -0
  69. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/repositories/filesystem_asset_repository.py +0 -0
  70. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/repositories/llm_query_repo.py +0 -0
  71. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/repositories/memory_repo.py +0 -0
  72. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/repositories/models.py +0 -0
  73. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/repositories/profile_repo.py +0 -0
  74. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/repositories/prompt_resource_repo.py +0 -0
  75. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/repositories/sql_dataset_repo.py +0 -0
  76. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/repositories/sql_source_repo.py +0 -0
  77. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/repositories/vs_repo.py +0 -0
  78. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/__init__.py +0 -0
  79. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/api_key_service.py +0 -0
  80. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/attachment_policy_service.py +0 -0
  81. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/auth_service.py +0 -0
  82. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/benchmark_service.py +0 -0
  83. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/branding_service.py +0 -0
  84. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/company_context_service.py +0 -0
  85. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/context_builder_service.py +0 -0
  86. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/dispatcher_service.py +0 -0
  87. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/embedding_service.py +0 -0
  88. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/excel_service.py +0 -0
  89. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/file_processor_service.py +0 -0
  90. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/history_manager_service.py +0 -0
  91. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/http_tool_service.py +0 -0
  92. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/i18n_service.py +0 -0
  93. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/inference_service.py +0 -0
  94. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/jwt_service.py +0 -0
  95. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/language_service.py +0 -0
  96. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/license_service.py +0 -0
  97. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/llm_client_service.py +0 -0
  98. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/mail_service.py +0 -0
  99. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/memory_compiler_service.py +0 -0
  100. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/memory_lint_service.py +0 -0
  101. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/memory_lookup_policy_service.py +0 -0
  102. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/memory_service.py +0 -0
  103. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/memory_wiki_service.py +0 -0
  104. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/noop_memory_compilation_trigger.py +0 -0
  105. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/noop_memory_lint_trigger.py +0 -0
  106. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/parsers/__init__.py +0 -0
  107. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/parsers/contracts.py +0 -0
  108. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/parsers/image_normalizer.py +0 -0
  109. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/parsers/parsing_service.py +0 -0
  110. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/parsers/pdf_ocr_detection.py +0 -0
  111. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/parsers/provider_factory.py +0 -0
  112. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/parsers/provider_resolver.py +0 -0
  113. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/parsers/providers/__init__.py +0 -0
  114. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/parsers/providers/basic_provider.py +0 -0
  115. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/parsers/providers/docling_provider.py +0 -0
  116. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/parsers/validator.py +0 -0
  117. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/pdf_service.py +0 -0
  118. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/profile_service.py +0 -0
  119. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/prompt_resource_service.py +0 -0
  120. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/prompt_service.py +0 -0
  121. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/query_service.py +0 -0
  122. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/signup_policy_resolver.py +0 -0
  123. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/sql_dataset_service.py +0 -0
  124. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/sql_service.py +0 -0
  125. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/sql_source_service.py +0 -0
  126. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/storage_service.py +0 -0
  127. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/structured_output_service.py +0 -0
  128. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/system_prompt_catalog.py +0 -0
  129. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/system_tools.py +0 -0
  130. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/tool_service.py +0 -0
  131. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/user_feedback_service.py +0 -0
  132. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/user_session_context_service.py +0 -0
  133. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/visual_kb_service.py +0 -0
  134. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/visual_tool_service.py +0 -0
  135. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/warmup_service.py +0 -0
  136. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/web_search/__init__.py +0 -0
  137. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/web_search/provider_factory.py +0 -0
  138. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/web_search/providers/__init__.py +0 -0
  139. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/web_search/providers/brave_provider.py +0 -0
  140. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/services/web_search_service.py +0 -0
  141. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/static/images/fernando.jpeg +0 -0
  142. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/static/images/iatoolkit_core.png +0 -0
  143. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/static/images/iatoolkit_logo.png +0 -0
  144. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/static/js/chat_feedback_button.js +0 -0
  145. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/static/js/chat_filepond.js +0 -0
  146. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/static/js/chat_help_content.js +0 -0
  147. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/static/js/chat_history_button.js +0 -0
  148. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/static/js/chat_logout_button.js +0 -0
  149. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/static/js/chat_main.js +0 -0
  150. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/static/js/chat_memory_button.js +0 -0
  151. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/static/js/chat_model_selector.js +0 -0
  152. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/static/js/chat_onboarding_button.js +0 -0
  153. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/static/js/chat_prompt_manager.js +0 -0
  154. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/static/js/chat_reload_button.js +0 -0
  155. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/static/styles/chat_iatoolkit.css +0 -0
  156. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/static/styles/chat_modal.css +0 -0
  157. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/static/styles/chat_public.css +0 -0
  158. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/static/styles/documents.css +0 -0
  159. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/static/styles/landing_page.css +0 -0
  160. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/static/styles/llm_output.css +0 -0
  161. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/static/styles/onboarding.css +0 -0
  162. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/system_prompts/__init__.py +0 -0
  163. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/system_prompts/chat_state_rules.prompt +0 -0
  164. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/system_prompts/chat_user_profile.prompt +0 -0
  165. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/system_prompts/core_identity.prompt +0 -0
  166. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/system_prompts/email_output.prompt +0 -0
  167. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/system_prompts/file_download_output.prompt +0 -0
  168. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/system_prompts/format_styles.prompt +0 -0
  169. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/system_prompts/links_documents.prompt +0 -0
  170. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/system_prompts/memory_usage.prompt +0 -0
  171. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/system_prompts/multimodal_basics.prompt +0 -0
  172. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/system_prompts/output_basics.prompt +0 -0
  173. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/system_prompts/presentation_formatting.prompt +0 -0
  174. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/system_prompts/query_main.prompt +0 -0
  175. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/system_prompts/sql_aggregation_scope.prompt +0 -0
  176. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/system_prompts/sql_casting.prompt +0 -0
  177. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/system_prompts/sql_core.prompt +0 -0
  178. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/system_prompts/sql_jsonb.prompt +0 -0
  179. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/system_prompts/sql_rules.prompt +0 -0
  180. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/system_prompts/tool_html_passthrough.prompt +0 -0
  181. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/templates/_company_header.html +0 -0
  182. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/templates/_login_widget.html +0 -0
  183. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/templates/base.html +0 -0
  184. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/templates/change_password.html +0 -0
  185. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/templates/chat.html +0 -0
  186. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/templates/chat_memory_modal.html +0 -0
  187. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/templates/chat_modals.html +0 -0
  188. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/templates/error.html +0 -0
  189. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/templates/forgot_password.html +0 -0
  190. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/templates/home_hosted_default.html +0 -0
  191. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/templates/memory/wiki_schema.md +0 -0
  192. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/templates/onboarding_shell.html +0 -0
  193. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/templates/pdf/base.html +0 -0
  194. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/templates/pdf/letter.html +0 -0
  195. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/templates/pdf/report.html +0 -0
  196. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/templates/pdf/simple.html +0 -0
  197. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/templates/signup.html +0 -0
  198. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/views/__init__.py +0 -0
  199. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/views/api_key_api_view.py +0 -0
  200. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/views/base_login_view.py +0 -0
  201. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/views/categories_api_view.py +0 -0
  202. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/views/change_password_view.py +0 -0
  203. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/views/chat_context_preview_api_view.py +0 -0
  204. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/views/chat_view.py +0 -0
  205. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/views/configuration_api_view.py +0 -0
  206. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/views/connectors_api_view.py +0 -0
  207. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/views/embedding_api_view.py +0 -0
  208. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/views/forgot_password_view.py +0 -0
  209. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/views/help_content_api_view.py +0 -0
  210. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/views/history_api_view.py +0 -0
  211. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/views/home_view.py +0 -0
  212. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/views/init_context_api_view.py +0 -0
  213. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/views/llmquery_api_view.py +0 -0
  214. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/views/load_document_api_view.py +0 -0
  215. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/views/login_view.py +0 -0
  216. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/views/logout_api_view.py +0 -0
  217. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/views/memory_api_view.py +0 -0
  218. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/views/profile_api_view.py +0 -0
  219. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/views/prompt_api_view.py +0 -0
  220. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/views/prompt_context_preview_api_view.py +0 -0
  221. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/views/prompt_resource_api_view.py +0 -0
  222. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/views/root_redirect_view.py +0 -0
  223. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/views/signup_view.py +0 -0
  224. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/views/static_page_view.py +0 -0
  225. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/views/tool_api_view.py +0 -0
  226. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/views/user_feedback_api_view.py +0 -0
  227. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/views/users_api_view.py +0 -0
  228. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit/views/verify_user_view.py +0 -0
  229. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit.egg-info/SOURCES.txt +0 -0
  230. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit.egg-info/dependency_links.txt +0 -0
  231. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/src/iatoolkit.egg-info/requires.txt +0 -0
  232. {iatoolkit-2.4.0 → iatoolkit-2.4.1}/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.4.0
3
+ Version: 2.4.1
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.4.0"
6
+ __version__ = "2.4.1"
7
7
 
8
8
  # Expose main classes and functions at the top level of the package
9
9
 
@@ -71,7 +71,6 @@ prompts:
71
71
  include:
72
72
  execution_modes:
73
73
  - chat
74
- - agent
75
74
  - key: file_download_output
76
75
  filename: file_download_output.prompt
77
76
  section: output_contract
@@ -86,6 +86,7 @@ class LLMProxy:
86
86
  company_short_name=company_short_name,
87
87
  model=model,
88
88
  )
89
+ model_config = self.configuration_service.get_llm_model_config(company_short_name, model) or {}
89
90
  provider_config = self.configuration_service.get_llm_provider_config(company_short_name, provider) or {}
90
91
 
91
92
  adapter = self._get_or_create_adapter(
@@ -98,6 +99,11 @@ class LLMProxy:
98
99
  provider_config=provider_config,
99
100
  request_kwargs=kwargs,
100
101
  )
102
+ request_kwargs = self._apply_model_request_overrides(
103
+ provider=provider,
104
+ model_config=model_config,
105
+ request_kwargs=request_kwargs,
106
+ )
101
107
 
102
108
  # Delegate to the adapter (OpenAI, Gemini, DeepSeek, xAI, Anthropic, etc.)
103
109
  return adapter.create_response(model=model, input=input, **request_kwargs)
@@ -218,6 +224,35 @@ class LLMProxy:
218
224
 
219
225
  return effective_kwargs
220
226
 
227
+ def _apply_model_request_overrides(
228
+ self,
229
+ provider: str,
230
+ model_config: Dict[str, Any],
231
+ request_kwargs: Dict[str, Any],
232
+ ) -> Dict[str, Any]:
233
+ effective_kwargs = dict(request_kwargs or {})
234
+
235
+ if provider != self.PROVIDER_OPENROUTER or not isinstance(model_config, dict):
236
+ return effective_kwargs
237
+
238
+ model_runtime_config = model_config.get("config")
239
+ if not isinstance(model_runtime_config, dict):
240
+ return effective_kwargs
241
+
242
+ openrouter_provider = model_runtime_config.get("routing")
243
+ if not isinstance(openrouter_provider, dict) or not openrouter_provider:
244
+ return effective_kwargs
245
+
246
+ existing_provider = effective_kwargs.get("provider")
247
+ if isinstance(existing_provider, dict):
248
+ merged_provider = dict(openrouter_provider)
249
+ merged_provider.update(existing_provider)
250
+ effective_kwargs["provider"] = merged_provider
251
+ elif existing_provider is None:
252
+ effective_kwargs["provider"] = dict(openrouter_provider)
253
+
254
+ return effective_kwargs
255
+
221
256
  # -------------------------------------------------------------------------
222
257
  # Client cache
223
258
  # -------------------------------------------------------------------------
@@ -1286,6 +1286,9 @@ ui:
1286
1286
  status_failed: "Failed"
1287
1287
  created_at: "Created"
1288
1288
  date_range: "Date range"
1289
+ metadata_field: "Metadata field"
1290
+ metadata_value: "Metadata value"
1291
+ select_metadata_field: "Select a field"
1289
1292
  delete_confirmation: "Delete File?"
1290
1293
  delete_message: "This action cannot be undone. The file will be permanently removed."
1291
1294
  delete_button: "Delete"
@@ -1290,6 +1290,9 @@ ui:
1290
1290
  status_failed: "Fallido"
1291
1291
  created_at: "Creado"
1292
1292
  date_range: "Rango de fechas"
1293
+ metadata_field: "Campo metadata"
1294
+ metadata_value: "Valor metadata"
1295
+ select_metadata_field: "Selecciona un campo"
1293
1296
  delete_confirmation: "¿Eliminar archivo?"
1294
1297
  delete_message: "Esta acción no se puede deshacer. El archivo se eliminará permanentemente."
1295
1298
  delete_button: "Eliminar"
@@ -52,6 +52,49 @@ class ConfigurationService:
52
52
  return {}
53
53
  return {"id": model_id}
54
54
 
55
+ @staticmethod
56
+ def _validate_openrouter_provider_preferences(add_error, section: str, provider_cfg) -> None:
57
+ if not isinstance(provider_cfg, dict):
58
+ add_error(section, "Must be a dictionary.")
59
+ return
60
+
61
+ for list_key in ("order", "only", "ignore"):
62
+ if list_key not in provider_cfg:
63
+ continue
64
+ raw_value = provider_cfg.get(list_key)
65
+ if not isinstance(raw_value, list) or any(not isinstance(item, str) or not item.strip() for item in raw_value):
66
+ add_error(f"{section}.{list_key}", "Must be a list of non-empty strings.")
67
+
68
+ for bool_key in ("allow_fallbacks", "require_parameters", "zdr"):
69
+ if bool_key in provider_cfg and not isinstance(provider_cfg.get(bool_key), bool):
70
+ add_error(f"{section}.{bool_key}", "Must be a boolean.")
71
+
72
+ if "data_collection" in provider_cfg:
73
+ data_collection = str(provider_cfg.get("data_collection") or "").strip().lower()
74
+ if data_collection not in {"allow", "deny"}:
75
+ add_error(f"{section}.data_collection", "Must be 'allow' or 'deny'.")
76
+
77
+ if "sort" in provider_cfg:
78
+ sort_value = provider_cfg.get("sort")
79
+ if isinstance(sort_value, str):
80
+ if sort_value.strip().lower() not in {"price", "throughput", "latency"}:
81
+ add_error(
82
+ f"{section}.sort",
83
+ "Must be one of: ['latency', 'price', 'throughput'], or a dictionary."
84
+ )
85
+ elif isinstance(sort_value, dict):
86
+ sort_by = str(sort_value.get("by") or "").strip().lower()
87
+ if sort_by and sort_by not in {"price", "throughput", "latency"}:
88
+ add_error(f"{section}.sort.by", "Must be one of: ['latency', 'price', 'throughput'].")
89
+ partition = sort_value.get("partition")
90
+ if partition is not None and str(partition).strip().lower() not in {"provider", "model", "none"}:
91
+ add_error(f"{section}.sort.partition", "Must be one of: ['model', 'none', 'provider'].")
92
+ else:
93
+ add_error(
94
+ f"{section}.sort",
95
+ "Must be one of: ['latency', 'price', 'throughput'], or a dictionary."
96
+ )
97
+
55
98
  def load_configuration(self, company_short_name: str):
56
99
  """
57
100
  Main entry point for configuring a company instance.
@@ -365,15 +408,43 @@ class ConfigurationService:
365
408
  for index, model_entry in enumerate(llm_available_models):
366
409
  normalized_model = self._normalize_model_entry(model_entry)
367
410
  provider = str(normalized_model.get("provider") or "").strip().lower()
411
+ model_specific_config = normalized_model.get("config")
368
412
  if provider and provider not in supported_llm_providers:
369
413
  add_error(
370
414
  f"llm.available_models[{index}].provider",
371
415
  f"Unsupported provider '{provider}'. Must be one of: {sorted(supported_llm_providers)}."
372
416
  )
417
+ if model_specific_config is not None and not isinstance(model_specific_config, dict):
418
+ add_error(f"llm.available_models[{index}].config", "Must be a dictionary.")
373
419
  if provider == "openai_compatible":
374
420
  openai_compatible_in_use = True
375
421
  if provider == "openrouter":
376
422
  openrouter_in_use = True
423
+ if isinstance(model_specific_config, dict):
424
+ if "routing" in model_specific_config:
425
+ self._validate_openrouter_provider_preferences(
426
+ add_error,
427
+ f"llm.available_models[{index}].config.routing",
428
+ model_specific_config.get("routing"),
429
+ )
430
+ if "openrouter_provider" in model_specific_config:
431
+ add_error(
432
+ f"llm.available_models[{index}].config.openrouter_provider",
433
+ "Unsupported key. Use 'config.routing' instead.",
434
+ )
435
+ elif isinstance(model_specific_config, dict) and (
436
+ "routing" in model_specific_config or "openrouter_provider" in model_specific_config
437
+ ):
438
+ if "routing" in model_specific_config:
439
+ add_error(
440
+ f"llm.available_models[{index}].config.routing",
441
+ "Only supported when the model provider is 'openrouter'.",
442
+ )
443
+ if "openrouter_provider" in model_specific_config:
444
+ add_error(
445
+ f"llm.available_models[{index}].config.openrouter_provider",
446
+ "Unsupported key. Use 'config.routing' instead.",
447
+ )
377
448
 
378
449
  providers_cfg = config.get("llm", {}).get("providers")
379
450
  if providers_cfg is not None and not isinstance(providers_cfg, dict):
@@ -752,6 +823,49 @@ class ConfigurationService:
752
823
  if not isinstance(docling_config, dict):
753
824
  add_error("knowledge_base.docling", "Must be a dictionary.")
754
825
 
826
+ metadata_search_fields = kb_config.get("metadata_search_fields")
827
+ if metadata_search_fields is not None:
828
+ if not isinstance(metadata_search_fields, list):
829
+ add_error("knowledge_base.metadata_search_fields", "Must be a list.")
830
+ else:
831
+ for i, item in enumerate(metadata_search_fields):
832
+ if isinstance(item, str):
833
+ if not item.strip():
834
+ add_error(
835
+ f"knowledge_base.metadata_search_fields[{i}]",
836
+ "Metadata field name cannot be empty."
837
+ )
838
+ elif isinstance(item, dict):
839
+ key = item.get("key")
840
+ if not isinstance(key, str) or not key.strip():
841
+ add_error(
842
+ f"knowledge_base.metadata_search_fields[{i}].key",
843
+ "Missing required key: 'key' (non-empty string)."
844
+ )
845
+ label = item.get("label")
846
+ if label is not None and (not isinstance(label, str) or not label.strip()):
847
+ add_error(
848
+ f"knowledge_base.metadata_search_fields[{i}].label",
849
+ "Must be a non-empty string if provided."
850
+ )
851
+ match = item.get("match")
852
+ if match is not None:
853
+ if not isinstance(match, str):
854
+ add_error(
855
+ f"knowledge_base.metadata_search_fields[{i}].match",
856
+ "Must be a string if provided."
857
+ )
858
+ elif match.strip().lower() not in {"exact", "contains"}:
859
+ add_error(
860
+ f"knowledge_base.metadata_search_fields[{i}].match",
861
+ "Must be one of: ['contains', 'exact']."
862
+ )
863
+ else:
864
+ add_error(
865
+ f"knowledge_base.metadata_search_fields[{i}]",
866
+ "Each metadata search field must be a string or an object with keys like {key, label, match}."
867
+ )
868
+
755
869
  prod_connector = kb_config.get("connectors", {}).get("production", {})
756
870
  if prod_connector.get("type") == "s3":
757
871
  for key in ["bucket", "prefix"]:
@@ -14,7 +14,7 @@ from iatoolkit.services.storage_service import StorageService
14
14
  from iatoolkit.services.parsers.parsing_service import ParsingService
15
15
  from langchain_text_splitters import RecursiveCharacterTextSplitter
16
16
  from iatoolkit.services.visual_kb_service import VisualKnowledgeBaseService
17
- from sqlalchemy import desc
17
+ from sqlalchemy import desc, func
18
18
  from typing import Any
19
19
  import json
20
20
  from iatoolkit.common.exceptions import IAToolkitException
@@ -564,6 +564,9 @@ class KnowledgeBaseService:
564
564
  filename_keyword: Optional[str] = None,
565
565
  from_date: Optional[datetime] = None,
566
566
  to_date: Optional[datetime] = None,
567
+ metadata_key: Optional[str] = None,
568
+ metadata_value: Optional[str] = None,
569
+ metadata_match_mode: Optional[str] = None,
567
570
  limit: int = 100,
568
571
  offset: int = 0) -> List[Document]:
569
572
  """
@@ -577,6 +580,9 @@ class KnowledgeBaseService:
577
580
  filename_keyword: Optional substring to search in filename.
578
581
  from_date: Optional start date filter (created_at).
579
582
  to_date: Optional end date filter (created_at).
583
+ metadata_key: Optional top-level metadata field name inside Document.meta.
584
+ metadata_value: Optional metadata field value to filter by.
585
+ metadata_match_mode: Optional metadata match mode: 'exact' or 'contains'.
580
586
  limit: Pagination limit.
581
587
  offset: Pagination offset.
582
588
 
@@ -613,6 +619,16 @@ class KnowledgeBaseService:
613
619
  if to_date:
614
620
  query = query.filter(Document.created_at <= to_date)
615
621
 
622
+ normalized_metadata_key = str(metadata_key or "").strip()
623
+ normalized_metadata_value = str(metadata_value or "").strip().lower()
624
+ normalized_match_mode = str(metadata_match_mode or "contains").strip().lower()
625
+ if normalized_metadata_key and normalized_metadata_value:
626
+ meta_value_expr = func.lower(func.coalesce(Document.meta[normalized_metadata_key].as_string(), ""))
627
+ if normalized_match_mode == "exact":
628
+ query = query.filter(meta_value_expr == normalized_metadata_value)
629
+ else:
630
+ query = query.filter(meta_value_expr.like(f"%{normalized_metadata_value}%"))
631
+
616
632
  # Apply sorting (newest first) and pagination
617
633
  query = query.order_by(desc(Document.created_at))
618
634
  query = query.limit(limit).offset(offset)
@@ -1,7 +1,7 @@
1
1
  ### HTML estructurado
2
2
 
3
3
  #### Tablas
4
- - Usa como base `table table-striped table-hover`.
4
+ - Usa como base `table table-striped table-hover` de Bootstrap como mínimo.
5
5
  - Si una columna contiene RUT, fecha, id certificado o valores similares, usa
6
6
  clase `nowrap` en el `<th>` y en el `<td>` correspondiente cuando aplique.
7
7
  - Si una columna debe ir centrada o alineada a la derecha, agrega
@@ -8,6 +8,7 @@ from iatoolkit.common.exceptions import IAToolkitException
8
8
  from iatoolkit.services.knowledge_base_service import KnowledgeBaseService
9
9
  from iatoolkit.services.visual_kb_service import VisualKnowledgeBaseService
10
10
  from iatoolkit.services.auth_service import AuthService
11
+ from iatoolkit.services.configuration_service import ConfigurationService
11
12
  from iatoolkit.common.util import Utility
12
13
  from iatoolkit.services.i18n_service import I18nService
13
14
  from flask import request, jsonify, send_file
@@ -27,11 +28,13 @@ class RagApiView(MethodView):
27
28
  def __init__(self,
28
29
  knowledge_base_service: KnowledgeBaseService,
29
30
  visual_kb_service: VisualKnowledgeBaseService,
31
+ configuration_service: ConfigurationService,
30
32
  auth_service: AuthService,
31
33
  i18n_service: I18nService,
32
34
  utility: Utility):
33
35
  self.knowledge_base_service = knowledge_base_service
34
36
  self.visual_kb_service = visual_kb_service
37
+ self.configuration_service = configuration_service
35
38
  self.auth_service = auth_service
36
39
  self.utility = utility
37
40
  self.i18n_service = i18n_service
@@ -65,18 +68,38 @@ class RagApiView(MethodView):
65
68
  # 2. Parse Input
66
69
  data = request.get_json() or {}
67
70
 
71
+ metadata_search_fields = self._get_metadata_search_fields(company_short_name)
72
+ metadata_field_map = {field["key"]: field for field in metadata_search_fields}
73
+
68
74
  status = data.get('status', [])
69
75
  user_identifier = data.get('user_identifier')
70
76
  keyword = data.get('filename_keyword')
71
77
  from_date_str = data.get('from_date')
72
78
  to_date_str = data.get('to_date')
73
79
  collection = data.get('collection', '')
80
+ metadata_key = str(data.get('metadata_key') or '').strip()
81
+ metadata_value = str(data.get('metadata_value') or '').strip()
82
+ metadata_match_mode = str(data.get('metadata_match_mode') or '').strip().lower()
74
83
  limit = int(data.get('limit', 100))
75
84
  offset = int(data.get('offset', 0))
76
85
 
77
86
  from_date = datetime.fromisoformat(from_date_str) if from_date_str else None
78
87
  to_date = datetime.fromisoformat(to_date_str) if to_date_str else None
79
88
 
89
+ if metadata_value and not metadata_key and len(metadata_search_fields) == 1:
90
+ metadata_key = metadata_search_fields[0]["key"]
91
+
92
+ if metadata_key:
93
+ selected_metadata_field = metadata_field_map.get(metadata_key)
94
+ if not selected_metadata_field:
95
+ return jsonify({
96
+ 'result': 'error',
97
+ 'message': f"Invalid metadata search field: {metadata_key}"
98
+ }), 400
99
+ metadata_match_mode = selected_metadata_field.get("match") or metadata_match_mode or "contains"
100
+ else:
101
+ metadata_match_mode = None
102
+
80
103
  # 3. Call Service
81
104
  documents = self.knowledge_base_service.list_documents(
82
105
  company_short_name=company_short_name,
@@ -86,6 +109,9 @@ class RagApiView(MethodView):
86
109
  user_identifier=user_identifier,
87
110
  from_date=from_date,
88
111
  to_date=to_date,
112
+ metadata_key=metadata_key or None,
113
+ metadata_value=metadata_value or None,
114
+ metadata_match_mode=metadata_match_mode,
89
115
  limit=limit,
90
116
  offset=offset
91
117
  )
@@ -107,7 +133,8 @@ class RagApiView(MethodView):
107
133
  return jsonify({
108
134
  'result': 'success',
109
135
  'count': len(response_list),
110
- 'documents': response_list
136
+ 'documents': response_list,
137
+ 'metadata_search_fields': metadata_search_fields
111
138
  }), 200
112
139
 
113
140
  except IAToolkitException as e:
@@ -115,6 +142,51 @@ class RagApiView(MethodView):
115
142
  except Exception as e:
116
143
  return jsonify({'result': 'error', 'message': str(e)}), 500
117
144
 
145
+ def _get_metadata_search_fields(self, company_short_name: str) -> list[dict]:
146
+ kb_config = self.configuration_service.get_configuration(company_short_name, "knowledge_base") or {}
147
+ raw_fields = kb_config.get("metadata_search_fields") or []
148
+ normalized_fields = []
149
+
150
+ if not isinstance(raw_fields, list):
151
+ return normalized_fields
152
+
153
+ for item in raw_fields:
154
+ normalized = self._normalize_metadata_search_field(item)
155
+ if normalized:
156
+ normalized_fields.append(normalized)
157
+
158
+ return normalized_fields
159
+
160
+ @staticmethod
161
+ def _normalize_metadata_search_field(item) -> dict | None:
162
+ if isinstance(item, str):
163
+ key = item.strip()
164
+ if not key:
165
+ return None
166
+ return {
167
+ "key": key,
168
+ "label": key,
169
+ "match": "contains"
170
+ }
171
+
172
+ if not isinstance(item, dict):
173
+ return None
174
+
175
+ key = str(item.get("key") or "").strip()
176
+ if not key:
177
+ return None
178
+
179
+ label = str(item.get("label") or key).strip() or key
180
+ match = str(item.get("match") or "contains").strip().lower()
181
+ if match not in {"exact", "contains"}:
182
+ match = "contains"
183
+
184
+ return {
185
+ "key": key,
186
+ "label": label,
187
+ "match": match
188
+ }
189
+
118
190
  def get_file_content(self, company_short_name, document_id):
119
191
  """
120
192
  GET /api/rag/<company_short_name>/files/<document_id>/content
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: iatoolkit
3
- Version: 2.4.0
3
+ Version: 2.4.1
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