iatoolkit 2.12.2__tar.gz → 2.14.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 (239) hide show
  1. {iatoolkit-2.12.2/src/iatoolkit.egg-info → iatoolkit-2.14.0}/PKG-INFO +1 -1
  2. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/__init__.py +1 -1
  3. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/locales/en.yaml +56 -1
  4. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/locales/es.yaml +56 -1
  5. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/context_builder_service.py +4 -0
  6. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/llm_client_service.py +249 -43
  7. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/prompt_service.py +42 -10
  8. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/query_service.py +4 -0
  9. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/telemetry_service.py +46 -3
  10. {iatoolkit-2.12.2 → iatoolkit-2.14.0/src/iatoolkit.egg-info}/PKG-INFO +1 -1
  11. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/LICENSE +0 -0
  12. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/LICENSE_COMMUNITY.md +0 -0
  13. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/pyproject.toml +0 -0
  14. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/readme.md +0 -0
  15. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/requirements.txt +0 -0
  16. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/setup.cfg +0 -0
  17. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/base_company.py +0 -0
  18. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/cli_commands.py +0 -0
  19. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/common/__init__.py +0 -0
  20. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/common/exceptions.py +0 -0
  21. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/common/interfaces/__init__.py +0 -0
  22. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/common/interfaces/asset_storage.py +0 -0
  23. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/common/interfaces/database_provider.py +0 -0
  24. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/common/interfaces/memory_compilation_trigger.py +0 -0
  25. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/common/interfaces/memory_lint_trigger.py +0 -0
  26. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/common/interfaces/secret_provider.py +0 -0
  27. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/common/interfaces/signup_policy_resolver.py +0 -0
  28. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/common/interfaces/web_search_provider.py +0 -0
  29. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/common/model_registry.py +0 -0
  30. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/common/routes.py +0 -0
  31. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/common/secret_resolver.py +0 -0
  32. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/common/session_manager.py +0 -0
  33. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/common/util.py +0 -0
  34. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/company_registry.py +0 -0
  35. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/config/__init__.py +0 -0
  36. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/config/llm_capabilities.yaml +0 -0
  37. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/config/system_prompts/chat_state_rules.prompt +0 -0
  38. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/config/system_prompts/chat_user_profile.prompt +0 -0
  39. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/config/system_prompts/core_identity.prompt +0 -0
  40. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/config/system_prompts/email_output.prompt +0 -0
  41. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/config/system_prompts/file_download_output.prompt +0 -0
  42. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/config/system_prompts/format_styles.prompt +0 -0
  43. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/config/system_prompts/html_structures.prompt +0 -0
  44. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/config/system_prompts/links_documents.prompt +0 -0
  45. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/config/system_prompts/memory_usage.prompt +0 -0
  46. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/config/system_prompts/multimodal_basics.prompt +0 -0
  47. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/config/system_prompts/output_basics.prompt +0 -0
  48. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/config/system_prompts/presentation_formatting.prompt +0 -0
  49. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/config/system_prompts/query_main.prompt +0 -0
  50. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/config/system_prompts/sql_aggregation_scope.prompt +0 -0
  51. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/config/system_prompts/sql_casting.prompt +0 -0
  52. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/config/system_prompts/sql_core.prompt +0 -0
  53. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/config/system_prompts/sql_jsonb.prompt +0 -0
  54. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/config/system_prompts/sql_mysql_casting.prompt +0 -0
  55. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/config/system_prompts/sql_mysql_json.prompt +0 -0
  56. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/config/system_prompts/sql_rules.prompt +0 -0
  57. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/config/system_prompts/tool_html_passthrough.prompt +0 -0
  58. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/config/system_prompts_pack.yaml +0 -0
  59. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/config/system_tools_pack.yaml +0 -0
  60. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/core.py +0 -0
  61. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/infra/__init__.py +0 -0
  62. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/infra/brevo_mail_app.py +0 -0
  63. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/infra/call_service.py +0 -0
  64. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/infra/connectors/__init__.py +0 -0
  65. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/infra/connectors/file_connector.py +0 -0
  66. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/infra/connectors/file_connector_factory.py +0 -0
  67. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/infra/connectors/google_cloud_storage_connector.py +0 -0
  68. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/infra/connectors/google_drive_connector.py +0 -0
  69. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/infra/connectors/local_file_connector.py +0 -0
  70. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/infra/connectors/s3_connector.py +0 -0
  71. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/infra/google_auth_client.py +0 -0
  72. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/infra/google_chat_app.py +0 -0
  73. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/infra/inference_embeddings_client.py +0 -0
  74. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/infra/inference_handler.py +0 -0
  75. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/infra/jina_embeddings_client.py +0 -0
  76. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/infra/llm_providers/__init__.py +0 -0
  77. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/infra/llm_providers/anthropic_adapter.py +0 -0
  78. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/infra/llm_providers/deepseek_adapter.py +0 -0
  79. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/infra/llm_providers/gemini_adapter.py +0 -0
  80. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/infra/llm_providers/openai_adapter.py +0 -0
  81. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/infra/llm_providers/openai_compatible_chat_adapter.py +0 -0
  82. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/infra/llm_providers/openrouter_adapter.py +0 -0
  83. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/infra/llm_proxy.py +0 -0
  84. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/infra/llm_response.py +0 -0
  85. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/infra/redis_session_manager.py +0 -0
  86. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/repositories/__init__.py +0 -0
  87. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/repositories/api_key_repo.py +0 -0
  88. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/repositories/database_manager.py +0 -0
  89. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/repositories/document_repo.py +0 -0
  90. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/repositories/env_secret_provider.py +0 -0
  91. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/repositories/filesystem_asset_repository.py +0 -0
  92. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/repositories/llm_query_repo.py +0 -0
  93. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/repositories/mcp_personal_access_token_repo.py +0 -0
  94. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/repositories/memory_repo.py +0 -0
  95. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/repositories/models.py +0 -0
  96. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/repositories/profile_repo.py +0 -0
  97. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/repositories/prompt_resource_repo.py +0 -0
  98. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/repositories/sql_dataset_repo.py +0 -0
  99. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/repositories/sql_source_repo.py +0 -0
  100. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/repositories/vs_repo.py +0 -0
  101. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/__init__.py +0 -0
  102. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/api_key_service.py +0 -0
  103. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/attachment_policy_service.py +0 -0
  104. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/auth_service.py +0 -0
  105. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/benchmark_service.py +0 -0
  106. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/branding_service.py +0 -0
  107. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/company_context_service.py +0 -0
  108. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/configuration_service.py +0 -0
  109. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/dispatcher_service.py +0 -0
  110. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/embedding_service.py +0 -0
  111. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/excel_service.py +0 -0
  112. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/file_processor_service.py +0 -0
  113. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/history_manager_service.py +0 -0
  114. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/http_tool_service.py +0 -0
  115. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/i18n_service.py +0 -0
  116. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/inference_service.py +0 -0
  117. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/jwt_service.py +0 -0
  118. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/knowledge_base_service.py +0 -0
  119. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/language_service.py +0 -0
  120. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/license_service.py +0 -0
  121. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/mail_service.py +0 -0
  122. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/mcp_personal_access_token_service.py +0 -0
  123. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/memory_compiler_service.py +0 -0
  124. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/memory_lint_service.py +0 -0
  125. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/memory_lookup_policy_service.py +0 -0
  126. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/memory_service.py +0 -0
  127. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/memory_wiki_service.py +0 -0
  128. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/noop_memory_compilation_trigger.py +0 -0
  129. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/noop_memory_lint_trigger.py +0 -0
  130. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/parsers/__init__.py +0 -0
  131. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/parsers/contracts.py +0 -0
  132. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/parsers/image_normalizer.py +0 -0
  133. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/parsers/parsing_service.py +0 -0
  134. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/parsers/pdf_ocr_detection.py +0 -0
  135. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/parsers/provider_factory.py +0 -0
  136. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/parsers/provider_resolver.py +0 -0
  137. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/parsers/providers/__init__.py +0 -0
  138. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/parsers/providers/basic_provider.py +0 -0
  139. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/parsers/providers/docling_provider.py +0 -0
  140. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/parsers/validator.py +0 -0
  141. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/pdf_service.py +0 -0
  142. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/profile_service.py +0 -0
  143. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/prompt_resource_service.py +0 -0
  144. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/signup_policy_resolver.py +0 -0
  145. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/sql_dataset_service.py +0 -0
  146. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/sql_service.py +0 -0
  147. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/sql_source_service.py +0 -0
  148. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/storage_service.py +0 -0
  149. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/structured_output_service.py +0 -0
  150. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/system_prompt_catalog.py +0 -0
  151. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/system_tools.py +0 -0
  152. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/tool_service.py +0 -0
  153. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/user_feedback_service.py +0 -0
  154. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/user_session_context_service.py +0 -0
  155. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/visual_kb_service.py +0 -0
  156. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/visual_tool_service.py +0 -0
  157. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/warmup_service.py +0 -0
  158. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/web_search/__init__.py +0 -0
  159. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/web_search/provider_factory.py +0 -0
  160. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/web_search/providers/__init__.py +0 -0
  161. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/web_search/providers/brave_provider.py +0 -0
  162. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/services/web_search_service.py +0 -0
  163. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/static/images/fernando.jpeg +0 -0
  164. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/static/images/iatoolkit_core.png +0 -0
  165. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/static/images/iatoolkit_logo.png +0 -0
  166. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/static/js/chat_feedback_button.js +0 -0
  167. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/static/js/chat_filepond.js +0 -0
  168. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/static/js/chat_help_content.js +0 -0
  169. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/static/js/chat_history_button.js +0 -0
  170. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/static/js/chat_logout_button.js +0 -0
  171. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/static/js/chat_main.js +0 -0
  172. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/static/js/chat_memory_button.js +0 -0
  173. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/static/js/chat_model_selector.js +0 -0
  174. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/static/js/chat_onboarding_button.js +0 -0
  175. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/static/js/chat_prompt_manager.js +0 -0
  176. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/static/js/chat_reload_button.js +0 -0
  177. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/static/styles/chat_iatoolkit.css +0 -0
  178. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/static/styles/chat_modal.css +0 -0
  179. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/static/styles/chat_public.css +0 -0
  180. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/static/styles/documents.css +0 -0
  181. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/static/styles/landing_page.css +0 -0
  182. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/static/styles/llm_output.css +0 -0
  183. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/static/styles/onboarding.css +0 -0
  184. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/system_prompts/__init__.py +0 -0
  185. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/templates/_company_header.html +0 -0
  186. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/templates/_login_widget.html +0 -0
  187. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/templates/account.html +0 -0
  188. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/templates/base.html +0 -0
  189. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/templates/change_password.html +0 -0
  190. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/templates/chat.html +0 -0
  191. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/templates/chat_memory_modal.html +0 -0
  192. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/templates/chat_modals.html +0 -0
  193. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/templates/error.html +0 -0
  194. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/templates/forgot_password.html +0 -0
  195. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/templates/home_hosted_default.html +0 -0
  196. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/templates/memory/wiki_schema.md +0 -0
  197. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/templates/onboarding_shell.html +0 -0
  198. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/templates/pdf/base.html +0 -0
  199. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/templates/pdf/letter.html +0 -0
  200. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/templates/pdf/report.html +0 -0
  201. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/templates/pdf/simple.html +0 -0
  202. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/templates/signup.html +0 -0
  203. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/views/__init__.py +0 -0
  204. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/views/account_view.py +0 -0
  205. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/views/api_key_api_view.py +0 -0
  206. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/views/base_login_view.py +0 -0
  207. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/views/categories_api_view.py +0 -0
  208. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/views/change_password_view.py +0 -0
  209. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/views/chat_context_preview_api_view.py +0 -0
  210. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/views/chat_view.py +0 -0
  211. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/views/configuration_api_view.py +0 -0
  212. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/views/connectors_api_view.py +0 -0
  213. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/views/embedding_api_view.py +0 -0
  214. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/views/forgot_password_view.py +0 -0
  215. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/views/help_content_api_view.py +0 -0
  216. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/views/history_api_view.py +0 -0
  217. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/views/home_view.py +0 -0
  218. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/views/init_context_api_view.py +0 -0
  219. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/views/llmquery_api_view.py +0 -0
  220. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/views/load_document_api_view.py +0 -0
  221. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/views/login_view.py +0 -0
  222. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/views/logout_api_view.py +0 -0
  223. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/views/memory_api_view.py +0 -0
  224. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/views/profile_api_view.py +0 -0
  225. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/views/prompt_api_view.py +0 -0
  226. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/views/prompt_context_preview_api_view.py +0 -0
  227. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/views/prompt_resource_api_view.py +0 -0
  228. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/views/rag_api_view.py +0 -0
  229. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/views/root_redirect_view.py +0 -0
  230. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/views/signup_view.py +0 -0
  231. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/views/static_page_view.py +0 -0
  232. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/views/tool_api_view.py +0 -0
  233. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/views/user_feedback_api_view.py +0 -0
  234. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/views/users_api_view.py +0 -0
  235. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit/views/verify_user_view.py +0 -0
  236. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit.egg-info/SOURCES.txt +0 -0
  237. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit.egg-info/dependency_links.txt +0 -0
  238. {iatoolkit-2.12.2 → iatoolkit-2.14.0}/src/iatoolkit.egg-info/requires.txt +0 -0
  239. {iatoolkit-2.12.2 → iatoolkit-2.14.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.12.2
3
+ Version: 2.14.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.12.2"
6
+ __version__ = "2.14.0"
7
7
 
8
8
  # Expose main classes and functions at the top level of the package
9
9
 
@@ -408,9 +408,28 @@ ui:
408
408
  tab_settings: "Settings"
409
409
  tab_audience: "Audience"
410
410
  tab_executions: "Executions"
411
+ whatsapp_templates_title: "WhatsApp Templates"
412
+ whatsapp_templates_empty: "No WhatsApp templates have been synced yet."
413
+ whatsapp_templates_subtitle: "Templates available in Kapso for WhatsApp campaigns."
414
+ sync_templates: "Sync templates"
415
+ sync_templates_success: "Templates synced."
416
+ sync_templates_error: "Could not sync templates."
411
417
  template_label: "Initial message"
412
418
  template_help: "This template is rendered per contact when the campaign is activated. You can use variables such as {{ full_name }}, {{ company_name }}, or {{ source.product }}."
413
419
  template_placeholder: "You can use variables like {{ full_name }}, {{ email }}, {{ phone_number }}, {{ government_id }}, {{ external_contact_key }}, {{ company_name }}, {{ company_short_name }}, {{ metadata.* }}, and {{ source.* }}"
420
+ initial_message_mode_label: "Start mode"
421
+ whatsapp_template_label: "WhatsApp template"
422
+ select_whatsapp_template: "Select a WhatsApp template"
423
+ whatsapp_template_preview_title: "Template preview"
424
+ whatsapp_template_variables_title: "Template variables"
425
+ whatsapp_template_variables_help: "Map each template variable using contact fields, metadata, source, or company values."
426
+ whatsapp_template_variable_mapping_placeholder: "Example: full_name or source.product"
427
+ whatsapp_template_variable_example: "Provider example: {value}"
428
+ whatsapp_template_no_preview: "Select a template to preview it and map its variables."
429
+ whatsapp_template_status: "Status"
430
+ whatsapp_template_language: "Language"
431
+ whatsapp_template_category: "Category"
432
+ whatsapp_template_last_synced: "Last sync"
414
433
  audience_title: "Audience"
415
434
  audience_help: "Upload a CSV, map the core columns, and turn those rows into contacts ready to activate over WhatsApp."
416
435
  audience_empty: "No audience has been imported yet."
@@ -421,6 +440,8 @@ ui:
421
440
  audience_col_email: "Email"
422
441
  audience_col_status: "Status"
423
442
  audience_col_delivery: "Activation"
443
+ audience_col_client: "Client"
444
+ audience_col_last_activity: "Last activity"
424
445
  audience_col_error: "Error"
425
446
  audience_col_actions: "Actions"
426
447
  audience_total_label: "{count} contacts"
@@ -428,11 +449,21 @@ ui:
428
449
  summary_ready: "Ready"
429
450
  summary_pending: "Pending"
430
451
  summary_activated: "Activated"
452
+ summary_not_replied: "No reply"
453
+ summary_replied: "Replied"
454
+ summary_agent_engaged: "Conversing"
431
455
  summary_failed: "Failed"
432
456
  summary_skipped: "Skipped"
433
457
  executions_title: "Execution status"
434
458
  executions_empty: "This campaign has not been launched yet."
435
459
  executions_last_launch: "Last launch: {date}"
460
+ executions_summary_snapshot: "{replied} replied · {engaged} in conversation"
461
+ executions_load_error: "Could not load campaign executions."
462
+ executions_attempted: "Attempted"
463
+ executions_processed: "Processed"
464
+ executions_summary_status: "{status} · {date} · {progress}% progress"
465
+ executions_row_counts: "{processed}/{attempted} processed · {activated} activated · {failed} failed · {skipped} skipped"
466
+ executions_row_progress: "{progress}% progress"
436
467
  select_campaign: "Select a campaign"
437
468
  workspace_placeholder: "Create or select a campaign to edit its template, settings, and audience."
438
469
  import_csv: "Import CSV"
@@ -463,7 +494,7 @@ ui:
463
494
  mapping_ignore: "Ignore"
464
495
  mapping_preview_first: "Load a preview first"
465
496
  launch_campaign: "Launch campaign"
466
- launch_success: "Campaign launched."
497
+ launch_success: "Campaign launch queued."
467
498
  launch_error: "Could not launch the campaign."
468
499
  select_campaign_first: "Select a campaign first."
469
500
  add_to_campaign: "Add to campaign"
@@ -489,6 +520,9 @@ ui:
489
520
  completed: "Completed"
490
521
  failed: "Failed"
491
522
  paused: "Paused"
523
+ initial_message_mode:
524
+ free_text: "Free text"
525
+ whatsapp_template: "WhatsApp template"
492
526
  audience_status:
493
527
  ready: "Ready"
494
528
  invalid: "Invalid"
@@ -498,6 +532,27 @@ ui:
498
532
  activated: "Activated"
499
533
  failed: "Failed"
500
534
  skipped: "Skipped"
535
+ execution_status:
536
+ pending: "Queued"
537
+ running: "Running"
538
+ completed: "Completed"
539
+ failed: "Failed"
540
+ cancelled: "Cancelled"
541
+ engagement_status:
542
+ not_replied: "No reply"
543
+ replied: "Replied"
544
+ agent_engaged: "Conversing"
545
+ last_message_direction:
546
+ inbound: "Client"
547
+ outbound: "Agent"
548
+ reply_latency_label: "First reply in {value}"
549
+ reply_latency_seconds: "{count}s"
550
+ reply_latency_minutes: "{count}m"
551
+ reply_latency_hours: "{count}h"
552
+ reply_latency_days: "{count}d"
553
+ message_count_label: "Messages: {inbound} inbound / {outbound} outbound"
554
+ last_message_label: "Last message: {value}"
555
+ first_reply_label: "First reply: {value}"
501
556
 
502
557
  admin:
503
558
  workspace: "Workspace"
@@ -409,9 +409,28 @@ ui:
409
409
  tab_settings: "Settings"
410
410
  tab_audience: "Audience"
411
411
  tab_executions: "Ejecuciones"
412
+ whatsapp_templates_title: "WhatsApp Templates"
413
+ whatsapp_templates_empty: "Todavía no hay templates de WhatsApp sincronizados."
414
+ whatsapp_templates_subtitle: "Templates disponibles en Kapso para campañas de WhatsApp."
415
+ sync_templates: "Sync templates"
416
+ sync_templates_success: "Templates sincronizados."
417
+ sync_templates_error: "No se pudieron sincronizar los templates."
412
418
  template_label: "Mensaje inicial"
413
419
  template_help: "Este template se renderiza por contacto al activar la campaña. Puedes usar variables como {{ full_name }}, {{ company_name }} o {{ source.producto }}."
414
420
  template_placeholder: "Puedes usar variables como {{ full_name }}, {{ email }}, {{ phone_number }}, {{ government_id }}, {{ external_contact_key }}, {{ company_name }}, {{ company_short_name }}, {{ metadata.* }} y {{ source.* }}"
421
+ initial_message_mode_label: "Modo de inicio"
422
+ whatsapp_template_label: "WhatsApp template"
423
+ select_whatsapp_template: "Selecciona un WhatsApp template"
424
+ whatsapp_template_preview_title: "Preview del template"
425
+ whatsapp_template_variables_title: "Variables del template"
426
+ whatsapp_template_variables_help: "Mapea cada variable del template usando campos del contacto, metadata, source o company."
427
+ whatsapp_template_variable_mapping_placeholder: "Ejemplo: full_name o source.producto"
428
+ whatsapp_template_variable_example: "Ejemplo provider: {value}"
429
+ whatsapp_template_no_preview: "Selecciona un template para ver su preview y mapear variables."
430
+ whatsapp_template_status: "Status"
431
+ whatsapp_template_language: "Idioma"
432
+ whatsapp_template_category: "Categoría"
433
+ whatsapp_template_last_synced: "Última sync"
415
434
  audience_title: "Audiencia"
416
435
  audience_help: "Carga un CSV, mapea columnas básicas y convierte las filas en contactos listos para activar por WhatsApp."
417
436
  audience_empty: "Todavía no hay audiencia cargada."
@@ -422,6 +441,8 @@ ui:
422
441
  audience_col_email: "Email"
423
442
  audience_col_status: "Estado"
424
443
  audience_col_delivery: "Activación"
444
+ audience_col_client: "Cliente"
445
+ audience_col_last_activity: "Última actividad"
425
446
  audience_col_error: "Error"
426
447
  audience_col_actions: "Acciones"
427
448
  audience_total_label: "{count} contactos"
@@ -429,11 +450,21 @@ ui:
429
450
  summary_ready: "Listos"
430
451
  summary_pending: "Pendientes"
431
452
  summary_activated: "Activados"
453
+ summary_not_replied: "Sin respuesta"
454
+ summary_replied: "Respondieron"
455
+ summary_agent_engaged: "Conversando"
432
456
  summary_failed: "Fallidos"
433
457
  summary_skipped: "Omitidos"
434
458
  executions_title: "Estado de ejecución"
435
459
  executions_empty: "Esta campaña todavía no se ha lanzado."
436
460
  executions_last_launch: "Último lanzamiento: {date}"
461
+ executions_summary_snapshot: "{replied} respondieron · {engaged} conversando"
462
+ executions_load_error: "No se pudieron cargar las ejecuciones de la campaña."
463
+ executions_attempted: "Intentados"
464
+ executions_processed: "Procesados"
465
+ executions_summary_status: "{status} · {date} · {progress}% de progreso"
466
+ executions_row_counts: "{processed}/{attempted} procesados · {activated} activados · {failed} fallidos · {skipped} omitidos"
467
+ executions_row_progress: "{progress}% de progreso"
437
468
  select_campaign: "Selecciona una campaña"
438
469
  workspace_placeholder: "Crea o selecciona una campaña para editar su template, settings y audiencia."
439
470
  import_csv: "Importar CSV"
@@ -464,7 +495,7 @@ ui:
464
495
  mapping_ignore: "Ignorar"
465
496
  mapping_preview_first: "Primero carga una previsualización"
466
497
  launch_campaign: "Lanzar campaña"
467
- launch_success: "Campaña lanzada."
498
+ launch_success: "Lanzamiento de campaña encolado."
468
499
  launch_error: "No se pudo lanzar la campaña."
469
500
  select_campaign_first: "Primero selecciona una campaña."
470
501
  add_to_campaign: "Agregar a campaña"
@@ -490,6 +521,9 @@ ui:
490
521
  completed: "Completada"
491
522
  failed: "Fallida"
492
523
  paused: "Pausada"
524
+ initial_message_mode:
525
+ free_text: "Texto libre"
526
+ whatsapp_template: "WhatsApp template"
493
527
  audience_status:
494
528
  ready: "Lista"
495
529
  invalid: "Inválida"
@@ -499,6 +533,27 @@ ui:
499
533
  activated: "Activada"
500
534
  failed: "Fallida"
501
535
  skipped: "Omitida"
536
+ execution_status:
537
+ pending: "En cola"
538
+ running: "En ejecución"
539
+ completed: "Completada"
540
+ failed: "Fallida"
541
+ cancelled: "Cancelada"
542
+ engagement_status:
543
+ not_replied: "Sin respuesta"
544
+ replied: "Respondió"
545
+ agent_engaged: "Conversando"
546
+ last_message_direction:
547
+ inbound: "Cliente"
548
+ outbound: "Agente"
549
+ reply_latency_label: "Primera respuesta en {value}"
550
+ reply_latency_seconds: "{count}s"
551
+ reply_latency_minutes: "{count}m"
552
+ reply_latency_hours: "{count}h"
553
+ reply_latency_days: "{count}d"
554
+ message_count_label: "Mensajes: {inbound} inbound / {outbound} outbound"
555
+ last_message_label: "Último mensaje: {value}"
556
+ first_reply_label: "Primera respuesta: {value}"
502
557
 
503
558
  admin:
504
559
  workspace: "Recursos"
@@ -333,13 +333,17 @@ class ContextBuilderService:
333
333
  collection_names=rag_collections,
334
334
  )
