iatoolkit 2.74.1__tar.gz → 2.74.3__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 (282) hide show
  1. {iatoolkit-2.74.1/src/iatoolkit.egg-info → iatoolkit-2.74.3}/PKG-INFO +1 -1
  2. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/__init__.py +1 -1
  3. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/config/system_agents/history_compaction.prompt +1 -1
  4. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/history_compaction_service.py +124 -20
  5. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/history_manager_service.py +54 -10
  6. {iatoolkit-2.74.1 → iatoolkit-2.74.3/src/iatoolkit.egg-info}/PKG-INFO +1 -1
  7. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/LICENSE +0 -0
  8. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/LICENSE_COMMUNITY.md +0 -0
  9. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/pyproject.toml +0 -0
  10. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/readme.md +0 -0
  11. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/setup.cfg +0 -0
  12. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/base_company.py +0 -0
  13. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/cli_commands.py +0 -0
  14. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/common/__init__.py +0 -0
  15. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/common/access.py +0 -0
  16. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/common/bridge_validation.py +0 -0
  17. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/common/company_paths.py +0 -0
  18. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/common/exceptions.py +0 -0
  19. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/common/interfaces/__init__.py +0 -0
  20. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/common/interfaces/asset_storage.py +0 -0
  21. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/common/interfaces/database_provider.py +0 -0
  22. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/common/interfaces/history_compaction_trigger.py +0 -0
  23. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/common/interfaces/memory_compilation_trigger.py +0 -0
  24. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/common/interfaces/secret_provider.py +0 -0
  25. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/common/interfaces/signup_policy_resolver.py +0 -0
  26. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/common/interfaces/web_search_provider.py +0 -0
  27. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/common/memory_tools.py +0 -0
  28. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/common/model_registry.py +0 -0
  29. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/common/routes.py +0 -0
  30. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/common/search_terms.py +0 -0
  31. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/common/secret_resolver.py +0 -0
  32. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/common/session_manager.py +0 -0
  33. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/common/text_splitter.py +0 -0
  34. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/common/url_safety.py +0 -0
  35. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/common/util.py +0 -0
  36. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/company_registry.py +0 -0
  37. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/config/__init__.py +0 -0
  38. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/config/llm_capabilities.yaml +0 -0
  39. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/config/system_agents/memory_compiler.prompt +0 -0
  40. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/config/system_agents/memory_correction.prompt +0 -0
  41. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/config/system_agents/memory_document_ingest.prompt +0 -0
  42. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/config/system_agents/memory_image_ingest.prompt +0 -0
  43. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/config/system_agents/memory_meeting_ingest.prompt +0 -0
  44. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/config/system_agents/memory_question_review.prompt +0 -0
  45. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/config/system_agents_pack.yaml +0 -0
  46. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/config/system_prompts/channel_business_identity.prompt +0 -0
  47. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/config/system_prompts/channel_conversation_continuity.prompt +0 -0
  48. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/config/system_prompts/channel_response_style.prompt +0 -0
  49. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/config/system_prompts/chat_state_rules.prompt +0 -0
  50. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/config/system_prompts/chat_user_profile.prompt +0 -0
  51. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/config/system_prompts/core_identity.prompt +0 -0
  52. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/config/system_prompts/email_output.prompt +0 -0
  53. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/config/system_prompts/file_download_output.prompt +0 -0
  54. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/config/system_prompts/format_styles.prompt +0 -0
  55. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/config/system_prompts/html_structures.prompt +0 -0
  56. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/config/system_prompts/links_documents.prompt +0 -0
  57. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/config/system_prompts/memory_usage.prompt +0 -0
  58. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/config/system_prompts/multimodal_basics.prompt +0 -0
  59. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/config/system_prompts/output_basics.prompt +0 -0
  60. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/config/system_prompts/presentation_formatting.prompt +0 -0
  61. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/config/system_prompts/query_main.prompt +0 -0
  62. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/config/system_prompts/sql_aggregation_scope.prompt +0 -0
  63. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/config/system_prompts/sql_casting.prompt +0 -0
  64. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/config/system_prompts/sql_core.prompt +0 -0
  65. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/config/system_prompts/sql_jsonb.prompt +0 -0
  66. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/config/system_prompts/sql_mysql_casting.prompt +0 -0
  67. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/config/system_prompts/sql_mysql_json.prompt +0 -0
  68. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/config/system_prompts/sql_redshift_basics.prompt +0 -0
  69. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/config/system_prompts/sql_redshift_types.prompt +0 -0
  70. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/config/system_prompts/sql_rules.prompt +0 -0
  71. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/config/system_prompts/tool_html_passthrough.prompt +0 -0
  72. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/config/system_prompts_pack.yaml +0 -0
  73. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/config/system_tools_pack.yaml +0 -0
  74. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/core.py +0 -0
  75. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/infra/__init__.py +0 -0
  76. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/infra/brevo_mail_app.py +0 -0
  77. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/infra/call_service.py +0 -0
  78. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/infra/connectors/__init__.py +0 -0
  79. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/infra/connectors/file_connector.py +0 -0
  80. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/infra/connectors/file_connector_factory.py +0 -0
  81. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/infra/connectors/google_cloud_storage_connector.py +0 -0
  82. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/infra/connectors/google_drive_connector.py +0 -0
  83. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/infra/connectors/local_file_connector.py +0 -0
  84. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/infra/connectors/s3_connector.py +0 -0
  85. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/infra/google_auth_client.py +0 -0
  86. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/infra/google_chat_app.py +0 -0
  87. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/infra/inference_embeddings_client.py +0 -0
  88. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/infra/inference_handler.py +0 -0
  89. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/infra/jina_embeddings_client.py +0 -0
  90. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/infra/llm_gateway_resolver.py +0 -0
  91. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/infra/llm_providers/__init__.py +0 -0
  92. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/infra/llm_providers/anthropic_adapter.py +0 -0
  93. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/infra/llm_providers/deepseek_adapter.py +0 -0
  94. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/infra/llm_providers/gemini_adapter.py +0 -0
  95. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/infra/llm_providers/openai_adapter.py +0 -0
  96. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/infra/llm_providers/openai_compatible_chat_adapter.py +0 -0
  97. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/infra/llm_providers/openrouter_adapter.py +0 -0
  98. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/infra/llm_proxy.py +0 -0
  99. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/infra/llm_response.py +0 -0
  100. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/infra/redis_session_manager.py +0 -0
  101. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/locales/en.yaml +0 -0
  102. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/locales/es.yaml +0 -0
  103. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/repositories/__init__.py +0 -0
  104. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/repositories/advisory_lock.py +0 -0
  105. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/repositories/api_key_repo.py +0 -0
  106. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/repositories/bridge_repo.py +0 -0
  107. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/repositories/database_manager.py +0 -0
  108. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/repositories/document_repo.py +0 -0
  109. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/repositories/env_secret_provider.py +0 -0
  110. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/repositories/filesystem_asset_repository.py +0 -0
  111. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/repositories/knowledge_wiki_repo.py +0 -0
  112. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/repositories/llm_query_repo.py +0 -0
  113. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/repositories/mcp_token_repo.py +0 -0
  114. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/repositories/memory_question_repo.py +0 -0
  115. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/repositories/memory_repo.py +0 -0
  116. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/repositories/memory_usage_repo.py +0 -0
  117. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/repositories/models.py +0 -0
  118. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/repositories/profile_repo.py +0 -0
  119. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/repositories/prompt_resource_repo.py +0 -0
  120. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/repositories/sql_dataset_repo.py +0 -0
  121. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/repositories/sql_source_repo.py +0 -0
  122. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/repositories/vs_repo.py +0 -0
  123. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/runtime_logging.py +0 -0
  124. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/__init__.py +0 -0
  125. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/api_key_service.py +0 -0
  126. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/attachment_policy_service.py +0 -0
  127. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/auth_service.py +0 -0
  128. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/branding_service.py +0 -0
  129. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/company_context_service.py +0 -0
  130. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/configuration_service.py +0 -0
  131. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/context_builder_service.py +0 -0
  132. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/dispatcher_service.py +0 -0
  133. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/embedding_service.py +0 -0
  134. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/excel_service.py +0 -0
  135. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/file_processor_service.py +0 -0
  136. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/http_tool_service.py +0 -0
  137. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/i18n_service.py +0 -0
  138. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/inference_service.py +0 -0
  139. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/jwt_service.py +0 -0
  140. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/knowledge_base_service.py +0 -0
  141. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/language_service.py +0 -0
  142. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/license_service.py +0 -0
  143. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/llm_client_service.py +0 -0
  144. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/mail_service.py +0 -0
  145. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/markdown_wiki_service.py +0 -0
  146. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/mcp_token_service.py +0 -0
  147. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/memory_compiler_service.py +0 -0
  148. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/memory_lookup_policy_service.py +0 -0
  149. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/memory_question_service.py +0 -0
  150. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/memory_service.py +0 -0
  151. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/memory_sources.py +0 -0
  152. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/memory_usage_service.py +0 -0
  153. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/memory_wiki_service.py +0 -0
  154. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/noop_history_compaction_trigger.py +0 -0
  155. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/noop_memory_compilation_trigger.py +0 -0
  156. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/operator_identity_service.py +0 -0
  157. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/parsers/__init__.py +0 -0
  158. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/parsers/contracts.py +0 -0
  159. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/parsers/image_normalizer.py +0 -0
  160. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/parsers/parsing_service.py +0 -0
  161. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/parsers/pdf_ocr_detection.py +0 -0
  162. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/parsers/provider_factory.py +0 -0
  163. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/parsers/provider_resolver.py +0 -0
  164. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/parsers/providers/__init__.py +0 -0
  165. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/parsers/providers/basic_provider.py +0 -0
  166. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/parsers/providers/docling_provider.py +0 -0
  167. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/parsers/validator.py +0 -0
  168. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/pdf_service.py +0 -0
  169. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/profile_service.py +0 -0
  170. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/prompt_resource_service.py +0 -0
  171. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/prompt_service.py +0 -0
  172. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/query_service.py +0 -0
  173. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/resource_access_scope.py +0 -0
  174. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/signup_policy_resolver.py +0 -0
  175. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/sql_dataset_service.py +0 -0
  176. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/sql_service.py +0 -0
  177. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/sql_source_service.py +0 -0
  178. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/storage_service.py +0 -0
  179. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/structured_output_service.py +0 -0
  180. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/system_agent_catalog.py +0 -0
  181. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/system_agent_runner.py +0 -0
  182. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/system_prompt_catalog.py +0 -0
  183. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/system_tools.py +0 -0
  184. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/telemetry_service.py +0 -0
  185. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/tenant_wiki_service.py +0 -0
  186. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/tool_output_contract.py +0 -0
  187. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/tool_service.py +0 -0
  188. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/user_feedback_service.py +0 -0
  189. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/user_session_context_service.py +0 -0
  190. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/visual_kb_service.py +0 -0
  191. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/visual_tool_service.py +0 -0
  192. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/warmup_service.py +0 -0
  193. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/web_search/__init__.py +0 -0
  194. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/web_search/provider_factory.py +0 -0
  195. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/web_search/providers/__init__.py +0 -0
  196. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/web_search/providers/brave_provider.py +0 -0
  197. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/web_search_service.py +0 -0
  198. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/services/wiki_page_index_service.py +0 -0
  199. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/static/images/favicon.ico +0 -0
  200. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/static/images/favicon.png +0 -0
  201. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/static/images/fernando.jpeg +0 -0
  202. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/static/images/iatoolkit_core.png +0 -0
  203. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/static/images/iatoolkit_logo.png +0 -0
  204. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/static/js/chat_feedback_button.js +0 -0
  205. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/static/js/chat_filepond.js +0 -0
  206. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/static/js/chat_header_navigation.js +0 -0
  207. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/static/js/chat_help_content.js +0 -0
  208. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/static/js/chat_history_button.js +0 -0
  209. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/static/js/chat_logout_button.js +0 -0
  210. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/static/js/chat_main.js +0 -0
  211. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/static/js/chat_memory_button.js +0 -0
  212. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/static/js/chat_model_selector.js +0 -0
  213. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/static/js/chat_onboarding_button.js +0 -0
  214. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/static/js/chat_prompt_manager.js +0 -0
  215. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/static/styles/account.css +0 -0
  216. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/static/styles/chat_iatoolkit.css +0 -0
  217. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/static/styles/chat_modal.css +0 -0
  218. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/static/styles/chat_public.css +0 -0
  219. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/static/styles/documents.css +0 -0
  220. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/static/styles/landing_page.css +0 -0
  221. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/static/styles/llm_output.css +0 -0
  222. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/static/styles/onboarding.css +0 -0
  223. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/static/styles/wiki_page.css +0 -0
  224. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/templates/_chat_header.html +0 -0
  225. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/templates/_company_header.html +0 -0
  226. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/templates/_login_widget.html +0 -0
  227. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/templates/account.html +0 -0
  228. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/templates/base.html +0 -0
  229. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/templates/change_password.html +0 -0
  230. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/templates/chat.html +0 -0
  231. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/templates/chat_memory_modal.html +0 -0
  232. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/templates/chat_modals.html +0 -0
  233. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/templates/error.html +0 -0
  234. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/templates/forgot_password.html +0 -0
  235. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/templates/home_hosted_default.html +0 -0
  236. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/templates/login_global.html +0 -0
  237. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/templates/memory/wiki_schema.md +0 -0
  238. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/templates/onboarding_shell.html +0 -0
  239. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/templates/pdf/base.html +0 -0
  240. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/templates/pdf/letter.html +0 -0
  241. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/templates/pdf/report.html +0 -0
  242. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/templates/pdf/simple.html +0 -0
  243. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/templates/signup.html +0 -0
  244. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/templates/wiki_page.html +0 -0
  245. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/views/__init__.py +0 -0
  246. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/views/account_view.py +0 -0
  247. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/views/api_key_api_view.py +0 -0
  248. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/views/base_login_view.py +0 -0
  249. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/views/categories_api_view.py +0 -0
  250. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/views/change_password_view.py +0 -0
  251. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/views/chat_context_preview_api_view.py +0 -0
  252. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/views/chat_view.py +0 -0
  253. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/views/configuration_api_view.py +0 -0
  254. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/views/connectors_api_view.py +0 -0
  255. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/views/embedding_api_view.py +0 -0
  256. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/views/forgot_password_view.py +0 -0
  257. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/views/help_content_api_view.py +0 -0
  258. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/views/history_api_view.py +0 -0
  259. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/views/home_view.py +0 -0
  260. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/views/init_context_api_view.py +0 -0
  261. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/views/llmquery_api_view.py +0 -0
  262. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/views/load_document_api_view.py +0 -0
  263. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/views/login_view.py +0 -0
  264. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/views/logout_api_view.py +0 -0
  265. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/views/memory_api_view.py +0 -0
  266. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/views/profile_api_view.py +0 -0
  267. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/views/prompt_api_view.py +0 -0
  268. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/views/prompt_context_preview_api_view.py +0 -0
  269. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/views/prompt_resource_api_view.py +0 -0
  270. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/views/rag_api_view.py +0 -0
  271. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/views/root_redirect_view.py +0 -0
  272. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/views/signup_view.py +0 -0
  273. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/views/static_page_view.py +0 -0
  274. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/views/tool_api_view.py +0 -0
  275. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/views/user_feedback_api_view.py +0 -0
  276. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/views/users_api_view.py +0 -0
  277. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/views/verify_user_view.py +0 -0
  278. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit/views/wiki_page_view.py +0 -0
  279. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit.egg-info/SOURCES.txt +0 -0
  280. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit.egg-info/dependency_links.txt +0 -0
  281. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit.egg-info/requires.txt +0 -0
  282. {iatoolkit-2.74.1 → iatoolkit-2.74.3}/src/iatoolkit.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: iatoolkit
