iatoolkit 2.73.8__tar.gz → 2.74.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 (284) hide show
  1. {iatoolkit-2.73.8/src/iatoolkit.egg-info → iatoolkit-2.74.1}/PKG-INFO +1 -1
  2. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/__init__.py +1 -1
  3. iatoolkit-2.74.1/src/iatoolkit/common/interfaces/history_compaction_trigger.py +21 -0
  4. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/common/model_registry.py +42 -31
  5. iatoolkit-2.74.1/src/iatoolkit/config/system_agents/history_compaction.prompt +24 -0
  6. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/config/system_agents_pack.yaml +22 -0
  7. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/core.py +4 -0
  8. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/infra/llm_providers/anthropic_adapter.py +1 -3
  9. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/infra/llm_providers/gemini_adapter.py +0 -1
  10. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/infra/llm_providers/openai_adapter.py +102 -40
  11. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/infra/llm_proxy.py +42 -0
  12. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/locales/en.yaml +0 -4
  13. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/locales/es.yaml +0 -4
  14. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/repositories/llm_query_repo.py +19 -5
  15. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/repositories/models.py +17 -3
  16. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/attachment_policy_service.py +51 -132
  17. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/configuration_service.py +5 -1
  18. iatoolkit-2.74.1/src/iatoolkit/services/history_compaction_service.py +272 -0
  19. iatoolkit-2.74.1/src/iatoolkit/services/history_manager_service.py +374 -0
  20. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/llm_client_service.py +13 -78
  21. iatoolkit-2.74.1/src/iatoolkit/services/noop_history_compaction_trigger.py +21 -0
  22. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/query_service.py +63 -169
  23. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/system_agent_runner.py +3 -3
  24. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/user_session_context_service.py +21 -40
  25. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/static/js/chat_header_navigation.js +1 -1
  26. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/templates/_chat_header.html +0 -8
  27. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/templates/chat.html +0 -1
  28. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/views/init_context_api_view.py +1 -5
  29. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/views/login_view.py +2 -1
  30. {iatoolkit-2.73.8 → iatoolkit-2.74.1/src/iatoolkit.egg-info}/PKG-INFO +1 -1
  31. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit.egg-info/SOURCES.txt +4 -1
  32. iatoolkit-2.73.8/src/iatoolkit/services/history_manager_service.py +0 -212
  33. iatoolkit-2.73.8/src/iatoolkit/static/js/chat_reload_button.js +0 -38
  34. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/LICENSE +0 -0
  35. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/LICENSE_COMMUNITY.md +0 -0
  36. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/pyproject.toml +0 -0
  37. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/readme.md +0 -0
  38. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/setup.cfg +0 -0
  39. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/base_company.py +0 -0
  40. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/cli_commands.py +0 -0
  41. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/common/__init__.py +0 -0
  42. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/common/access.py +0 -0
  43. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/common/bridge_validation.py +0 -0
  44. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/common/company_paths.py +0 -0
  45. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/common/exceptions.py +0 -0
  46. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/common/interfaces/__init__.py +0 -0
  47. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/common/interfaces/asset_storage.py +0 -0
  48. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/common/interfaces/database_provider.py +0 -0
  49. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/common/interfaces/memory_compilation_trigger.py +0 -0
  50. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/common/interfaces/secret_provider.py +0 -0
  51. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/common/interfaces/signup_policy_resolver.py +0 -0
  52. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/common/interfaces/web_search_provider.py +0 -0
  53. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/common/memory_tools.py +0 -0
  54. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/common/routes.py +0 -0
  55. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/common/search_terms.py +0 -0
  56. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/common/secret_resolver.py +0 -0
  57. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/common/session_manager.py +0 -0
  58. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/common/text_splitter.py +0 -0
  59. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/common/url_safety.py +0 -0
  60. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/common/util.py +0 -0
  61. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/company_registry.py +0 -0
  62. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/config/__init__.py +0 -0
  63. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/config/llm_capabilities.yaml +0 -0
  64. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/config/system_agents/memory_compiler.prompt +0 -0
  65. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/config/system_agents/memory_correction.prompt +0 -0
  66. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/config/system_agents/memory_document_ingest.prompt +0 -0
  67. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/config/system_agents/memory_image_ingest.prompt +0 -0
  68. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/config/system_agents/memory_meeting_ingest.prompt +0 -0
  69. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/config/system_agents/memory_question_review.prompt +0 -0
  70. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/config/system_prompts/channel_business_identity.prompt +0 -0
  71. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/config/system_prompts/channel_conversation_continuity.prompt +0 -0
  72. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/config/system_prompts/channel_response_style.prompt +0 -0
  73. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/config/system_prompts/chat_state_rules.prompt +0 -0
  74. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/config/system_prompts/chat_user_profile.prompt +0 -0
  75. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/config/system_prompts/core_identity.prompt +0 -0
  76. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/config/system_prompts/email_output.prompt +0 -0
  77. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/config/system_prompts/file_download_output.prompt +0 -0
  78. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/config/system_prompts/format_styles.prompt +0 -0
  79. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/config/system_prompts/html_structures.prompt +0 -0
  80. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/config/system_prompts/links_documents.prompt +0 -0
  81. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/config/system_prompts/memory_usage.prompt +0 -0
  82. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/config/system_prompts/multimodal_basics.prompt +0 -0
  83. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/config/system_prompts/output_basics.prompt +0 -0
  84. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/config/system_prompts/presentation_formatting.prompt +0 -0
  85. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/config/system_prompts/query_main.prompt +0 -0
  86. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/config/system_prompts/sql_aggregation_scope.prompt +0 -0
  87. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/config/system_prompts/sql_casting.prompt +0 -0
  88. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/config/system_prompts/sql_core.prompt +0 -0
  89. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/config/system_prompts/sql_jsonb.prompt +0 -0
  90. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/config/system_prompts/sql_mysql_casting.prompt +0 -0
  91. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/config/system_prompts/sql_mysql_json.prompt +0 -0
  92. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/config/system_prompts/sql_redshift_basics.prompt +0 -0
  93. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/config/system_prompts/sql_redshift_types.prompt +0 -0
  94. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/config/system_prompts/sql_rules.prompt +0 -0
  95. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/config/system_prompts/tool_html_passthrough.prompt +0 -0
  96. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/config/system_prompts_pack.yaml +0 -0
  97. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/config/system_tools_pack.yaml +0 -0
  98. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/infra/__init__.py +0 -0
  99. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/infra/brevo_mail_app.py +0 -0
  100. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/infra/call_service.py +0 -0
  101. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/infra/connectors/__init__.py +0 -0
  102. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/infra/connectors/file_connector.py +0 -0
  103. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/infra/connectors/file_connector_factory.py +0 -0
  104. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/infra/connectors/google_cloud_storage_connector.py +0 -0
  105. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/infra/connectors/google_drive_connector.py +0 -0
  106. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/infra/connectors/local_file_connector.py +0 -0
  107. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/infra/connectors/s3_connector.py +0 -0
  108. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/infra/google_auth_client.py +0 -0
  109. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/infra/google_chat_app.py +0 -0
  110. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/infra/inference_embeddings_client.py +0 -0
  111. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/infra/inference_handler.py +0 -0
  112. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/infra/jina_embeddings_client.py +0 -0
  113. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/infra/llm_gateway_resolver.py +0 -0
  114. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/infra/llm_providers/__init__.py +0 -0
  115. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/infra/llm_providers/deepseek_adapter.py +0 -0
  116. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/infra/llm_providers/openai_compatible_chat_adapter.py +0 -0
  117. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/infra/llm_providers/openrouter_adapter.py +0 -0
  118. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/infra/llm_response.py +0 -0
  119. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/infra/redis_session_manager.py +0 -0
  120. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/repositories/__init__.py +0 -0
  121. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/repositories/advisory_lock.py +0 -0
  122. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/repositories/api_key_repo.py +0 -0
  123. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/repositories/bridge_repo.py +0 -0
  124. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/repositories/database_manager.py +0 -0
  125. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/repositories/document_repo.py +0 -0
  126. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/repositories/env_secret_provider.py +0 -0
  127. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/repositories/filesystem_asset_repository.py +0 -0
  128. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/repositories/knowledge_wiki_repo.py +0 -0
  129. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/repositories/mcp_token_repo.py +0 -0
  130. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/repositories/memory_question_repo.py +0 -0
  131. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/repositories/memory_repo.py +0 -0
  132. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/repositories/memory_usage_repo.py +0 -0
  133. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/repositories/profile_repo.py +0 -0
  134. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/repositories/prompt_resource_repo.py +0 -0
  135. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/repositories/sql_dataset_repo.py +0 -0
  136. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/repositories/sql_source_repo.py +0 -0
  137. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/repositories/vs_repo.py +0 -0
  138. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/runtime_logging.py +0 -0
  139. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/__init__.py +0 -0
  140. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/api_key_service.py +0 -0
  141. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/auth_service.py +0 -0
  142. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/branding_service.py +0 -0
  143. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/company_context_service.py +0 -0
  144. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/context_builder_service.py +0 -0
  145. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/dispatcher_service.py +0 -0
  146. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/embedding_service.py +0 -0
  147. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/excel_service.py +0 -0
  148. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/file_processor_service.py +0 -0
  149. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/http_tool_service.py +0 -0
  150. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/i18n_service.py +0 -0
  151. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/inference_service.py +0 -0
  152. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/jwt_service.py +0 -0
  153. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/knowledge_base_service.py +0 -0
  154. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/language_service.py +0 -0
  155. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/license_service.py +0 -0
  156. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/mail_service.py +0 -0
  157. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/markdown_wiki_service.py +0 -0
  158. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/mcp_token_service.py +0 -0
  159. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/memory_compiler_service.py +0 -0
  160. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/memory_lookup_policy_service.py +0 -0
  161. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/memory_question_service.py +0 -0
  162. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/memory_service.py +0 -0
  163. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/memory_sources.py +0 -0
  164. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/memory_usage_service.py +0 -0
  165. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/memory_wiki_service.py +0 -0
  166. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/noop_memory_compilation_trigger.py +0 -0
  167. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/operator_identity_service.py +0 -0
  168. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/parsers/__init__.py +0 -0
  169. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/parsers/contracts.py +0 -0
  170. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/parsers/image_normalizer.py +0 -0
  171. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/parsers/parsing_service.py +0 -0
  172. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/parsers/pdf_ocr_detection.py +0 -0
  173. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/parsers/provider_factory.py +0 -0
  174. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/parsers/provider_resolver.py +0 -0
  175. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/parsers/providers/__init__.py +0 -0
  176. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/parsers/providers/basic_provider.py +0 -0
  177. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/parsers/providers/docling_provider.py +0 -0
  178. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/parsers/validator.py +0 -0
  179. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/pdf_service.py +0 -0
  180. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/profile_service.py +0 -0
  181. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/prompt_resource_service.py +0 -0
  182. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/prompt_service.py +0 -0
  183. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/resource_access_scope.py +0 -0
  184. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/signup_policy_resolver.py +0 -0
  185. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/sql_dataset_service.py +0 -0
  186. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/sql_service.py +0 -0
  187. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/sql_source_service.py +0 -0
  188. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/storage_service.py +0 -0
  189. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/structured_output_service.py +0 -0
  190. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/system_agent_catalog.py +0 -0
  191. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/system_prompt_catalog.py +0 -0
  192. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/system_tools.py +0 -0
  193. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/telemetry_service.py +0 -0
  194. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/tenant_wiki_service.py +0 -0
  195. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/tool_output_contract.py +0 -0
  196. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/tool_service.py +0 -0
  197. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/user_feedback_service.py +0 -0
  198. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/visual_kb_service.py +0 -0
  199. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/visual_tool_service.py +0 -0
  200. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/warmup_service.py +0 -0
  201. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/web_search/__init__.py +0 -0
  202. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/web_search/provider_factory.py +0 -0
  203. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/web_search/providers/__init__.py +0 -0
  204. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/web_search/providers/brave_provider.py +0 -0
  205. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/web_search_service.py +0 -0
  206. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/services/wiki_page_index_service.py +0 -0
  207. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/static/images/favicon.ico +0 -0
  208. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/static/images/favicon.png +0 -0
  209. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/static/images/fernando.jpeg +0 -0
  210. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/static/images/iatoolkit_core.png +0 -0
  211. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/static/images/iatoolkit_logo.png +0 -0
  212. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/static/js/chat_feedback_button.js +0 -0
  213. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/static/js/chat_filepond.js +0 -0
  214. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/static/js/chat_help_content.js +0 -0
  215. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/static/js/chat_history_button.js +0 -0
  216. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/static/js/chat_logout_button.js +0 -0
  217. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/static/js/chat_main.js +0 -0
  218. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/static/js/chat_memory_button.js +0 -0
  219. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/static/js/chat_model_selector.js +0 -0
  220. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/static/js/chat_onboarding_button.js +0 -0
  221. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/static/js/chat_prompt_manager.js +0 -0
  222. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/static/styles/account.css +0 -0
  223. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/static/styles/chat_iatoolkit.css +0 -0
  224. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/static/styles/chat_modal.css +0 -0
  225. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/static/styles/chat_public.css +0 -0
  226. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/static/styles/documents.css +0 -0
  227. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/static/styles/landing_page.css +0 -0
  228. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/static/styles/llm_output.css +0 -0
  229. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/static/styles/onboarding.css +0 -0
  230. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/static/styles/wiki_page.css +0 -0
  231. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/templates/_company_header.html +0 -0
  232. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/templates/_login_widget.html +0 -0
  233. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/templates/account.html +0 -0
  234. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/templates/base.html +0 -0
  235. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/templates/change_password.html +0 -0
  236. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/templates/chat_memory_modal.html +0 -0
  237. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/templates/chat_modals.html +0 -0
  238. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/templates/error.html +0 -0
  239. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/templates/forgot_password.html +0 -0
  240. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/templates/home_hosted_default.html +0 -0
  241. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/templates/login_global.html +0 -0
  242. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/templates/memory/wiki_schema.md +0 -0
  243. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/templates/onboarding_shell.html +0 -0
  244. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/templates/pdf/base.html +0 -0
  245. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/templates/pdf/letter.html +0 -0
  246. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/templates/pdf/report.html +0 -0
  247. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/templates/pdf/simple.html +0 -0
  248. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/templates/signup.html +0 -0
  249. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/templates/wiki_page.html +0 -0
  250. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/views/__init__.py +0 -0
  251. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/views/account_view.py +0 -0
  252. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/views/api_key_api_view.py +0 -0
  253. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/views/base_login_view.py +0 -0
  254. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/views/categories_api_view.py +0 -0
  255. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/views/change_password_view.py +0 -0
  256. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/views/chat_context_preview_api_view.py +0 -0
  257. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/views/chat_view.py +0 -0
  258. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/views/configuration_api_view.py +0 -0
  259. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/views/connectors_api_view.py +0 -0
  260. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/views/embedding_api_view.py +0 -0
  261. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/views/forgot_password_view.py +0 -0
  262. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/views/help_content_api_view.py +0 -0
  263. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/views/history_api_view.py +0 -0
  264. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/views/home_view.py +0 -0
  265. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/views/llmquery_api_view.py +0 -0
  266. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/views/load_document_api_view.py +0 -0
  267. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/views/logout_api_view.py +0 -0
  268. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/views/memory_api_view.py +0 -0
  269. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/views/profile_api_view.py +0 -0
  270. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/views/prompt_api_view.py +0 -0
  271. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/views/prompt_context_preview_api_view.py +0 -0
  272. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/views/prompt_resource_api_view.py +0 -0
  273. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/views/rag_api_view.py +0 -0
  274. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/views/root_redirect_view.py +0 -0
  275. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/views/signup_view.py +0 -0
  276. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/views/static_page_view.py +0 -0
  277. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/views/tool_api_view.py +0 -0
  278. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/views/user_feedback_api_view.py +0 -0
  279. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/views/users_api_view.py +0 -0
  280. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/views/verify_user_view.py +0 -0
  281. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit/views/wiki_page_view.py +0 -0
  282. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit.egg-info/dependency_links.txt +0 -0
  283. {iatoolkit-2.73.8 → iatoolkit-2.74.1}/src/iatoolkit.egg-info/requires.txt +0 -0
  284. {iatoolkit-2.73.8 → iatoolkit-2.74.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.73.8
3
+ Version: 2.74.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.73.8"
6
+ __version__ = "2.74.1"
7
7
 
8
8
  # Expose main classes and functions at the top level of the package
9
9
 
@@ -0,0 +1,21 @@
1
+ # Copyright (c) 2024 Fernando Libedinsky
2
+ # Product: IAToolkit
3
+ #
4
+ # IAToolkit is open source software.
5
+
6
+ from __future__ import annotations
7
+
8
+ from abc import ABC, abstractmethod
9
+
10
+
11
+ class HistoryCompactionTrigger(ABC):
12
+ """Asks for a conversation history to be compacted in the background (BL-009).
13
+
14
+ The core has no task queue, so its default does nothing and a history is
15
+ compacted in line, on the turn that would no longer fit. A deployment with
16
+ workers (enterprise) binds one that queues the work instead.
17
+ """
18
+
19
+ @abstractmethod
20
+ def trigger(self, company_short_name: str, user_identifier: str, model: str) -> bool:
21
+ """Queues the compaction. True when something was queued or already was."""
@@ -15,17 +15,9 @@ from injector import inject, singleton
15
15
  from typing import Literal
16
16
 
17
17
 
18
- HistoryType = Literal["server_side", "client_side"]
19
18
  ProviderType = Literal["openai", "gemini", "deepseek", "xai", "anthropic", "openrouter", "openai_compatible", "unknown"]
20
19
 
21
20
 
22
- @dataclass(frozen=True)
23
- class ModelMetadata:
24
- """Static metadata for a logical family of models."""
25
- provider: ProviderType
26
- history_type: HistoryType
27
-
28
-
29
21
  #: Providers a model can actually be served by: the ones `LLMProxy._build_adapter`
30
22
  #: knows how to build. Deliberately narrower than `ProviderType`, which also
31
23
  #: contains `xai` — `normalize_provider` accepts it and a client is built for it,
@@ -118,7 +110,6 @@ class ModelRegistry:
118
110
 
119
111
  Responsibilities:
120
112
  - Map a model name to its provider (openai, gemini, deepseek, etc.).
121
- - Decide which history strategy to use for a model (server_side / client_side).
122
113
  - Provide convenience helpers (is_openai, is_gemini, is_deepseek, etc.).
123
114
  """
124
115
 
@@ -174,30 +165,66 @@ class ModelRegistry:
174
165
  return candidate # type: ignore[return-value]
175
166
  return self.get_provider(model or "")
176
167
 
177
- def get_capabilities(self, model: str, provider: str | None = None) -> dict:
168
+ @staticmethod
169
+ def catalog_capabilities(model_config: dict | None) -> dict | None:
170
+ """The capabilities the model catalogue holds for a model, or None when unknown.
171
+
172
+ Written by `models-sync` from OpenRouter (BL-009, Fase F) and carried in
173
+ the model's configuration. Empty, or a company.yaml model outside the
174
+ catalogue, means unknown: the provider's rules decide.
175
+ """
176
+ capabilities = (model_config or {}).get("capabilities") if isinstance(model_config, dict) else None
177
+ if not isinstance(capabilities, dict):
178
+ return None
179
+ if not capabilities.get("supported_parameters") and not capabilities.get("input_modalities"):
180
+ return None
181
+ return capabilities
182
+
183
+ @staticmethod
184
+ def _declares(capabilities: dict | None, *parameters: str) -> bool | None:
185
+ """Whether the model declares any of `parameters`; None when nothing is known."""
186
+ if not capabilities:
187
+ return None
188
+ declared = {str(value).strip().lower() for value in capabilities.get("supported_parameters") or []}
189
+ if not declared:
190
+ return None
191
+ return any(parameter in declared for parameter in parameters)
192
+
193
+ def get_capabilities(self, model: str, provider: str | None = None, capabilities: dict | None = None) -> dict:
194
+ """What the request may carry for this model.
195
+
196
+ Two halves, both required: what the provider's adapter knows how to send,
197
+ and what the model accepts. The second comes from the model catalogue
198
+ (`capabilities`) when it is known; without it, the provider decides alone.
199
+ The catalogue only ever narrows: a parameter the adapter cannot send is
200
+ never offered because the model would accept it.
201
+ """
178
202
  normalized_provider = self.normalize_provider(provider=provider, model=model)
179
203
  # `openai_compatible` is absent on purpose. Its adapter targets any server
180
204
  # that speaks chat.completions — llama.cpp, vLLM, a private gateway — and
181
205
  # forwards no reasoning field, because one the server does not know earns a
182
206
  # 400. Claiming the capability here made the tenant's Models page offer a
183
207
  # reasoning control whose value went nowhere.
184
- supports_reasoning_effort = normalized_provider in {
208
+ adapter_sends_reasoning = normalized_provider in {
185
209
  "openai",
186
210
  "xai",
187
211
  "openrouter",
188
212
  "deepseek",
189
213
  }
190
- supports_text_verbosity = normalized_provider in {"openai", "xai", "openrouter"}
191
- supports_store = normalized_provider in {"openai", "xai"}
214
+ adapter_sends_verbosity = normalized_provider in {"openai", "xai", "openrouter"}
215
+
216
+ model_reasons = self._declares(capabilities, "reasoning", "reasoning_effort")
217
+ model_takes_verbosity = self._declares(capabilities, "verbosity")
218
+ supports_reasoning_effort = adapter_sends_reasoning and model_reasons is not False
219
+ supports_text_verbosity = adapter_sends_verbosity and model_takes_verbosity is not False
192
220
 
193
221
  return {
194
222
  "provider": normalized_provider,
195
- "history_type": self.get_history_type(model),
196
223
  "supports_reasoning_effort": supports_reasoning_effort,
197
224
  "allowed_reasoning_efforts": list(self._reasoning_effort_options) if supports_reasoning_effort else [],
198
225
  "supports_text_verbosity": supports_text_verbosity,
199
226
  "allowed_text_verbosity": list(self._text_verbosity_options) if supports_text_verbosity else [],
200
- "supports_store": supports_store,
227
+ "capabilities_source": "catalog" if model_reasons is not None else "provider",
201
228
  }
202
229
 
203
230
  def get_request_defaults(self, model: str) -> dict:
@@ -246,22 +273,6 @@ class ModelRegistry:
246
273
  "reasoning": merged_reasoning,
247
274
  }
248
275
 
249
- def get_history_type(self, model: str) -> HistoryType:
250
- """
251
- Returns the history strategy for a given model.
252
-
253
- Current rules:
254
- - openai/xai: server_side (API manages conversation state via ids)
255
- - gemini/deepseek/anthropic/unknown: client_side (we manage full message history)
256
- """
257
- provider = self.get_provider(model)
258
-
259
- if provider in ("openai", "xai"):
260
- return "server_side"
261
-
262
- # Default for gemini, deepseek, anthropic and any unknown provider
263
- return "client_side"
264
-
265
276
  # ------------------------------------------------------------------
266
277
  # Convenience helpers (used during migration)
267
278
  # ------------------------------------------------------------------
@@ -0,0 +1,24 @@
1
+ You compact the older part of a conversation between a person and a company's AI assistant. The conversation is too long for the model's context, so the turns below will be replaced by your summary; the most recent turns stay as they are. The assistant will continue the conversation from your summary alone, so anything you leave out is lost.
2
+
3
+ Write the summary in the language of the conversation, as Markdown, with these sections (omit a section only when there is nothing for it):
4
+
5
+ - **Objective**: what the person is trying to achieve, and how it evolved.
6
+ - **Decisions**: what was agreed, chosen or ruled out, and why when it was said.
7
+ - **Data obtained**: the concrete facts the assistant found or computed with its tools — figures, dates, names, identifiers, table names, SQL that worked, document titles, URLs. Keep exact values; never round or paraphrase a number.
8
+ - **Pending**: questions still open and what the person asked for that is not done yet.
9
+ - **Preferences**: how the person wants to be answered (format, language, level of detail, things to avoid).
10
+
11
+ Rules:
12
+
13
+ - Keep facts, drop chatter. Do not repeat the same fact twice.
14
+ - Attribute statements correctly: what the person said is not what the assistant concluded.
15
+ - Do not add information that is not in the turns or in the previous summary.
16
+ - When a previous summary is given, merge it with the new turns into one summary: keep what is still true, update what changed, and drop what was superseded.
17
+
18
+ Return the summary in `summary`.
19
+
20
+ PREVIOUS SUMMARY:
21
+ {{ previous_summary or "(none)" }}
22
+
23
+ TURNS TO COMPACT:
24
+ {{ transcript }}
@@ -312,3 +312,25 @@ agents:
312
312
  additionalProperties: false
313
313
  inputs: [source, captured_on, wiki_schema, page_index, candidate_pages]
314
314
  default_model: null
315
+
316
+ - key: history_compaction
317
+ name: Compactación del historial
318
+ name_en: History compaction
319
+ description: >-
320
+ (Chat) Resume la parte antigua de una conversación larga cuando se acerca al límite de contexto del
321
+ modelo, para que la conversación siga sin perder lo importante.
322
+ description_en: >-
323
+ (Chat) Summarizes the older part of a long conversation when it nears the model's context limit,
324
+ so the conversation can go on without losing what matters.
325
+ module: chat
326
+ prompt: history_compaction.prompt
327
+ output_schema:
328
+ type: object
329
+ properties:
330
+ summary:
331
+ type: string
332
+ required: [summary]
333
+ additionalProperties: false
334
+ inputs: [previous_summary, transcript]
335
+ default_model: null
336
+
@@ -408,6 +408,8 @@ class IAToolkit:
408
408
  from iatoolkit.repositories.env_secret_provider import EnvSecretProvider
409
409
  from iatoolkit.common.interfaces.memory_compilation_trigger import MemoryCompilationTrigger
410
410
  from iatoolkit.services.noop_memory_compilation_trigger import NoopMemoryCompilationTrigger
411
+ from iatoolkit.common.interfaces.history_compaction_trigger import HistoryCompactionTrigger
412
+ from iatoolkit.services.noop_history_compaction_trigger import NoopHistoryCompactionTrigger
411
413
  from iatoolkit.services.memory_lookup_policy_service import MemoryLookupPolicyService
412
414
 
413
415
  binder.bind(ApiKeyRepo, to=ApiKeyRepo)
@@ -430,6 +432,8 @@ class IAToolkit:
430
432
  binder.bind(SecretProvider, to=EnvSecretProvider)
431
433
  if not is_bound(self._injector, MemoryCompilationTrigger):
432
434
  binder.bind(MemoryCompilationTrigger, to=NoopMemoryCompilationTrigger)
435
+ if not is_bound(self._injector, HistoryCompactionTrigger):
436
+ binder.bind(HistoryCompactionTrigger, to=NoopHistoryCompactionTrigger)
433
437
  binder.bind(MemoryLookupPolicyService, to=MemoryLookupPolicyService)
434
438
 
435
439
  def _bind_services(self, binder: Binder):
@@ -24,7 +24,6 @@ class AnthropicAdapter:
24
24
  def create_response(self,
25
25
  model: str,
26
26
  input: List[Dict],
27
- previous_response_id: Optional[str] = None,
28
27
  context_history: Optional[List[Dict]] = None,
29
28
  tools: Optional[List[Dict]] = None,
30
29
  text: Optional[Dict] = None,
@@ -39,10 +38,9 @@ class AnthropicAdapter:
39
38
  Calls Anthropic Messages API and maps the response to common LLMResponse.
40
39
 
41
40
  Notes:
42
- - Anthropic is integrated as client-side history, so previous_response_id is ignored.
41
+ - Anthropic receives the whole client-side history on every call.
43
42
  - reasoning is currently not sent as a provider-specific parameter.
44
43
  """
45
- _ = previous_response_id
46
44
  _ = reasoning
47
45
  _ = attachments
48
46
  _ = store
@@ -43,7 +43,6 @@ class GeminiAdapter:
43
43
  def create_response(self,
44
44
  model: str,
45
45
  input: List[Dict],
46
- previous_response_id: Optional[str] = None,
47
46
  context_history: Optional[List[Dict]] = None,
48
47
  tools: Optional[List[Dict]] = None,
49
48
  text: Optional[Dict] = None,
@@ -18,10 +18,15 @@ class OpenAIAdapter:
18
18
  def __init__(self, openai_client):
19
19
  self.client = openai_client
20
20
 
21
+ #: Reasoning models whose reasoning can travel between calls as encrypted
22
+ #: items, for a model the catalogue does not describe: a model without
23
+ #: reasoning answers the `include` with a 400. When the catalogue knows the
24
+ #: model, the proxy says so (`carries_reasoning`) and this list is not read.
25
+ _ENCRYPTED_REASONING_MODEL_PREFIXES = ("gpt-5", "o1", "o3", "o4")
26
+
21
27
  def create_response(self,
22
28
  model: str,
23
29
  input: List[Dict],
24
- previous_response_id: Optional[str] = None,
25
30
  context_history: Optional[List[Dict]] = None,
26
31
  tools: Optional[List[Dict]] = None,
27
32
  text: Optional[Dict] = None,
@@ -31,12 +36,19 @@ class OpenAIAdapter:
31
36
  attachments: Optional[List[Dict]] = None,
32
37
  store: Optional[bool] = None,
33
38
  metadata: Optional[Dict[str, str]] = None,
34
- telemetry_execution: Any = None) -> LLMResponse:
35
- """Llamada a la API de OpenAI y mapeo a estructura común"""
39
+ telemetry_execution: Any = None,
40
+ carries_reasoning: Optional[bool] = None) -> LLMResponse:
41
+ """Llamada a la API de OpenAI y mapeo a estructura común.
42
+
43
+ IAToolkit owns the history (BL-009): every call carries the whole
44
+ conversation and nothing is kept at OpenAI. `store` is always False,
45
+ whatever a prompt or company.yaml still declares; it is accepted only so
46
+ configurations that set it keep loading.
47
+ """
48
+ _ = store
36
49
  try:
37
50
  input = self._normalize_input_items(
38
51
  input_items=input,
39
- previous_response_id=previous_response_id,
40
52
  context_history=context_history,
41
53
  )
42
54
 
@@ -50,16 +62,18 @@ class OpenAIAdapter:
50
62
  'input': input
51
63
  }