335
335
 
336
+ company_context_blocks = self.company_context_service.get_company_context_blocks(company_short_name)
337
+
336
338
  final_system_context = self._join_context_sections(
337
339
  rendered_sections.get("identity"),
340
+ company_context_blocks.get("markdown_context"),
338
341
  rendered_sections.get("conversation_rules"),
339
342
  rendered_sections.get("retrieval_guidance"),
340
343
  collection_context,
341
344
  rendered_sections.get("data_access_rules"),
342
345
  sql_context,
346
+ company_context_blocks.get("yaml_context"),
343
347
  rendered_sections.get("output_contract"),
344
348
  )
345
349
 
@@ -27,6 +27,10 @@ from iatoolkit.services.structured_output_service import StructuredOutputService
27
27
  from iatoolkit.services.telemetry_service import NoopTelemetryService
28
28
 
29
29
  CONTEXT_ERROR_MESSAGE = 'Tu consulta supera el límite de contexto, utiliza el boton de recarga de contexto.'
30
+ TELEMETRY_MAX_STRING_LENGTH = 1000
31
+ TELEMETRY_MAX_COLLECTION_ITEMS = 20
32
+ TELEMETRY_MAX_DEPTH = 4
33
+ TELEMETRY_REDACTED_VALUE = "[REDACTED]"
30
34
 
