unique_toolkit 1.17.3__tar.gz → 1.18.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.

Potentially problematic release.


This version of unique_toolkit might be problematic. Click here for more details.

Files changed (173) hide show
  1. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/CHANGELOG.md +8 -0
  2. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/PKG-INFO +9 -1
  3. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/pyproject.toml +1 -1
  4. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/tools/a2a/evaluation/evaluator.py +56 -9
  5. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/tools/a2a/postprocessing/_display.py +5 -1
  6. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/tools/a2a/postprocessing/postprocessor.py +100 -37
  7. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/tools/a2a/postprocessing/test/test_consolidate_references.py +17 -34
  8. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/tools/a2a/tool/config.py +10 -0
  9. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/tools/a2a/tool/service.py +2 -1
  10. unique_toolkit-1.18.1/unique_toolkit/agentic/tools/utils/__init__.py +19 -0
  11. unique_toolkit-1.17.3/unique_toolkit/agentic/tools/utils/__init__.py +0 -1
  12. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/LICENSE +0 -0
  13. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/README.md +0 -0
  14. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/__init__.py +0 -0
  15. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/_common/_base_service.py +0 -0
  16. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/_common/_time_utils.py +0 -0
  17. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/_common/api_calling/human_verification_manager.py +0 -0
  18. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/_common/base_model_type_attribute.py +0 -0
  19. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/_common/chunk_relevancy_sorter/config.py +0 -0
  20. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/_common/chunk_relevancy_sorter/exception.py +0 -0
  21. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/_common/chunk_relevancy_sorter/schemas.py +0 -0
  22. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/_common/chunk_relevancy_sorter/service.py +0 -0
  23. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/_common/chunk_relevancy_sorter/tests/test_service.py +0 -0
  24. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/_common/default_language_model.py +0 -0
  25. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/_common/endpoint_builder.py +0 -0
  26. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/_common/endpoint_requestor.py +0 -0
  27. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/_common/exception.py +0 -0
  28. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/_common/feature_flags/schema.py +0 -0
  29. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/_common/pydantic/rjsf_tags.py +0 -0
  30. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/_common/pydantic_helpers.py +0 -0
  31. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/_common/string_utilities.py +0 -0
  32. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/_common/token/image_token_counting.py +0 -0
  33. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/_common/token/token_counting.py +0 -0
  34. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/_common/utils/__init__.py +0 -0
  35. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/_common/utils/files.py +0 -0
  36. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/_common/utils/structured_output/__init__.py +0 -0
  37. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/_common/utils/structured_output/schema.py +0 -0
  38. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/_common/utils/write_configuration.py +0 -0
  39. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/_common/validate_required_values.py +0 -0
  40. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/_common/validators.py +0 -0
  41. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/__init__.py +0 -0
  42. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/debug_info_manager/debug_info_manager.py +0 -0
  43. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/debug_info_manager/test/test_debug_info_manager.py +0 -0
  44. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/evaluation/config.py +0 -0
  45. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/evaluation/context_relevancy/prompts.py +0 -0
  46. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/evaluation/context_relevancy/schema.py +0 -0
  47. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/evaluation/context_relevancy/service.py +0 -0
  48. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/evaluation/evaluation_manager.py +0 -0
  49. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/evaluation/exception.py +0 -0
  50. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/evaluation/hallucination/constants.py +0 -0
  51. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/evaluation/hallucination/hallucination_evaluation.py +0 -0
  52. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/evaluation/hallucination/prompts.py +0 -0
  53. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/evaluation/hallucination/service.py +0 -0
  54. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/evaluation/hallucination/utils.py +0 -0
  55. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/evaluation/output_parser.py +0 -0
  56. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/evaluation/schemas.py +0 -0
  57. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/evaluation/tests/test_context_relevancy_service.py +0 -0
  58. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/evaluation/tests/test_output_parser.py +0 -0
  59. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/history_manager/history_construction_with_contents.py +0 -0
  60. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/history_manager/history_manager.py +0 -0
  61. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/history_manager/loop_token_reducer.py +0 -0
  62. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/history_manager/utils.py +0 -0
  63. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/postprocessor/postprocessor_manager.py +0 -0
  64. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/reference_manager/reference_manager.py +0 -0
  65. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/responses_api/__init__.py +0 -0
  66. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/responses_api/postprocessors/code_display.py +0 -0
  67. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/responses_api/postprocessors/generated_files.py +0 -0
  68. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/responses_api/stream_handler.py +0 -0
  69. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/short_term_memory_manager/persistent_short_term_memory_manager.py +0 -0
  70. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/thinking_manager/thinking_manager.py +0 -0
  71. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/tools/__init__.py +0 -0
  72. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/tools/a2a/__init__.py +0 -0
  73. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/tools/a2a/config.py +0 -0
  74. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/tools/a2a/evaluation/__init__.py +0 -0
  75. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/tools/a2a/evaluation/_utils.py +0 -0
  76. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/tools/a2a/evaluation/config.py +0 -0
  77. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/tools/a2a/evaluation/summarization_user_message.j2 +0 -0
  78. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/tools/a2a/manager.py +0 -0
  79. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/tools/a2a/postprocessing/__init__.py +0 -0
  80. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/tools/a2a/postprocessing/_utils.py +0 -0
  81. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/tools/a2a/postprocessing/config.py +0 -0
  82. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/tools/a2a/postprocessing/test/test_display.py +0 -0
  83. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/tools/a2a/postprocessing/test/test_postprocessor_reference_functions.py +0 -0
  84. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/tools/a2a/prompts.py +0 -0
  85. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/tools/a2a/tool/__init__.py +0 -0
  86. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/tools/a2a/tool/_memory.py +0 -0
  87. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/tools/a2a/tool/_schema.py +0 -0
  88. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/tools/agent_chunks_hanlder.py +0 -0
  89. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/tools/config.py +0 -0
  90. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/tools/factory.py +0 -0
  91. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/tools/mcp/__init__.py +0 -0
  92. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/tools/mcp/manager.py +0 -0
  93. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/tools/mcp/models.py +0 -0
  94. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/tools/mcp/tool_wrapper.py +0 -0
  95. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/tools/openai_builtin/__init__.py +0 -0
  96. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/tools/openai_builtin/base.py +0 -0
  97. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/tools/openai_builtin/code_interpreter/__init__.py +0 -0
  98. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/tools/openai_builtin/code_interpreter/config.py +0 -0
  99. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/tools/openai_builtin/code_interpreter/service.py +0 -0
  100. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/tools/openai_builtin/manager.py +0 -0
  101. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/tools/schemas.py +0 -0
  102. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/tools/test/test_mcp_manager.py +0 -0
  103. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/tools/test/test_tool_progress_reporter.py +0 -0
  104. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/tools/tool.py +0 -0
  105. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/tools/tool_manager.py +0 -0
  106. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/tools/tool_progress_reporter.py +0 -0
  107. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/tools/utils/execution/__init__.py +0 -0
  108. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/tools/utils/execution/execution.py +0 -0
  109. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/tools/utils/source_handling/__init__.py +0 -0
  110. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/tools/utils/source_handling/schema.py +0 -0
  111. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/tools/utils/source_handling/source_formatting.py +0 -0
  112. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/agentic/tools/utils/source_handling/tests/test_source_formatting.py +0 -0
  113. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/app/__init__.py +0 -0
  114. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/app/dev_util.py +0 -0
  115. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/app/init_logging.py +0 -0
  116. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/app/init_sdk.py +0 -0
  117. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/app/performance/async_tasks.py +0 -0
  118. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/app/performance/async_wrapper.py +0 -0
  119. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/app/schemas.py +0 -0
  120. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/app/unique_settings.py +0 -0
  121. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/app/verification.py +0 -0
  122. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/chat/__init__.py +0 -0
  123. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/chat/constants.py +0 -0
  124. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/chat/deprecated/service.py +0 -0
  125. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/chat/functions.py +0 -0
  126. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/chat/responses_api.py +0 -0
  127. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/chat/schemas.py +0 -0
  128. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/chat/service.py +0 -0
  129. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/chat/state.py +0 -0
  130. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/chat/utils.py +0 -0
  131. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/content/__init__.py +0 -0
  132. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/content/constants.py +0 -0
  133. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/content/functions.py +0 -0
  134. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/content/schemas.py +0 -0
  135. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/content/service.py +0 -0
  136. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/content/smart_rules.py +0 -0
  137. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/content/utils.py +0 -0
  138. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/embedding/__init__.py +0 -0
  139. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/embedding/constants.py +0 -0
  140. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/embedding/functions.py +0 -0
  141. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/embedding/schemas.py +0 -0
  142. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/embedding/service.py +0 -0
  143. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/embedding/utils.py +0 -0
  144. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/framework_utilities/__init__.py +0 -0
  145. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/framework_utilities/langchain/client.py +0 -0
  146. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/framework_utilities/langchain/history.py +0 -0
  147. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/framework_utilities/openai/__init__.py +0 -0
  148. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/framework_utilities/openai/client.py +0 -0
  149. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/framework_utilities/openai/message_builder.py +0 -0
  150. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/framework_utilities/utils.py +0 -0
  151. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/language_model/__init__.py +0 -0
  152. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/language_model/builder.py +0 -0
  153. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/language_model/constants.py +0 -0
  154. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/language_model/default_language_model.py +0 -0
  155. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/language_model/functions.py +0 -0
  156. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/language_model/infos.py +0 -0
  157. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/language_model/prompt.py +0 -0
  158. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/language_model/reference.py +0 -0
  159. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/language_model/schemas.py +0 -0
  160. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/language_model/service.py +0 -0
  161. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/language_model/utils.py +0 -0
  162. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/protocols/support.py +0 -0
  163. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/services/__init__.py +0 -0
  164. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/services/chat_service.py +0 -0
  165. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/services/knowledge_base.py +0 -0
  166. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/short_term_memory/__init__.py +0 -0
  167. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/short_term_memory/constants.py +0 -0
  168. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/short_term_memory/functions.py +0 -0
  169. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/short_term_memory/schemas.py +0 -0
  170. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/short_term_memory/service.py +0 -0
  171. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/smart_rules/__init__.py +0 -0
  172. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/smart_rules/compile.py +0 -0
  173. {unique_toolkit-1.17.3 → unique_toolkit-1.18.1}/unique_toolkit/test_utilities/events.py +0 -0
