unique_toolkit 1.20.1__tar.gz → 1.21.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.

Potentially problematic release.


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

Files changed (174) hide show
  1. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/CHANGELOG.md +3 -0
  2. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/PKG-INFO +4 -1
  3. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/pyproject.toml +1 -1
  4. unique_toolkit-1.21.0/unique_toolkit/agentic/tools/test/test_tool_progress_reporter.py +429 -0
  5. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/tools/tool_progress_reporter.py +79 -14
  6. unique_toolkit-1.20.1/unique_toolkit/agentic/tools/test/test_tool_progress_reporter.py +0 -205
  7. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/LICENSE +0 -0
  8. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/README.md +0 -0
  9. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/__init__.py +0 -0
  10. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/_common/_base_service.py +0 -0
  11. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/_common/_time_utils.py +0 -0
  12. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/_common/api_calling/human_verification_manager.py +0 -0
  13. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/_common/base_model_type_attribute.py +0 -0
  14. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/_common/chunk_relevancy_sorter/config.py +0 -0
  15. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/_common/chunk_relevancy_sorter/exception.py +0 -0
  16. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/_common/chunk_relevancy_sorter/schemas.py +0 -0
  17. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/_common/chunk_relevancy_sorter/service.py +0 -0
  18. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/_common/chunk_relevancy_sorter/tests/test_service.py +0 -0
  19. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/_common/default_language_model.py +0 -0
  20. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/_common/endpoint_builder.py +0 -0
  21. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/_common/endpoint_requestor.py +0 -0
  22. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/_common/exception.py +0 -0
  23. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/_common/feature_flags/schema.py +0 -0
  24. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/_common/pydantic/rjsf_tags.py +0 -0
  25. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/_common/pydantic_helpers.py +0 -0
  26. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/_common/string_utilities.py +0 -0
  27. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/_common/token/image_token_counting.py +0 -0
  28. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/_common/token/token_counting.py +0 -0
  29. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/_common/utils/__init__.py +0 -0
  30. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/_common/utils/files.py +0 -0
  31. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/_common/utils/structured_output/__init__.py +0 -0
  32. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/_common/utils/structured_output/schema.py +0 -0
  33. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/_common/utils/write_configuration.py +0 -0
  34. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/_common/validate_required_values.py +0 -0
  35. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/_common/validators.py +0 -0
  36. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/__init__.py +0 -0
  37. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/debug_info_manager/debug_info_manager.py +0 -0
  38. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/debug_info_manager/test/test_debug_info_manager.py +0 -0
  39. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/evaluation/config.py +0 -0
  40. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/evaluation/context_relevancy/prompts.py +0 -0
  41. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/evaluation/context_relevancy/schema.py +0 -0
  42. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/evaluation/context_relevancy/service.py +0 -0
  43. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/evaluation/evaluation_manager.py +0 -0
  44. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/evaluation/exception.py +0 -0
  45. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/evaluation/hallucination/constants.py +0 -0
  46. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/evaluation/hallucination/hallucination_evaluation.py +0 -0
  47. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/evaluation/hallucination/prompts.py +0 -0
  48. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/evaluation/hallucination/service.py +0 -0
  49. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/evaluation/hallucination/utils.py +0 -0
  50. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/evaluation/output_parser.py +0 -0
  51. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/evaluation/schemas.py +0 -0
  52. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/evaluation/tests/test_context_relevancy_service.py +0 -0
  53. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/evaluation/tests/test_output_parser.py +0 -0
  54. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/history_manager/history_construction_with_contents.py +0 -0
  55. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/history_manager/history_manager.py +0 -0
  56. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/history_manager/loop_token_reducer.py +0 -0
  57. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/history_manager/utils.py +0 -0
  58. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/postprocessor/postprocessor_manager.py +0 -0
  59. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/reference_manager/reference_manager.py +0 -0
  60. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/responses_api/__init__.py +0 -0
  61. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/responses_api/postprocessors/code_display.py +0 -0
  62. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/responses_api/postprocessors/generated_files.py +0 -0
  63. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/responses_api/stream_handler.py +0 -0
  64. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/short_term_memory_manager/persistent_short_term_memory_manager.py +0 -0
  65. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/thinking_manager/thinking_manager.py +0 -0
  66. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/tools/__init__.py +0 -0
  67. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/tools/a2a/__init__.py +0 -0
  68. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/tools/a2a/config.py +0 -0
  69. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/tools/a2a/evaluation/__init__.py +0 -0
  70. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/tools/a2a/evaluation/_utils.py +0 -0
  71. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/tools/a2a/evaluation/config.py +0 -0
  72. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/tools/a2a/evaluation/evaluator.py +0 -0
  73. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/tools/a2a/evaluation/summarization_user_message.j2 +0 -0
  74. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/tools/a2a/manager.py +0 -0
  75. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/tools/a2a/postprocessing/__init__.py +0 -0
  76. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/tools/a2a/postprocessing/_display.py +0 -0
  77. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/tools/a2a/postprocessing/_utils.py +0 -0
  78. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/tools/a2a/postprocessing/config.py +0 -0
  79. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/tools/a2a/postprocessing/postprocessor.py +0 -0
  80. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/tools/a2a/postprocessing/test/test_consolidate_references.py +0 -0
  81. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/tools/a2a/postprocessing/test/test_display.py +0 -0
  82. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/tools/a2a/postprocessing/test/test_postprocessor_reference_functions.py +0 -0
  83. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/tools/a2a/prompts.py +0 -0
  84. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/tools/a2a/tool/__init__.py +0 -0
  85. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/tools/a2a/tool/_memory.py +0 -0
  86. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/tools/a2a/tool/_schema.py +0 -0
  87. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/tools/a2a/tool/config.py +0 -0
  88. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/tools/a2a/tool/service.py +0 -0
  89. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/tools/agent_chunks_hanlder.py +0 -0
  90. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/tools/config.py +0 -0
  91. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/tools/factory.py +0 -0
  92. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/tools/mcp/__init__.py +0 -0
  93. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/tools/mcp/manager.py +0 -0
  94. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/tools/mcp/models.py +0 -0
  95. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/tools/mcp/tool_wrapper.py +0 -0
  96. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/tools/openai_builtin/__init__.py +0 -0
  97. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/tools/openai_builtin/base.py +0 -0
  98. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/tools/openai_builtin/code_interpreter/__init__.py +0 -0
  99. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/tools/openai_builtin/code_interpreter/config.py +0 -0
  100. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/tools/openai_builtin/code_interpreter/service.py +0 -0
  101. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/tools/openai_builtin/manager.py +0 -0
  102. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/tools/schemas.py +0 -0
  103. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/tools/test/test_mcp_manager.py +0 -0
  104. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/tools/tool.py +0 -0
  105. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/tools/tool_manager.py +0 -0
  106. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/tools/utils/__init__.py +0 -0
  107. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/tools/utils/execution/__init__.py +0 -0
  108. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/tools/utils/execution/execution.py +0 -0
  109. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/tools/utils/source_handling/__init__.py +0 -0
  110. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/tools/utils/source_handling/schema.py +0 -0
  111. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/tools/utils/source_handling/source_formatting.py +0 -0
  112. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/agentic/tools/utils/source_handling/tests/test_source_formatting.py +0 -0
  113. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/app/__init__.py +0 -0
  114. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/app/dev_util.py +0 -0
  115. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/app/init_logging.py +0 -0
  116. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/app/init_sdk.py +0 -0
  117. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/app/performance/async_tasks.py +0 -0
  118. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/app/performance/async_wrapper.py +0 -0
  119. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/app/schemas.py +0 -0
  120. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/app/unique_settings.py +0 -0
  121. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/app/verification.py +0 -0
  122. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/chat/__init__.py +0 -0
  123. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/chat/constants.py +0 -0
  124. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/chat/deprecated/service.py +0 -0
  125. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/chat/functions.py +0 -0
  126. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/chat/rendering.py +0 -0
  127. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/chat/responses_api.py +0 -0
  128. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/chat/schemas.py +0 -0
  129. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/chat/service.py +0 -0
  130. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/chat/state.py +0 -0
  131. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/chat/utils.py +0 -0
  132. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/content/__init__.py +0 -0
  133. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/content/constants.py +0 -0
  134. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/content/functions.py +0 -0
  135. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/content/schemas.py +0 -0
  136. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/content/service.py +0 -0
  137. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/content/smart_rules.py +0 -0
  138. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/content/utils.py +0 -0
  139. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/embedding/__init__.py +0 -0
  140. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/embedding/constants.py +0 -0
  141. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/embedding/functions.py +0 -0
  142. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/embedding/schemas.py +0 -0
  143. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/embedding/service.py +0 -0
  144. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/embedding/utils.py +0 -0
  145. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/framework_utilities/__init__.py +0 -0
  146. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/framework_utilities/langchain/client.py +0 -0
  147. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/framework_utilities/langchain/history.py +0 -0
  148. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/framework_utilities/openai/__init__.py +0 -0
  149. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/framework_utilities/openai/client.py +0 -0
  150. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/framework_utilities/openai/message_builder.py +0 -0
  151. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/framework_utilities/utils.py +0 -0
  152. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/language_model/__init__.py +0 -0
  153. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/language_model/builder.py +0 -0
  154. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/language_model/constants.py +0 -0
  155. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/language_model/default_language_model.py +0 -0
  156. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/language_model/functions.py +0 -0
  157. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/language_model/infos.py +0 -0
  158. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/language_model/prompt.py +0 -0
  159. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/language_model/reference.py +0 -0
  160. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/language_model/schemas.py +0 -0
  161. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/language_model/service.py +0 -0
  162. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/language_model/utils.py +0 -0
  163. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/protocols/support.py +0 -0
  164. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/services/__init__.py +0 -0
  165. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/services/chat_service.py +0 -0
  166. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/services/knowledge_base.py +0 -0
  167. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/short_term_memory/__init__.py +0 -0
  168. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/short_term_memory/constants.py +0 -0
  169. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/short_term_memory/functions.py +0 -0
  170. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/short_term_memory/schemas.py +0 -0
  171. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/short_term_memory/service.py +0 -0
  172. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/smart_rules/__init__.py +0 -0
  173. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/smart_rules/compile.py +0 -0
  174. {unique_toolkit-1.20.1 → unique_toolkit-1.21.0}/unique_toolkit/test_utilities/events.py +0 -0
@@ -6,6 +6,9 @@ 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
8
 
9
+ ## [1.21.0] - 2025-10-30
10
+ - Add option to customize the display of tool progress statuses.
11
+
9
12
  ## [1.20.1] - 2025-10-30
10
13
  - Fix typing issues in `LanguageModelFunction`.
11
14
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: unique_toolkit
3
- Version: 1.20.1
3
+ Version: 1.21.0
4
4
  Summary:
5
5
  License: Proprietary
6
6
  Author: Cedric Klinkert
@@ -119,6 +119,9 @@ 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
121
 
122
+ ## [1.21.0] - 2025-10-30
123
+ - Add option to customize the display of tool progress statuses.
124
+
122
125
  ## [1.20.1] - 2025-10-30
123
126
  - Fix typing issues in `LanguageModelFunction`.
124
127
 
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "unique_toolkit"
3
- version = "1.20.1"
3
+ version = "1.21.0"
4
4
  description = ""
5
5
  authors = [
6
6
  "Cedric Klinkert <cedric.klinkert@unique.ch>",
@@ -0,0 +1,429 @@
1
+ from unittest.mock import AsyncMock
2
+
3
+ import pytest
4
+
5
+ from unique_toolkit.agentic.tools.tool_progress_reporter import (
6
+ DUMMY_REFERENCE_PLACEHOLDER,
7
+ ProgressState,
8
+ ToolExecutionStatus,
9
+ ToolProgressReporter,
10
+ ToolProgressReporterConfig,
11
+ ToolWithToolProgressReporter,
12
+ track_tool_progress,
13
+ )
14
+ from unique_toolkit.chat.service import ChatService
15
+ from unique_toolkit.content.schemas import ContentReference
16
+ from unique_toolkit.language_model.schemas import LanguageModelFunction
17
+
18
+
19
+ @pytest.fixture
20
+ def chat_service():
21
+ return AsyncMock(spec=ChatService)
22
+
23
+
24
+ @pytest.fixture
25
+ def tool_progress_reporter(chat_service):
26
+ return ToolProgressReporter(chat_service)
27
+
28
+
29
+ @pytest.fixture
30
+ def tool_call():
31
+ return LanguageModelFunction(id="test_id", name="test_tool")
32
+
33
+
34
+ class TestToolProgressReporter:
35
+ @pytest.mark.asyncio
36
+ async def test_notify_from_tool_call(self, tool_progress_reporter, tool_call):
37
+ # Arrange
38
+ name = "Test Tool"
39
+ message = "Processing..."
40
+ state = ProgressState.RUNNING
41
+ references = [
42
+ ContentReference(
43
+ sequence_number=1,
44
+ id="1",
45
+ message_id="1",
46
+ name="1",
47
+ source="1",
48
+ source_id="1",
49
+ url="1",
50
+ )
51
+ ]
52
+
53
+ # Act
54
+ await tool_progress_reporter.notify_from_tool_call(
55
+ tool_call=tool_call,
56
+ name=name,
57
+ message=message,
58
+ state=state,
59
+ references=references,
60
+ requires_new_assistant_message=True,
61
+ )
62
+
63
+ # Assert
64
+ assert tool_call.id in tool_progress_reporter.tool_statuses
65
+ status = tool_progress_reporter.tool_statuses[tool_call.id]
66
+ assert status.name == name
67
+ assert status.message == message
68
+ assert status.state == state
69
+ assert status.references == references
70
+ assert tool_progress_reporter.requires_new_assistant_message is True
71
+
72
+ def test_replace_placeholders(self, tool_progress_reporter):
73
+ # Arrange
74
+ message = (
75
+ f"Test{DUMMY_REFERENCE_PLACEHOLDER}message{DUMMY_REFERENCE_PLACEHOLDER}"
76
+ )
77
+
78
+ # Act
79
+ result = tool_progress_reporter._replace_placeholders(message, start_number=1)
80
+
81
+ # Assert
82
+ assert result == "Test<sup>1</sup>message<sup>2</sup>"
83
+
84
+ def test_correct_reference_sequence(self, tool_progress_reporter):
85
+ # Arrange
86
+ references = [
87
+ ContentReference(
88
+ sequence_number=0,
89
+ id="1",
90
+ message_id="1",
91
+ name="1",
92
+ source="1",
93
+ source_id="1",
94
+ url="1",
95
+ ),
96
+ ContentReference(
97
+ sequence_number=0,
98
+ id="2",
99
+ message_id="2",
100
+ name="2",
101
+ source="2",
102
+ source_id="2",
103
+ url="2",
104
+ ),
105
+ ]
106
+
107
+ # Act
108
+ result = tool_progress_reporter._correct_reference_sequence(
109
+ references, start_number=1
110
+ )
111
+
112
+ # Assert
113
+ assert len(result) == 2
114
+ assert result[0].sequence_number == 1
115
+ assert result[1].sequence_number == 2
116
+
117
+ @pytest.mark.asyncio
118
+ async def test_publish_updates_chat_service(
119
+ self, tool_progress_reporter, tool_call
120
+ ):
121
+ # Arrange
122
+ status = ToolExecutionStatus(
123
+ name="Test Tool",
124
+ message="Test message",
125
+ state=ProgressState.FINISHED,
126
+ references=[
127
+ ContentReference(
128
+ sequence_number=1,
129
+ id="1",
130
+ message_id="1",
131
+ name="1",
132
+ source="1",
133
+ source_id="1",
134
+ url="1",
135
+ )
136
+ ],
137
+ )
138
+ tool_progress_reporter.tool_statuses[tool_call.id] = status
139
+
140
+ # Act
141
+ await tool_progress_reporter.publish()
142
+
143
+ # Assert
144
+ tool_progress_reporter.chat_service.modify_assistant_message_async.assert_called_once()
145
+
146
+
147
+ class TestToolProgressDecorator:
148
+ class DummyTool(ToolWithToolProgressReporter):
149
+ def __init__(self, tool_progress_reporter):
150
+ self.tool_progress_reporter = tool_progress_reporter
151
+
152
+ @track_tool_progress(
153
+ message="Processing",
154
+ on_start_state=ProgressState.STARTED,
155
+ on_success_state=ProgressState.FINISHED,
156
+ on_success_message="Completed",
157
+ requires_new_assistant_message=True,
158
+ )
159
+ async def execute(self, tool_call, notification_tool_name):
160
+ return {
161
+ "references": [
162
+ ContentReference(
163
+ sequence_number=1,
164
+ id="1",
165
+ message_id="1",
166
+ name="1",
167
+ source="1",
168
+ source_id="1",
169
+ url="1",
170
+ )
171
+ ]
172
+ }
173
+
174
+ @pytest.mark.asyncio
175
+ async def test_decorator_success_flow(self, tool_progress_reporter, tool_call):
176
+ # Arrange
177
+ tool = self.DummyTool(tool_progress_reporter)
178
+
179
+ # Act
180
+ await tool.execute(tool_call, "Test Tool")
181
+
182
+ # Assert
183
+ assert len(tool_progress_reporter.tool_statuses) == 1
184
+ status = tool_progress_reporter.tool_statuses[tool_call.id]
185
+ assert status.state == ProgressState.FINISHED
186
+ assert status.message == "Completed"
187
+
188
+ @pytest.mark.asyncio
189
+ async def test_decorator_error_flow(self, tool_progress_reporter, tool_call):
190
+ # Arrange
191
+ class ErrorTool(ToolWithToolProgressReporter):
192
+ def __init__(self, tool_progress_reporter):
193
+ self.tool_progress_reporter = tool_progress_reporter
194
+
195
+ @track_tool_progress(message="Processing")
196
+ async def execute(self, tool_call, notification_tool_name):
197
+ raise ValueError("Test error")
198
+
199
+ tool = ErrorTool(tool_progress_reporter)
200
+
201
+ # Act & Assert
202
+ with pytest.raises(ValueError):
203
+ await tool.execute(tool_call, "Test Tool")
204
+
205
+ status = tool_progress_reporter.tool_statuses[tool_call.id]
206
+ assert status.state == ProgressState.FAILED
207
+
208
+
209
+ class TestToolProgressReporterConfig:
210
+ """Tests for ToolProgressReporterConfig and custom display configuration."""
211
+
212
+ @pytest.mark.ai
213
+ @pytest.mark.asyncio
214
+ async def test_config__uses_default_templates__when_no_config_provided(
215
+ self, chat_service, tool_call
216
+ ) -> None:
217
+ """
218
+ Purpose: Verify that default state-to-display templates are used when no config is provided.
219
+ Why this matters: Ensures backward compatibility and default behavior.
220
+ Setup summary: Create reporter without config, add status, verify default template is used.
221
+ """
222
+ # Arrange
223
+ reporter = ToolProgressReporter(chat_service)
224
+
225
+ # Act
226
+ await reporter.notify_from_tool_call(
227
+ tool_call=tool_call,
228
+ name="Test Tool",
229
+ message="Processing data",
230
+ state=ProgressState.RUNNING,
231
+ )
232
+
233
+ # Assert
234
+ assert tool_call.id in reporter.tool_statuses
235
+ chat_service.modify_assistant_message_async.assert_called()
236
+ call_args = chat_service.modify_assistant_message_async.call_args
237
+ content = call_args.kwargs["content"]
238
+ assert "Test Tool" in content
239
+ assert "🟡" in content # Default emoji for RUNNING state
240
+ assert "Processing data" in content
241
+
242
+ @pytest.mark.ai
243
+ @pytest.mark.asyncio
244
+ async def test_config__uses_custom_templates__when_config_provided(
245
+ self, chat_service, tool_call
246
+ ) -> None:
247
+ """
248
+ Purpose: Verify that custom templates are used when provided via config.
249
+ Why this matters: Enables customization of progress display format.
250
+ Setup summary: Create reporter with custom template, verify custom format is used.
251
+ """
252
+ # Arrange
253
+ custom_config = ToolProgressReporterConfig(
254
+ state_to_display_template={
255
+ ProgressState.RUNNING: "⏳ {tool_name}: {message}",
256
+ ProgressState.FINISHED: "✅ {tool_name}: {message}",
257
+ }
258
+ )
259
+ reporter = ToolProgressReporter(chat_service, config=custom_config)
260
+
261
+ # Act
262
+ await reporter.notify_from_tool_call(
263
+ tool_call=tool_call,
264
+ name="My Tool",
265
+ message="Working on it",
266
+ state=ProgressState.RUNNING,
267
+ )
268
+
269
+ # Assert
270
+ chat_service.modify_assistant_message_async.assert_called()
271
+ call_args = chat_service.modify_assistant_message_async.call_args
272
+ content = call_args.kwargs["content"]
273
+ assert "⏳ My Tool: Working on it" in content
274
+ assert "🟡" not in content # Default emoji should not appear
275
+
276
+ @pytest.mark.ai
277
+ @pytest.mark.asyncio
278
+ async def test_config__skips_states_not_in_template__when_state_excluded(
279
+ self, chat_service, tool_call
280
+ ) -> None:
281
+ """
282
+ Purpose: Verify that states not in the config mapping are not displayed.
283
+ Why this matters: Allows selective display of only certain states (e.g., hide STARTED).
284
+ Setup summary: Create config excluding RUNNING state, verify message is not displayed.
285
+ """
286
+ # Arrange
287
+ custom_config = ToolProgressReporterConfig(
288
+ state_to_display_template={
289
+ ProgressState.FINISHED: "✅ {tool_name}: {message}",
290
+ # RUNNING state is intentionally excluded
291
+ }
292
+ )
293
+ reporter = ToolProgressReporter(chat_service, config=custom_config)
294
+
295
+ # Act
296
+ await reporter.notify_from_tool_call(
297
+ tool_call=tool_call,
298
+ name="Test Tool",
299
+ message="Processing",
300
+ state=ProgressState.RUNNING,
301
+ )
302
+
303
+ # Assert
304
+ chat_service.modify_assistant_message_async.assert_called()
305
+ call_args = chat_service.modify_assistant_message_async.call_args
306
+ content = call_args.kwargs["content"]
307
+ # Content should not contain the message since RUNNING is excluded
308
+ assert "Processing" not in content
309
+ assert "Test Tool" not in content
310
+
311
+ @pytest.mark.ai
312
+ @pytest.mark.asyncio
313
+ async def test_config__formats_placeholders_correctly__with_multiple_tools(
314
+ self, chat_service
315
+ ) -> None:
316
+ """
317
+ Purpose: Verify that {tool_name} and {message} placeholders are replaced correctly for multiple tools.
318
+ Why this matters: Ensures template formatting works correctly in multi-tool scenarios.
319
+ Setup summary: Add multiple tool statuses with different names/messages, verify formatting.
320
+ """
321
+ # Arrange
322
+ custom_config = ToolProgressReporterConfig(
323
+ state_to_display_template={
324
+ ProgressState.RUNNING: "▶️ {tool_name} - {message}",
325
+ ProgressState.FINISHED: "✓ {tool_name} - {message}",
326
+ }
327
+ )
328
+ reporter = ToolProgressReporter(chat_service, config=custom_config)
329
+ tool_call_1 = LanguageModelFunction(id="tool_1", name="search")
330
+ tool_call_2 = LanguageModelFunction(id="tool_2", name="analyze")
331
+
332
+ # Act
333
+ await reporter.notify_from_tool_call(
334
+ tool_call=tool_call_1,
335
+ name="Search Tool",
336
+ message="Searching database",
337
+ state=ProgressState.RUNNING,
338
+ )
339
+ await reporter.notify_from_tool_call(
340
+ tool_call=tool_call_2,
341
+ name="Analysis Tool",
342
+ message="Analyzing results",
343
+ state=ProgressState.FINISHED,
344
+ )
345
+
346
+ # Assert
347
+ call_args = chat_service.modify_assistant_message_async.call_args
348
+ content = call_args.kwargs["content"]
349
+ assert "▶️ Search Tool - Searching database" in content
350
+ assert "✓ Analysis Tool - Analyzing results" in content
351
+
352
+ @pytest.mark.ai
353
+ @pytest.mark.asyncio
354
+ async def test_config__shows_only_finished_state__when_only_finished_configured(
355
+ self, chat_service, tool_call
356
+ ) -> None:
357
+ """
358
+ Purpose: Verify selective state display shows only FINISHED when it's the only state configured.
359
+ Why this matters: Use case where user only wants final results, not intermediate steps.
360
+ Setup summary: Configure only FINISHED state, send STARTED and FINISHED, verify only FINISHED appears.
361
+ """
362
+ # Arrange
363
+ custom_config = ToolProgressReporterConfig(
364
+ state_to_display_template={
365
+ ProgressState.FINISHED: "Done: {tool_name} - {message}",
366
+ }
367
+ )
368
+ reporter = ToolProgressReporter(chat_service, config=custom_config)
369
+
370
+ # Act - Send STARTED state (should not appear)
371
+ await reporter.notify_from_tool_call(
372
+ tool_call=tool_call,
373
+ name="Test Tool",
374
+ message="Starting",
375
+ state=ProgressState.STARTED,
376
+ )
377
+
378
+ # Get first call content
379
+ first_call_args = chat_service.modify_assistant_message_async.call_args
380
+ first_content = first_call_args.kwargs["content"]
381
+
382
+ # Act - Update to FINISHED state (should appear)
383
+ await reporter.notify_from_tool_call(
384
+ tool_call=tool_call,
385
+ name="Test Tool",
386
+ message="Completed successfully",
387
+ state=ProgressState.FINISHED,
388
+ )
389
+
390
+ # Assert
391
+ final_call_args = chat_service.modify_assistant_message_async.call_args
392
+ final_content = final_call_args.kwargs["content"]
393
+
394
+ # STARTED state should not appear in first call
395
+ assert "Starting" not in first_content
396
+
397
+ # FINISHED state should appear in final call
398
+ assert "Done: Test Tool - Completed successfully" in final_content
399
+
400
+ @pytest.mark.ai
401
+ @pytest.mark.asyncio
402
+ async def test_config__handles_empty_template_dict__when_all_states_excluded(
403
+ self, chat_service, tool_call
404
+ ) -> None:
405
+ """
406
+ Purpose: Verify that an empty template dict results in no messages being displayed.
407
+ Why this matters: Edge case handling and allows disabling all progress display.
408
+ Setup summary: Create config with empty dict, verify no tool messages appear.
409
+ """
410
+ # Arrange
411
+ custom_config = ToolProgressReporterConfig(state_to_display_template={})
412
+ reporter = ToolProgressReporter(chat_service, config=custom_config)
413
+
414
+ # Act
415
+ await reporter.notify_from_tool_call(
416
+ tool_call=tool_call,
417
+ name="Test Tool",
418
+ message="Processing",
419
+ state=ProgressState.RUNNING,
420
+ )
421
+
422
+ # Assert
423
+ chat_service.modify_assistant_message_async.assert_called()
424
+ call_args = chat_service.modify_assistant_message_async.call_args
425
+ content = call_args.kwargs["content"]
426
+
427
+ # Should only have the progress start text and newlines, no actual messages
428
+ assert "Test Tool" not in content
429
+ assert "Processing" not in content
@@ -1,11 +1,12 @@
1
1
  import re
2
2
  from datetime import datetime
3
- from enum import Enum
3
+ from enum import StrEnum
4
4
  from functools import wraps
5
5
  from typing import Protocol
6
6
 
7
- from pydantic import BaseModel
7
+ from pydantic import BaseModel, Field
8
8
 
9
+ from unique_toolkit._common.pydantic_helpers import get_configuration_dict
9
10
  from unique_toolkit.chat.service import ChatService
10
11
  from unique_toolkit.content.schemas import ContentReference
11
12
  from unique_toolkit.language_model.schemas import (
@@ -17,11 +18,11 @@ ARROW = "&#8594;&nbsp;"
17
18
  DUMMY_REFERENCE_PLACEHOLDER = "<sup></sup>"
18
19
 
19
20
 
20
- class ProgressState(Enum):
21
- STARTED = ""
22
- RUNNING = "🟡"
23
- FAILED = "🔴"
24
- FINISHED = "🟢"
21
+ class ProgressState(StrEnum):
22
+ STARTED = "started"
23
+ RUNNING = "running"
24
+ FAILED = "failed"
25
+ FINISHED = "finished"
25
26
 
26
27
 
27
28
  class ToolExecutionStatus(BaseModel):
@@ -29,15 +30,56 @@ class ToolExecutionStatus(BaseModel):
29
30
  message: str
30
31
  state: ProgressState
31
32
  references: list[ContentReference] = []
32
- timestamp: datetime = datetime.now()
33
+ timestamp: datetime = Field(default_factory=datetime.now)
34
+
35
+
36
+ _DEFAULT_STATE_TO_DISPLAY_TEMPLATE = {
37
+ ProgressState.FINISHED: "{arrow}**{{tool_name}}** 🟢: {{message}}".format(
38
+ arrow=ARROW
39
+ ),
40
+ ProgressState.RUNNING: "{arrow}**{{tool_name}}** 🟡: {{message}}".format(
41
+ arrow=ARROW
42
+ ),
43
+ ProgressState.FAILED: "{arrow}**{{tool_name}}** 🔴: {{message}}".format(
44
+ arrow=ARROW
45
+ ),
46
+ ProgressState.STARTED: "{arrow}**{{tool_name}}** ⚪: {{message}}".format(
47
+ arrow=ARROW
48
+ ),
49
+ }
50
+
51
+
52
+ state_to_display_template_description = """
53
+ A mapping progress states to display templates.
54
+ The display template is a string that will be used to display the progress status.
55
+ The template can contain the following placeholders:
56
+ - `{tool_name}`: The name of the tool
57
+ - `{message}`: The message to display (sent by the tool)
58
+
59
+ If a state is not present in the mapping, then updates for that state will not be displayed.
60
+ """.strip()
61
+
62
+
63
+ class ToolProgressReporterConfig(BaseModel):
64
+ model_config = get_configuration_dict()
65
+
66
+ state_to_display_template: dict[ProgressState, str] = Field(
67
+ default=_DEFAULT_STATE_TO_DISPLAY_TEMPLATE,
68
+ description=state_to_display_template_description,
69
+ )
33
70
 
34
71
 
35
72
  class ToolProgressReporter:
36
- def __init__(self, chat_service: ChatService):
73
+ def __init__(
74
+ self,
75
+ chat_service: ChatService,
76
+ config: ToolProgressReporterConfig | None = None,
77
+ ):
37
78
  self.chat_service = chat_service
38
79
  self.tool_statuses: dict[str, ToolExecutionStatus] = {}
39
80
  self._progress_start_text = ""
40
81
  self._requires_new_assistant_message = False
82
+ self._config = config or ToolProgressReporterConfig()
41
83
 
42
84
  @property
43
85
  def requires_new_assistant_message(self):
@@ -77,16 +119,13 @@ class ToolProgressReporter:
77
119
  references (list[ContentReference], optional): List of content references. Defaults to [].
78
120
  requires_new_assistant_message (bool, optional): Whether a new assistant message is needed when tool call is finished.
79
121
  Defaults to False. If yes, the agentic steps will remain in chat history and will be overwritten by the stream response.
80
-
81
- Raises:
82
- AssertionError: If tool_call.id is None
83
122
  """
84
- assert tool_call.id is not None
85
123
  self.tool_statuses[tool_call.id] = ToolExecutionStatus(
86
124
  name=name,
87
125
  message=message,
88
126
  state=state,
89
127
  references=references,
128
+ timestamp=self._get_timestamp_for_tool_call(tool_call),
90
129
  )
91
130
  self.requires_new_assistant_message = (
92
131
  self.requires_new_assistant_message or requires_new_assistant_message
@@ -103,7 +142,11 @@ class ToolProgressReporter:
103
142
  references = self._correct_reference_sequence(references, start_number)
104
143
  all_references.extend(references)
105
144
 
106
- messages.append(f"{ARROW}**{item.name} {item.state.value}**: {message}")
145
+ display_message = self._get_tool_status_display_message(
146
+ name=item.name, message=message, state=item.state
147
+ )
148
+ if display_message is not None:
149
+ messages.append(display_message)
107
150
 
108
151
  await self.chat_service.modify_assistant_message_async(
109
152
  content=self._progress_start_text + "\n\n" + "\n\n".join(messages),
@@ -130,6 +173,28 @@ class ToolProgressReporter:
130
173
  reference.sequence_number = i
131
174
  return references
132
175
 
176
+ def _get_timestamp_for_tool_call(
177
+ self, tool_call: LanguageModelFunction
178
+ ) -> datetime:
179
+ """
180
+ Keep the same timestamp if the tool call is already in the statuses.
181
+ This ensures the display order stays consistent.
182
+ """
183
+ if tool_call.id in self.tool_statuses:
184
+ return self.tool_statuses[tool_call.id].timestamp
185
+
186
+ return datetime.now()
187
+
188
+ def _get_tool_status_display_message(
189
+ self, name: str, message: str, state: ProgressState
190
+ ) -> str | None:
191
+ if state in self._config.state_to_display_template:
192
+ return self._config.state_to_display_template[state].format(
193
+ tool_name=name,
194
+ message=message,
195
+ )
196
+ return None
197
+
133
198
 
134
199
  class ToolWithToolProgressReporter(Protocol):
135
200
  tool_progress_reporter: ToolProgressReporter