52
64
 
53
- if previous_response_id:
54
- params['previous_response_id'] = previous_response_id
65
+ # Nothing stays at OpenAI: the next call sends the history again.
66
+ params['store'] = False
67
+ if self._carries_encrypted_reasoning(model, carries_reasoning):
68
+ # Without a stored response the model would lose its reasoning
69
+ # between tool rounds; it comes back encrypted and is sent again.
70
+ params['include'] = ["reasoning.encrypted_content"]
55
71
  if tools:
56
72
  params['tools'] = tools
57
73
  if text:
58
74
  params['text'] = text
59
75
  if reasoning:
60
76
  params['reasoning'] = reasoning
61
- if store is not None:
62
- params['store'] = store
63
77
  if metadata:
64
78
  params['metadata'] = metadata
65
79
  tool_choice_payload = self._map_tool_choice(tool_choice, tools or [])
@@ -80,36 +94,36 @@ class OpenAIAdapter:
80
94
 
81
95
  raise IAToolkitException(IAToolkitException.ErrorType.LLM_ERROR, error_message)
82
96
 
97
+ @classmethod
98
+ def _carries_encrypted_reasoning(cls, model: str, carries_reasoning: Optional[bool] = None) -> bool:
99
+ if carries_reasoning is not None:
100
+ return carries_reasoning
101
+ name = str(model or "").strip().lower()
102
+ if "-chat" in name:
103
+ return False # gpt-5-chat-latest and the like do not reason
104
+ return name.startswith(cls._ENCRYPTED_REASONING_MODEL_PREFIXES)
105
+
83
106
  def _normalize_input_items(
84
107
  self,
85
108
  input_items: Optional[List[Dict]],
86
- previous_response_id: Optional[str] = None,
87
109
  context_history: Optional[List[Dict]] = None,
88
110
  ) -> List[Dict[str, Any]]:
89
111
  """
90
112
  Normalize our internal history format to the subset accepted by Responses API.
91
113
 
114
+ The client-side history comes first, then the items of the current call.
115
+
92
116
  Important cases:
93
117
  - Assistant messages with `tool_calls` must become top-level `function_call` items.
118
+ - An assistant message's encrypted reasoning items go back in front of its
119
+ own message and calls, the order OpenAI produced them in.
94
120
  - `function_call_output` items must not include internal-only fields such as `status`.
95
- - Without `previous_response_id`, include client-side `context_history` before
96
- the current turn so OpenAI can run from locally managed history if needed.
97
- - When continuing from a prior response with `previous_response_id`, tool follow-ups
98
- should only append the `function_call_output` items because the previous response
99
- already contains the originating user/assistant turns on OpenAI's side.
100
121
  """
101
122
  combined_input: List[Dict[str, Any]] = []
102
- if not previous_response_id:
103
- combined_input.extend(context_history or [])
123
+ combined_input.extend(context_history or [])
104
124
  combined_input.extend(input_items or [])
105
125
 
106
- has_function_outputs = any(
107
- isinstance(item, dict) and item.get("type") == "function_call_output"
108
- for item in combined_input
109
- )
110
-
111
126
  normalized_items: List[Dict[str, Any]] = []
