unique_toolkit 1.51.0__tar.gz → 1.53.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (287) hide show
  1. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/PKG-INFO +2 -1
  2. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/pyproject.toml +2 -1
  3. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/loop_runner/__init__.py +3 -3
  4. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/loop_runner/_iteration_handler_utils.py +11 -4
  5. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/loop_runner/_stream_handler_utils.py +2 -2
  6. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/loop_runner/runners/__init__.py +4 -2
  7. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/loop_runner/runners/basic.py +22 -4
  8. unique_toolkit-1.53.0/unique_toolkit/agentic/loop_runner/runners/mistral/__init__.py +7 -0
  9. unique_toolkit-1.53.0/unique_toolkit/agentic/loop_runner/runners/mistral/mistral_runner.py +30 -0
  10. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/loop_runner/runners/qwen/__init__.py +0 -4
  11. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/loop_runner/runners/qwen/helpers.py +0 -12
  12. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/loop_runner/runners/qwen/qwen_runner.py +18 -40
  13. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/chat/responses_api.py +127 -3
  14. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/services/chat_service.py +30 -0
  15. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/README.md +0 -0
  16. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/__init__.py +0 -0
  17. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/__init__.py +0 -0
  18. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/_base_service.py +0 -0
  19. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/_time_utils.py +0 -0
  20. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/api_calling/human_verification_manager.py +0 -0
  21. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/base_model_type_attribute.py +0 -0
  22. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/chunk_relevancy_sorter/config.py +0 -0
  23. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/chunk_relevancy_sorter/exception.py +0 -0
  24. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/chunk_relevancy_sorter/schemas.py +0 -0
  25. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/chunk_relevancy_sorter/service.py +0 -0
  26. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/chunk_relevancy_sorter/tests/test_service.py +0 -0
  27. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/config_checker/README.md +0 -0
  28. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/config_checker/__init__.py +0 -0
  29. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/config_checker/__main__.py +0 -0
  30. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/config_checker/cli.py +0 -0
  31. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/config_checker/differ.py +0 -0
  32. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/config_checker/exporter.py +0 -0
  33. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/config_checker/models.py +0 -0
  34. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/config_checker/registry.py +0 -0
  35. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/config_checker/validator.py +0 -0
  36. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/default_language_model.py +0 -0
  37. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/docx_generator/__init__.py +0 -0
  38. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/docx_generator/config.py +0 -0
  39. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/docx_generator/pandoc_converter.py +0 -0
  40. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/docx_generator/schemas.py +0 -0
  41. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/docx_generator/service.py +0 -0
  42. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/docx_generator/template/Doc Template.docx +0 -0
  43. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/endpoint_builder.py +0 -0
  44. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/endpoint_requestor.py +0 -0
  45. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/event_bus.py +0 -0
  46. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/exception.py +0 -0
  47. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/execution.py +0 -0
  48. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/experimental/endpoint_builder.py +0 -0
  49. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/experimental/endpoint_requestor.py +0 -0
  50. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/experimental/write_up_agent/README.md +0 -0
  51. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/experimental/write_up_agent/__init__.py +0 -0
  52. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/experimental/write_up_agent/agent.py +0 -0
  53. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/experimental/write_up_agent/config.py +0 -0
  54. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/experimental/write_up_agent/examples/data.csv +0 -0
  55. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/experimental/write_up_agent/examples/example_usage.py +0 -0
  56. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/experimental/write_up_agent/schemas.py +0 -0
  57. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/experimental/write_up_agent/services/__init__.py +0 -0
  58. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/experimental/write_up_agent/services/dataframe_handler/__init__.py +0 -0
  59. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/experimental/write_up_agent/services/dataframe_handler/exceptions.py +0 -0
  60. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/experimental/write_up_agent/services/dataframe_handler/service.py +0 -0
  61. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/experimental/write_up_agent/services/dataframe_handler/utils.py +0 -0
  62. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/experimental/write_up_agent/services/generation_handler/__init__.py +0 -0
  63. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/experimental/write_up_agent/services/generation_handler/config.py +0 -0
  64. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/experimental/write_up_agent/services/generation_handler/exceptions.py +0 -0
  65. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/experimental/write_up_agent/services/generation_handler/prompts/config.py +0 -0
  66. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/experimental/write_up_agent/services/generation_handler/prompts/system_prompt.j2 +0 -0
  67. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/experimental/write_up_agent/services/generation_handler/prompts/user_prompt.j2 +0 -0
  68. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/experimental/write_up_agent/services/generation_handler/service.py +0 -0
  69. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/experimental/write_up_agent/services/template_handler/__init__.py +0 -0
  70. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/experimental/write_up_agent/services/template_handler/default_template.j2 +0 -0
  71. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/experimental/write_up_agent/services/template_handler/exceptions.py +0 -0
  72. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/experimental/write_up_agent/services/template_handler/service.py +0 -0
  73. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/experimental/write_up_agent/services/template_handler/utils.py +0 -0
  74. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/experimental/write_up_agent/utils.py +0 -0
  75. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/feature_flags/schema.py +0 -0
  76. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/pydantic/rjsf_tags.py +0 -0
  77. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/pydantic_helpers.py +0 -0
  78. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/referencing.py +0 -0
  79. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/string_utilities.py +0 -0
  80. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/tests/test_referencing.py +0 -0
  81. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/tests/test_string_utilities.py +0 -0
  82. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/token/__init__.py +0 -0
  83. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/token/image_token_counting.py +0 -0
  84. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/token/token_counting.py +0 -0
  85. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/token/tokenizers/deepseek/tokenizer.json +0 -0
  86. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/token/tokenizers/qwen/tokenizer.json +0 -0
  87. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/utils/__init__.py +0 -0
  88. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/utils/files.py +0 -0
  89. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/utils/image/encode.py +0 -0
  90. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/utils/jinja/helpers.py +0 -0
  91. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/utils/jinja/render.py +0 -0
  92. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/utils/jinja/schema.py +0 -0
  93. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/utils/jinja/utils.py +0 -0
  94. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/utils/structured_output/__init__.py +0 -0
  95. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/utils/structured_output/schema.py +0 -0
  96. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/utils/write_configuration.py +0 -0
  97. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/validate_required_values.py +0 -0
  98. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/_common/validators.py +0 -0
  99. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/__init__.py +0 -0
  100. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/debug_info_manager/debug_info_manager.py +0 -0
  101. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/debug_info_manager/test/test_debug_info_manager.py +0 -0
  102. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/evaluation/config.py +0 -0
  103. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/evaluation/context_relevancy/prompts/__init__.py +0 -0
  104. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/evaluation/context_relevancy/prompts/system_prompt.j2 +0 -0
  105. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/evaluation/context_relevancy/prompts/user_prompt.j2 +0 -0
  106. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/evaluation/context_relevancy/schema.py +0 -0
  107. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/evaluation/context_relevancy/service.py +0 -0
  108. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/evaluation/evaluation_manager.py +0 -0
  109. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/evaluation/exception.py +0 -0
  110. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/evaluation/hallucination/constants.py +0 -0
  111. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/evaluation/hallucination/hallucination_evaluation.py +0 -0
  112. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/evaluation/hallucination/prompts/__init__.py +0 -0
  113. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/evaluation/hallucination/prompts/system_prompt.j2 +0 -0
  114. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/evaluation/hallucination/prompts/user_prompt.j2 +0 -0
  115. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/evaluation/hallucination/service.py +0 -0
  116. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/evaluation/hallucination/utils.py +0 -0
  117. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/evaluation/output_parser.py +0 -0
  118. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/evaluation/schemas.py +0 -0
  119. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/evaluation/tests/fixtures.py +0 -0
  120. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/evaluation/tests/test_config.py +0 -0
  121. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/evaluation/tests/test_context_relevancy_service.py +0 -0
  122. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/evaluation/tests/test_hallucination_constants.py +0 -0
  123. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/evaluation/tests/test_hallucination_utils.py +0 -0
  124. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/evaluation/tests/test_output_parser.py +0 -0
  125. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/evaluation/tests/test_prompt_loaders.py +0 -0
  126. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/evaluation/utils.py +0 -0
  127. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/feature_flags/__init__.py +0 -0
  128. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/feature_flags/feature_flags.py +0 -0
  129. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/history_manager/history_construction_with_contents.py +0 -0
  130. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/history_manager/history_manager.py +0 -0
  131. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/history_manager/loop_token_reducer.py +0 -0
  132. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/history_manager/utils.py +0 -0
  133. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/loop_runner/_responses_iteration_handler_utils.py +0 -0
  134. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/loop_runner/_responses_stream_handler_utils.py +0 -0
  135. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/loop_runner/base.py +0 -0
  136. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/loop_runner/middleware/__init__.py +0 -0
  137. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/loop_runner/middleware/planning/__init__.py +0 -0
  138. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/loop_runner/middleware/planning/planning.py +0 -0
  139. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/loop_runner/middleware/planning/schema.py +0 -0
  140. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/message_log_manager/__init__.py +0 -0
  141. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/message_log_manager/service.py +0 -0
  142. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/postprocessor/postprocessor_manager.py +0 -0
  143. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/reference_manager/reference_manager.py +0 -0
  144. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/responses_api/__init__.py +0 -0
  145. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/responses_api/postprocessors/code_display.py +0 -0
  146. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/responses_api/postprocessors/generated_files.py +0 -0
  147. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/responses_api/stream_handler.py +0 -0
  148. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/short_term_memory_manager/persistent_short_term_memory_manager.py +0 -0
  149. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/thinking_manager/thinking_manager.py +0 -0
  150. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/__init__.py +0 -0
  151. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/a2a/__init__.py +0 -0
  152. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/a2a/config.py +0 -0
  153. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/a2a/evaluation/__init__.py +0 -0
  154. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/a2a/evaluation/_utils.py +0 -0
  155. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/a2a/evaluation/config.py +0 -0
  156. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/a2a/evaluation/evaluator.py +0 -0
  157. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/a2a/evaluation/summarization_user_message.j2 +0 -0
  158. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/a2a/manager.py +0 -0
  159. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/a2a/postprocessing/__init__.py +0 -0
  160. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/a2a/postprocessing/_display_utils.py +0 -0
  161. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/a2a/postprocessing/_ref_utils.py +0 -0
  162. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/a2a/postprocessing/config.py +0 -0
  163. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/a2a/postprocessing/display.py +0 -0
  164. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/a2a/postprocessing/references.py +0 -0
  165. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/a2a/postprocessing/test/test_display.py +0 -0
  166. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/a2a/postprocessing/test/test_display_utils.py +0 -0
  167. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/a2a/postprocessing/test/test_ref_utils.py +0 -0
  168. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/a2a/prompts.py +0 -0
  169. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/a2a/response_watcher/__init__.py +0 -0
  170. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/a2a/response_watcher/service.py +0 -0
  171. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/a2a/tool/__init__.py +0 -0
  172. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/a2a/tool/_memory.py +0 -0
  173. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/a2a/tool/_schema.py +0 -0
  174. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/a2a/tool/config.py +0 -0
  175. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/a2a/tool/service.py +0 -0
  176. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/a2a/tool/test/test_service_utils.py +0 -0
  177. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/agent_chunks_hanlder.py +0 -0
  178. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/config.py +0 -0
  179. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/factory.py +0 -0
  180. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/mcp/__init__.py +0 -0
  181. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/mcp/manager.py +0 -0
  182. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/mcp/models.py +0 -0
  183. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/mcp/tool_wrapper.py +0 -0
  184. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/openai_builtin/__init__.py +0 -0
  185. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/openai_builtin/base.py +0 -0
  186. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/openai_builtin/code_interpreter/__init__.py +0 -0
  187. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/openai_builtin/code_interpreter/config.py +0 -0
  188. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/openai_builtin/code_interpreter/postprocessors/__init__.py +0 -0
  189. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/openai_builtin/code_interpreter/postprocessors/code_display.py +0 -0
  190. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/openai_builtin/code_interpreter/postprocessors/generated_files.py +0 -0
  191. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/openai_builtin/code_interpreter/service.py +0 -0
  192. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/openai_builtin/manager.py +0 -0
  193. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/schemas.py +0 -0
  194. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/test/test_mcp_manager.py +0 -0
  195. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/test/test_tool_progress_reporter.py +0 -0
  196. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/tool.py +0 -0
  197. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/tool_manager.py +0 -0
  198. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/tool_progress_reporter.py +0 -0
  199. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/utils/__init__.py +0 -0
  200. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/utils/source_handling/__init__.py +0 -0
  201. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/utils/source_handling/schema.py +0 -0
  202. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/utils/source_handling/source_formatting.py +0 -0
  203. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic/tools/utils/source_handling/tests/test_source_formatting.py +0 -0
  204. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic_table/__init__.py +0 -0
  205. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic_table/schemas.py +0 -0
  206. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/agentic_table/service.py +0 -0
  207. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/app/__init__.py +0 -0
  208. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/app/dev_util.py +0 -0
  209. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/app/fast_api_factory.py +0 -0
  210. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/app/init_logging.py +0 -0
  211. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/app/init_sdk.py +0 -0
  212. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/app/performance/async_tasks.py +0 -0
  213. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/app/performance/async_wrapper.py +0 -0
  214. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/app/schemas.py +0 -0
  215. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/app/unique_settings.py +0 -0
  216. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/app/verification.py +0 -0
  217. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/app/webhook.py +0 -0
  218. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/chat/__init__.py +0 -0
  219. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/chat/cancellation.py +0 -0
  220. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/chat/constants.py +0 -0
  221. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/chat/deprecated/service.py +0 -0
  222. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/chat/functions.py +0 -0
  223. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/chat/rendering.py +0 -0
  224. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/chat/schemas.py +0 -0
  225. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/chat/service.py +0 -0
  226. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/chat/state.py +0 -0
  227. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/chat/utils.py +0 -0
  228. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/content/__init__.py +0 -0
  229. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/content/constants.py +0 -0
  230. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/content/functions.py +0 -0
  231. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/content/schemas.py +0 -0
  232. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/content/service.py +0 -0
  233. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/content/smart_rules.py +0 -0
  234. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/content/utils.py +0 -0
  235. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/data_extraction/README.md +0 -0
  236. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/data_extraction/__init__.py +0 -0
  237. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/data_extraction/augmented/__init__.py +0 -0
  238. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/data_extraction/augmented/service.py +0 -0
  239. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/data_extraction/base.py +0 -0
  240. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/data_extraction/basic/__init__.py +0 -0
  241. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/data_extraction/basic/config.py +0 -0
  242. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/data_extraction/basic/prompt.py +0 -0
  243. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/data_extraction/basic/service.py +0 -0
  244. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/elicitation/__init__.py +0 -0
  245. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/elicitation/constants.py +0 -0
  246. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/elicitation/exceptions.py +0 -0
  247. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/elicitation/functions.py +0 -0
  248. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/elicitation/schemas.py +0 -0
  249. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/elicitation/service.py +0 -0
  250. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/embedding/__init__.py +0 -0
  251. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/embedding/constants.py +0 -0
  252. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/embedding/functions.py +0 -0
  253. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/embedding/schemas.py +0 -0
  254. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/embedding/service.py +0 -0
  255. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/embedding/utils.py +0 -0
  256. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/framework_utilities/__init__.py +0 -0
  257. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/framework_utilities/langchain/__init__.py +0 -0
  258. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/framework_utilities/langchain/client.py +0 -0
  259. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/framework_utilities/langchain/history.py +0 -0
  260. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/framework_utilities/openai/__init__.py +0 -0
  261. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/framework_utilities/openai/client.py +0 -0
  262. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/framework_utilities/openai/message_builder.py +0 -0
  263. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/framework_utilities/utils.py +0 -0
  264. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/language_model/__init__.py +0 -0
  265. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/language_model/_responses_api_utils.py +0 -0
  266. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/language_model/builder.py +0 -0
  267. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/language_model/constants.py +0 -0
  268. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/language_model/default_language_model.py +0 -0
  269. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/language_model/functions.py +0 -0
  270. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/language_model/infos.py +0 -0
  271. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/language_model/prompt.py +0 -0
  272. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/language_model/reference.py +0 -0
  273. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/language_model/schemas.py +0 -0
  274. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/language_model/service.py +0 -0
  275. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/language_model/stream_transform.py +0 -0
  276. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/language_model/utils.py +0 -0
  277. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/protocols/support.py +0 -0
  278. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/services/__init__.py +0 -0
  279. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/services/knowledge_base.py +0 -0
  280. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/short_term_memory/__init__.py +0 -0
  281. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/short_term_memory/constants.py +0 -0
  282. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/short_term_memory/functions.py +0 -0
  283. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/short_term_memory/schemas.py +0 -0
  284. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/short_term_memory/service.py +0 -0
  285. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/smart_rules/__init__.py +0 -0
  286. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/smart_rules/compile.py +0 -0
  287. {unique_toolkit-1.51.0 → unique_toolkit-1.53.0}/unique_toolkit/test_utilities/events.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: unique-toolkit
3
- Version: 1.51.0
3
+ Version: 1.53.0
4
4
  Summary:
5
5
  Author: Cedric Klinkert, Martin Fadler, Sadique Sheik, Fabian Schläpfer, Pascal Hauri, Ejiroghene Oki-Peter, Rami Azouz, Ricardo Visini, Sanzio Monti
6
6
  Author-email: Cedric Klinkert <cedric.klinkert@unique.ch>, Martin Fadler <martin.fadler@unique.ch>, Sadique Sheik <sadique@unique.ch>, Fabian Schläpfer <fabian@unique.ch>, Pascal Hauri <pascal@unique.ch>, Ejiroghene Oki-Peter <oki-peter.ejiroghene@unique.ai>, Rami Azouz <rami.ext@unique.ch>, Ricardo Visini <ricardo.visini@unique.ch>, Sanzio Monti <sanzio.monti@unique.ai>
@@ -29,6 +29,7 @@ Requires-Dist: pandas>=2.3.0,<3
29
29
  Requires-Dist: click>=8.1.0,<9
30
30
  Requires-Dist: deepdiff>=8.6.1,<9
31
31
  Requires-Dist: pypandoc>=1.16.2,<2
32
+ Requires-Dist: tenacity>=9.1.4
32
33
  Requires-Dist: fastapi>=0.121.0,<0.122 ; extra == 'fastapi'
33
34
  Requires-Dist: starlette>=0.49.1 ; extra == 'fastapi'
34
35
  Requires-Dist: uvicorn>=0.37.0,<0.38 ; extra == 'fastapi'
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "unique_toolkit"
3
- version = "1.51.0"
3
+ version = "1.53.0"
4
4
  description = ""
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12"
@@ -41,6 +41,7 @@ dependencies = [
41
41
  "click>=8.1.0,<9",
42
42
  "deepdiff>=8.6.1,<9",
43
43
  "pypandoc>=1.16.2,<2",
44
+ "tenacity>=9.1.4",
44
45
  ]
45
46
 
46
47
  [project.optional-dependencies]
@@ -18,9 +18,9 @@ from unique_toolkit.agentic.loop_runner.runners import (
18
18
  QWEN_MAX_LOOP_ITERATIONS,
19
19
  BasicLoopIterationRunner,
20
20
  BasicLoopIterationRunnerConfig,
21
+ MistralLoopIterationRunner,
21
22
  QwenLoopIterationRunner,
22
23
  ResponsesBasicLoopIterationRunner,
23
- is_qwen_model,
24
24
  )
25
25
 
26
26
  __all__ = [
@@ -28,10 +28,10 @@ __all__ = [
28
28
  "PlanningConfig",
29
29
  "PlanningMiddleware",
30
30
  "PlanningSchemaConfig",
31
- "QwenLoopIterationRunner",
32
- "is_qwen_model",
33
31
  "BasicLoopIterationRunnerConfig",
34
32
  "BasicLoopIterationRunner",
33
+ "MistralLoopIterationRunner",
34
+ "QwenLoopIterationRunner",
35
35
  "handle_forced_tools_iteration",
36
36
  "handle_last_iteration",
37
37
  "handle_normal_iteration",
@@ -47,13 +47,17 @@ async def run_forced_tools_iteration(
47
47
  *,
48
48
  loop_runner_kwargs: _LoopIterationRunnerKwargs,
49
49
  prepare_loop_runner_kwargs: PrepareForcedToolIterationKwargs | None = None,
50
+ tool_choice_override: str | None = None,
50
51
  ) -> LanguageModelStreamResponse:
51
52
  """
52
53
  Execute a "forced tools" iteration by running one stream_response per tool choice,
53
54
  then merging tool calls and references into a single response.
54
55
 
55
- Some models (e.g. Qwen) need per-tool-choice message rewriting; this can be done
56
- via prepare_loop_runner_kwargs (called once per tool choice, on a copy of kwargs).
56
+ Args:
57
+ prepare_loop_runner_kwargs: Optional callback to transform kwargs per tool choice
58
+ (e.g. Qwen rewrites messages with tool-specific instructions).
59
+ tool_choice_override: If set, replaces the per-tool named dict with this value
60
+ (e.g. Mistral needs "any" instead of the named format).
57
61
  """
58
62
  assert "tool_choices" in loop_runner_kwargs
59
63
 
@@ -74,13 +78,16 @@ async def run_forced_tools_iteration(
74
78
  if prepare_loop_runner_kwargs:
75
79
  per_choice_kwargs = prepare_loop_runner_kwargs(func_name, per_choice_kwargs)
76
80
 
81
+ effective_tool_choice = tool_choice_override or opt
77
82
  limited_tool = available_tools.get(func_name) if func_name else None
78
- stream_kwargs = {"loop_runner_kwargs": per_choice_kwargs, "tool_choice": opt}
83
+ stream_kwargs = {
84
+ "loop_runner_kwargs": per_choice_kwargs,
85
+ "tool_choice": effective_tool_choice,
86
+ }
79
87
  if limited_tool:
80
88
  stream_kwargs["tools"] = [limited_tool]
81
89
  responses.append(await stream_response(**stream_kwargs))
82
90
 
83
- # Merge responses and refs:
84
91
  tool_calls = []
85
92
  references = []
86
93
  for r in responses:
@@ -1,6 +1,6 @@
1
1
  from typing import Any, Required
2
2
 
3
- from openai.types.chat import ChatCompletionNamedToolChoiceParam
3
+ from openai.types.chat import ChatCompletionToolChoiceOptionParam
4
4
  from typing_extensions import TypedDict
5
5
 
6
6
  from unique_toolkit import LanguageModelToolDescription
@@ -18,7 +18,7 @@ class _StreamingHandlerKwargs(TypedDict, total=False):
18
18
  start_text: str
19
19
  debug_info: dict[str, Any]
20
20
  temperature: float
21
- tool_choice: ChatCompletionNamedToolChoiceParam
21
+ tool_choice: ChatCompletionToolChoiceOptionParam
22
22
  other_options: dict[str, Any]
23
23
 
24
24
 
@@ -3,21 +3,23 @@ from unique_toolkit.agentic.loop_runner.runners.basic import (
3
3
  BasicLoopIterationRunnerConfig,
4
4
  ResponsesBasicLoopIterationRunner,
5
5
  )
6
+ from unique_toolkit.agentic.loop_runner.runners.mistral import (
7
+ MistralLoopIterationRunner,
8
+ )
6
9
  from unique_toolkit.agentic.loop_runner.runners.qwen import (
7
10
  QWEN_FORCED_TOOL_CALL_INSTRUCTION,
8
11
  QWEN_LAST_ITERATION_INSTRUCTION,
9
12
  QWEN_MAX_LOOP_ITERATIONS,
10
13
  QwenLoopIterationRunner,
11
- is_qwen_model,
12
14
  )
13
15
 
14
16
  __all__ = [
15
17
  "BasicLoopIterationRunnerConfig",
16
18
  "BasicLoopIterationRunner",
17
19
  "ResponsesBasicLoopIterationRunner",
20
+ "MistralLoopIterationRunner",
18
21
  "QwenLoopIterationRunner",
19
22
  "QWEN_FORCED_TOOL_CALL_INSTRUCTION",
20
23
  "QWEN_LAST_ITERATION_INSTRUCTION",
21
24
  "QWEN_MAX_LOOP_ITERATIONS",
22
- "is_qwen_model",
23
25
  ]
@@ -5,9 +5,9 @@ from pydantic import BaseModel
5
5
 
6
6
  from unique_toolkit._common.pydantic_helpers import get_configuration_dict
7
7
  from unique_toolkit.agentic.loop_runner._iteration_handler_utils import (
8
- handle_forced_tools_iteration,
9
8
  handle_last_iteration,
10
9
  handle_normal_iteration,
10
+ run_forced_tools_iteration,
11
11
  )
12
12
  from unique_toolkit.agentic.loop_runner._responses_iteration_handler_utils import (
13
13
  handle_responses_forced_tools_iteration,
@@ -44,11 +44,29 @@ class BasicLoopIterationRunner(LoopIterationRunner):
44
44
  iteration_index = kwargs["iteration_index"]
45
45
 
46
46
  if len(tool_choices) > 0 and iteration_index == 0:
47
- return await handle_forced_tools_iteration(**kwargs)
47
+ return await self._handle_forced_tools(**kwargs)
48
48
  elif iteration_index == self._config.max_loop_iterations - 1:
49
- return await handle_last_iteration(**kwargs)
49
+ return await self._handle_last_iteration(**kwargs)
50
50
  else:
51
- return await handle_normal_iteration(**kwargs)
51
+ return await self._handle_normal_iteration(**kwargs)
52
+
53
+ async def _handle_forced_tools(
54
+ self,
55
+ **kwargs: Unpack[_LoopIterationRunnerKwargs],
56
+ ) -> LanguageModelStreamResponse:
57
+ return await run_forced_tools_iteration(loop_runner_kwargs=kwargs)
58
+
59
+ async def _handle_last_iteration(
60
+ self,
61
+ **kwargs: Unpack[_LoopIterationRunnerKwargs],
62
+ ) -> LanguageModelStreamResponse:
63
+ return await handle_last_iteration(**kwargs)
64
+
65
+ async def _handle_normal_iteration(
66
+ self,
67
+ **kwargs: Unpack[_LoopIterationRunnerKwargs],
68
+ ) -> LanguageModelStreamResponse:
69
+ return await handle_normal_iteration(**kwargs)
52
70
 
53
71
 
54
72
  class ResponsesBasicLoopIterationRunner(ResponsesLoopIterationRunner):
@@ -0,0 +1,7 @@
1
+ from unique_toolkit.agentic.loop_runner.runners.mistral.mistral_runner import (
2
+ MistralLoopIterationRunner,
3
+ )
4
+
5
+ __all__ = [
6
+ "MistralLoopIterationRunner",
7
+ ]
@@ -0,0 +1,30 @@
1
+ from typing import Unpack
2
+
3
+ from unique_toolkit.agentic.loop_runner._iteration_handler_utils import (
4
+ run_forced_tools_iteration,
5
+ )
6
+ from unique_toolkit.agentic.loop_runner.base import _LoopIterationRunnerKwargs
7
+ from unique_toolkit.agentic.loop_runner.runners.basic import (
8
+ BasicLoopIterationRunner,
9
+ )
10
+ from unique_toolkit.chat.functions import LanguageModelStreamResponse
11
+
12
+
13
+ class MistralLoopIterationRunner(BasicLoopIterationRunner):
14
+ """Runner for Mistral models.
15
+
16
+ Mistral doesn't support named tool_choice (``{"type": "function", ...}``).
17
+ This runner overrides forced-tool handling to send ``"any"`` instead,
18
+ which forces the model to call a tool. Since each forced iteration already
19
+ restricts the tools list to a single tool, ``"any"`` effectively forces
20
+ the correct one.
21
+ """
22
+
23
+ async def _handle_forced_tools(
24
+ self,
25
+ **kwargs: Unpack[_LoopIterationRunnerKwargs],
26
+ ) -> LanguageModelStreamResponse:
27
+ return await run_forced_tools_iteration(
28
+ loop_runner_kwargs=kwargs,
29
+ tool_choice_override="any",
30
+ )
@@ -1,6 +1,3 @@
1
- from unique_toolkit.agentic.loop_runner.runners.qwen.helpers import (
2
- is_qwen_model,
3
- )
4
1
  from unique_toolkit.agentic.loop_runner.runners.qwen.qwen_runner import (
5
2
  QWEN_FORCED_TOOL_CALL_INSTRUCTION,
6
3
  QWEN_LAST_ITERATION_INSTRUCTION,
@@ -10,7 +7,6 @@ from unique_toolkit.agentic.loop_runner.runners.qwen.qwen_runner import (
10
7
 
11
8
  __all__ = [
12
9
  "QwenLoopIterationRunner",
13
- "is_qwen_model",
14
10
  "QWEN_FORCED_TOOL_CALL_INSTRUCTION",
15
11
  "QWEN_LAST_ITERATION_INSTRUCTION",
16
12
  "QWEN_MAX_LOOP_ITERATIONS",
@@ -1,4 +1,3 @@
1
- from unique_toolkit.language_model.infos import LanguageModelInfo
2
1
  from unique_toolkit.language_model.schemas import (
3
2
  LanguageModelAssistantMessage,
4
3
  LanguageModelMessageRole,
@@ -6,17 +5,6 @@ from unique_toolkit.language_model.schemas import (
6
5
  )
7
6
 
8
7
 
9
- def is_qwen_model(*, model: str | LanguageModelInfo | None) -> bool:
10
- """Check if the model is a Qwen model."""
11
- if isinstance(model, LanguageModelInfo):
12
- name = model.name
13
- # name is an Enum with a .value attribute
14
- return "qwen" in str(getattr(name, "value", name)).lower()
15
- elif isinstance(model, str):
16
- return "qwen" in model.lower()
17
- return False
18
-
19
-
20
8
  def append_qwen_forced_tool_call_instruction(
21
9
  *,
22
10
  messages: LanguageModelMessages,
@@ -2,13 +2,12 @@ import logging
2
2
  from typing import Unpack
3
3
 
4
4
  from unique_toolkit.agentic.loop_runner._iteration_handler_utils import (
5
- handle_last_iteration,
6
- handle_normal_iteration,
7
5
  run_forced_tools_iteration,
8
6
  )
9
- from unique_toolkit.agentic.loop_runner.base import (
10
- LoopIterationRunner,
11
- _LoopIterationRunnerKwargs,
7
+ from unique_toolkit.agentic.loop_runner.base import _LoopIterationRunnerKwargs
8
+ from unique_toolkit.agentic.loop_runner.runners.basic import (
9
+ BasicLoopIterationRunner,
10
+ BasicLoopIterationRunnerConfig,
12
11
  )
13
12
  from unique_toolkit.agentic.loop_runner.runners.qwen.helpers import (
14
13
  append_qwen_forced_tool_call_instruction,
@@ -30,45 +29,30 @@ QWEN_LAST_ITERATION_INSTRUCTION = """The maximum number of loop iteration have b
30
29
  Based on the found information, an answer should be generated"""
31
30
 
32
31
 
33
- class QwenLoopIterationRunner(LoopIterationRunner):
32
+ class QwenLoopIterationRunner(BasicLoopIterationRunner):
34
33
  def __init__(
35
34
  self,
36
35
  *,
37
- qwen_forced_tool_call_instruction: str,
38
- qwen_last_iteration_instruction: str,
39
- max_loop_iterations: int,
36
+ config: BasicLoopIterationRunnerConfig,
37
+ forced_tool_call_instruction: str,
38
+ last_iteration_instruction: str,
40
39
  chat_service: ChatService,
41
40
  ) -> None:
42
- self._qwen_forced_tool_call_instruction = qwen_forced_tool_call_instruction
43
- self._qwen_last_iteration_instruction = qwen_last_iteration_instruction
44
- self._max_loop_iterations = max_loop_iterations
41
+ super().__init__(config)
42
+ self._forced_tool_call_instruction = forced_tool_call_instruction
43
+ self._last_iteration_instruction = last_iteration_instruction
45
44
  self._chat_service = chat_service
46
45
 
47
- async def __call__(
46
+ async def _handle_forced_tools(
48
47
  self, **kwargs: Unpack[_LoopIterationRunnerKwargs]
49
48
  ) -> LanguageModelStreamResponse:
50
- tool_choices = kwargs.get("tool_choices") or []
51
- iteration_index = kwargs["iteration_index"]
52
-
53
- if len(tool_choices) > 0 and iteration_index == 0:
54
- return await self._qwen_handle_forced_tools_iteration(**kwargs)
55
- elif iteration_index == self._max_loop_iterations - 1:
56
- return await self._qwen_handle_last_iteration(**kwargs)
57
- else:
58
- return await self._qwen_handle_normal_iteration(**kwargs)
59
-
60
- async def _qwen_handle_forced_tools_iteration(
61
- self, **kwargs: Unpack[_LoopIterationRunnerKwargs]
62
- ) -> LanguageModelStreamResponse:
63
- # For Qwen models, append tool call instruction to the last user message. These models ignore the parameter tool_choice.
64
- # As the message has to be modified for each tool call instruction, the function from the basic runner cant be used.
65
49
  original_messages = kwargs["messages"].model_copy(deep=True)
66
50
 
67
51
  def _prepare(
68
52
  func_name: str | None,
69
53
  per_choice_kwargs: _LoopIterationRunnerKwargs,
70
54
  ) -> _LoopIterationRunnerKwargs:
71
- prompt_instruction = self._qwen_forced_tool_call_instruction.format(
55
+ prompt_instruction = self._forced_tool_call_instruction.format(
72
56
  TOOL_NAME=func_name or ""
73
57
  )
74
58
  per_choice_kwargs["messages"] = append_qwen_forced_tool_call_instruction(
@@ -83,34 +67,28 @@ class QwenLoopIterationRunner(LoopIterationRunner):
83
67
  )
84
68
  return self._process_response(response)
85
69
 
86
- async def _qwen_handle_last_iteration(
70
+ async def _handle_last_iteration(
87
71
  self, **kwargs: Unpack[_LoopIterationRunnerKwargs]
88
72
  ) -> LanguageModelStreamResponse:
89
- # For Qwen models, append an assistant message with instructions to not call any tool in this iteration.
90
73
  _LOGGER.info(
91
74
  "Reached last iteration, removing tools. Appending assistant message with instructions to not call any tool in this iteration."
92
75
  )
93
76
  kwargs["messages"] = append_qwen_last_iteration_assistant_message(
94
77
  messages=kwargs["messages"],
95
- last_iteration_instruction=self._qwen_last_iteration_instruction,
78
+ last_iteration_instruction=self._last_iteration_instruction,
96
79
  )
97
-
98
- response = await handle_last_iteration(
99
- **kwargs,
100
- )
101
-
80
+ response = await super()._handle_last_iteration(**kwargs)
102
81
  return self._process_response(response)
103
82
 
104
- async def _qwen_handle_normal_iteration(
83
+ async def _handle_normal_iteration(
105
84
  self, **kwargs: Unpack[_LoopIterationRunnerKwargs]
106
85
  ) -> LanguageModelStreamResponse:
107
- response = await handle_normal_iteration(**kwargs)
86
+ response = await super()._handle_normal_iteration(**kwargs)
108
87
  return self._process_response(response)
109
88
 
110
89
  def _process_response(
111
90
  self, response: LanguageModelStreamResponse
112
91
  ) -> LanguageModelStreamResponse:
113
- # Check if content of response is </tool_call>
114
92
  if "</tool_call>" == response.message.text.strip():
115
93
  _LOGGER.warning(
116
94
  "Response contains only <tool_call>. This is not allowed. Returning empty response."
@@ -1,5 +1,7 @@
1
1
  import json
2
2
  import logging
3
+ import random
4
+ from collections.abc import Awaitable, Callable
3
5
  from typing import Any, NamedTuple, Sequence
4
6
 
5
7
  import unique_sdk
@@ -13,7 +15,14 @@ from openai.types.responses import (
13
15
  response_create_params,
14
16
  )
15
17
  from openai.types.shared_params import Metadata, Reasoning
16
- from pydantic import BaseModel, TypeAdapter, ValidationError
18
+ from pydantic import BaseModel, Field, TypeAdapter, ValidationError
19
+ from pydantic_settings import BaseSettings, SettingsConfigDict
20
+ from tenacity import (
21
+ AsyncRetrying,
22
+ RetryCallState,
23
+ retry_if_exception,
24
+ stop_after_attempt,
25
+ )
17
26
 
18
27
  from unique_toolkit._common.execution import (
19
28
  failsafe,
@@ -329,6 +338,114 @@ def _prepare_responses_args(
329
338
  return options
330
339
 
331
340
 
341
+ _RATE_LIMIT_KEYWORDS = ("too_many_requests", "too many requests", "ratelimitreached")
342
+
343
+
344
+ class RateLimitRetryConfig(BaseSettings):
345
+ """Config for Responses API rate-limit retry. Set via env vars with prefix RATE_LIMIT_RETRY_."""
346
+
347
+ initial_delay_seconds: float = Field(
348
+ default=30.0,
349
+ description="First wait after SDK retries exhausted. Backoff then 2x (30→60→120s).",
350
+ )
351
+ max_attempts: int = Field(
352
+ default=2,
353
+ ge=1,
354
+ le=10,
355
+ description="Total attempts (1 initial + retries). Default 2 = 1 retry (~30s wait). Set to 1 to disable.",
356
+ )
357
+ log_message_on_retry: bool = Field(
358
+ default=True,
359
+ description="Write a message-log entry when a retry is about to sleep (e.g. 'Retrying in 30s').",
360
+ )
361
+
362
+ model_config = SettingsConfigDict(
363
+ env_prefix="RATE_LIMIT_RETRY_",
364
+ env_file=".env",
365
+ env_file_encoding="utf-8",
366
+ case_sensitive=False,
367
+ extra="ignore",
368
+ )
369
+
370
+
371
+ rate_limit_retry_config = RateLimitRetryConfig()
372
+
373
+
374
+ def _rate_limit_wait(retry_state: RetryCallState) -> float:
375
+ """Exponential backoff with up to 10% jitter: initial_delay → 2x → 4x."""
376
+ n = retry_state.attempt_number - 1 # 0-indexed
377
+ base = rate_limit_retry_config.initial_delay_seconds * (2.0**n)
378
+ return base + random.uniform(0.0, base * 0.1)
379
+
380
+
381
+ async def _responses_stream_with_rate_limit_retry(
382
+ responses_args: dict[str, Any],
383
+ model_name: str,
384
+ on_rate_limit_retry: Callable[[int, float], Awaitable[None]] | None = None,
385
+ ) -> "unique_sdk.Integrated.ResponsesStreamResult":
386
+ """Wrap responses_stream_async with exponential backoff for rate-limit errors.
387
+
388
+ The SDK already retries 3× (1s/2s/4s) before raising. This layer adds further
389
+ retries with longer delays, which are needed for models with tighter RPM limits
390
+ (e.g. GPT-4o) when large-token requests (web search, code execution) are in the loop.
391
+
392
+ Args:
393
+ responses_args: Keyword arguments forwarded to responses_stream_async.
394
+ model_name: Model name used in log messages.
395
+ on_rate_limit_retry: Optional async callback invoked before each retry sleep.
396
+ Receives (attempt_1based, wait_seconds). Useful for writing a message-log
397
+ entry so the user sees progress during long waits.
398
+ """
399
+
400
+ def _is_rate_limit(exc: BaseException) -> bool:
401
+ return isinstance(exc, unique_sdk.APIError) and any(
402
+ kw in str(exc).lower() for kw in _RATE_LIMIT_KEYWORDS
403
+ )
404
+
405
+ max_attempts = rate_limit_retry_config.max_attempts
406
+ max_retries = max_attempts - 1
407
+
408
+ def _log_attempt(retry_state: RetryCallState) -> None:
409
+ exc = retry_state.outcome.exception() if retry_state.outcome else None
410
+ if exc is None:
411
+ return
412
+ logger.error(
413
+ "responses_stream_async error on toolkit attempt %d/%d "
414
+ "model=%s code=%s http_status=%s is_rate_limit=%s original_error=%r",
415
+ retry_state.attempt_number,
416
+ max_attempts,
417
+ model_name,
418
+ getattr(exc, "code", None),
419
+ getattr(exc, "http_status", None),
420
+ _is_rate_limit(exc),
421
+ getattr(exc, "original_error", None),
422
+ )
423
+
424
+ async def _before_sleep(retry_state: RetryCallState) -> None:
425
+ wait_secs = retry_state.upcoming_sleep
426
+ logger.warning(
427
+ "Rate limit hit for model=%s. Toolkit-level retry %d/%d in %.1fs",
428
+ model_name,
429
+ retry_state.attempt_number,
430
+ max_retries,
431
+ wait_secs,
432
+ )
433
+ if on_rate_limit_retry is not None:
434
+ await on_rate_limit_retry(retry_state.attempt_number, wait_secs)
435
+
436
+ async def _call() -> "unique_sdk.Integrated.ResponsesStreamResult":
437
+ return await unique_sdk.Integrated.responses_stream_async(**responses_args)
438
+
439
+ return await AsyncRetrying(
440
+ retry=retry_if_exception(_is_rate_limit),
441
+ stop=stop_after_attempt(max_attempts),
442
+ wait=_rate_limit_wait,
443
+ after=_log_attempt,
444
+ before_sleep=_before_sleep,
445
+ reraise=True,
446
+ )(_call)
447
+
448
+
332
449
  def stream_responses_with_references(
333
450
  *,
334
451
  company_id: str,
@@ -426,6 +543,7 @@ async def stream_responses_with_references_async(
426
543
  top_p: float | None = None,
427
544
  reasoning: Reasoning | None = None,
428
545
  other_options: dict | None = None,
546
+ on_rate_limit_retry: Callable[[int, float], Awaitable[None]] | None = None,
429
547
  ) -> ResponsesLanguageModelStreamResponse:
430
548
  responses_params = _prepare_responses_params_util(
431
549
  model_name=model_name,
@@ -458,8 +576,14 @@ async def stream_responses_with_references_async(
458
576
  other_options=other_options,
459
577
  )
460
578
 
579
+ logger.info(
580
+ "Calling responses_stream_async model=%s",
581
+ responses_params.model_name,
582
+ )
461
583
  return ResponsesLanguageModelStreamResponse.model_validate(
462
- await unique_sdk.Integrated.responses_stream_async(
463
- **responses_args,
584
+ await _responses_stream_with_rate_limit_retry(
585
+ responses_args=responses_args,
586
+ model_name=responses_params.model_name,
587
+ on_rate_limit_retry=on_rate_limit_retry,
464
588
  )
465
589
  )
@@ -17,6 +17,7 @@ from pydantic import BaseModel
17
17
  from typing_extensions import deprecated
18
18
 
19
19
  from unique_toolkit._common.utils.files import is_file_content, is_image_content
20
+ from unique_toolkit.agentic.feature_flags import feature_flags
20
21
  from unique_toolkit.chat.cancellation import CancellationWatcher
21
22
  from unique_toolkit.chat.constants import (
22
23
  DEFAULT_MAX_MESSAGES,
@@ -50,6 +51,7 @@ from unique_toolkit.chat.functions import (
50
51
  update_message_log_async,
51
52
  )
52
53
  from unique_toolkit.chat.responses_api import (
54
+ rate_limit_retry_config,
53
55
  stream_responses_with_references,
54
56
  stream_responses_with_references_async,
55
57
  )
@@ -1637,6 +1639,33 @@ class ChatService(ChatServiceDeprecated):
1637
1639
  reasoning: Reasoning | None = None,
1638
1640
  other_options: dict | None = None,
1639
1641
  ) -> ResponsesLanguageModelStreamResponse:
1642
+ async def _on_rate_limit_retry(attempt: int, wait_secs: float) -> None:
1643
+ if not rate_limit_retry_config.log_message_on_retry:
1644
+ return
1645
+ if not feature_flags.enable_new_answers_ui_un_14411.is_enabled(
1646
+ self._company_id
1647
+ ):
1648
+ return
1649
+ from unique_toolkit.agentic.message_log_manager.service import (
1650
+ _request_counters,
1651
+ )
1652
+
1653
+ msg_id = self._assistant_message_id
1654
+ _request_counters[msg_id] += 1
1655
+ order = _request_counters[msg_id]
1656
+ try:
1657
+ await self.create_message_log_async(
1658
+ message_id=msg_id,
1659
+ text=f"Rate limit reached; retrying in {wait_secs:.0f}s (attempt {attempt})",
1660
+ status=MessageLogStatus.RUNNING,
1661
+ order=order,
1662
+ )
1663
+ except Exception:
1664
+ logger.warning(
1665
+ "Failed to write rate-limit retry message log",
1666
+ exc_info=True,
1667
+ )
1668
+
1640
1669
  return await stream_responses_with_references_async(
1641
1670
  company_id=self._company_id,
1642
1671
  user_id=self._user_id,
@@ -1661,6 +1690,7 @@ class ChatService(ChatServiceDeprecated):
1661
1690
  top_p=top_p,
1662
1691
  reasoning=reasoning,
1663
1692
  other_options=other_options,
1693
+ on_rate_limit_retry=_on_rate_limit_retry,
1664
1694
  )
1665
1695
 
1666
1696
  # Chat Content Methods