3
- Version: 2.74.1
3
+ Version: 2.74.3
4
4
  Summary: IAToolkit
5
5
  Author: Fernando Libedinsky
6
6
  License-Expression: MIT
@@ -3,7 +3,7 @@
3
3
  #
4
4
  # IAToolkit is open source software.
5
5
 
6
- __version__ = "2.74.1"
6
+ __version__ = "2.74.3"
7
7
 
8
8
  # Expose main classes and functions at the top level of the package
9
9
 
@@ -1,6 +1,6 @@
1
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
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):
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). Write the section headings in that language too, as level-2 headings (`## …`), and do not wrap the summary in a code block:
4
4
 
5
5
  - **Objective**: what the person is trying to achieve, and how it evolved.
6
6
  - **Decisions**: what was agreed, chosen or ruled out, and why when it was said.
@@ -54,7 +54,13 @@ class HistoryCompactionService:
54
54
  #: Tool outputs and long answers are cut in the transcript the agent reads:
55
55
  #: the summary keeps facts, and a 200-row result would crowd out the rest.
56
56
  MAX_MESSAGE_CHARS = 4000
57
+ #: What one call to the agent reads. A longer stretch is summarized in
58
+ #: parts, oldest first, each part extending the summary of the previous one.
57
59
  MAX_TRANSCRIPT_CHARS = 400_000
60
+ #: Parts per compaction: in the background, enough for a history that grew
61
+ #: without compaction (before BL-009) without summarizing forever; in line,
62
+ #: one, because the person is waiting.
63
+ MAX_CHUNKS = 4
58
64
 
59
65
  @inject
60
66
  def __init__(self,
@@ -73,7 +79,19 @@ class HistoryCompactionService:
73
79
  # Entry point
74
80
  # ------------------------------------------------------------------
75
81
 
76
- def compact(self, company_short_name: str, user_identifier: str, model: str) -> dict:
82
+ def compact(self, company_short_name: str, user_identifier: str, model: str,
83
+ max_chunks: Optional[int] = None) -> dict:
84
+ result = self._compact(company_short_name, user_identifier, model, max_chunks)
85
+ if result.get("status") != "compacted":
86
+ # A run that ends without applying anything is as worth knowing as
87
+ # one that does: in production both looked the same ("executed").
88
+ log = logging.warning if result.get("status") == "error" else logging.info
89
+ log("History of %s/%s (model=%s) not compacted: %s",
90
+ company_short_name, user_identifier, model, result)
91
+ return result
92
+
93
+ def _compact(self, company_short_name: str, user_identifier: str, model: str,
94
+ max_chunks: Optional[int]) -> dict:
77
95
  history = self.session_context.get_context_history(company_short_name, user_identifier, model=model) or []
78
96
  budget = self.history_manager.context_budget_tokens(company_short_name, model)
79
97
  plan = self.plan(history, budget)
@@ -86,24 +104,72 @@ class HistoryCompactionService:
86
104
  if not company:
87
105
  return {"status": "error", "reason": "company_not_found"}
88
106
 
89
- try:
90
- response = self.system_agent_runner.run(
91
- company,
92
- self.AGENT_KEY,
93
- {
94
- "previous_summary": plan.previous_summary,
95
- "transcript": self.render_transcript(plan.material),
96
- },
97
- user_identifier=user_identifier,
107
+ chunks = self.chunk_material(plan.material)
108
+ limit = max(int(max_chunks or self.MAX_CHUNKS), 1)
109
+ dropped_chunks = max(len(chunks) - limit, 0)
110
+ if dropped_chunks:
111
+ # The oldest parts go unsummarized: a cost bound, logged so a short
112
+ # summary of a very long conversation can be explained.
113
+ logging.warning(
114
+ "History of %s/%s (model=%s) needs %s parts to summarize; only the %s most recent are.",
115
+ company_short_name, user_identifier, model, len(chunks), limit,
98
116
  )
99
- except SystemAgentUnavailable as e:
100
- return {"status": "skipped", "reason": str(e)}
101
-
102
- summary = self._summary_from(response)
103
- if not summary:
104
- return {"status": "error", "reason": "empty_summary"}
117
+ chunks = chunks[-limit:]
118
+
119
+ summary = plan.previous_summary
120
+ for index, chunk in enumerate(chunks):
121
+ if index and not self._still_matches(company_short_name, user_identifier, model, plan):
122
+ # Each part costs a model call of minutes; once the history has
123
+ # changed under the plan, the rest would be summarized for nothing.
124
+ return {"status": "skipped", "reason": "history_changed", "summarized_parts": index}
125
+ try:
126
+ response = self.system_agent_runner.run(
127
+ company,
128
+ self.AGENT_KEY,
129
+ {"previous_summary": summary, "transcript": self.render_transcript(chunk)},
130
+ user_identifier=user_identifier,
131
+ )
132
+ except SystemAgentUnavailable as e:
133
+ return {"status": "skipped", "reason": str(e)}
134
+ part = self._summary_from(response)
135
+ if not part:
136
+ return {"status": "error", "reason": "empty_summary"}
137
+ summary = part
138
+
139
+ result = self._apply(company_short_name, user_identifier, model, plan, summary)
140
+ if result.get("status") == "compacted":
141
+ result["chunks"] = len(chunks)
142
+ if dropped_chunks:
143
+ result["dropped_chunks"] = dropped_chunks
144
+ return result
105
145
 
106
- return self._apply(company_short_name, user_identifier, model, plan, summary)
146
+ @classmethod
147
+ def chunk_material(cls, material: list) -> list[list]:
148
+ """The material split into parts the agent can read in one call, at turn boundaries.
149
+
150
+ A turn is never split, so a tool call stays with its result. A single
151
+ turn longer than a part is a part of its own (render_transcript clips it).
152
+ """
153
+ turns: list[list] = []
154
+ for message in material or []:
155
+ if (isinstance(message, dict) and message.get("role") == "user") or not turns:
156
+ turns.append([message])
157
+ else:
158
+ turns[-1].append(message)
159
+
160
+ chunks: list[list] = []
161
+ current: list = []
162
+ current_chars = 0
163
+ for turn in turns:
164
+ turn_chars = len(cls.render_transcript(turn))
165
+ if current and current_chars + turn_chars > cls.MAX_TRANSCRIPT_CHARS:
166
+ chunks.append(current)
167
+ current, current_chars = [], 0
168
+ current.extend(turn)
169
+ current_chars += turn_chars
170
+ if current:
171
+ chunks.append(current)
172
+ return chunks
107
173
 
108
174
  # ------------------------------------------------------------------
109
175
  # Planning
@@ -214,6 +280,11 @@ class HistoryCompactionService:
214
280
  # Applying
215
281
  # ------------------------------------------------------------------
216
282
 
283
+ def _still_matches(self, company_short_name: str, user_identifier: str, model: str,
284
+ plan: CompactionPlan) -> bool:
285
+ current = self.session_context.get_context_history(company_short_name, user_identifier, model=model) or []
286
+ return len(current) >= plan.cut and self._fingerprint(current[:plan.cut]) == plan.prefix_hash
287
+
217
288
  def _apply(self, company_short_name: str, user_identifier: str, model: str,
218
289
  plan: CompactionPlan, summary: str) -> dict:
219
290
  lock_key = self.history_manager.history_lock_key(company_short_name, user_identifier, model)
@@ -253,13 +324,46 @@ class HistoryCompactionService:
253
324
 
254
325
  @staticmethod
255
326
  def _summary_from(response: Any) -> str:
327
+ """The summary, however the model returned it.
328
+
329
+ The agent asks for `{"summary": ...}`, but over a long transcript a model
330
+ may answer the Markdown alone. That is still the summary; dropping it
331
+ threw away minutes of work and left the history to grow.
332
+ """
256
333
  if not isinstance(response, dict):
257
334
  return ""
258
- structured = response.get("structured_output")
259
- if isinstance(structured, dict) and isinstance(structured.get("summary"), str):
260
- return structured["summary"].strip()
335
+ for key in ("structured_output", "parsed_output"):
336
+ structured = response.get(key)
337
+ if isinstance(structured, dict) and isinstance(structured.get("summary"), str):
338
+ return HistoryCompactionService._unfence(structured["summary"])
339
+ answer = response.get("answer")
340
+ if isinstance(answer, str) and answer.strip():
341
+ text = HistoryCompactionService._unfence(answer)
342
+ try:
343
+ parsed = json.loads(text)
344
+ except (TypeError, ValueError):
345
+ return text
346
+ if isinstance(parsed, dict) and isinstance(parsed.get("summary"), str):
347
+ return HistoryCompactionService._unfence(parsed["summary"])
348
+ return text
261
349
  return ""
262
350
 
351
+ @staticmethod
352
+ def _unfence(text: str) -> str:
353
+ """The text without a Markdown code block around it.
354
+
355
+ Seen in production: the summary came back as ```summary ... ```, which
356
+ stored as is would put the whole summary inside a code block.
357
+ """
358
+ stripped = str(text or "").strip()
359
+ if not stripped.startswith("```"):
360
+ return stripped
361
+ lines = stripped.split("\n")
362
+ body = lines[1:]
363
+ if body and body[-1].strip() == "```":
364
+ body = body[:-1]
365
+ return "\n".join(body).strip()
366
+
263
367
  def _count(self, message: Any) -> int:
264
368
  try:
265
369
  return int(self.llm_client.count_tokens(json.dumps(message, ensure_ascii=False, default=str)))
@@ -39,15 +39,29 @@ class HistoryManagerService:
39
39
  #: declare 128k of output; reserving all of it would waste a quarter of a
40
40
  #: 400k window on an answer that is almost never that long.
41
41
  MAX_OUTPUT_RESERVE_TOKENS = 32000
42
+ #: The most the history may take, whatever the model's window. Every turn
43
+ #: (and every round of its tool loop) sends the whole history, so a
44
+ #: million-token window filled on each call is a cost nobody chose: seen in
45
+ #: production, three calls of 393k tokens for one question. A company may
46
+ #: set its own with `llm.max_context_tokens`.
47
+ DEFAULT_MAX_CONTEXT_TOKENS = 200000
42
48
 
43
49
  #: Share of the budget at which a finished turn asks for a background
44
50
  #: compaction, and at which the next turn compacts in line because the
45
51
  #: background one did not land in time (BL-009, Fase E).
46
52
  COMPACTION_TRIGGER_SHARE = 0.70
47
53
  INLINE_COMPACTION_SHARE = 0.95
54
+ #: Parts an in-line compaction may summarize: one, the person is waiting.
55
+ INLINE_COMPACTION_MAX_CHUNKS = 1
48
56
  #: How long a turn waits for a compaction that is writing the history.
49
57
  HISTORY_LOCK_WAIT_SECONDS = 2.0
50
58
  HISTORY_LOCK_TTL_SECONDS = 30
59
+ #: The stored history never grows past this many budgets. Only the copy sent
60
+ #: to the model used to be trimmed, so a conversation that was never
61
+ #: compacted kept every turn in the session (829k tokens seen on a 400k
62
+ #: budget). Two budgets leave the background compaction room to summarize
63
+ #: what is over one; past them, the oldest turns go.
64
+ STORED_HISTORY_MAX_BUDGETS = 2
51
65
 
52
66
  #: Marks the message that holds the summary of the compacted turns. It goes
53
67
  #: to the model as it is, so it also tells the model what the text is.
@@ -187,6 +201,8 @@ class HistoryManagerService:
187
201
  elif response.get('answer'):
188
202
  context_history.append({"role": "assistant", "content": response.get('answer', '')})
189
203
 
204
+ self._cap_stored_history(company_short_name, model, context_history)
205
+
190
206
  self.session_context.save_context_history(
191
207
  company_short_name,
192
208
  user_identifier,
@@ -215,7 +231,14 @@ class HistoryManagerService:
215
231
 
216
232
  def _compact_in_line_if_needed(self, company_short_name: str, user_identifier: str, model: Optional[str],
217
233
  user_turn_prompt: str, budget: int):
218
- """Compacts now when the turn about to run would not fit: the background one did not land in time."""
234
+ """Handles a turn that would not fit because the background compaction did not land in time.
235
+
236
+ With workers, the turn asks for the compaction again and goes out
237
+ trimmed: a summary takes one to three minutes (seen in production), and
238
+ the request would die long before (gunicorn's timeout is 60s). Only an
239
+ installation without workers compacts in line, since nothing else ever
240
+ would.
241
+ """
219
242
  try:
220
243
  measured = self.session_context.get_context_tokens(company_short_name, user_identifier, model=model)
221
244
  if not measured:
@@ -223,7 +246,12 @@ class HistoryManagerService:
223
246
  estimated = measured + self.llm_client.count_tokens(user_turn_prompt or "")
224
247
  if estimated < budget * self.INLINE_COMPACTION_SHARE:
225
248
  return
226
- result = self.compaction_service.compact(company_short_name, user_identifier, model)
249
+ if self.compaction_trigger.trigger(company_short_name, user_identifier, model):
250
+ return
251
+ result = self.compaction_service.compact(
252
+ company_short_name, user_identifier, model,
253
+ max_chunks=self.INLINE_COMPACTION_MAX_CHUNKS,
254
+ )
227
255
  logging.info(f"In-line compaction of {company_short_name}/{user_identifier}: {result}")
228
256
  except Exception as e:
229
257
  # The trim that follows still keeps the request inside the window.
@@ -282,13 +310,12 @@ class HistoryManagerService:
282
310
  else:
283
311
  budget = self.DEFAULT_CONTEXT_BUDGET_TOKENS
284
312
 
285
- # A company may cap it below the window: filling a million-token window
286
- # on every turn is a cost decision, not a technical one.
287
- company_cap = self._company_context_cap(company_short_name)
288
- return min(budget, company_cap) if company_cap else budget
313
+ # The window is a ceiling, not a target: the cap is a cost decision.
314
+ cap = self._company_context_cap(company_short_name) or self.DEFAULT_MAX_CONTEXT_TOKENS
315
+ return min(budget, cap)
289
316
 
290
317
  def _company_context_cap(self, company_short_name: str) -> int:
291
- """`llm.max_context_tokens` in company.yaml; 0 when not set."""
318
+ """`llm.max_context_tokens` in company.yaml; 0 when not set (the platform default applies)."""
292
319
  if self.configuration_service is None:
293
320
  return 0
294
321
  try:
@@ -322,7 +349,17 @@ class HistoryManagerService:
322
349
  and not cls.is_summary_message(message)
323
350
  ]
324
351
 
325
- def _trim_context_history(self, context_history: list, budget_tokens: Optional[int] = None):
352
+ def _cap_stored_history(self, company_short_name: str, model: Optional[str], context_history: list):
353
+ """Keeps the stored history under STORED_HISTORY_MAX_BUDGETS budgets, whole turns at a time."""
354
+ cap = self.context_budget_tokens(company_short_name, model) * self.STORED_HISTORY_MAX_BUDGETS
355
+ # A cheap upper estimate first (a token is rarely under 3 characters):
356
+ # counting every save with the tokenizer would cost what this saves.
357
+ if len(json.dumps(context_history, default=str)) <= cap * 3:
358
+ return
359
+ self._trim_context_history(context_history, cap, purpose="stored")
360
+
361
+ def _trim_context_history(self, context_history: list, budget_tokens: Optional[int] = None,
362
+ purpose: str = "request"):
326
363
  """Drops whole turns, oldest first, until the history fits the budget.
327
364
 
328
365
  A turn is a user message and everything up to the next one: the
@@ -341,6 +378,9 @@ class HistoryManagerService:
341
378
  return
342
379
 
343
380
  total_tokens = sum(token_counts)
381
+ initial_tokens = total_tokens
382
+ removed_turns = 0
383
+ removed_messages = 0
344
384
  while total_tokens > budget:
345
385
  turn_starts = self.turn_starts(context_history)
346
386
  if len(turn_starts) < 2:
@@ -350,9 +390,13 @@ class HistoryManagerService:
350
390
  del context_history[first:second]
351
391
  del token_counts[first:second]
352
392
  total_tokens -= removed_tokens
393
+ removed_turns += 1
394
+ removed_messages += second - first
395
+
396
+ if removed_turns:
353
397
  logging.warning(
354
- f"History tokens exceed the budget of {budget}. Removed the oldest turn "
355
- f"({second - first} messages). New total: {total_tokens} tokens."
398
+ f"History ({purpose}) over the budget of {budget} tokens: removed the {removed_turns} "
399
+ f"oldest turns ({removed_messages} messages), {initial_tokens} -> {total_tokens} tokens."
356
400
  )
357
401
 
358
402
  # --- this is for the history popup in the chat page
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: iatoolkit
3
- Version: 2.74.1
3
+ Version: 2.74.3
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