112
- function_output_items: List[Dict[str, Any]] = []
113
127
 
114
128
  for item in combined_input:
115
129
  if not isinstance(item, dict):
@@ -121,13 +135,17 @@ class OpenAIAdapter:
121
135
  if not call_id:
122
136
  continue
123
137
 
124
- normalized_output = {
138
+ normalized_items.append({
125
139
  "type": "function_call_output",
126
140
  "call_id": call_id,
127
141
  "output": item.get("output", ""),
128
- }
129
- normalized_items.append(normalized_output)
130
- function_output_items.append(normalized_output)
142
+ })
143
+ continue
144
+
145
+ if item_type == "reasoning":
146
+ reasoning_item = self._normalize_reasoning_item(item)
147
+ if reasoning_item:
148
+ normalized_items.append(reasoning_item)
131
149
  continue
132
150
 
133
151
  if item_type == "function_call":
@@ -139,6 +157,8 @@ class OpenAIAdapter:
139
157
  role = "assistant"
140
158
 
141
159
  content = item.get("content")
160
+ if role == "assistant":
161
+ normalized_items.extend(self._reasoning_items_from(item.get("reasoning_details")))
142
162
  tool_calls = self._normalize_tool_call_items(item.get("tool_calls"))
143
163
  if tool_calls:
144
164
  if role == "assistant" and content not in (None, "", []):
@@ -155,22 +175,41 @@ class OpenAIAdapter:
155
175
  "content": content,
156
176
  })
157
177
 
158
- if previous_response_id and has_function_outputs and function_output_items:
159
- # Only the outputs answering the previous response's calls. The tool loop
160
- # keeps every round's outputs in its input (client-side providers need
161
- # them), and they come last; earlier rounds are already in the chain
162
- # `previous_response_id` points to. Sending them all again repeated every
163
- # tool result in each following round, so the context grew quadratically
164
- # and long tool loops hit context_length_exceeded.
165
- latest_round: List[Dict[str, Any]] = []
166
- for item in reversed(normalized_items):
167
- if item.get("type") != "function_call_output":
168
- break
169
- latest_round.append(item)
170
- return list(reversed(latest_round)) or function_output_items
171
-
172
178
  return normalized_items
173
179
 
180
+ @classmethod
181
+ def _reasoning_items_from(cls, reasoning_details: Any) -> List[Dict[str, Any]]:
182
+ """The OpenAI reasoning items stored with an assistant message, ready to resend.
183
+
184
+ `reasoning_details` is shared with other adapters (OpenRouter writes
185
+ `reasoning.text` blocks there); only items of type `reasoning` carrying
186
+ encrypted content are OpenAI's and make sense to send back.
187
+ """
188
+ if not isinstance(reasoning_details, list):
189
+ return []
190
+ items = []
191
+ for detail in reasoning_details:
192
+ item = cls._normalize_reasoning_item(detail)
193
+ if item:
194
+ items.append(item)
195
+ return items
196
+
197
+ @staticmethod
198
+ def _normalize_reasoning_item(detail: Any) -> Optional[Dict[str, Any]]:
199
+ if not isinstance(detail, dict) or detail.get("type") != "reasoning":
200
+ return None
201
+ encrypted = detail.get("encrypted_content")
202
+ if not encrypted:
203
+ return None
204
+ item = {
205
+ "type": "reasoning",
206
+ "summary": detail.get("summary") if isinstance(detail.get("summary"), list) else [],
207
+ "encrypted_content": encrypted,
208
+ }
209
+ if detail.get("id"):
210
+ item["id"] = detail["id"]
211
+ return item
212
+
174
213
  @staticmethod
175
214
  def _normalize_tool_call_items(tool_calls: Any) -> List[Dict[str, Any]]:
176
215
  normalized_tool_calls: List[Dict[str, Any]] = []
@@ -408,9 +447,32 @@ class OpenAIAdapter:
408
447
  output=tool_calls,
409
448
  usage=usage,
410
449
  reasoning_content=reasoning_str,
450
+ reasoning_details=self._extract_encrypted_reasoning_items(openai_response) or None,
411
451
  content_parts=content_parts
412
452
  )
413
453
 
454
+ @staticmethod
455
+ def _extract_encrypted_reasoning_items(openai_response) -> List[Dict[str, Any]]:
456
+ """The response's reasoning items that can be sent back on the next call."""
457
+ items: List[Dict[str, Any]] = []
458
+ for item in getattr(openai_response, "output", None) or []:
459
+ if getattr(item, "type", None) != "reasoning":
460
+ continue
461
+ encrypted = getattr(item, "encrypted_content", None)
462
+ if not encrypted:
463
+ continue
464
+ summary = []
465
+ for part in getattr(item, "summary", None) or []:
466
+ text = getattr(part, "text", None)
467
+ if text:
468
+ summary.append({"type": "summary_text", "text": str(text)})
469
+ reasoning_item = {"type": "reasoning", "summary": summary, "encrypted_content": encrypted}
470
+ item_id = getattr(item, "id", None)
471
+ if item_id:
472
+ reasoning_item["id"] = item_id
473
+ items.append(reasoning_item)
474
+ return items
475
+
414
476
  def _extract_reasoning_content(self, openai_response) -> List[str]:
415
477
  """
416
478
  Extract reasoning summaries (preferred) or reasoning content fragments from Responses API output.
@@ -160,6 +160,12 @@ class LLMProxy:
160
160
  provider=provider,
161
161
  request_kwargs=request_kwargs,
162
162
  )
163
+ request_kwargs = self._apply_model_capabilities(
164
+ model=model,
165
+ provider=provider,
166
+ model_config=model_config,
167
+ request_kwargs=request_kwargs,
168
+ )
163
169
  if telemetry_execution is not None:
164
170
  request_kwargs["telemetry_execution"] = telemetry_execution
165
171
 
@@ -451,6 +457,42 @@ class LLMProxy:
451
457
  effective_kwargs["reasoning"] = merged_reasoning
452
458
  return effective_kwargs
453
459
 
460
+ def _apply_model_capabilities(
461
+ self,
462
+ model: str,
463
+ provider: str,
464
+ model_config: Dict[str, Any] | None,
465
+ request_kwargs: Dict[str, Any],
466
+ ) -> Dict[str, Any]:
467
+ """Drops the parameters the model itself does not accept (BL-009, Fase F).
468
+
469
+ The steps before this one decide by provider: every OpenAI model gets a
470
+ reasoning effort and a verbosity, which a model that does not reason
471
+ (gpt-4.1, gpt-5-chat) refuses. When the catalogue knows the model, its
472
+ `supported_parameters` have the last word. When it does not, nothing
473
+ changes: the provider's rules stay as they were.
474
+ """
475
+ catalog_capabilities = ModelRegistry.catalog_capabilities(model_config)
476
+ if catalog_capabilities is None:
477
+ return request_kwargs
478
+
479
+ capabilities = self.model_registry.get_capabilities(
480
+ model, provider=provider, capabilities=catalog_capabilities
481
+ )
482
+ effective_kwargs = dict(request_kwargs or {})
483
+ if not capabilities.get("supports_reasoning_effort"):
484
+ effective_kwargs.pop("reasoning", None)
485
+ effective_kwargs.pop("reasoning_effort", None)
486
+ if not capabilities.get("supports_text_verbosity"):
487
+ text = effective_kwargs.get("text")
488
+ if isinstance(text, dict) and "verbosity" in text:
489
+ effective_kwargs["text"] = {key: value for key, value in text.items() if key != "verbosity"}
490
+ if provider == self.PROVIDER_OPENAI:
491
+ # Whether the model's reasoning can travel between calls: the adapter
492
+ # asks for it only then, instead of guessing from the model's name.
493
+ effective_kwargs["carries_reasoning"] = bool(capabilities.get("supports_reasoning_effort"))
494
+ return effective_kwargs
495
+
454
496
  # -------------------------------------------------------------------------
455
497
  # Client cache
456
498
  # -------------------------------------------------------------------------
@@ -2784,7 +2784,6 @@ ui:
2784
2784
  tooltips:
2785
2785
  history: "History of my queries"
2786
2786
  memory: "Company memory"
2787
- reload_context: "Force Context Reload"
2788
2787
  feedback: "Your feedback is very important"
2789
2788
  usage_guide: "Usage Guide"
2790
2789
  onboarding: "How to ask better questions"
@@ -2897,7 +2896,6 @@ errors:
2897
2896
  file_validation_error: "Error validating file"
2898
2897
  user_not_authorized: "user is not authorized for this company"
2899
2898
  account_not_verified: "Your account has not been verified. Please check your email."
2900
- missing_response_id: "Can not found 'previous_response_id' for '{company_short_name}/{user_identifier}'. Reinit context"
2901
2899
  context_rebuild_failed: "Company context rebuild failed."
2902
2900
  cannot_read_excel: "Cannot read Excel file"
2903
2901
  cannot_read_csv: "Cannot read CSV file"
@@ -2951,7 +2949,6 @@ js_messages:
2951
2949
  feedback_sent_error: "Could not send feedback, please try again."
2952
2950
  feedback_rating_error: "Please rate the assistant using the stars."
2953
2951
  feedback_comment_error: "Please write your comment before sending."
2954
- context_reloaded: "Context has been reloaded."
2955
2952
  error_loading_history: "An error occurred while loading the history."
2956
2953
  request_aborted: "The response generation has been stopped."
2957
2954
  processing_error: "An error occurred while processing the request."
@@ -2959,7 +2956,6 @@ js_messages:
2959
2956
  network_error: "A network error occurred. Please try again in a few moments."
2960
2957
  unknown_server_error: "Unknown server error."
2961
2958
  loading: "Loading..."
2962
- reload_init: "init reloading context in background..."
2963
2959
  no_history_found: "No query history found."
2964
2960
  prompts_available: "Available prompts"
2965
2961
  example: "Example:"
@@ -2800,7 +2800,6 @@ ui:
2800
2800
  tooltips:
2801
2801
  history: "Historial con mis consultas"
2802
2802
  memory: "Memoria de la empresa"
2803
- reload_context: "Forzar Recarga de Contexto"
2804
2803
  feedback: "Tu feedback es muy importante"
2805
2804
  usage_guide: "Guía de Uso"
2806
2805
  onboarding: "Cómo preguntar mejor"
@@ -2916,7 +2915,6 @@ errors:
2916
2915
  file_validation_error : "Error validando archivo"
2917
2916
  user_not_authorized: "Usuario no esta autorizado para esta empresa"
2918
2917
  account_not_verified: "Tu cuenta no ha sido verificada. Por favor, revisa tu correo."
2919
- missing_response_id: "No se encontró 'previous_response_id' para '{company_short_name}/{user_identifier}'. Reinicia el contexto."
2920
2918
  context_rebuild_failed: "No se pudo reconstruir el contexto de la empresa."
2921
2919
  cannot_read_excel: "No se pudo leer el archivo excel"
2922
2920
  cannot_read_csv: "No se pudo leer el archivo CSV"
@@ -2970,7 +2968,6 @@ js_messages:
2970
2968
  feedback_sent_error: "No se pudo enviar el feedback, por favor intente nuevamente."
2971
2969
  feedback_rating_error: "Por favor, califica al asistente con las estrellas."
2972
2970
  feedback_comment_error: "Por favor, escribe tu comentario antes de enviar."
2973
- context_reloaded: "El contexto ha sido recargado."
2974
2971
  error_loading_history: "Ocurrió un error al cargar el historial."
2975
2972
  request_aborted: "La generación de la respuesta ha sido detenida."
2976
2973
  processing_error: "Ocurrió un error al procesar la solicitud."
@@ -2978,7 +2975,6 @@ js_messages:
2978
2975
  network_error: "Ocurrió un error de red. Por favor, inténtalo de nuevo en unos momentos."
2979
2976
  unknown_server_error: "Error desconocido del servidor."
2980
2977
  loading: "Cargando..."
2981
- reload_init: "Iniciando recarga de contexto en segundo plano..."
2982
2978
  no_history_found: "No existe historial de consultas."
2983
2979
  prompts_available: "Prompts disponibles"
2984
2980
  example: "Ejemplo:"
@@ -35,17 +35,31 @@ class LLMQueryRepo:
35
35
  self.session.commit()
36
36
  return query
37
37
 
38
- @staticmethod
39
- def not_context_init():
40
- """Filter for rows that are a conversation turn, not a context initialization."""
38
+ #: iat_queries.prompt_name of the platform's own model calls (system agents,
39
+ #: see system_agent_catalog.PROMPT_NAME_PREFIX). Restated here because the
40
+ #: catalog sits above the repositories.
41
+ SYSTEM_AGENT_PROMPT_PREFIX = "system_agent:"
42
+
43
+ @classmethod
44
+ def conversation_turns_only(cls):
45
+ """Filter for rows a person asked: not a context initialization, not a system agent run.
46
+
47
+ A system agent's execution is billed like any other call, but it is the
48
+ platform's own work (a memory compilation, a history compaction): shown in
49
+ a user's history or replayed as a turn, it would read as a question they
50
+ never asked.
51
+ """
41
52
  request_source = LLMQuery.stats["request_source"].as_string()
42
- return or_(request_source.is_(None), request_source != CONTEXT_INIT_REQUEST_SOURCE)
53
+ return and_(
54
+ or_(request_source.is_(None), request_source != CONTEXT_INIT_REQUEST_SOURCE),
55
+ or_(LLMQuery.prompt_name.is_(None), ~LLMQuery.prompt_name.startswith(cls.SYSTEM_AGENT_PROMPT_PREFIX)),
56
+ )
43
57
 
44
58
  # get user query history
45
59
  def get_history(self, company: Company, user_identifier: str, limit: int = 100) -> list[LLMQuery]:
46
60
  return self.session.query(LLMQuery).filter(
47
61
  LLMQuery.user_identifier == user_identifier,
48
- self.not_context_init(),
62
+ self.conversation_turns_only(),
49
63
  ).filter_by(company_id=company.id).order_by(LLMQuery.created_at.desc()).limit(limit).all()
50
64
 
51
65