@@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.18.1] - 2025-10-28
9
+ - Fix bug where sub agent references were not properly displayed in the main agent response when the sub agent response was hidden.
10
+
11
+ ## [1.18.0] - 2025-10-27
12
+ - Temporary fix to rendering of sub agent responses.
13
+ - Add config option `stop_condition` to `SubAgentToolConfig`
14
+ - Add config option `tool_choices` to `SubAgentToolConfig`
15
+ - Make sub agent evaluation use the name of the sub agent name if only one assessment is valid
8
16
 
9
17
  ## [1.17.3] - 2025-10-27
10
18
  - Update Hallucination check citation regex parsing pattern
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: unique_toolkit
3
- Version: 1.17.3
3
+ Version: 1.18.1
4
4
  Summary:
5
5
  License: Proprietary
6
6
  Author: Cedric Klinkert
@@ -118,6 +118,14 @@ All notable changes to this project will be documented in this file.
118
118
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
119
119
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
120
120
 
121
+ ## [1.18.1] - 2025-10-28
122
+ - Fix bug where sub agent references were not properly displayed in the main agent response when the sub agent response was hidden.
123
+
124
+ ## [1.18.0] - 2025-10-27
125
+ - Temporary fix to rendering of sub agent responses.
126
+ - Add config option `stop_condition` to `SubAgentToolConfig`
127
+ - Add config option `tool_choices` to `SubAgentToolConfig`
128
+ - Make sub agent evaluation use the name of the sub agent name if only one assessment is valid
121
129
 