31
35
  class llmClient:
32
36
  _llm_clients_cache = {} # class attribute, for the clients cache
@@ -121,6 +125,7 @@ class llmClient:
121
125
  text_payload = request_params["text"]
122
126
  reasoning_payload = request_params["reasoning"]
123
127
  telemetry_execution = self.telemetry_service.start_execution(telemetry_request)
128
+ request_source = str((execution_metadata or {}).get("request_source") or "").strip().lower()
124
129
 
125
130
  try:
126
131
  start_time = time.time()
@@ -209,58 +214,105 @@ class llmClient:
209
214
  raise
210
215
  logging.debug(f"[Dispatcher] Parsed args = {args}")
211
216
 
217
+ tool_call_id = str(getattr(tool_call, "call_id", "") or "").strip()
218
+ tool_span = None
219
+ tool_status = None
220
+ tool_result_for_telemetry = None
221
+ tool_error_message = None
222
+ tool_output_type = None
223
+ tool_attachments_count = 0
224
+ tool_elapsed_seconds = 0.0
225
+
212
226
  try:
213
227
  call_kwargs = dict(args)
214
228
  if images:
215
229
  call_kwargs["request_images"] = images
216
230
 
217
- result = self.dispatcher.dispatch(
218
- company_short_name=company.short_name,
219
- function_name=function_name,
220
- user_identifier=user_identifier,
221
- **call_kwargs
231
+ tool_span = telemetry_execution.start_child_span(
232
+ name=f"tool.{function_name}",
233
+ span_type="tool",
234
+ event=self._build_tool_telemetry_start_event(
235
+ company_short_name=company.short_name,
236
+ function_name=function_name,
237
+ call_id=tool_call_id,
238
+ args=call_kwargs,
239
+ request_source=request_source,
240
+ ),
222
241
  )
223
- force_tool_name = None
224
- except IAToolkitException as e:
225
- if (e.error_type == IAToolkitException.ErrorType.DATABASE_ERROR and
226
- sql_retry_count < self.MAX_SQL_RETRIES):
227
- sql_retry_count += 1
228
- sql_query_with_error = args.get('query', 'No se pudo extraer la consulta.')
229
- original_db_error = str(e.__cause__) if e.__cause__ else str(e)
230
-
231
- logging.warning(
232
- f"Error de SQL capturado, intentando corregir con el LLM (Intento {sql_retry_count}/{self.MAX_SQL_RETRIES}).")
233
- result = self._create_sql_retry_prompt(function_name, sql_query_with_error, original_db_error)
234
-
235
- # force the next call to be this function
236
- force_tool_name = function_name
237
- else:
238
- error_message = f"**LLM_DISPATCHER** error en dispatch para tool: '{function_name}': {str(e)}"
242
+
243
+ try:
244
+ result = self.dispatcher.dispatch(
245
+ company_short_name=company.short_name,
246
+ function_name=function_name,
247
+ user_identifier=user_identifier,
248
+ **call_kwargs
249
+ )
250
+ force_tool_name = None
251
+ tool_status = "completed"
252
+ except IAToolkitException as e:
253
+ if (e.error_type == IAToolkitException.ErrorType.DATABASE_ERROR and
254
+ sql_retry_count < self.MAX_SQL_RETRIES):
255
+ sql_retry_count += 1
256
+ sql_query_with_error = args.get('query', 'No se pudo extraer la consulta.')
257
+ original_db_error = str(e.__cause__) if e.__cause__ else str(e)
258
+
259
+ logging.warning(
260
+ f"Error de SQL capturado, intentando corregir con el LLM (Intento {sql_retry_count}/{self.MAX_SQL_RETRIES}).")
261
+ result = self._create_sql_retry_prompt(function_name, sql_query_with_error, original_db_error)
262
+
263
+ # force the next call to be this function
264
+ force_tool_name = function_name
265
+ tool_status = "retry_generated"
266
+ else:
267
+ error_message = f"**LLM_DISPATCHER** error en dispatch para tool: '{function_name}': {str(e)}"
268
+ tool_status = "error"
269
+ tool_error_message = error_message
270
+ raise IAToolkitException(IAToolkitException.ErrorType.CALL_ERROR, error_message)
271
+ except Exception as e:
272
+ error_message = f"Dispatch error en tool {function_name} con args {args} -******- {str(e)}"
273
+ tool_status = "error"
274
+ tool_error_message = error_message
239
275
  raise IAToolkitException(IAToolkitException.ErrorType.CALL_ERROR, error_message)
240
- except Exception as e:
241
- error_message = f"Dispatch error en tool {function_name} con args {args} -******- {str(e)}"
242
- raise IAToolkitException(IAToolkitException.ErrorType.CALL_ERROR, error_message)
243
-
244
- result, tool_native_attachments = self._split_tool_result_and_native_attachments(result)
245
- active_attachments = self._merge_native_attachments(active_attachments, tool_native_attachments)
246
-
247
- # add the return value into the list of messages
248
- input_messages.append({
249
- "type": "function_call_output",
250
- "call_id": tool_call.call_id,
251
- "status": "completed",
252
- "output": self._serialize_tool_output(result)
253
- })
254
- history_messages.append({
255
- "type": "function_call_output",
256
- "call_id": tool_call.call_id,
257
- "status": "completed",
258
- "output": self._serialize_tool_output(result),
259
- })
260
- function_calls = True
276
+
277
+ result, tool_native_attachments = self._split_tool_result_and_native_attachments(result)
278
+ active_attachments = self._merge_native_attachments(active_attachments, tool_native_attachments)
279
+ tool_result_for_telemetry = result
280
+ tool_output_type = type(result).__name__
281
+ tool_attachments_count = len(tool_native_attachments or [])
282
+
283
+ # add the return value into the list of messages
284
+ input_messages.append({
285
+ "type": "function_call_output",
286
+ "call_id": tool_call.call_id,
287
+ "status": "completed",
288
+ "output": self._serialize_tool_output(result)
289
+ })
290
+ history_messages.append({
291
+ "type": "function_call_output",
292
+ "call_id": tool_call.call_id,
293
+ "status": "completed",
294
+ "output": self._serialize_tool_output(result),
295
+ })
296
+ function_calls = True
297
+ finally:
298
+ tool_elapsed_seconds = time.time() - fcall_time
299
+ telemetry_execution.log_child_span(
300
+ tool_span,
301
+ self._build_tool_telemetry_finish_event(
302
+ function_name=function_name,
303
+ call_id=tool_call_id,
304
+ status=tool_status,
305
+ elapsed_seconds=tool_elapsed_seconds,
306
+ result=tool_result_for_telemetry,
307
+ error_message=tool_error_message,
308
+ output_type=tool_output_type,
309
+ attachments_count=tool_attachments_count,
310
+ ),
311
+ )
312
+ telemetry_execution.end_child_span(tool_span)
261
313
 
262
314
  # log the function call parameters and execution time in secs
263
- elapsed = time.time() - fcall_time
315
+ elapsed = tool_elapsed_seconds
264
316
  f_call_identity = {function_name:args, 'time': f'{elapsed:.1f}' }
265
317
  f_calls.append(f_call_identity)
266
318
  f_call_time += elapsed
@@ -305,6 +357,8 @@ class llmClient:
305
357
  stats['model'] = model
306
358
 
307
359
  combined_stats = self.add_stats(stats, stats_fcall)
360
+ combined_stats["tool_call_count"] = len(f_calls)
361
+ combined_stats["tool_time_ms_total"] = int(round(f_call_time * 1000))
308
362
  if isinstance(execution_metadata, dict):
309
363
  combined_stats = dict(combined_stats or {})
310
364
  request_source = str(execution_metadata.get("request_source") or "").strip().lower()
@@ -344,6 +398,8 @@ class llmClient:
344
398
  "total_tokens": combined_stats.get("total_tokens"),
345
399
  "response_time": combined_stats.get("response_time"),
346
400
  "sql_retry_count": combined_stats.get("sql_retry_count"),
401
+ "tool_call_count": combined_stats.get("tool_call_count"),
402
+ "tool_time_ms_total": combined_stats.get("tool_time_ms_total"),
347
403
  },
