iatoolkit 2.75.4__tar.gz → 2.76.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 (281) hide show
  1. {iatoolkit-2.75.4/src/iatoolkit.egg-info → iatoolkit-2.76.1}/PKG-INFO +1 -1
  2. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/__init__.py +1 -1
  3. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/config/system_tools_pack.yaml +29 -0
  4. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/dispatcher_service.py +1 -0
  5. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/history_compaction_service.py +3 -0
  6. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/history_manager_service.py +30 -12
  7. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/llm_client_service.py +23 -1
  8. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/memory_question_service.py +80 -0
  9. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/tool_service.py +13 -0
  10. {iatoolkit-2.75.4 → iatoolkit-2.76.1/src/iatoolkit.egg-info}/PKG-INFO +1 -1
  11. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/LICENSE +0 -0
  12. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/LICENSE_COMMUNITY.md +0 -0
  13. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/pyproject.toml +0 -0
  14. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/readme.md +0 -0
  15. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/setup.cfg +0 -0
  16. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/base_company.py +0 -0
  17. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/cli_commands.py +0 -0
  18. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/common/__init__.py +0 -0
  19. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/common/access.py +0 -0
  20. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/common/bridge_validation.py +0 -0
  21. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/common/company_paths.py +0 -0
  22. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/common/exceptions.py +0 -0
  23. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/common/interfaces/__init__.py +0 -0
  24. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/common/interfaces/asset_storage.py +0 -0
  25. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/common/interfaces/database_provider.py +0 -0
  26. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/common/interfaces/history_compaction_trigger.py +0 -0
  27. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/common/interfaces/memory_compilation_trigger.py +0 -0
  28. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/common/interfaces/secret_provider.py +0 -0
  29. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/common/interfaces/signup_policy_resolver.py +0 -0
  30. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/common/interfaces/web_search_provider.py +0 -0
  31. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/common/memory_tools.py +0 -0
  32. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/common/model_registry.py +0 -0
  33. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/common/routes.py +0 -0
  34. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/common/search_terms.py +0 -0
  35. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/common/secret_resolver.py +0 -0
  36. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/common/session_manager.py +0 -0
  37. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/common/text_splitter.py +0 -0
  38. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/common/url_safety.py +0 -0
  39. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/common/util.py +0 -0
  40. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/company_registry.py +0 -0
  41. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/config/__init__.py +0 -0
  42. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/config/llm_capabilities.yaml +0 -0
  43. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/config/system_agents/history_compaction.prompt +0 -0
  44. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/config/system_agents/memory_compiler.prompt +0 -0
  45. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/config/system_agents/memory_correction.prompt +0 -0
  46. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/config/system_agents/memory_document_ingest.prompt +0 -0
  47. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/config/system_agents/memory_image_ingest.prompt +0 -0
  48. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/config/system_agents/memory_meeting_ingest.prompt +0 -0
  49. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/config/system_agents/memory_question_review.prompt +0 -0
  50. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/config/system_agents_pack.yaml +0 -0
  51. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/config/system_prompts/channel_business_identity.prompt +0 -0
  52. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/config/system_prompts/channel_conversation_continuity.prompt +0 -0
  53. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/config/system_prompts/channel_response_style.prompt +0 -0
  54. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/config/system_prompts/chat_state_rules.prompt +0 -0
  55. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/config/system_prompts/chat_user_profile.prompt +0 -0
  56. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/config/system_prompts/core_identity.prompt +0 -0
  57. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/config/system_prompts/email_output.prompt +0 -0
  58. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/config/system_prompts/file_download_output.prompt +0 -0
  59. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/config/system_prompts/format_styles.prompt +0 -0
  60. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/config/system_prompts/html_structures.prompt +0 -0
  61. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/config/system_prompts/links_documents.prompt +0 -0
  62. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/config/system_prompts/memory_usage.prompt +0 -0
  63. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/config/system_prompts/multimodal_basics.prompt +0 -0
  64. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/config/system_prompts/output_basics.prompt +0 -0
  65. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/config/system_prompts/presentation_formatting.prompt +0 -0
  66. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/config/system_prompts/query_main.prompt +0 -0
  67. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/config/system_prompts/sql_aggregation_scope.prompt +0 -0
  68. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/config/system_prompts/sql_casting.prompt +0 -0
  69. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/config/system_prompts/sql_core.prompt +0 -0
  70. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/config/system_prompts/sql_jsonb.prompt +0 -0
  71. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/config/system_prompts/sql_mysql_casting.prompt +0 -0
  72. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/config/system_prompts/sql_mysql_json.prompt +0 -0
  73. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/config/system_prompts/sql_redshift_basics.prompt +0 -0
  74. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/config/system_prompts/sql_redshift_types.prompt +0 -0
  75. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/config/system_prompts/tool_html_passthrough.prompt +0 -0
  76. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/config/system_prompts_pack.yaml +0 -0
  77. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/core.py +0 -0
  78. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/infra/__init__.py +0 -0
  79. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/infra/brevo_mail_app.py +0 -0
  80. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/infra/call_service.py +0 -0
  81. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/infra/connectors/__init__.py +0 -0
  82. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/infra/connectors/file_connector.py +0 -0
  83. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/infra/connectors/file_connector_factory.py +0 -0
  84. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/infra/connectors/google_cloud_storage_connector.py +0 -0
  85. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/infra/connectors/google_drive_connector.py +0 -0
  86. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/infra/connectors/local_file_connector.py +0 -0
  87. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/infra/connectors/s3_connector.py +0 -0
  88. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/infra/google_auth_client.py +0 -0
  89. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/infra/google_chat_app.py +0 -0
  90. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/infra/inference_embeddings_client.py +0 -0
  91. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/infra/inference_handler.py +0 -0
  92. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/infra/jina_embeddings_client.py +0 -0
  93. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/infra/llm_gateway_resolver.py +0 -0
  94. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/infra/llm_providers/__init__.py +0 -0
  95. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/infra/llm_providers/anthropic_adapter.py +0 -0
  96. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/infra/llm_providers/deepseek_adapter.py +0 -0
  97. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/infra/llm_providers/gemini_adapter.py +0 -0
  98. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/infra/llm_providers/openai_adapter.py +0 -0
  99. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/infra/llm_providers/openai_compatible_chat_adapter.py +0 -0
  100. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/infra/llm_providers/openrouter_adapter.py +0 -0
  101. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/infra/llm_proxy.py +0 -0
  102. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/infra/llm_response.py +0 -0
  103. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/infra/redis_session_manager.py +0 -0
  104. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/locales/en.yaml +0 -0
  105. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/locales/es.yaml +0 -0
  106. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/repositories/__init__.py +0 -0
  107. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/repositories/advisory_lock.py +0 -0
  108. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/repositories/api_key_repo.py +0 -0
  109. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/repositories/bridge_repo.py +0 -0
  110. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/repositories/database_manager.py +0 -0
  111. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/repositories/document_repo.py +0 -0
  112. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/repositories/env_secret_provider.py +0 -0
  113. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/repositories/filesystem_asset_repository.py +0 -0
  114. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/repositories/knowledge_wiki_repo.py +0 -0
  115. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/repositories/llm_query_repo.py +0 -0
  116. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/repositories/mcp_token_repo.py +0 -0
  117. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/repositories/memory_question_repo.py +0 -0
  118. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/repositories/memory_repo.py +0 -0
  119. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/repositories/memory_usage_repo.py +0 -0
  120. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/repositories/models.py +0 -0
  121. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/repositories/profile_repo.py +0 -0
  122. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/repositories/prompt_resource_repo.py +0 -0
  123. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/repositories/sql_dataset_repo.py +0 -0
  124. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/repositories/sql_source_repo.py +0 -0
  125. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/repositories/vs_repo.py +0 -0
  126. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/runtime_logging.py +0 -0
  127. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/__init__.py +0 -0
  128. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/api_key_service.py +0 -0
  129. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/attachment_policy_service.py +0 -0
  130. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/auth_service.py +0 -0
  131. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/branding_service.py +0 -0
  132. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/company_context_service.py +0 -0
  133. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/configuration_service.py +0 -0
  134. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/context_builder_service.py +0 -0
  135. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/embedding_service.py +0 -0
  136. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/excel_service.py +0 -0
  137. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/file_processor_service.py +0 -0
  138. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/http_tool_service.py +0 -0
  139. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/i18n_service.py +0 -0
  140. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/inference_service.py +0 -0
  141. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/jwt_service.py +0 -0
  142. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/knowledge_base_service.py +0 -0
  143. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/language_service.py +0 -0
  144. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/license_service.py +0 -0
  145. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/mail_service.py +0 -0
  146. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/markdown_wiki_service.py +0 -0
  147. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/mcp_token_service.py +0 -0
  148. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/memory_compiler_service.py +0 -0
  149. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/memory_lookup_policy_service.py +0 -0
  150. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/memory_service.py +0 -0
  151. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/memory_sources.py +0 -0
  152. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/memory_usage_service.py +0 -0
  153. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/memory_wiki_service.py +0 -0
  154. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/noop_history_compaction_trigger.py +0 -0
  155. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/noop_memory_compilation_trigger.py +0 -0
  156. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/operator_identity_service.py +0 -0
  157. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/parsers/__init__.py +0 -0
  158. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/parsers/contracts.py +0 -0
  159. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/parsers/image_normalizer.py +0 -0
  160. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/parsers/parsing_service.py +0 -0
  161. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/parsers/pdf_ocr_detection.py +0 -0
  162. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/parsers/provider_factory.py +0 -0
  163. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/parsers/provider_resolver.py +0 -0
  164. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/parsers/providers/__init__.py +0 -0
  165. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/parsers/providers/basic_provider.py +0 -0
  166. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/parsers/providers/docling_provider.py +0 -0
  167. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/parsers/validator.py +0 -0
  168. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/pdf_service.py +0 -0
  169. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/profile_service.py +0 -0
  170. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/prompt_resource_service.py +0 -0
  171. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/prompt_service.py +0 -0
  172. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/query_service.py +0 -0
  173. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/resource_access_scope.py +0 -0
  174. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/signup_policy_resolver.py +0 -0
  175. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/sql_catalog_service.py +0 -0
  176. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/sql_dataset_service.py +0 -0
  177. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/sql_service.py +0 -0
  178. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/sql_source_service.py +0 -0
  179. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/storage_service.py +0 -0
  180. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/structured_output_service.py +0 -0
  181. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/system_agent_catalog.py +0 -0
  182. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/system_agent_runner.py +0 -0
  183. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/system_prompt_catalog.py +0 -0
  184. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/system_tools.py +0 -0
  185. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/telemetry_service.py +0 -0
  186. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/tenant_wiki_service.py +0 -0
  187. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/tool_output_contract.py +0 -0
  188. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/user_feedback_service.py +0 -0
  189. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/user_session_context_service.py +0 -0
  190. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/visual_kb_service.py +0 -0
  191. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/visual_tool_service.py +0 -0
  192. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/warmup_service.py +0 -0
  193. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/web_search/__init__.py +0 -0
  194. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/web_search/provider_factory.py +0 -0
  195. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/web_search/providers/__init__.py +0 -0
  196. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/web_search/providers/brave_provider.py +0 -0
  197. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/web_search_service.py +0 -0
  198. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/services/wiki_page_index_service.py +0 -0
  199. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/static/images/favicon.ico +0 -0
  200. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/static/images/favicon.png +0 -0
  201. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/static/images/fernando.jpeg +0 -0
  202. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/static/images/iatoolkit_core.png +0 -0
  203. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/static/images/iatoolkit_logo.png +0 -0
  204. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/static/js/chat_feedback_button.js +0 -0
  205. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/static/js/chat_filepond.js +0 -0
  206. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/static/js/chat_header_navigation.js +0 -0
  207. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/static/js/chat_help_content.js +0 -0
  208. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/static/js/chat_history_button.js +0 -0
  209. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/static/js/chat_logout_button.js +0 -0
  210. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/static/js/chat_main.js +0 -0
  211. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/static/js/chat_memory_button.js +0 -0
  212. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/static/js/chat_model_selector.js +0 -0
  213. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/static/js/chat_onboarding_button.js +0 -0
  214. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/static/js/chat_prompt_manager.js +0 -0
  215. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/static/styles/account.css +0 -0
  216. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/static/styles/chat_iatoolkit.css +0 -0
  217. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/static/styles/chat_modal.css +0 -0
  218. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/static/styles/chat_public.css +0 -0
  219. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/static/styles/documents.css +0 -0
  220. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/static/styles/landing_page.css +0 -0
  221. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/static/styles/llm_output.css +0 -0
  222. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/static/styles/onboarding.css +0 -0
  223. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/static/styles/wiki_page.css +0 -0
  224. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/templates/_chat_header.html +0 -0
  225. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/templates/_company_header.html +0 -0
  226. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/templates/_login_widget.html +0 -0
  227. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/templates/account.html +0 -0
  228. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/templates/base.html +0 -0
  229. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/templates/change_password.html +0 -0
  230. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/templates/chat.html +0 -0
  231. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/templates/chat_memory_modal.html +0 -0
  232. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/templates/chat_modals.html +0 -0
  233. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/templates/error.html +0 -0
  234. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/templates/forgot_password.html +0 -0
  235. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/templates/home_hosted_default.html +0 -0
  236. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/templates/login_global.html +0 -0
  237. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/templates/memory/wiki_schema.md +0 -0
  238. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/templates/pdf/base.html +0 -0
  239. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/templates/pdf/letter.html +0 -0
  240. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/templates/pdf/report.html +0 -0
  241. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/templates/pdf/simple.html +0 -0
  242. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/templates/signup.html +0 -0
  243. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/templates/wiki_page.html +0 -0
  244. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/views/__init__.py +0 -0
  245. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/views/account_view.py +0 -0
  246. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/views/api_key_api_view.py +0 -0
  247. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/views/base_login_view.py +0 -0
  248. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/views/categories_api_view.py +0 -0
  249. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/views/change_password_view.py +0 -0
  250. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/views/chat_context_preview_api_view.py +0 -0
  251. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/views/chat_view.py +0 -0
  252. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/views/configuration_api_view.py +0 -0
  253. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/views/connectors_api_view.py +0 -0
  254. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/views/embedding_api_view.py +0 -0
  255. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/views/forgot_password_view.py +0 -0
  256. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/views/help_content_api_view.py +0 -0
  257. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/views/history_api_view.py +0 -0
  258. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/views/home_view.py +0 -0
  259. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/views/init_context_api_view.py +0 -0
  260. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/views/llmquery_api_view.py +0 -0
  261. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/views/load_document_api_view.py +0 -0
  262. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/views/login_view.py +0 -0
  263. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/views/logout_api_view.py +0 -0
  264. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/views/memory_api_view.py +0 -0
  265. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/views/profile_api_view.py +0 -0
  266. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/views/prompt_api_view.py +0 -0
  267. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/views/prompt_context_preview_api_view.py +0 -0
  268. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/views/prompt_resource_api_view.py +0 -0
  269. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/views/rag_api_view.py +0 -0
  270. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/views/root_redirect_view.py +0 -0
  271. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/views/signup_view.py +0 -0
  272. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/views/static_page_view.py +0 -0
  273. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/views/tool_api_view.py +0 -0
  274. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/views/user_feedback_api_view.py +0 -0
  275. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/views/users_api_view.py +0 -0
  276. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/views/verify_user_view.py +0 -0
  277. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit/views/wiki_page_view.py +0 -0
  278. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit.egg-info/SOURCES.txt +0 -0
  279. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit.egg-info/dependency_links.txt +0 -0
  280. {iatoolkit-2.75.4 → iatoolkit-2.76.1}/src/iatoolkit.egg-info/requires.txt +0 -0
  281. {iatoolkit-2.75.4 → iatoolkit-2.76.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.75.4
3
+ Version: 2.76.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.75.4"
6
+ __version__ = "2.76.1"
7
7
 
8
8
  # Expose main classes and functions at the top level of the package
9
9
 
@@ -666,6 +666,35 @@ tools:
666
666
  required:
667
667
  - question_id
668
668
  - answer
669
+ - function_name: iat_memory_register_question
670
+ description: Registra una pregunta sobre cómo se hacen las cosas en la empresa que la Memoria de la empresa no pudo responder, para que alguien que sabe la responda y la Memoria lo aprenda. Úsala cuando, después de buscar en la Memoria y en los documentos, no encontraste la respuesta, o cuando el usuario pida agregar la pregunta a la Memoria. No guarda quién preguntó. No la uses para preguntas personales, del momento o que no son de la empresa. Cuéntale al usuario que quedó registrada y qué pasa después (o que no se registró, si así lo dice el resultado).
671
+ execution_config:
672
+ side_effects: true
673
+ destructive: false
674
+ routing_profile:
675
+ tags:
676
+ - memory
677
+ - company_memory
678
+ - questions
679
+ - unanswered
680
+ - gap
681
+ intents:
682
+ - Register a question about the company that the memory could not answer.
683
+ - Add the user's question to the company memory's open questions.
684
+ examples:
685
+ - iat_memory_register_question(question="¿Cuál es el procedimiento para emitir una factura en euros?")
686
+ cost:
687
+ penalty: 0.1
688
+ latency_class: low
689
+ expensive: false
690
+ parameters:
691
+ type: object
692
+ properties:
693
+ question:
694
+ type: string
695
+ description: La pregunta, redactada en tono neutro y autocontenida (debe entenderse sin la conversación), sin nombres ni datos personales.
696
+ required:
697
+ - question
669
698
  - function_name: iat_image_search
670
699
  description: Busca imágenes en la base de conocimiento visual de la empresa usando una descripción de texto. Útil cuando el usuario pide 'ver' algo, 'muéstrame una foto de...', o busca gráficos y diagramas.
671
700
  routing:
@@ -31,6 +31,7 @@ class Dispatcher:
31
31
  "iat_memory_save",
32
32
  "iat_memory_pending_questions",
33
33
  "iat_memory_answer_question",
34
+ "iat_memory_register_question",
34
35
  "iat_wiki_search",
35
36
  "iat_wiki_get_page",
36
37
  # The schema shown is the person's: their sources and tables (BL-017).
@@ -300,6 +300,9 @@ class HistoryCompactionService:
300
300
  return {"status": "skipped", "reason": "history_changed"}
301
301
 
302
302
  compacted = [current[0], HistoryManagerService.summary_message(summary)] + current[plan.cut:]
303
+ # The turns kept verbatim keep their words, not their old tool
304
+ # outputs: else a compaction can leave the history as big as it was.
305
+ HistoryManagerService._trim_old_tool_outputs(compacted)
303
306
  self.session_context.save_context_history(company_short_name, user_identifier, compacted, model=model)
304
307
  # The provider's last measure described the long history; until the
305
308
  # next turn measures again, an estimate keeps the in-line check from
@@ -64,8 +64,10 @@ class HistoryManagerService:
64
64
  #: stored history: an SQL result or a schema is what the model needs on the
65
65
  #: turn that asked for it, and resending it whole on every later turn was
66
66
  #: most of the history's growth (4k -> 11k tokens on one SQL turn in
67
- #: production). The model can call the tool again.
68
- KEEP_TOOL_OUTPUT_TURNS = 2
67
+ #: production). The model can call the tool again. One: the last turn, the
68
+ #: one a follow-up ("of those...") refers to; with two, one turn of 80k of
69
+ #: results kept a compacted history at 130k.
70
+ KEEP_TOOL_OUTPUT_TURNS = 1
69
71
  #: What is kept of a cut output: its beginning, enough to remember its shape.
70
72
  TRIMMED_TOOL_OUTPUT_CHARS = 1500
71
73
  TRIMMED_TOOL_OUTPUT_MARKER = "[tool output trimmed"
@@ -388,13 +390,19 @@ class HistoryManagerService:
388
390
 
389
391
  @classmethod
390
392
  def _trim_old_tool_outputs(cls, context_history: list):
391
- """Cuts the long tool outputs of all but the last KEEP_TOOL_OUTPUT_TURNS turns, in place.
392
-
393
- Each output keeps its message (a tool call without its output is a
394
- history every provider rejects) and its beginning, plus a note naming the
395
- tool so the model knows it can call it again. An output is cut once: the
396
- stored history then stays the same from turn to turn, which is what a
397
- provider's prompt cache reuses.
393
+ """Cuts what the turns before the last KEEP_TOOL_OUTPUT_TURNS carry for their tools, in place.
394
+
395
+ - Long tool outputs keep their beginning and a note naming the tool, so
396
+ the model knows it can call it again.
397
+ - Long tool call arguments (a whole dataset passed to an Excel, for
398
+ example) become a short valid JSON object: some adapters parse them.
399
+ - The reasoning of those turns is dropped: providers need it only within
400
+ the turn that produced it, and 8 rounds of it stayed in a compacted
401
+ history (110k tokens one turn after compacting, in production).
402
+
403
+ Every call keeps its message and its output message, so the history is
404
+ always valid for the provider. A message is cut once: the stored history
405
+ then stays the same from turn to turn, which is what a prompt cache reuses.
398
406
  """
399
407
  turn_starts = cls.turn_starts(context_history)
400
408
  if len(turn_starts) <= cls.KEEP_TOOL_OUTPUT_TURNS:
@@ -402,9 +410,19 @@ class HistoryManagerService:
402
410
  boundary = turn_starts[-cls.KEEP_TOOL_OUTPUT_TURNS]
403
411
  tool_names = {}
404
412
  for message in context_history[:boundary]:
405
- for call in (message.get("tool_calls") or []) if isinstance(message, dict) else []:
406
- if isinstance(call, dict):
407
- tool_names[call.get("id")] = (call.get("function") or {}).get("name")
413
+ if not isinstance(message, dict):
414
+ continue
415
+ message.pop("reasoning_content", None)
416
+ message.pop("reasoning_details", None)
417
+ for call in message.get("tool_calls") or []:
418
+ if not isinstance(call, dict):
419
+ continue
420
+ function = call.get("function") if isinstance(call.get("function"), dict) else {}
421
+ tool_names[call.get("id")] = function.get("name")
422
+ arguments = function.get("arguments")
423
+ if isinstance(arguments, str) and len(arguments) > cls.TRIMMED_TOOL_OUTPUT_CHARS:
424
+ function["arguments"] = json.dumps(
425
+ {"trimmed": f"{len(arguments)} characters of arguments, from an earlier turn"})
408
426
  for message in context_history[:boundary]:
409
427
  if not isinstance(message, dict) or message.get("type") != "function_call_output":
410
428
  continue
@@ -66,6 +66,16 @@ class llmClient:
66
66
  # a wiki page withheld).
67
67
  TOOL_CALL_RESULT_KEY = "result"
68
68
  TOOL_CALL_EXCERPT_MAX_LENGTH = 300
69
+ # The most of one tool output the model reads (~10k tokens). Every round of
70
+ # the loop resends every output, so a few results of hundreds of rows took
71
+ # one turn from 54k to 133k tokens in production (BL-009). Past this, the
72
+ # model is told to narrow the query instead.
73
+ MAX_TOOL_OUTPUT_CHARS = 40000
74
+ TOOL_OUTPUT_CUT_NOTICE = (
75
+ "[Resultado cortado: se muestran {shown} de {total} caracteres. No lo completes ni "
76
+ "lo inventes: si necesitas el resto, vuelve a llamar la herramienta pidiendo menos "
77
+ "(filtros, agregaciones, LIMIT o por partes).]"
78
+ )
69
79
  TOOL_RESULT_FAILED_STATUSES = frozenset({"error", "auth_required", "forbidden", "unavailable"})
70
80
 
71
81
  @inject
@@ -408,7 +418,8 @@ class llmClient:
408
418
  tool_attachments_count = len(tool_native_attachments or [])
409
419
 
410
420
  # add the return value into the list of messages
411
- tool_output_text = self._serialize_tool_output(result)
421
+ tool_output_text = self._cap_tool_output(
422
+ company.short_name, function_name, self._serialize_tool_output(result))
412
423
  last_tool_output_message = {
413
424
  "type": "function_call_output",
414
425
  "call_id": tool_call.call_id,
@@ -774,6 +785,17 @@ class llmClient:
774
785
  except Exception:
775
786
  return str(result)
776
787
 
788
+ @classmethod
789
+ def _cap_tool_output(cls, company_short_name: str, function_name: str, text: str) -> str:
790
+ if not isinstance(text, str) or len(text) <= cls.MAX_TOOL_OUTPUT_CHARS:
791
+ return text
792
+ logging.warning(
793
+ f"[{company_short_name}] output of {function_name} cut to {cls.MAX_TOOL_OUTPUT_CHARS} "
794
+ f"of {len(text)} characters."
795
+ )
796
+ notice = cls.TOOL_OUTPUT_CUT_NOTICE.format(shown=cls.MAX_TOOL_OUTPUT_CHARS, total=len(text))
797
+ return f"{text[:cls.MAX_TOOL_OUTPUT_CHARS]}\n{notice}"
798
+
777
799
  @staticmethod
778
800
  def _split_tool_result_and_native_attachments(result):
779
801
  if not isinstance(result, dict):
@@ -7,6 +7,7 @@ from __future__ import annotations
7
7
 
8
8
  import json
9
9
  import logging
10
+ import re
10
11
  from contextlib import contextmanager
11
12
  from datetime import datetime, timedelta
12
13
 
@@ -206,6 +207,85 @@ class MemoryQuestionService:
206
207
  except Exception:
207
208
  logging.exception("Memoria search miss could not be recorded for %s", company_short_name)
208
209
 
210
+ # =====================================================================
211
+ # A question someone says the Memoria does not answer
212
+ # =====================================================================
213
+
214
+ # Words that say nothing about the topic of a question.
215
+ QUESTION_STOPWORDS = frozenset({
216
+ "como", "cual", "cuales", "cuando", "cuanto", "cuanta", "cuantos", "cuantas", "donde", "quien", "quienes",
217
+ "para", "pero", "porque", "sobre", "entre", "desde", "hasta", "esta", "este", "estos", "estas", "esto",
218
+ "puedo", "puede", "pueden", "podemos", "debo", "debe", "tiene", "tienen", "tenemos", "hacer", "hace",
219
+ "existe", "algun", "alguna", "empresa", "nuestra", "nuestro", "what", "when", "where", "which", "does",
220
+ "there", "this", "that", "with", "from", "have", "should", "company",
221
+ })
222
+ QUESTION_TOPIC_PREFIX = 5
223
+
224
+ def register_question(self, company_short_name: str, user_identifier: str | None, question: str,
225
+ channel: str = memory_tools.CHANNEL_CHAT) -> dict:
226
+ """
227
+ A question the Memoria could not answer, as the AI or the person says (chat or MCP).
228
+ Over MCP the answer is written outside IAToolkit, so only they know it went unanswered.
229
+
230
+ It enters as a candidate: the hourly review writes it neutrally, gives it a topic,
231
+ groups it with the open ones and someone is assigned, as with any other. Who asked
232
+ is not kept. A question whose topic is in content the person may not read (a
233
+ restricted folder) is not opened for the whole company (BL-015, hallazgo 1).
234
+ """
235
+ text = " ".join(str(question or "").split())
236
+ if not text:
237
+ return {"status": "error", "error_message": "question is required"}
238
+ company = self.profile_repo.get_company_by_short_name(company_short_name)
239
+ if not company:
240
+ return {"status": "error", "error_message": "company not found"}
241
+ if self._topic_is_restricted_for(company_short_name, user_identifier, text):
242
+ return {
243
+ "status": "success",
244
+ "registered": False,
245
+ "reason": "restricted",
246
+ "message": "No quedó registrada como pregunta abierta de la empresa: ese tema puede estar en "
247
+ "información de acceso restringido. Consúltalo con la persona a cargo del área.",
248
+ }
249
+ self.question_repo.add(MemoryQuestionCandidate(
250
+ company_id=company.id,
251
+ query_text=text[:self.MAX_CANDIDATE_CHARS],
252
+ source=channel if channel in (memory_tools.CHANNEL_CHAT, memory_tools.CHANNEL_MCP) else memory_tools.CHANNEL_CHAT,
253
+ ))
254
+ self.question_repo.commit()
255
+ return {
256
+ "status": "success",
257
+ "registered": True,
258
+ "message": "Registrada. Dentro de la próxima hora se suma a las preguntas sin respuesta de la empresa "
259
+ "(junto a las parecidas) y se le sugiere a quien sabe del tema; cuando alguien la responda, "
260
+ "la Memoria lo aprende.",
261
+ }
262
+
263
+ def _topic_is_restricted_for(self, company_short_name: str, user_identifier: str | None, question: str) -> bool:
264
+ """Whether a page the person may not read covers the question's topic (its title or summary)."""
265
+ visible = self.memory_service.audiences_for(company_short_name, user_identifier)
266
+ if visible is None:
267
+ return False # they read everything: nothing hidden to give away
268
+ hidden = [page for page in self.memory_service.memory_wiki_service.list_pages(company_short_name)
269
+ if page.get("audience_key") and page.get("audience_key") not in visible]
270
+ if not hidden:
271
+ return False
272
+ words = self._topic_words(question)
273
+ if not words:
274
+ return False
275
+ needed = min(2, len(words))
276
+ for page in hidden:
277
+ page_words = self._topic_words(f"{page.get('title') or ''} {page.get('summary') or ''}")
278
+ if sum(1 for word in words if word in page_words) >= needed:
279
+ return True
280
+ return False
281
+
282
+ @classmethod
283
+ def _topic_words(cls, text: str) -> set[str]:
284
+ """The question's topic words, cut to a prefix so "bono" and "bonos" match."""
285
+ normalized = MemoryService._normalize_text(text)
286
+ return {word[:cls.QUESTION_TOPIC_PREFIX] for word in re.findall(r"[a-z0-9]+", normalized)
287
+ if len(word) >= 4 and word not in cls.QUESTION_STOPWORDS}
288
+
209
289
  def has_pending_work(self, company_short_name: str) -> bool:
210
290
  """Whether a scan would find anything new; lets the hourly dispatch skip quiet tenants."""
211
291
  company = self.profile_repo.get_company_by_short_name(company_short_name)
@@ -121,6 +121,7 @@ class ToolService:
121
121
  "iat_memory_save": self._handle_memory_save_tool,
122
122
  "iat_memory_pending_questions": self._handle_memory_pending_questions_tool,
123
123
  "iat_memory_answer_question": self._handle_memory_answer_question_tool,
124
+ "iat_memory_register_question": self._handle_memory_register_question_tool,
124
125
  "iat_wiki_search": self._handle_wiki_search_tool,
125
126
  "iat_wiki_get_page": self._handle_wiki_get_page_tool,
126
127
  "iat_web_search": self._handle_web_search_tool,
@@ -429,6 +430,18 @@ class ToolService:
429
430
  return {"status": "error", "error_message": "question_id is required"}
430
431
  return self._memory_question_service().answer(company_short_name, question_id, str(answer or ""), user_identifier)
431
432
 
433
+ def _handle_memory_register_question_tool(self,
434
+ company_short_name: str,
435
+ question: str,
436
+ user_identifier: str | None = None,
437
+ **kwargs):
438
+ """Registers a question the Memoria could not answer, so someone who knows answers it."""
439
+ if not user_identifier:
440
+ return {"status": "error", "error_message": "memory not available without an identified user"}
441
+ channel = str(kwargs.get("_iat_runtime_source") or "chat").strip() or "chat"
442
+ return self._memory_question_service().register_question(
443
+ company_short_name, user_identifier, str(question or ""), channel=channel)
444
+
432
445
  def _handle_memory_save_tool(self,
433
446
  company_short_name: str,
434
447
  content: str,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: iatoolkit
3
- Version: 2.75.4
3
+ Version: 2.76.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