122
130
  ## [1.17.3] - 2025-10-27
123
131
  - Update Hallucination check citation regex parsing pattern
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "unique_toolkit"
3
- version = "1.17.3"
3
+ version = "1.18.1"
4
4
  description = ""
5
5
  authors = [
6
6
  "Cedric Klinkert <cedric.klinkert@unique.ch>",
@@ -3,6 +3,7 @@ from typing import override
3
3
 
4
4
  import unique_sdk
5
5
  from jinja2 import Template
6
+ from pydantic import BaseModel
6
7
  from typing_extensions import TypedDict
7
8
 
8
9
  from unique_toolkit.agentic.evaluation.evaluation_manager import Evaluation
@@ -21,6 +22,7 @@ from unique_toolkit.agentic.tools.a2a.evaluation.config import (
21
22
  SubAgentEvaluationServiceConfig,
22
23
  )
23
24
  from unique_toolkit.agentic.tools.a2a.tool import SubAgentTool
25
+ from unique_toolkit.agentic.tools.utils import failsafe
24
26
  from unique_toolkit.chat.schemas import (
25
27
  ChatMessageAssessmentLabel,
26
28
  ChatMessageAssessmentStatus,
@@ -38,7 +40,27 @@ class _SubAgentToolInfo(TypedDict):
38
40
  display_name: str
39
41
 
40
42
 
41
- NO_ASSESSMENTS_FOUND = "NO_ASSESSMENTS_FOUND"
43
+ _NO_ASSESSMENTS_FOUND = "NO_ASSESSMENTS_FOUND"
44
+
45
+
46
+ class _SingleAssessmentData(BaseModel):
47
+ name: str
48
+ explanation: str
49
+
50
+
51
+ def _format_single_assessment_found(name: str, explanation: str) -> str:
52
+ return _SingleAssessmentData(name=name, explanation=explanation).model_dump_json()
53
+
54
+
55
+ @failsafe(failure_return_value=False)
56
+ def _is_single_assessment_found(value: str) -> bool:
57
+ _ = _SingleAssessmentData.model_validate_json(value)
58
+ return True
59
+
60
+
61
+ def _parse_single_assessment_found(value: str) -> tuple[str, str]:
62
+ data = _SingleAssessmentData.model_validate_json(value)
63
+ return data.name, data.explanation
42
64
 
43
65
 
44
66
  class SubAgentEvaluationService(Evaluation):
@@ -99,15 +121,36 @@ class SubAgentEvaluationService(Evaluation):
99
121
 
100
122
  sub_agents_display_data.append(data)
101
123
 
124
+ # No valid assessments found
102
125
  if len(sub_agents_display_data) == 0:
103
126
  logger.warning("No valid sub agent assessments found")
104
127
 
105
128
  return EvaluationMetricResult(
106
129
  name=self.get_name(),
107
- value=NO_ASSESSMENTS_FOUND,
130
+ # This is a trick to be able to indicate to `evaluation_metric_to_assessment`
131
+ # that no valid assessments were found
132
+ value=_NO_ASSESSMENTS_FOUND,
108
133
  reason="No sub agents assessments found",
109
134
  )
110
135
 
136
+ # Only one valid assessment found, no need to perform summarization
137
+ if (
138
+ len(sub_agents_display_data) == 1
139
+ and len(sub_agents_display_data[0]["assessments"]) == 1
140
+ ):
141
+ assessment = sub_agents_display_data[0]["assessments"][0]
142
+ explanation = assessment["explanation"] or ""
143
+ name = sub_agents_display_data[0]["name"]
144
+ label = assessment["label"]
145
+
146
+ return EvaluationMetricResult(
147
+ name=self.get_name(),
148
+ value=label,
149
+ # This is a trick to be able to pass the display name to the UI in `evaluation_metric_to_assessment`
150
+ reason=_format_single_assessment_found(name, explanation),
151
+ is_positive=label == ChatMessageAssessmentLabel.GREEN,
152
+ )
153
+
111
154
  reason = await self._get_reason(sub_agents_display_data)
112
155
 
113
156
  return EvaluationMetricResult(
@@ -121,7 +164,7 @@ class SubAgentEvaluationService(Evaluation):
121
164
  async def evaluation_metric_to_assessment(
122
165
  self, evaluation_result: EvaluationMetricResult
123
166
  ) -> EvaluationAssessmentMessage:
124
- if evaluation_result.value == NO_ASSESSMENTS_FOUND:
167
+ if evaluation_result.value == _NO_ASSESSMENTS_FOUND:
125
168
  return EvaluationAssessmentMessage(
126
169
  status=ChatMessageAssessmentStatus.DONE,
127
170
  explanation="No valid sub agents assessments found to consolidate.",
@@ -130,6 +173,16 @@ class SubAgentEvaluationService(Evaluation):
130
173
  type=self.get_assessment_type(),
131
174
  )
132
175
 
176
+ if _is_single_assessment_found(evaluation_result.reason):
177
+ name, reason = _parse_single_assessment_found(evaluation_result.reason)
178
+ return EvaluationAssessmentMessage(
179
+ status=ChatMessageAssessmentStatus.DONE,
180
+ explanation=reason,
181
+ title=name,
182
+ label=evaluation_result.value, # type: ignore
183
+ type=self.get_assessment_type(),
184
+ )
185
+
133
186
  return EvaluationAssessmentMessage(
134
187
  status=ChatMessageAssessmentStatus.DONE,
135
188
  explanation=evaluation_result.reason,
@@ -182,12 +235,6 @@ class SubAgentEvaluationService(Evaluation):
182
235
  )
183
236
 
184
237
  async def _get_reason(self, sub_agents_display_data: list[dict]) -> str:
185
- if (
186
- len(sub_agents_display_data) == 1
187
- and len(sub_agents_display_data[0]["assessments"]) == 1
188
- ):
189
- return sub_agents_display_data[0]["assessments"][0]["explanation"] or ""
190
-
191
238
  messages = (
192
239
  MessagesBuilder()
193
240
  .system_message_append(self._config.summarization_system_message)
@@ -94,13 +94,17 @@ def _get_display_template(
94
94
  assistant_id_placeholder, "{%s}" % answer_placeholder, sep="\n\n"
95
95
  ) # Double line break is needed for markdown formatting
96
96
 
97
+ template = _add_line_break(template, before=True, after=False)
98
+
97
99
  if add_quote_border:
98
100
  template = _wrap_with_quote_border(template)
99
101
 
100
102
  match mode:
101
103
  case SubAgentResponseDisplayMode.DETAILS_OPEN:
102
104
  template = _wrap_with_details_tag(
103
- template, "open", display_name_placeholder
105
+ template,
106
+ "open",
107
+ display_name_placeholder,
104
108
  )
105
109
  case SubAgentResponseDisplayMode.DETAILS_CLOSED:
106
110
  template = _wrap_with_details_tag(
@@ -1,9 +1,12 @@
1
+ import asyncio
1
2
  import logging
2
3
  import re
3
4
  from typing import TypedDict, override
4
5
 
5
6
  import unique_sdk
7
+ from pydantic import BaseModel, Field
6
8
 
9
+ from unique_toolkit._common.pydantic_helpers import get_configuration_dict
7
10
  from unique_toolkit.agentic.postprocessor.postprocessor_manager import Postprocessor
8
11
  from unique_toolkit.agentic.tools.a2a.postprocessing._display import (
9
12
  _build_sub_agent_answer_display,
@@ -37,12 +40,21 @@ class _SubAgentToolInfo(TypedDict):
37
40
  responses: dict[int, _SubAgentMessageInfo]
38
41
 
39
42
 
43
+ class SubAgentResponsesPostprocessorConfig(BaseModel):
44
+ model_config = get_configuration_dict()
45
+
46
+ sleep_time_before_update: float = Field(
47
+ default=0.5, description="Time to sleep before updating the main agent message."
48
+ )
49
+
50
+
40
51
  class SubAgentResponsesPostprocessor(Postprocessor):
41
52
  def __init__(
42
53
  self,
43
54
  user_id: str,
44
55
  company_id: str,
45
56
  main_agent_chat_id: str,
57
+ config: SubAgentResponsesPostprocessorConfig | None = None,
46
58
  ) -> None:
47
59
  super().__init__(name=self.__class__.__name__)
48
60
 
@@ -52,6 +64,7 @@ class SubAgentResponsesPostprocessor(Postprocessor):
52
64
 
53
65
  self._assistant_id_to_tool_info: dict[str, _SubAgentToolInfo] = {}
54
66
  self._main_agent_message: SpaceMessage | None = None
67
+ self._config = config or SubAgentResponsesPostprocessorConfig()
55
68
 
56
69
  @override
57
70
  async def run(self, loop_response: LanguageModelStreamResponse) -> None:
@@ -60,6 +73,9 @@ class SubAgentResponsesPostprocessor(Postprocessor):
60
73
  company_id=self._company_id,
61
74
  chat_id=self._main_agent_chat_id,
62
75
  )
76
+ await asyncio.sleep(
77
+ self._config.sleep_time_before_update
78
+ ) # Frontend rendering issues
63
79
 
64
80
  @override
65
81
  def apply_postprocessing_to_response(
@@ -79,17 +95,29 @@ class SubAgentResponsesPostprocessor(Postprocessor):
79
95
  "Main agent message is not set, the `run` method must be called first"
80
96
  )
81
97
 
98
+ _add_sub_agent_references_in_place(
99
+ loop_response=loop_response,
100
+ sub_agent_infos=list(self._assistant_id_to_tool_info.values()),
101
+ )
102
+
82
103
  existing_refs = {
83
104
  ref.source_id: ref.sequence_number
84
105
  for ref in loop_response.message.references
85
106
  }
86
107
 
108
+ displayed_sub_agent_infos = dict(
109
+ (assistant_id, sub_agent_info)
110
+ for assistant_id, sub_agent_info in self._assistant_id_to_tool_info.items()
111
+ if sub_agent_info["display_config"].mode
112
+ != SubAgentResponseDisplayMode.HIDDEN
113
+ )
114
+
87
115
  _consolidate_references_in_place(
88
- list(self._assistant_id_to_tool_info.values()), existing_refs, loop_response
116
+ list(displayed_sub_agent_infos.values()), existing_refs
89
117
  )
90
118
 
91
119
  answers = []
92
- for assistant_id in self._assistant_id_to_tool_info.keys():
120
+ for assistant_id in displayed_sub_agent_infos.keys():
93
121
  messages = self._assistant_id_to_tool_info[assistant_id]["responses"]
94
122
 
95
123
  for sequence_number in sorted(messages):
@@ -124,9 +152,12 @@ class SubAgentResponsesPostprocessor(Postprocessor):
124
152
  for ref in message["references"]
125
153
  )
126
154
 
127
- loop_response.message.text = (
128
- "\n\n".join(answers) + "<br>\n\n" + loop_response.message.text.strip()
129
- )
155
+ if len(answers) > 0:
156
+ loop_response.message.text = (
157
+ "<br>\n\n".join(answers)
158
+ + "<br>\n\n"
159
+ + loop_response.message.text.strip()
160
+ )
130
161
 
131
162
  return True
132
163
 
@@ -147,13 +178,6 @@ class SubAgentResponsesPostprocessor(Postprocessor):
147
178
  def register_sub_agent_tool(
148
179
  self, tool: SubAgentTool, display_config: SubAgentDisplayConfig
149
180
  ) -> None:
150
- if display_config.mode == SubAgentResponseDisplayMode.HIDDEN:
151
- logger.info(
152
- "Sub agent tool %s has display mode `hidden`, responses will be ignored.",
153
- tool.config.assistant_id,
154
- )
155
- return
156
-
157
181
  if tool.config.assistant_id not in self._assistant_id_to_tool_info:
158
182
  tool.subscribe(self)
159
183
  self._assistant_id_to_tool_info[tool.config.assistant_id] = (
@@ -200,10 +224,73 @@ class SubAgentResponsesPostprocessor(Postprocessor):
200
224
  }
201
225
 
202
226
 
227
+ def _add_sub_agent_references_in_place(
228
+ loop_response: LanguageModelStreamResponse,
229
+ sub_agent_infos: list[_SubAgentToolInfo],
230
+ ) -> None:
231
+ message_text = loop_response.message.text
232
+
233
+ existing_refs = {
234
+ ref.source_id: ref.sequence_number
235
+ for ref in loop_response.message.references or []
236
+ }
237
+ start_index = max(existing_refs.values(), default=0) + 1
238
+
239
+ for sub_agent_info in sub_agent_infos:
240
+ sub_agent_name = sub_agent_info["name"]
241
+ for sequence_number in sorted(sub_agent_info["responses"]):
242
+ sub_agent_response = sub_agent_info["responses"][sequence_number]
243
+
244
+ for reference in sorted(
245
+ sub_agent_response["references"], key=lambda r: r["sequenceNumber"]
246
+ ):
247
+ ref_num = reference["sequenceNumber"]
248
+ source_id = reference["sourceId"]
249
+
250
+ reference_str = SubAgentTool.get_sub_agent_reference_format(
251
+ name=sub_agent_name,
252
+ sequence_number=sequence_number,
253
+ reference_number=ref_num,
254
+ )
255
+
256
+ if reference_str not in message_text:
257
+ # Reference not used
258
+ continue
259
+
260
+ if source_id in existing_refs:
261
+ new_ref_num = existing_refs[source_id]
262
+
263
+ else:
264
+ new_ref_num = start_index
265
+ existing_refs[source_id] = new_ref_num
266
+ start_index += 1
267
+
268
+ loop_response.message.references.append(
269
+ ContentReference(
270
+ name=reference["name"],
271
+ url=reference["url"] or "",
272
+ sequence_number=new_ref_num,
273
+ source_id=source_id,
274
+ source=reference["source"],
275
+ )
276
+ )
277
+
278
+ message_text = re.sub(
279
+ rf"\s*{re.escape(reference_str)}",
280
+ f" <sup>{new_ref_num}</sup>",
281
+ message_text,
282
+ )
283
+
284
+ loop_response.message.text = message_text
285
+ # Remove spaces between consecutive references
286
+ loop_response.message.text = re.sub(
287
+ r"</sup>\s*<sup>", "</sup><sup>", loop_response.message.text
288
+ )
289
+
290
+
203
291
  def _consolidate_references_in_place(
204
292
  messages: list[_SubAgentToolInfo],
205
293
  existing_refs: dict[str, int],
206
- loop_response: LanguageModelStreamResponse,
207
294
  ) -> None:
208
295
  start_index = max(existing_refs.values(), default=0) + 1
209
296
 
@@ -237,29 +324,5 @@ def _consolidate_references_in_place(
237
324
  ref_map[reference["sequenceNumber"]] = reference_num
238
325
  reference["sequenceNumber"] = reference_num
239
326
 
240
- loop_response.message.text = (
241
- _replace_sub_agent_references_in_main_agent_message(
242
- loop_response.message.text,
243
- assistant_tool_info["name"],
244
- sequence_number,
245
- ref_map,
246
- )
247
- )
248
327
  message["text"] = _replace_references_in_text(message["text"], ref_map)
249
328
  message["references"] = message_new_refs
250
-
251
-
252
- def _replace_sub_agent_references_in_main_agent_message(
253
- message: str, sub_agent_name: str, sequence_number: int, ref_map: dict[int, int]
254
- ) -> str:
255
- for old_seq_num, new_seq_num in ref_map.items():
256
- reference = SubAgentTool.get_sub_agent_reference_format(
257
- name=sub_agent_name,
258
- sequence_number=sequence_number,
259
- reference_number=old_seq_num,
260
- )
261
- message = re.sub(rf"\s*{reference}", f" <sup>{new_seq_num}</sup>", message)
262
-
263
- # Remove spaces between consecutive references
264
- message = re.sub(r"</sup>\s*<sup>", "</sup><sup>", message)
265
- return message
@@ -22,9 +22,8 @@ class TestConsolidateReferencesInPlace:
22
22
  """Test with empty messages list."""
23
23
  messages = []
24
24
  existing_refs = {}
25
- loop_response = self._create_mock_loop_response()
26
25
 
27
- _consolidate_references_in_place(messages, existing_refs, loop_response)
26
+ _consolidate_references_in_place(messages, existing_refs)
28
27
 
29
28
  assert existing_refs == {}
30
29
 
@@ -53,9 +52,8 @@ class TestConsolidateReferencesInPlace:
53
52
  }
54
53
  ]
55
54
  existing_refs = {}
56
- loop_response = self._create_mock_loop_response()
57
55
 
58
- _consolidate_references_in_place(messages, existing_refs, loop_response) # type: ignore
56
+ _consolidate_references_in_place(messages, existing_refs) # type: ignore
59
57
 
60
58
  # Should start from index 1 since existing_refs is empty
61
59
  assert existing_refs == {"source1": 1}
@@ -90,9 +88,8 @@ class TestConsolidateReferencesInPlace:
90
88
  }
91
89
  ]
92
90
  existing_refs = {"existing_source": 5}
93
- loop_response = self._create_mock_loop_response()
94
91
 
95
- _consolidate_references_in_place(messages, existing_refs, loop_response) # type: ignore
92
+ _consolidate_references_in_place(messages, existing_refs) # type: ignore
96
93
 
97
94
  # Should start from 6 (max existing + 1)
98
95
  assert existing_refs == {"existing_source": 5, "new_source": 6}
@@ -141,8 +138,7 @@ class TestConsolidateReferencesInPlace:
141
138
  ]