348
404
  )
349
405
  telemetry_stats = telemetry_execution.build_stats()
@@ -479,6 +535,156 @@ class llmClient:
479
535
 
480
536
  return merged
481
537
 
538
+ @staticmethod
539
+ def _build_tool_telemetry_start_event(
540
+ company_short_name: str,
541
+ function_name: str,
542
+ call_id: str,
543
+ args: dict[str, Any],
544
+ request_source: str = "",
545
+ ) -> dict[str, Any]:
546
+ metadata = {
547
+ "company": company_short_name,
548
+ "tool_name": function_name,
549
+ }
550
+ if call_id:
551
+ metadata["call_id"] = call_id
552
+ if request_source:
553
+ metadata["request_source"] = request_source
554
+
555
+ return {
556
+ "metadata": metadata,
557
+ "input": {
558
+ "arguments": llmClient._sanitize_tool_payload_for_telemetry(args),
559
+ },
560
+ }
561
+
562
+ @staticmethod
563
+ def _build_tool_telemetry_finish_event(
564
+ function_name: str,
565
+ call_id: str,
566
+ status: Optional[str],
567
+ elapsed_seconds: float,
568
+ result: Any = None,
569
+ error_message: Optional[str] = None,
570
+ output_type: Optional[str] = None,
571
+ attachments_count: int = 0,
572
+ ) -> dict[str, Any]:
573
+ metadata: dict[str, Any] = {
574
+ "tool_name": function_name,
575
+ "status": status or "unknown",
576
+ "elapsed_ms": int(round(max(elapsed_seconds, 0.0) * 1000)),
577
+ }
578
+ if call_id:
579
+ metadata["call_id"] = call_id
580
+ if output_type:
581
+ metadata["output_type"] = output_type
582
+ if attachments_count:
583
+ metadata["attachments_count"] = attachments_count
584
+ if error_message:
585
+ metadata["error_message"] = llmClient._truncate_telemetry_string(str(error_message))
586
+
587
+ event: dict[str, Any] = {"metadata": metadata}
588
+ if result is not None:
589
+ event["output"] = {
590
+ "preview": llmClient._sanitize_tool_payload_for_telemetry(result, parent_key="output"),
591
+ }
592
+ return event
593
+
594
+ @staticmethod
595
+ def _sanitize_tool_payload_for_telemetry(
596
+ value: Any,
597
+ *,
598
+ parent_key: str = "",
599
+ depth: int = 0,
600
+ ) -> Any:
601
+ if depth >= TELEMETRY_MAX_DEPTH:
602
+ return "[TRUNCATED_DEPTH]"
603
+
604
+ if isinstance(value, dict):
605
+ sanitized: dict[str, Any] = {}
606
+ items = list(value.items())
607
+ for index, (key, item) in enumerate(items):
608
+ if index >= TELEMETRY_MAX_COLLECTION_ITEMS:
609
+ sanitized["__truncated_items__"] = len(items) - TELEMETRY_MAX_COLLECTION_ITEMS
610
+ break
611
+
612
+ key_str = str(key)
613
+ key_name = key_str.strip().lower()
614
+ if llmClient._is_sensitive_telemetry_key(key_name):
615
+ sanitized[key_str] = TELEMETRY_REDACTED_VALUE
616
+ continue
617
+
618
+ if key_name in {"request_images", "images"} and isinstance(item, list):
619
+ sanitized[key_str] = {"count": len(item), "content": "[OMITTED_IMAGES]"}
620
+ continue
621
+
622
+ if key_name in {"attachments", "native_attachments", "request_attachments"} and isinstance(item, list):
623
+ sanitized[key_str] = {"count": len(item), "content": "[OMITTED_ATTACHMENTS]"}
624
+ continue
625
+
626
+ sanitized[key_str] = llmClient._sanitize_tool_payload_for_telemetry(
627
+ item,
628
+ parent_key=key_name,
629
+ depth=depth + 1,
630
+ )
631
+ return sanitized
632
+
633
+ if isinstance(value, (list, tuple, set)):
634
+ items = list(value)
635
+ sanitized_items = [
636
+ llmClient._sanitize_tool_payload_for_telemetry(item, parent_key=parent_key, depth=depth + 1)
637
+ for item in items[:TELEMETRY_MAX_COLLECTION_ITEMS]
638
+ ]
639
+ if len(items) > TELEMETRY_MAX_COLLECTION_ITEMS:
640
+ sanitized_items.append(f"[TRUNCATED_ITEMS:{len(items) - TELEMETRY_MAX_COLLECTION_ITEMS}]")
641
+ return sanitized_items
642
+
643
+ if isinstance(value, (bytes, bytearray)):
644
+ return f"[BINARY:{len(value)} bytes]"
645
+
646
+ if isinstance(value, str):
647
+ if llmClient._looks_like_base64(value) or parent_key in {"base64", "data"}:
648
+ return "[REDACTED_BINARY_TEXT]"
649
+ return llmClient._truncate_telemetry_string(value)
650
+
651
+ if isinstance(value, (int, float, bool)) or value is None:
652
+ return value
653
+
654
+ return llmClient._truncate_telemetry_string(str(value))
655
+
656
+ @staticmethod
657
+ def _is_sensitive_telemetry_key(key_name: str) -> bool:
658
+ if not key_name:
659
+ return False
660
+
661
+ return any(
662
+ marker in key_name
663
+ for marker in (
664
+ "api_key",
665
+ "apikey",
666
+ "secret",
667
+ "password",
668
+ "token",
669
+ "authorization",
670
+ "credential",
671
+ )
672
+ )
673
+
674
+ @staticmethod
675
+ def _looks_like_base64(value: str) -> bool:
676
+ candidate = str(value or "").strip()
677
+ if len(candidate) < 256 or len(candidate) % 4 != 0:
678
+ return False
679
+ return bool(re.fullmatch(r"[A-Za-z0-9+/=\s]+", candidate))
680
+
681
+ @staticmethod
682
+ def _truncate_telemetry_string(value: str, max_length: int = TELEMETRY_MAX_STRING_LENGTH) -> str:
683
+ text = str(value or "")
684
+ if len(text) <= max_length:
685
+ return text
686
+ return f"{text[:max_length]}...[truncated]"
687
+
482
688
  @staticmethod
483
689
  def _build_history_messages_from_response(response) -> list[dict]:
484
690
  if response is None: