unique_toolkit 1.57__tar.gz → 1.58.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (288) hide show
  1. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/PKG-INFO +1 -1
  2. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/pyproject.toml +1 -1
  3. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/evaluation/evaluation_manager.py +11 -1
  4. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/evaluation/tests/test_hallucination_utils.py +13 -7
  5. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/history_manager/history_construction_with_contents.py +3 -3
  6. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/postprocessor/postprocessor_manager.py +11 -0
  7. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/openai_builtin/code_interpreter/postprocessors/generated_files.py +72 -1
  8. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/tool_manager.py +8 -1
  9. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/chat/schemas.py +53 -37
  10. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/content/schemas.py +1 -1
  11. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/language_model/__init__.py +2 -0
  12. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/language_model/functions.py +4 -3
  13. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/language_model/schemas.py +20 -30
  14. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/services/chat_service.py +44 -0
  15. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/README.md +0 -0
  16. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/__init__.py +0 -0
  17. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/__init__.py +0 -0
  18. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/_base_service.py +0 -0
  19. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/_time_utils.py +0 -0
  20. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/api_calling/human_verification_manager.py +0 -0
  21. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/base_model_type_attribute.py +0 -0
  22. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/chunk_relevancy_sorter/config.py +0 -0
  23. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/chunk_relevancy_sorter/exception.py +0 -0
  24. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/chunk_relevancy_sorter/schemas.py +0 -0
  25. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/chunk_relevancy_sorter/service.py +0 -0
  26. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/chunk_relevancy_sorter/tests/test_service.py +0 -0
  27. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/config_checker/README.md +0 -0
  28. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/config_checker/__init__.py +0 -0
  29. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/config_checker/__main__.py +0 -0
  30. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/config_checker/cli.py +0 -0
  31. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/config_checker/differ.py +0 -0
  32. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/config_checker/exporter.py +0 -0
  33. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/config_checker/models.py +0 -0
  34. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/config_checker/registry.py +0 -0
  35. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/config_checker/validator.py +0 -0
  36. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/default_language_model.py +0 -0
  37. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/docx_generator/__init__.py +0 -0
  38. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/docx_generator/config.py +0 -0
  39. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/docx_generator/pandoc_converter.py +0 -0
  40. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/docx_generator/schemas.py +0 -0
  41. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/docx_generator/service.py +0 -0
  42. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/docx_generator/template/Doc Template.docx +0 -0
  43. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/endpoint_builder.py +0 -0
  44. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/endpoint_requestor.py +0 -0
  45. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/event_bus.py +0 -0
  46. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/exception.py +0 -0
  47. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/execution.py +0 -0
  48. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/experimental/endpoint_builder.py +0 -0
  49. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/experimental/endpoint_requestor.py +0 -0
  50. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/experimental/write_up_agent/README.md +0 -0
  51. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/experimental/write_up_agent/__init__.py +0 -0
  52. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/experimental/write_up_agent/agent.py +0 -0
  53. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/experimental/write_up_agent/config.py +0 -0
  54. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/experimental/write_up_agent/examples/data.csv +0 -0
  55. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/experimental/write_up_agent/examples/example_usage.py +0 -0
  56. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/experimental/write_up_agent/schemas.py +0 -0
  57. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/experimental/write_up_agent/services/__init__.py +0 -0
  58. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/experimental/write_up_agent/services/dataframe_handler/__init__.py +0 -0
  59. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/experimental/write_up_agent/services/dataframe_handler/exceptions.py +0 -0
  60. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/experimental/write_up_agent/services/dataframe_handler/service.py +0 -0
  61. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/experimental/write_up_agent/services/dataframe_handler/utils.py +0 -0
  62. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/experimental/write_up_agent/services/generation_handler/__init__.py +0 -0
  63. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/experimental/write_up_agent/services/generation_handler/config.py +0 -0
  64. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/experimental/write_up_agent/services/generation_handler/exceptions.py +0 -0
  65. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/experimental/write_up_agent/services/generation_handler/prompts/config.py +0 -0
  66. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/experimental/write_up_agent/services/generation_handler/prompts/system_prompt.j2 +0 -0
  67. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/experimental/write_up_agent/services/generation_handler/prompts/user_prompt.j2 +0 -0
  68. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/experimental/write_up_agent/services/generation_handler/service.py +0 -0
  69. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/experimental/write_up_agent/services/template_handler/__init__.py +0 -0
  70. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/experimental/write_up_agent/services/template_handler/default_template.j2 +0 -0
  71. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/experimental/write_up_agent/services/template_handler/exceptions.py +0 -0
  72. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/experimental/write_up_agent/services/template_handler/service.py +0 -0
  73. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/experimental/write_up_agent/services/template_handler/utils.py +0 -0
  74. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/experimental/write_up_agent/utils.py +0 -0
  75. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/feature_flags/schema.py +0 -0
  76. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/pydantic/rjsf_tags.py +0 -0
  77. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/pydantic_helpers.py +0 -0
  78. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/referencing.py +0 -0
  79. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/string_utilities.py +0 -0
  80. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/tests/test_referencing.py +0 -0
  81. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/tests/test_string_utilities.py +0 -0
  82. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/token/__init__.py +0 -0
  83. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/token/image_token_counting.py +0 -0
  84. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/token/token_counting.py +0 -0
  85. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/token/tokenizers/deepseek/tokenizer.json +0 -0
  86. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/token/tokenizers/qwen/tokenizer.json +0 -0
  87. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/utils/__init__.py +0 -0
  88. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/utils/files.py +0 -0
  89. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/utils/image/encode.py +0 -0
  90. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/utils/jinja/helpers.py +0 -0
  91. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/utils/jinja/render.py +0 -0
  92. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/utils/jinja/schema.py +0 -0
  93. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/utils/jinja/utils.py +0 -0
  94. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/utils/structured_output/__init__.py +0 -0
  95. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/utils/structured_output/schema.py +0 -0
  96. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/utils/write_configuration.py +0 -0
  97. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/validate_required_values.py +0 -0
  98. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/_common/validators.py +0 -0
  99. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/__init__.py +0 -0
  100. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/debug_info_manager/debug_info_manager.py +0 -0
  101. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/debug_info_manager/test/test_debug_info_manager.py +0 -0
  102. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/evaluation/config.py +0 -0
  103. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/evaluation/context_relevancy/prompts/__init__.py +0 -0
  104. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/evaluation/context_relevancy/prompts/system_prompt.j2 +0 -0
  105. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/evaluation/context_relevancy/prompts/user_prompt.j2 +0 -0
  106. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/evaluation/context_relevancy/schema.py +0 -0
  107. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/evaluation/context_relevancy/service.py +0 -0
  108. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/evaluation/exception.py +0 -0
  109. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/evaluation/hallucination/constants.py +0 -0
  110. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/evaluation/hallucination/hallucination_evaluation.py +0 -0
  111. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/evaluation/hallucination/prompts/__init__.py +0 -0
  112. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/evaluation/hallucination/prompts/system_prompt.j2 +0 -0
  113. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/evaluation/hallucination/prompts/user_prompt.j2 +0 -0
  114. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/evaluation/hallucination/service.py +0 -0
  115. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/evaluation/hallucination/utils.py +0 -0
  116. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/evaluation/output_parser.py +0 -0
  117. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/evaluation/schemas.py +0 -0
  118. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/evaluation/tests/fixtures.py +0 -0
  119. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/evaluation/tests/test_config.py +0 -0
  120. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/evaluation/tests/test_context_relevancy_service.py +0 -0
  121. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/evaluation/tests/test_hallucination_constants.py +0 -0
  122. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/evaluation/tests/test_output_parser.py +0 -0
  123. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/evaluation/tests/test_prompt_loaders.py +0 -0
  124. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/evaluation/utils.py +0 -0
  125. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/feature_flags/__init__.py +0 -0
  126. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/feature_flags/feature_flags.py +0 -0
  127. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/history_manager/history_manager.py +0 -0
  128. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/history_manager/loop_token_reducer.py +0 -0
  129. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/history_manager/utils.py +0 -0
  130. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/loop_runner/__init__.py +0 -0
  131. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/loop_runner/_iteration_handler_utils.py +0 -0
  132. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/loop_runner/_responses_iteration_handler_utils.py +0 -0
  133. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/loop_runner/_responses_stream_handler_utils.py +0 -0
  134. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/loop_runner/_stream_handler_utils.py +0 -0
  135. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/loop_runner/base.py +0 -0
  136. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/loop_runner/middleware/__init__.py +0 -0
  137. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/loop_runner/middleware/planning/__init__.py +0 -0
  138. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/loop_runner/middleware/planning/planning.py +0 -0
  139. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/loop_runner/middleware/planning/schema.py +0 -0
  140. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/loop_runner/runners/__init__.py +0 -0
  141. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/loop_runner/runners/basic.py +0 -0
  142. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/loop_runner/runners/mistral/__init__.py +0 -0
  143. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/loop_runner/runners/mistral/mistral_runner.py +0 -0
  144. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/loop_runner/runners/qwen/__init__.py +0 -0
  145. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/loop_runner/runners/qwen/helpers.py +0 -0
  146. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/loop_runner/runners/qwen/qwen_runner.py +0 -0
  147. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/message_log_manager/__init__.py +0 -0
  148. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/message_log_manager/service.py +0 -0
  149. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/reference_manager/reference_manager.py +0 -0
  150. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/responses_api/__init__.py +0 -0
  151. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/responses_api/postprocessors/code_display.py +0 -0
  152. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/responses_api/postprocessors/generated_files.py +0 -0
  153. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/responses_api/stream_handler.py +0 -0
  154. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/short_term_memory_manager/persistent_short_term_memory_manager.py +0 -0
  155. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/thinking_manager/thinking_manager.py +0 -0
  156. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/__init__.py +0 -0
  157. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/a2a/__init__.py +0 -0
  158. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/a2a/config.py +0 -0
  159. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/a2a/evaluation/__init__.py +0 -0
  160. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/a2a/evaluation/_utils.py +0 -0
  161. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/a2a/evaluation/config.py +0 -0
  162. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/a2a/evaluation/evaluator.py +0 -0
  163. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/a2a/evaluation/summarization_user_message.j2 +0 -0
  164. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/a2a/manager.py +0 -0
  165. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/a2a/postprocessing/__init__.py +0 -0
  166. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/a2a/postprocessing/_display_utils.py +0 -0
  167. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/a2a/postprocessing/_ref_utils.py +0 -0
  168. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/a2a/postprocessing/config.py +0 -0
  169. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/a2a/postprocessing/display.py +0 -0
  170. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/a2a/postprocessing/references.py +0 -0
  171. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/a2a/postprocessing/test/test_display.py +0 -0
  172. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/a2a/postprocessing/test/test_display_utils.py +0 -0
  173. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/a2a/postprocessing/test/test_ref_utils.py +0 -0
  174. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/a2a/prompts.py +0 -0
  175. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/a2a/response_watcher/__init__.py +0 -0
  176. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/a2a/response_watcher/service.py +0 -0
  177. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/a2a/tool/__init__.py +0 -0
  178. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/a2a/tool/_memory.py +0 -0
  179. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/a2a/tool/_schema.py +0 -0
  180. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/a2a/tool/config.py +0 -0
  181. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/a2a/tool/service.py +0 -0
  182. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/a2a/tool/test/test_service_utils.py +0 -0
  183. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/agent_chunks_hanlder.py +0 -0
  184. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/config.py +0 -0
  185. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/factory.py +0 -0
  186. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/mcp/__init__.py +0 -0
  187. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/mcp/manager.py +0 -0
  188. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/mcp/models.py +0 -0
  189. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/mcp/tool_wrapper.py +0 -0
  190. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/openai_builtin/__init__.py +0 -0
  191. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/openai_builtin/base.py +0 -0
  192. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/openai_builtin/code_interpreter/__init__.py +0 -0
  193. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/openai_builtin/code_interpreter/config.py +0 -0
  194. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/openai_builtin/code_interpreter/postprocessors/__init__.py +0 -0
  195. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/openai_builtin/code_interpreter/postprocessors/code_display.py +0 -0
  196. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/openai_builtin/code_interpreter/schemas.py +0 -0
  197. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/openai_builtin/code_interpreter/service.py +0 -0
  198. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/openai_builtin/manager.py +0 -0
  199. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/schemas.py +0 -0
  200. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/test/test_mcp_manager.py +0 -0
  201. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/test/test_tool_progress_reporter.py +0 -0
  202. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/tool.py +0 -0
  203. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/tool_progress_reporter.py +0 -0
  204. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/utils/__init__.py +0 -0
  205. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/utils/source_handling/__init__.py +0 -0
  206. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/utils/source_handling/schema.py +0 -0
  207. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/utils/source_handling/source_formatting.py +0 -0
  208. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic/tools/utils/source_handling/tests/test_source_formatting.py +0 -0
  209. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic_table/__init__.py +0 -0
  210. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic_table/schemas.py +0 -0
  211. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/agentic_table/service.py +0 -0
  212. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/app/__init__.py +0 -0
  213. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/app/dev_util.py +0 -0
  214. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/app/fast_api_factory.py +0 -0
  215. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/app/init_logging.py +0 -0
  216. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/app/init_sdk.py +0 -0
  217. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/app/performance/async_tasks.py +0 -0
  218. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/app/performance/async_wrapper.py +0 -0
  219. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/app/schemas.py +0 -0
  220. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/app/unique_settings.py +0 -0
  221. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/app/verification.py +0 -0
  222. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/app/webhook.py +0 -0
  223. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/chat/__init__.py +0 -0
  224. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/chat/cancellation.py +0 -0
  225. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/chat/constants.py +0 -0
  226. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/chat/deprecated/service.py +0 -0
  227. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/chat/functions.py +0 -0
  228. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/chat/rendering.py +0 -0
  229. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/chat/responses_api.py +0 -0
  230. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/chat/service.py +0 -0
  231. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/chat/state.py +0 -0
  232. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/chat/utils.py +0 -0
  233. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/content/__init__.py +0 -0
  234. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/content/constants.py +0 -0
  235. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/content/functions.py +0 -0
  236. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/content/service.py +0 -0
  237. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/content/smart_rules.py +0 -0
  238. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/content/utils.py +0 -0
  239. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/data_extraction/README.md +0 -0
  240. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/data_extraction/__init__.py +0 -0
  241. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/data_extraction/augmented/__init__.py +0 -0
  242. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/data_extraction/augmented/service.py +0 -0
  243. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/data_extraction/base.py +0 -0
  244. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/data_extraction/basic/__init__.py +0 -0
  245. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/data_extraction/basic/config.py +0 -0
  246. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/data_extraction/basic/prompt.py +0 -0
  247. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/data_extraction/basic/service.py +0 -0
  248. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/elicitation/__init__.py +0 -0
  249. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/elicitation/constants.py +0 -0
  250. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/elicitation/exceptions.py +0 -0
  251. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/elicitation/functions.py +0 -0
  252. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/elicitation/schemas.py +0 -0
  253. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/elicitation/service.py +0 -0
  254. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/embedding/__init__.py +0 -0
  255. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/embedding/constants.py +0 -0
  256. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/embedding/functions.py +0 -0
  257. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/embedding/schemas.py +0 -0
  258. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/embedding/service.py +0 -0
  259. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/embedding/utils.py +0 -0
  260. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/framework_utilities/__init__.py +0 -0
  261. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/framework_utilities/langchain/__init__.py +0 -0
  262. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/framework_utilities/langchain/client.py +0 -0
  263. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/framework_utilities/langchain/history.py +0 -0
  264. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/framework_utilities/openai/__init__.py +0 -0
  265. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/framework_utilities/openai/client.py +0 -0
  266. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/framework_utilities/openai/message_builder.py +0 -0
  267. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/framework_utilities/utils.py +0 -0
  268. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/language_model/_responses_api_utils.py +0 -0
  269. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/language_model/builder.py +0 -0
  270. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/language_model/constants.py +0 -0
  271. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/language_model/default_language_model.py +0 -0
  272. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/language_model/infos.py +0 -0
  273. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/language_model/prompt.py +0 -0
  274. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/language_model/reference.py +0 -0
  275. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/language_model/service.py +0 -0
  276. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/language_model/stream_transform.py +0 -0
  277. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/language_model/utils.py +0 -0
  278. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/protocols/support.py +0 -0
  279. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/services/__init__.py +0 -0
  280. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/services/knowledge_base.py +0 -0
  281. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/short_term_memory/__init__.py +0 -0
  282. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/short_term_memory/constants.py +0 -0
  283. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/short_term_memory/functions.py +0 -0
  284. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/short_term_memory/schemas.py +0 -0
  285. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/short_term_memory/service.py +0 -0
  286. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/smart_rules/__init__.py +0 -0
  287. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/unique_toolkit/smart_rules/compile.py +0 -0
  288. {unique_toolkit-1.57 → unique_toolkit-1.58.1}/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.57
3
+ Version: 1.58.1
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>
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "unique_toolkit"
3
- version = "1.57"
3
+ version = "1.58.1"
4
4
  description = ""
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12"
@@ -1,4 +1,5 @@
1
1
  import asyncio
2
+ import time
2
3
  from abc import ABC
3
4
  from logging import Logger
4
5
 
@@ -86,6 +87,7 @@ class EvaluationManager:
86
87
  self._chat_service = chat_service
87
88
  self._evaluations: dict[EvaluationMetricName, Evaluation] = {}
88
89
  self._evaluation_passed: bool = True
90
+ self._execution_times: dict[str, float] = {}
89
91
 
90
92
  def add_evaluation(self, evaluation: Evaluation):
91
93
  self._evaluations[evaluation.get_name()] = evaluation
@@ -99,6 +101,8 @@ class EvaluationManager:
99
101
  loop_response: LanguageModelStreamResponse,
100
102
  assistant_message_id: str,
101
103
  ) -> list[EvaluationMetricResult]:
104
+ self._execution_times = {}
105
+
102
106
  task_executor = SafeTaskExecutor(
103
107
  logger=self._logger,
104
108
  )
@@ -134,6 +138,9 @@ class EvaluationManager:
134
138
 
135
139
  return evaluation_results_unpacked
136
140
 
141
+ def get_execution_times(self) -> dict[str, float]:
142
+ return self._execution_times.copy()
143
+
137
144
  async def execute_evaluation_call(
138
145
  self,
139
146
  evaluation_name: EvaluationMetricName,
@@ -145,13 +152,16 @@ class EvaluationManager:
145
152
  evaluation_instance = self.get_evaluation_by_name(evaluation_name)
146
153
 
147
154
  if evaluation_instance:
148
- # Execute the evaluation
155
+ start = time.perf_counter()
149
156
  await self._create_assistant_message(
150
157
  evaluation_instance, assistant_message_id
151
158
  )
152
159
  evaluation_metric_result: EvaluationMetricResult = (
153
160
  await evaluation_instance.run(loop_response)
154
161
  )
162
+ self._execution_times[str(evaluation_name)] = round(
163
+ time.perf_counter() - start, 3
164
+ )
155
165
  return evaluation_metric_result
156
166
 
157
167
  return EvaluationMetricResult(
@@ -17,13 +17,13 @@ from unique_toolkit.agentic.evaluation.hallucination.utils import (
17
17
  context_text_from_stream_response,
18
18
  )
19
19
  from unique_toolkit.agentic.evaluation.schemas import EvaluationMetricInput
20
+ from unique_toolkit.chat.schemas import ChatMessage
20
21
  from unique_toolkit.content import ContentReference
21
22
  from unique_toolkit.content.schemas import ContentChunk
22
23
  from unique_toolkit.language_model.schemas import (
23
24
  LanguageModelMessageRole,
24
25
  LanguageModelMessages,
25
26
  LanguageModelStreamResponse,
26
- LanguageModelStreamResponseMessage,
27
27
  )
28
28
 
29
29
 
@@ -580,8 +580,9 @@ def test_context_text_from_stream_response__extracts_context__using_from_ids_mod
580
580
  """
581
581
  # Arrange
582
582
  response: LanguageModelStreamResponse = LanguageModelStreamResponse(
583
- message=LanguageModelStreamResponseMessage(
583
+ message=ChatMessage(
584
584
  id="msg_1",
585
+ chat_id="",
585
586
  previous_message_id=None,
586
587
  role=LanguageModelMessageRole.ASSISTANT,
587
588
  text="Test",
@@ -612,8 +613,9 @@ def test_context_text_from_stream_response__extracts_context__using_from_order_m
612
613
  """
613
614
  # Arrange
614
615
  response: LanguageModelStreamResponse = LanguageModelStreamResponse(
615
- message=LanguageModelStreamResponseMessage(
616
+ message=ChatMessage(
616
617
  id="msg_1",
618
+ chat_id="",
617
619
  previous_message_id=None,
618
620
  role=LanguageModelMessageRole.ASSISTANT,
619
621
  text="Test",
@@ -653,8 +655,9 @@ def test_context_text_from_stream_response__extracts_context__using_from_origina
653
655
  )
654
656
  ]
655
657
  response: LanguageModelStreamResponse = LanguageModelStreamResponse(
656
- message=LanguageModelStreamResponseMessage(
658
+ message=ChatMessage(
657
659
  id="msg_1",
660
+ chat_id="",
658
661
  previous_message_id=None,
659
662
  role=LanguageModelMessageRole.ASSISTANT,
660
663
  text="Test",
@@ -690,8 +693,9 @@ def test_context_text_from_stream_response__falls_back_to_default__with_invalid_
690
693
  """
691
694
  # Arrange
692
695
  response: LanguageModelStreamResponse = LanguageModelStreamResponse(
693
- message=LanguageModelStreamResponseMessage(
696
+ message=ChatMessage(
694
697
  id="msg_1",
698
+ chat_id="",
695
699
  previous_message_id=None,
696
700
  role=LanguageModelMessageRole.ASSISTANT,
697
701
  text="Test",
@@ -731,8 +735,9 @@ def test_context_text_from_stream_response__falls_back_to_default__on_extraction
731
735
  )
732
736
  ]
733
737
  response: LanguageModelStreamResponse = LanguageModelStreamResponse(
734
- message=LanguageModelStreamResponseMessage(
738
+ message=ChatMessage(
735
739
  id="msg_1",
740
+ chat_id="",
736
741
  previous_message_id=None,
737
742
  role=LanguageModelMessageRole.ASSISTANT,
738
743
  text="Test",
@@ -763,8 +768,9 @@ def test_context_text_from_stream_response__returns_text_strings__not_chunk_obje
763
768
  """
764
769
  # Arrange
765
770
  response: LanguageModelStreamResponse = LanguageModelStreamResponse(
766
- message=LanguageModelStreamResponseMessage(
771
+ message=ChatMessage(
767
772
  id="msg_1",
773
+ chat_id="",
768
774
  previous_message_id=None,
769
775
  role=LanguageModelMessageRole.ASSISTANT,
770
776
  text="Test",
@@ -173,12 +173,12 @@ def get_full_history_with_contents(
173
173
 
174
174
  builder = LanguageModelMessages([]).builder()
175
175
  for c in grouped_elements:
176
- # LanguageModelUserMessage has not field original content
177
- text = c.original_content if c.original_content else c.content
176
+ # LanguageModelUserMessage has not field original_text
177
+ text = c.original_text if c.original_text else c.content
178
178
  if text is None:
179
179
  if c.role == ChatRole.USER:
180
180
  raise ValueError(
181
- "Content or original_content of LanguageModelMessages should exist.",
181
+ "Content or original_text of LanguageModelMessages should exist.",
182
182
  )
183
183
  text = ""
184
184
 
@@ -1,4 +1,5 @@
1
1
  import asyncio
2
+ import time
2
3
  from abc import ABC
3
4
  from logging import Logger
4
5
 
@@ -84,6 +85,7 @@ class PostprocessorManager:
84
85
  self._logger = logger
85
86
  self._chat_service = chat_service
86
87
  self._postprocessors: list[Postprocessor | ResponsesApiPostprocessor] = []
88
+ self._execution_times: dict[str, float] = {}
87
89
 
88
90
  # Allow to add postprocessors that should be run before or after the others.
89
91
  self._first_postprocessor: Postprocessor | ResponsesApiPostprocessor | None = (
@@ -123,6 +125,8 @@ class PostprocessorManager:
123
125
  self,
124
126
  loop_response: LanguageModelStreamResponse,
125
127
  ) -> None:
128
+ self._execution_times = {}
129
+
126
130
  task_executor = SafeTaskExecutor(
127
131
  logger=self._logger,
128
132
  )
@@ -158,12 +162,19 @@ class PostprocessorManager:
158
162
  references=loop_response.message.references,
159
163
  )
160
164
 
165
+ def get_execution_times(self) -> dict[str, float]:
166
+ return self._execution_times.copy()
167
+
161
168
  async def execute_postprocessors(
162
169
  self,
163
170
  loop_response: LanguageModelStreamResponse,
164
171
  postprocessor_instance: Postprocessor | ResponsesApiPostprocessor,
165
172
  ) -> None:
173
+ start = time.perf_counter()
166
174
  await postprocessor_instance.run(loop_response) # type: ignore
175
+ self._execution_times[postprocessor_instance.name] = round(
176
+ time.perf_counter() - start, 3
177
+ )
167
178
 
168
179
  async def remove_from_text(
169
180
  self,
@@ -495,10 +495,25 @@ def _build_code_blocks(
495
495
  For each file, the LAST code block that references its path is treated as the
496
496
  producer — this handles the case where a file is overwritten across blocks, where
497
497
  the final content belongs to the last writer.
498
+
499
+ Three matching tiers are used in priority order:
500
+ 1. Primary: literal path ``/mnt/data/{filename}`` appears in the code.
501
+ 2. Secondary: the filename (with or without extension) appears as a quoted
502
+ string literal — last-writer-wins among blocks (same as primary), but
503
+ never overrides a primary match. Covers helper patterns such as:
504
+ - stem only: ``save_fig(fig, "nvda_price_sma")``
505
+ - full name: ``make_chart(kind, "random_line_chart.png", 42)``
506
+ 3. Last-resort: assign remaining unmatched files to the last code block —
507
+ covers fully dynamic names built via f-strings or variable concatenation,
508
+ e.g. ``f"/mnt/data/chart_{chart_type}_{i}.png"``, where no static token
509
+ in the source matches the actual filename.
510
+ Primary matches always take precedence over secondary ones; secondary always
511
+ takes precedence over the last-resort fallback.
498
512
  """
499
513
  calls = loop_response.code_interpreter_calls
500
514
 
501
- # Step 1: for each file, find the index of the last block that references it.
515
+ # Step 1a: primary matching — full literal path /mnt/data/{filename} in code.
516
+ # Last-writer-wins: later blocks overwrite earlier ones for the same file.
502
517
  file_to_block_idx: dict[str, int] = {}
503
518
  for idx, call in enumerate(calls):
504
519
  if not call.code:
@@ -510,6 +525,62 @@ def _build_code_blocks(
510
525
  ):
511
526
  file_to_block_idx[annotation.filename] = idx
512
527
 
528
+ # Snapshot primary matches only — secondary must not override these, but within
529
+ # secondary we use last-writer-wins (later blocks overwrite earlier), same as 1a.
530
+ primary_matched_filenames = set(file_to_block_idx.keys())
531
+
532
+ # Step 1b: secondary matching for files not matched by primary.
533
+ # Handles two common helper-function patterns where the full /mnt/data/ path
534
+ # is never a literal string in the code:
535
+ #
536
+ # Pattern A — stem only (no extension at the call site):
537
+ # save_fig(fig, "nvda_price_sma") → f"/mnt/data/{name}.png" at runtime
538
+ # → matches quoted stem "nvda_price_sma"
539
+ #
540
+ # Pattern B — full filename at the call site:
541
+ # make_chart(kind, "random_line_chart.png", 42)
542
+ # fig.savefig(os.path.join(output_dir, filename), ...)
543
+ # → matches quoted full filename "random_line_chart.png"
544
+ #
545
+ # Last-writer-wins within secondary: do not skip when a prior block already matched
546
+ # via secondary — only skip filenames that matched in Step 1a (primary).
547
+ for idx, call in enumerate(calls):
548
+ if not call.code:
549
+ continue
550
+ for annotation in loop_response.container_files:
551
+ if annotation.filename in primary_matched_filenames:
552
+ continue
553
+ if content_map.get(annotation.filename) is None:
554
+ continue
555
+ fname = annotation.filename
556
+ stem = fname.rsplit(".", 1)[0]
557
+ quoted_fname = f'"{fname}"' in call.code or f"'{fname}'" in call.code
558
+ quoted_stem = bool(stem) and (
559
+ f'"{stem}"' in call.code or f"'{stem}'" in call.code
560
+ )
561
+ if quoted_fname or quoted_stem:
562
+ file_to_block_idx[annotation.filename] = idx
563
+
564
+ # Step 1c: last-resort fallback for files still unmatched after primary and secondary.
565
+ # Covers Pattern C: filenames assembled entirely at runtime via f-strings or
566
+ # variable concatenation, e.g. f"/mnt/data/chart_{chart_type}_{i}.png", where
567
+ # no static string token in the code corresponds to the actual filename.
568
+ # The last code block is used as the owner; when there is only one block this is
569
+ # always correct. For multi-block responses it is a best-effort heuristic: the
570
+ # worst outcome is the fence shows code from the wrong block, which is still
571
+ # better than leaving the file as a bare inline image with no fence at all.
572
+ last_block_idx: int | None = None
573
+ for idx, call in enumerate(calls):
574
+ if call.code:
575
+ last_block_idx = idx
576
+ if last_block_idx is not None:
577
+ for annotation in loop_response.container_files:
578
+ if annotation.filename in file_to_block_idx:
579
+ continue
580
+ if content_map.get(annotation.filename) is None:
581
+ continue
582
+ file_to_block_idx[annotation.filename] = last_block_idx
583
+
513
584
  # Step 2: group files by their owning block index, deduplicating by filename.
514
585
  # OpenAI may emit multiple annotations for the same filename when a file is
515
586
  # overwritten across executions. Using a dict keyed by filename ensures each
@@ -1,4 +1,5 @@
1
1
  import asyncio
2
+ import time
2
3
  from logging import Logger, getLogger
3
4
  from typing import Generic, Literal, TypeVar, overload
4
5
 
@@ -288,10 +289,16 @@ class _ToolManager(Generic[_ApiMode]):
288
289
  raise ValueError(f"Tool {tool_call.name} cannot be run")
289
290
 
290
291
  if tool_instance:
291
- # Execute the tool
292
+ tool_start = time.perf_counter()
292
293
  tool_response: ToolCallResponse = await tool_instance.run(
293
294
  tool_call=tool_call
294
295
  )
296
+ tool_execution_time = round(time.perf_counter() - tool_start, 3)
297
+
298
+ if tool_response.debug_info is None:
299
+ tool_response.debug_info = {}
300
+ tool_response.debug_info["execution_time_s"] = tool_execution_time
301
+
295
302
  evaluation_checks = tool_instance.evaluation_check_list()
296
303
  self._tool_evaluation_check_list.update(evaluation_checks)
297
304
 
@@ -66,26 +66,67 @@ class ToolCall(BaseModel):
66
66
  )
67
67
 
68
68
 
69
+ class ChatMessageAssessmentStatus(StrEnum):
70
+ PENDING = "PENDING"
71
+ DONE = "DONE"
72
+ ERROR = "ERROR"
73
+
74
+
75
+ class ChatMessageAssessmentLabel(StrEnum):
76
+ RED = "RED"
77
+ YELLOW = "YELLOW"
78
+ GREEN = "GREEN"
79
+
80
+
81
+ class ChatMessageAssessmentType(StrEnum):
82
+ HALLUCINATION = "HALLUCINATION"
83
+ COMPLIANCE = "COMPLIANCE"
84
+
85
+
86
+ class ChatMessageAssessment(BaseModel):
87
+ model_config = model_config
88
+
89
+ id: str
90
+ object: str
91
+ message_id: str
92
+ status: ChatMessageAssessmentStatus
93
+ type: ChatMessageAssessmentType
94
+ title: str | None = None
95
+ explanation: str | None = None
96
+ label: ChatMessageAssessmentLabel | None = None
97
+ is_visible: bool
98
+ created_at: datetime | None = None
99
+ updated_at: datetime | None = None
100
+
101
+
69
102
  class ChatMessage(BaseModel):
70
- # TODO: The below seems not to be True anymore @irina-unique. To be checked in separate PR
71
- # This model should strictly meets https://github.com/Unique-AG/monorepo/blob/master/node/apps/node-chat/src/public-api/2023-12-06/dtos/message/public-message.dto.ts
103
+ # This model maps to PublicMessageDto from the backend public API:
104
+ # next/services/node-chat/src/public-api/2023-12-06/dtos/message/public-message.dto.ts
105
+ # Fields previous_message_id, tool_calls, tool_call_id are internal extensions not in the DTO.
72
106
  model_config = model_config
73
107
 
74
108
  id: str | None = None
75
109
  chat_id: str
76
110
  object: str | None = None
111
+ # alias="text" applies only to construction (model_validate / __init__).
112
+ # model_dump() uses the field name "content", not "text". Use model_dump(by_alias=True)
113
+ # to get "text" as the key, or access via the .text property.
77
114
  content: str | None = Field(default=None, alias="text")
78
- original_content: str | None = Field(default=None, alias="originalText")
115
+ original_text: str | None = None
79
116
  role: ChatMessageRole
117
+ previous_message_id: str | None = None
80
118
  gpt_request: list[dict] | None = None
81
119
  tool_calls: list[ToolCall] | None = None
82
120
  tool_call_id: str | None = None
83
121
  debug_info: dict | None = {}
84
122
  created_at: datetime | None = None
85
123
  completed_at: datetime | None = None
124
+ started_streaming_at: datetime | None = None
125
+ stopped_streaming_at: datetime | None = None
86
126
  user_aborted_at: datetime | None = None
87
127
  updated_at: datetime | None = None
88
- references: list[ContentReference] | None = None
128
+ references: list[ContentReference] | None = []
129
+ assessment: list[ChatMessageAssessment] | None = None
89
130
 
90
131
  # TODO make sdk return role consistently in lowercase
91
132
  # Currently needed as sdk returns role in uppercase
@@ -93,6 +134,14 @@ class ChatMessage(BaseModel):
93
134
  def set_role(cls, value: str):
94
135
  return value.lower()
95
136
 
137
+ @property
138
+ def text(self) -> str | None:
139
+ return self.content
140
+
141
+ @text.setter
142
+ def text(self, value: str | None) -> None:
143
+ self.content = value
144
+
96
145
  # Ensure tool_call_ids is required if role is 'tool'
97
146
  @model_validator(mode="after")
98
147
  def check_tool_call_ids_for_tool_role(self):
@@ -133,39 +182,6 @@ class ChatMessage(BaseModel):
133
182
  raise NotImplementedError
134
183
 
135
184
 
136
- class ChatMessageAssessmentStatus(StrEnum):
137
- PENDING = "PENDING"
138
- DONE = "DONE"
139
- ERROR = "ERROR"
140
-
141
-
142
- class ChatMessageAssessmentLabel(StrEnum):
143
- RED = "RED"
144
- YELLOW = "YELLOW"
145
- GREEN = "GREEN"
146
-
147
-
148
- class ChatMessageAssessmentType(StrEnum):
149
- HALLUCINATION = "HALLUCINATION"
150
- COMPLIANCE = "COMPLIANCE"
151
-
152
-
153
- class ChatMessageAssessment(BaseModel):
154
- model_config = model_config
155
-
156
- id: str
157
- object: str
158
- message_id: str
159
- status: ChatMessageAssessmentStatus
160
- type: ChatMessageAssessmentType
161
- title: str | None = None
162
- explanation: str | None = None
163
- label: ChatMessageAssessmentLabel | None = None
164
- is_visible: bool
165
- created_at: datetime | None = None
166
- updated_at: datetime | None = None
167
-
168
-
169
185
  class MessageLogStatus(StrEnum):
170
186
  RUNNING = "RUNNING"
171
187
  COMPLETED = "COMPLETED"
@@ -117,7 +117,7 @@ class ContentReference(BaseModel):
117
117
  url: str
118
118
  original_index: list[int] = Field(
119
119
  default=[],
120
- description="List of indices in the ChatMessage original_content this reference refers to. This is usually the id in the functionCallResponse. List type due to implementation in node-chat",
120
+ description="List of indices in the ChatMessage original_text this reference refers to. This is usually the id in the functionCallResponse. List type due to implementation in node-chat",
121
121
  )
122
122
 
123
123
  @classmethod
@@ -20,6 +20,7 @@ from .schemas import (
20
20
  LanguageModelStreamResponseMessage,
21
21
  LanguageModelSystemMessage,
22
22
  LanguageModelTokenLimits,
23
+ LanguageModelTokenUsage,
23
24
  LanguageModelTool,
24
25
  LanguageModelToolDescription,
25
26
  LanguageModelToolMessage,
@@ -57,6 +58,7 @@ __all__ = [
57
58
  "LanguageModelStreamResponseMessage",
58
59
  "LanguageModelSystemMessage",
59
60
  "LanguageModelTokenLimits",
61
+ "LanguageModelTokenUsage",
60
62
  "LanguageModelTool",
61
63
  "LanguageModelToolDescription",
62
64
  "LanguageModelToolMessage",
@@ -30,7 +30,6 @@ from unique_toolkit.language_model.schemas import (
30
30
  LanguageModelMessages,
31
31
  LanguageModelResponse,
32
32
  LanguageModelStreamResponse,
33
- LanguageModelStreamResponseMessage,
34
33
  LanguageModelTool,
35
34
  LanguageModelToolDescription,
36
35
  )
@@ -528,12 +527,13 @@ def _create_language_model_stream_response_with_references(
528
527
  search_context=content_chunks,
529
528
  )
530
529
 
531
- stream_response_message = LanguageModelStreamResponseMessage(
530
+ stream_response_message = ChatMessage(
532
531
  id="stream_unknown",
533
532
  previous_message_id=None,
534
533
  role=LanguageModelMessageRole.ASSISTANT,
535
534
  text=message.content or "",
536
535
  original_text=content,
536
+ chat_id="stream_unknown",
537
537
  references=[
538
538
  ContentReference(**u.model_dump()) for u in message.references or []
539
539
  ],
@@ -657,8 +657,9 @@ async def stream_complete_with_references_openai(
657
657
  ]
658
658
 
659
659
  return LanguageModelStreamResponse(
660
- message=LanguageModelStreamResponseMessage(
660
+ message=ChatMessage(
661
661
  id=message_id or uuid4().hex,
662
+ chat_id="",
662
663
  previous_message_id=None,
663
664
  role=LanguageModelMessageRole.ASSISTANT,
664
665
  text=text_,
@@ -1,6 +1,5 @@
1
1
  import json
2
2
  import math
3
- from enum import StrEnum
4
3
  from typing import Any, Literal, Self, TypeVar
5
4
  from uuid import uuid4
6
5
 
@@ -40,7 +39,8 @@ from pydantic import (
40
39
  )
41
40
  from typing_extensions import deprecated, overload
42
41
 
43
- from unique_toolkit.content.schemas import ContentReference
42
+ from unique_toolkit.chat.schemas import ChatMessage
43
+ from unique_toolkit.chat.schemas import ChatMessageRole as LanguageModelMessageRole
44
44
  from unique_toolkit.language_model._responses_api_utils import (
45
45
  convert_user_message_content_to_responses_api,
46
46
  )
@@ -54,33 +54,14 @@ model_config = ConfigDict(
54
54
  )
55
55
 
56
56
 
57
- # Equivalent to
58
- # from openai.types.chat.chat_completion_role import ChatCompletionRole
59
- class LanguageModelMessageRole(StrEnum):
60
- USER = "user"
61
- SYSTEM = "system"
62
- ASSISTANT = "assistant"
63
- TOOL = "tool"
64
-
65
-
66
- # This is tailored to the unique backend
67
- class LanguageModelStreamResponseMessage(BaseModel):
68
- model_config = model_config
69
-
70
- id: str
71
- previous_message_id: (
72
- str | None
73
- ) # Stream response can return a null previous_message_id if an assisstant message is manually added
74
- role: LanguageModelMessageRole
75
- text: str
76
- original_text: str | None = None
77
- references: list[ContentReference] = []
78
-
79
- # TODO make sdk return role in lowercase
80
- # Currently needed as sdk returns role in uppercase
81
- @field_validator("role", mode="before")
82
- def set_role(cls, value: str):
83
- return value.lower()
57
+ # Backward compatibility alias — use ChatMessage directly.
58
+ # LanguageModelStreamResponseMessage was a toolkit-only subclass with stricter types
59
+ # (required id/content, non-null references). The backend DTOs (PublicMessageDto,
60
+ # PublicStreamResultDto) use a single message type, so this distinction was unnecessary.
61
+ # Note: id and content are now optional (str | None) instead of required (str). This is a
62
+ # deliberate contract relaxation — the backend always returns non-null values in stream
63
+ # responses, but callers that relied on the stricter types should add explicit null checks.
64
+ LanguageModelStreamResponseMessage = ChatMessage
84
65
 
85
66
 
86
67
  class LanguageModelFunction(BaseModel):
@@ -163,12 +144,21 @@ class LanguageModelFunction(BaseModel):
163
144
  )
164
145
 
165
146
 
147
+ class LanguageModelTokenUsage(BaseModel):
148
+ model_config = model_config
149
+
150
+ completion_tokens: int | None = None
151
+ prompt_tokens: int | None = None
152
+ total_tokens: int | None = None
153
+
154
+
166
155
  class LanguageModelStreamResponse(BaseModel):
167
156
  model_config = model_config
168
157
 
169
- message: LanguageModelStreamResponseMessage
158
+ message: ChatMessage
170
159
  tool_calls: list[LanguageModelFunction] | None = None
171
160
  stopped_by_user: bool = False
161
+ usage: LanguageModelTokenUsage | None = None
172
162
 
173
163
  def is_empty(self) -> bool:
174
164
  """
@@ -140,6 +140,50 @@ class ChatService(ChatServiceDeprecated):
140
140
 
141
141
  return self._elicitation_service
142
142
 
143
+ def get_debug_info(self) -> dict[str, Any]:
144
+ """Retrieves the debug information from the current user message.
145
+
146
+ Returns:
147
+ dict[str, Any]: The debug information stored on the user message,
148
+ or an empty dict if retrieval fails or no debug info exists.
149
+
150
+ """
151
+ try:
152
+ raw_msg = unique_sdk.Message.retrieve(
153
+ user_id=self._user_id,
154
+ company_id=self._company_id,
155
+ id=self._user_message_id,
156
+ chatId=self._chat_id,
157
+ )
158
+ return getattr(raw_msg, "debugInfo", {}) or {}
159
+ except Exception:
160
+ logging.getLogger(__name__).warning(
161
+ "Failed to retrieve debug info from user message", exc_info=True
162
+ )
163
+ return {}
164
+
165
+ async def get_debug_info_async(self) -> dict[str, Any]:
166
+ """Retrieves the debug information from the current user message asynchronously.
167
+
168
+ Returns:
169
+ dict[str, Any]: The debug information stored on the user message,
170
+ or an empty dict if retrieval fails or no debug info exists.
171
+
172
+ """
173
+ try:
174
+ raw_msg = await unique_sdk.Message.retrieve_async(
175
+ user_id=self._user_id,
176
+ company_id=self._company_id,
177
+ id=self._user_message_id,
178
+ chatId=self._chat_id,
179
+ )
180
+ return getattr(raw_msg, "debugInfo", {}) or {}
181
+ except Exception:
182
+ logging.getLogger(__name__).warning(
183
+ "Failed to retrieve debug info from user message", exc_info=True
184
+ )
185
+ return {}
186
+
143
187
  async def update_debug_info_async(self, debug_info: dict):
144
188
  """Updates the debug information for the chat session.
145
189
 
File without changes