142
139
  existing_refs = {}
143
140
 
144
- loop_response = self._create_mock_loop_response()
145
- _consolidate_references_in_place(messages, existing_refs, loop_response) # type: ignore
141
+ _consolidate_references_in_place(messages, existing_refs) # type: ignore
146
142
 
147
143
  # Both should map to the same consolidated reference number
148
144
  assert existing_refs == {"shared_source": 1}
@@ -187,8 +183,7 @@ class TestConsolidateReferencesInPlace:
187
183
  ]
188
184
  existing_refs = {}
189
185
 
190
- loop_response = self._create_mock_loop_response()
191
- _consolidate_references_in_place(messages, existing_refs, loop_response) # type: ignore
186
+ _consolidate_references_in_place(messages, existing_refs) # type: ignore
192
187
 
193
188
  assert existing_refs == {"source1": 1, "source2": 2}
194
189
  # Both references should be in the message since they're unique
@@ -240,8 +235,7 @@ class TestConsolidateReferencesInPlace:
240
235
  ]
241
236
  existing_refs = {}
242
237
 
243
- loop_response = self._create_mock_loop_response()
244
- _consolidate_references_in_place(messages, existing_refs, loop_response) # type: ignore
238
+ _consolidate_references_in_place(messages, existing_refs) # type: ignore
245
239
 
246
240
  # Should be processed in order 1, 2, 3 and assigned consecutive numbers
247
241
  assert existing_refs == {"source1": 1, "source2": 2, "source3": 3}
@@ -262,8 +256,7 @@ class TestConsolidateReferencesInPlace:
262
256
  ]
263
257
  existing_refs = {}
264
258
 
265
- loop_response = self._create_mock_loop_response()
266
- _consolidate_references_in_place(messages, existing_refs, loop_response) # type: ignore
259
+ _consolidate_references_in_place(messages, existing_refs) # type: ignore
267
260
 
268
261
  assert existing_refs == {}
269
262
  assert messages[0]["responses"][1]["text"] == "Text with no references"
@@ -314,8 +307,7 @@ class TestConsolidateReferencesInPlace:
314
307
  ]
315
308
  existing_refs = {}
316
309
 
317
- loop_response = self._create_mock_loop_response()
318
- _consolidate_references_in_place(messages, existing_refs, loop_response) # type: ignore
310
+ _consolidate_references_in_place(messages, existing_refs) # type: ignore
319
311
 
320
312
  assert existing_refs == {"source1": 1, "source2": 2}
321
313
  assert messages[0]["responses"][1]["text"] == "Assistant 1 text <sup>1</sup>"
@@ -368,8 +360,7 @@ class TestConsolidateReferencesInPlace:
368
360
  ]
369
361
  existing_refs = {"existing": 10} # Start from 11
370
362
 
371
- loop_response = self._create_mock_loop_response()
372
- _consolidate_references_in_place(messages, existing_refs, loop_response) # type: ignore
363
+ _consolidate_references_in_place(messages, existing_refs) # type: ignore
373
364
 
374
365
  # sourceB gets 11 (first in sorted order), sourceA gets 12
375
366
  assert existing_refs == {"existing": 10, "sourceB": 11, "sourceA": 12}
@@ -416,8 +407,7 @@ class TestConsolidateReferencesInPlace:
416
407
  ]
417
408
  existing_refs = {}
418
409
 
419
- loop_response = self._create_mock_loop_response()
420
- _consolidate_references_in_place(messages, existing_refs, loop_response) # type: ignore
410
+ _consolidate_references_in_place(messages, existing_refs) # type: ignore
421
411
 
422
412
  # Should call _replace_references_in_text with the original text and ref mapping
423
413
  mock_replace.assert_called_once_with("Original text <sup>1</sup>", {1: 1})
@@ -446,8 +436,7 @@ class TestConsolidateReferencesInPlace:
446
436
  ]
447
437
  existing_refs = {}
448
438
 
449
- loop_response = self._create_mock_loop_response()
450
- _consolidate_references_in_place(messages, existing_refs, loop_response) # type: ignore
439
+ _consolidate_references_in_place(messages, existing_refs) # type: ignore
451
440
 
452
441
  # The original reference object should be modified in place
453
442
  assert original_ref["sequenceNumber"] == 1
@@ -488,8 +477,7 @@ class TestConsolidateReferencesInPlace:
488
477
  ]
489
478
 
490
479
  existing_refs_copy = existing_refs.copy()
491
- loop_response = self._create_mock_loop_response()
492
- _consolidate_references_in_place(messages, existing_refs_copy, loop_response) # type: ignore
480
+ _consolidate_references_in_place(messages, existing_refs_copy) # type: ignore
493
481
 
494
482
  assert existing_refs_copy["new_source"] == expected_start
495
483
 
@@ -505,8 +493,7 @@ class TestConsolidateReferencesInPlace:
505
493
  ]
506
494
  existing_refs = {}
507
495
 
508
- loop_response = self._create_mock_loop_response()
509
- _consolidate_references_in_place(messages, existing_refs, loop_response) # type: ignore
496
+ _consolidate_references_in_place(messages, existing_refs) # type: ignore
510
497
 
511
498
  assert existing_refs == {}
512
499
 
@@ -550,8 +537,7 @@ class TestConsolidateReferencesInPlace:
550
537
  ]
551
538
  existing_refs = {}
552
539
 
553
- loop_response = self._create_mock_loop_response()
554
- _consolidate_references_in_place(messages, existing_refs, loop_response) # type: ignore
540
+ _consolidate_references_in_place(messages, existing_refs) # type: ignore
555
541
 
556
542
  # Only valid messages should be processed
557
543
  assert existing_refs == {"source1": 1, "source3": 2}
@@ -611,8 +597,7 @@ class TestConsolidateReferencesInPlace:
611
597
  ]
612
598
  existing_refs = {}
613
599
 
614
- loop_response = self._create_mock_loop_response()
615
- _consolidate_references_in_place(messages, existing_refs, loop_response) # type: ignore
600
+ _consolidate_references_in_place(messages, existing_refs) # type: ignore
616
601
 
617
602
  # Should be processed in order 1, 2, 3 based on response sequence numbers
618
603
  assert existing_refs == {"source1": 1, "source2": 2, "source3": 3}
@@ -646,8 +631,7 @@ class TestConsolidateReferencesInPlace:
646
631
  ]
647
632
  existing_refs = {"existing_source": 99}
648
633
 
649
- loop_response = self._create_mock_loop_response()
650
- _consolidate_references_in_place(messages, existing_refs, loop_response) # type: ignore
634
+ _consolidate_references_in_place(messages, existing_refs) # type: ignore
651
635
 
652
636
  # Should use existing reference number and not add to new refs
653
637
  assert existing_refs == {"existing_source": 99}
@@ -685,8 +669,7 @@ class TestConsolidateReferencesInPlace:
685
669
  ]
686
670
  existing_refs = {"zero": 0, "negative": -5, "positive": 3}
687
671
 
688
- loop_response = self._create_mock_loop_response()
689
- _consolidate_references_in_place(messages, existing_refs, loop_response) # type: ignore
672
+ _consolidate_references_in_place(messages, existing_refs) # type: ignore
690
673
 
691
674
  # Should start from max(0, -5, 3) + 1 = 4
692
675
  assert existing_refs["new_source"] == 4
@@ -1,3 +1,5 @@
1
+ from typing import Literal
2
+
1
3
  from pydantic import Field
2
4
 
3
5
  from unique_toolkit._common.pydantic_helpers import get_configuration_dict
@@ -27,6 +29,10 @@ class SubAgentToolConfig(BaseToolConfig):
27
29
  default=True,
28
30
  description="Whether this sub agent's references should be used in the main agent's response.",
29
31
  )
32
+ forced_tools: list[str] | None = Field(
33
+ default=None,
34
+ description="The list of tool names that will be forced to be called for this sub-agent.",
35
+ )
30
36
 
31
37
  tool_description_for_system_prompt: str = Field(
32
38
  default="",
@@ -61,3 +67,7 @@ class SubAgentToolConfig(BaseToolConfig):
61
67
  default=120.0,
62
68
  description="Maximum time in seconds to wait for the sub-agent response before timing out.",
63
69
  )
70
+ stop_condition: Literal["stoppedStreamingAt", "completedAt"] = Field(
71
+ default="completedAt",
72
+ description="The condition that will be used to stop the polling for the sub-agent response.",
73
+ )
@@ -282,8 +282,9 @@ class SubAgentTool(Tool[SubAgentToolConfig]):
282
282
  text=tool_user_message,
283
283
  chat_id=chat_id,
284
284
  poll_interval=self.config.poll_interval,
285
+ tool_choices=self.config.forced_tools,
285
286
  max_wait=self.config.max_wait,
286
- stop_condition="completedAt",
287
+ stop_condition=self.config.stop_condition,
287
288
  )
288
289
  except TimeoutError as e:
289
290
  await self._notify_progress(
@@ -0,0 +1,19 @@
1
+ """Utilities for tools."""
2
+
3
+ from unique_toolkit.agentic.tools.utils.execution.execution import (
4
+ Result,
5
+ SafeTaskExecutor,
6
+ failsafe,
7
+ failsafe_async,
8
+ safe_execute,
9
+ safe_execute_async,
10
+ )
11
+
12
+ __all__ = [
13
+ "failsafe",
14
+ "failsafe_async",
15
+ "safe_execute",
16
+ "safe_execute_async",
17
+ "SafeTaskExecutor",
18
+ "Result",
19
+ ]
@@ -1 +0,0 @@
1
- """Utilities for tools."""
File without changes