unique_toolkit 1.31.1__py3-none-any.whl → 1.32.0__py3-none-any.whl

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.
@@ -5,6 +5,7 @@ import re
5
5
  import pytest
6
6
 
7
7
  from unique_toolkit.agentic.tools.a2a.postprocessing._display_utils import (
8
+ SubAgentAnswerPart,
8
9
  _add_line_break,
9
10
  _get_display_removal_re,
10
11
  _get_display_template,
@@ -16,6 +17,7 @@ from unique_toolkit.agentic.tools.a2a.postprocessing._display_utils import (
16
17
  _wrap_with_details_tag,
17
18
  _wrap_with_quote_border,
18
19
  get_sub_agent_answer_display,
20
+ get_sub_agent_answer_from_parts,
19
21
  get_sub_agent_answer_parts,
20
22
  remove_sub_agent_answer_from_text,
21
23
  )
@@ -1721,3 +1723,381 @@ def test_get_sub_agent_answer_parts__works_with_details_modes__extracts_normally
1721
1723
  # Assert
1722
1724
  assert len(result) == 1
1723
1725
  assert result[0].matching_text == "SUCCESS"
1726
+
1727
+
1728
+ # Test get_sub_agent_answer_from_parts
1729
+
1730
+
1731
+ @pytest.mark.ai
1732
+ def test_get_sub_agent_answer_from_parts__returns_empty__with_empty_list() -> None:
1733
+ """
1734
+ Purpose: Verify empty or minimal output when no answer parts provided.
1735
+ Why this matters: Handles edge case of no extracted content.
1736
+ Setup summary: Provide empty list, assert minimal rendered output.
1737
+ """
1738
+ # Arrange
1739
+ answer_parts: list[SubAgentAnswerPart] = []
1740
+ config = SubAgentDisplayConfig(
1741
+ mode=SubAgentResponseDisplayMode.PLAIN,
1742
+ )
1743
+
1744
+ # Act
1745
+ result = get_sub_agent_answer_from_parts(
1746
+ answer_parts=answer_parts,
1747
+ config=config,
1748
+ )
1749
+
1750
+ # Assert
1751
+ assert result == ""
1752
+
1753
+
1754
+ @pytest.mark.ai
1755
+ def test_get_sub_agent_answer_from_parts__renders_single_part__with_default_template() -> (
1756
+ None
1757
+ ):
1758
+ """
1759
+ Purpose: Verify single answer part is rendered using default template.
1760
+ Why this matters: Core functionality for single substring display.
1761
+ Setup summary: Provide single part with default template, assert rendered text.
1762
+ """
1763
+ # Arrange
1764
+ answer_parts = [
1765
+ SubAgentAnswerPart(matching_text="42", formatted_text="The answer is 42"),
1766
+ ]
1767
+ config = SubAgentDisplayConfig(
1768
+ mode=SubAgentResponseDisplayMode.PLAIN,
1769
+ )
1770
+
1771
+ # Act
1772
+ result = get_sub_agent_answer_from_parts(
1773
+ answer_parts=answer_parts,
1774
+ config=config,
1775
+ )
1776
+
1777
+ # Assert
1778
+ assert "The answer is 42" in result
1779
+
1780
+
1781
+ @pytest.mark.ai
1782
+ def test_get_sub_agent_answer_from_parts__renders_multiple_parts__with_default_template() -> (
1783
+ None
1784
+ ):
1785
+ """
1786
+ Purpose: Verify multiple answer parts are rendered with default template.
1787
+ Why this matters: Supports displaying multiple extracted substrings.
1788
+ Setup summary: Provide multiple parts, assert all rendered in output.
1789
+ """
1790
+ # Arrange
1791
+ answer_parts = [
1792
+ SubAgentAnswerPart(
1793
+ matching_text="john@example.com", formatted_text="Email: john@example.com"
1794
+ ),
1795
+ SubAgentAnswerPart(matching_text="555-1234", formatted_text="Phone: 555-1234"),
1796
+ SubAgentAnswerPart(matching_text="John Doe", formatted_text="Name: John Doe"),
1797
+ ]
1798
+ config = SubAgentDisplayConfig(
1799
+ mode=SubAgentResponseDisplayMode.PLAIN,
1800
+ )
1801
+
1802
+ # Act
1803
+ result = get_sub_agent_answer_from_parts(
1804
+ answer_parts=answer_parts,
1805
+ config=config,
1806
+ )
1807
+
1808
+ # Assert
1809
+ assert "Email: john@example.com" in result
1810
+ assert "Phone: 555-1234" in result
1811
+ assert "Name: John Doe" in result
1812
+
1813
+
1814
+ @pytest.mark.ai
1815
+ def test_get_sub_agent_answer_from_parts__uses_formatted_text__not_matching_text() -> (
1816
+ None
1817
+ ):
1818
+ """
1819
+ Purpose: Verify function uses formatted_text from parts, not matching_text.
1820
+ Why this matters: Formatted text includes display template application.
1821
+ Setup summary: Provide parts with different matching vs formatted text, assert formatted used.
1822
+ """
1823
+ # Arrange
1824
+ answer_parts = [
1825
+ SubAgentAnswerPart(matching_text="72", formatted_text="Temperature: 72°F"),
1826
+ ]
1827
+ config = SubAgentDisplayConfig(
1828
+ mode=SubAgentResponseDisplayMode.PLAIN,
1829
+ )
1830
+
1831
+ # Act
1832
+ result = get_sub_agent_answer_from_parts(
1833
+ answer_parts=answer_parts,
1834
+ config=config,
1835
+ )
1836
+
1837
+ # Assert
1838
+ assert "Temperature: 72°F" in result
1839
+ assert result.count("72") == 1 # Only formatted version, not raw matching_text
1840
+
1841
+
1842
+ @pytest.mark.ai
1843
+ def test_get_sub_agent_answer_from_parts__renders_with_custom_template__single_part() -> (
1844
+ None
1845
+ ):
1846
+ """
1847
+ Purpose: Verify custom Jinja template is applied correctly for single part.
1848
+ Why this matters: Supports custom formatting via configuration.
1849
+ Setup summary: Provide custom template with HTML, assert custom rendering.
1850
+ """
1851
+ # Arrange
1852
+ answer_parts = [
1853
+ SubAgentAnswerPart(matching_text="Success", formatted_text="Status: Success"),
1854
+ ]
1855
+ custom_template = "<div class='result'>{{ substrings[0] }}</div>"
1856
+ config = SubAgentDisplayConfig(
1857
+ mode=SubAgentResponseDisplayMode.PLAIN,
1858
+ answer_substrings_jinja_template=custom_template,
1859
+ )
1860
+
1861
+ # Act
1862
+ result = get_sub_agent_answer_from_parts(
1863
+ answer_parts=answer_parts,
1864
+ config=config,
1865
+ )
1866
+
1867
+ # Assert
1868
+ assert result == "<div class='result'>Status: Success</div>"
1869
+
1870
+
1871
+ @pytest.mark.ai
1872
+ def test_get_sub_agent_answer_from_parts__renders_with_custom_template__multiple_parts() -> (
1873
+ None
1874
+ ):
1875
+ """
1876
+ Purpose: Verify custom template works with multiple parts and loop constructs.
1877
+ Why this matters: Supports complex formatting with iteration.
1878
+ Setup summary: Provide custom template with for loop, assert all parts rendered.
1879
+ """
1880
+ # Arrange
1881
+ answer_parts = [
1882
+ SubAgentAnswerPart(matching_text="Item1", formatted_text="- Item 1"),
1883
+ SubAgentAnswerPart(matching_text="Item2", formatted_text="- Item 2"),
1884
+ SubAgentAnswerPart(matching_text="Item3", formatted_text="- Item 3"),
1885
+ ]
1886
+ custom_template = """
1887
+ <ul>
1888
+ {% for substring in substrings %}
1889
+ <li>{{ substring }}</li>
1890
+ {% endfor %}
1891
+ </ul>
1892
+ """.strip()
1893
+ config = SubAgentDisplayConfig(
1894
+ mode=SubAgentResponseDisplayMode.PLAIN,
1895
+ answer_substrings_jinja_template=custom_template,
1896
+ )
1897
+
1898
+ # Act
1899
+ result = get_sub_agent_answer_from_parts(
1900
+ answer_parts=answer_parts,
1901
+ config=config,
1902
+ )
1903
+
1904
+ # Assert
1905
+ assert "<ul>" in result
1906
+ assert "</ul>" in result
1907
+ assert "<li>- Item 1</li>" in result
1908
+ assert "<li>- Item 2</li>" in result
1909
+ assert "<li>- Item 3</li>" in result
1910
+
1911
+
1912
+ @pytest.mark.ai
1913
+ def test_get_sub_agent_answer_from_parts__preserves_order__of_parts() -> None:
1914
+ """
1915
+ Purpose: Verify parts are rendered in the order they appear in the list.
1916
+ Why this matters: Predictable output order based on input order.
1917
+ Setup summary: Provide parts in specific order, assert same order in output.
1918
+ """
1919
+ # Arrange
1920
+ answer_parts = [
1921
+ SubAgentAnswerPart(matching_text="First", formatted_text="1. First"),
1922
+ SubAgentAnswerPart(matching_text="Second", formatted_text="2. Second"),
1923
+ SubAgentAnswerPart(matching_text="Third", formatted_text="3. Third"),
1924
+ ]
1925
+ config = SubAgentDisplayConfig(
1926
+ mode=SubAgentResponseDisplayMode.PLAIN,
1927
+ )
1928
+
1929
+ # Act
1930
+ result = get_sub_agent_answer_from_parts(
1931
+ answer_parts=answer_parts,
1932
+ config=config,
1933
+ )
1934
+
1935
+ # Assert
1936
+ # Check order by finding positions
1937
+ pos_first = result.find("1. First")
1938
+ pos_second = result.find("2. Second")
1939
+ pos_third = result.find("3. Third")
1940
+ assert pos_first < pos_second < pos_third
1941
+
1942
+
1943
+ @pytest.mark.ai
1944
+ def test_get_sub_agent_answer_from_parts__handles_special_chars__in_formatted_text() -> (
1945
+ None
1946
+ ):
1947
+ """
1948
+ Purpose: Verify formatted text with special characters renders correctly.
1949
+ Why this matters: Answers may contain HTML entities or special symbols.
1950
+ Setup summary: Provide parts with special chars, assert rendered as-is.
1951
+ """
1952
+ # Arrange
1953
+ answer_parts = [
1954
+ SubAgentAnswerPart(
1955
+ matching_text="test",
1956
+ formatted_text="Result: <tag> & 'quotes' & \"double\" & 50% & $100",
1957
+ ),
1958
+ ]
1959
+ config = SubAgentDisplayConfig(
1960
+ mode=SubAgentResponseDisplayMode.PLAIN,
1961
+ )
1962
+
1963
+ # Act
1964
+ result = get_sub_agent_answer_from_parts(
1965
+ answer_parts=answer_parts,
1966
+ config=config,
1967
+ )
1968
+
1969
+ # Assert
1970
+ # Jinja2 default behavior does not escape, so special chars should be preserved
1971
+ assert "<tag>" in result
1972
+ assert "&" in result
1973
+ assert "'" in result
1974
+ assert '"' in result
1975
+ assert "%" in result
1976
+ assert "$" in result
1977
+
1978
+
1979
+ @pytest.mark.ai
1980
+ def test_get_sub_agent_answer_from_parts__handles_multiline_formatted_text() -> None:
1981
+ """
1982
+ Purpose: Verify formatted text with newlines renders correctly.
1983
+ Why this matters: Formatted content may span multiple lines.
1984
+ Setup summary: Provide parts with newlines, assert multiline output.
1985
+ """
1986
+ # Arrange
1987
+ answer_parts = [
1988
+ SubAgentAnswerPart(
1989
+ matching_text="multiline",
1990
+ formatted_text="Line 1\nLine 2\nLine 3",
1991
+ ),
1992
+ ]
1993
+ config = SubAgentDisplayConfig(
1994
+ mode=SubAgentResponseDisplayMode.PLAIN,
1995
+ )
1996
+
1997
+ # Act
1998
+ result = get_sub_agent_answer_from_parts(
1999
+ answer_parts=answer_parts,
2000
+ config=config,
2001
+ )
2002
+
2003
+ # Assert
2004
+ assert "Line 1" in result
2005
+ assert "Line 2" in result
2006
+ assert "Line 3" in result
2007
+
2008
+
2009
+ @pytest.mark.ai
2010
+ def test_get_sub_agent_answer_from_parts__works_with_custom_template__conditional_logic() -> (
2011
+ None
2012
+ ):
2013
+ """
2014
+ Purpose: Verify custom template with Jinja conditionals works correctly.
2015
+ Why this matters: Supports advanced formatting with conditional rendering.
2016
+ Setup summary: Provide custom template with if statement, assert conditional output.
2017
+ """
2018
+ # Arrange
2019
+ answer_parts = [
2020
+ SubAgentAnswerPart(matching_text="a", formatted_text="Item A"),
2021
+ SubAgentAnswerPart(matching_text="b", formatted_text="Item B"),
2022
+ ]
2023
+ custom_template = """
2024
+ {% if substrings|length > 1 %}
2025
+ Multiple items: {{ substrings|join(', ') }}
2026
+ {% else %}
2027
+ Single item: {{ substrings[0] }}
2028
+ {% endif %}
2029
+ """.strip()
2030
+ config = SubAgentDisplayConfig(
2031
+ mode=SubAgentResponseDisplayMode.PLAIN,
2032
+ answer_substrings_jinja_template=custom_template,
2033
+ )
2034
+
2035
+ # Act
2036
+ result = get_sub_agent_answer_from_parts(
2037
+ answer_parts=answer_parts,
2038
+ config=config,
2039
+ )
2040
+
2041
+ # Assert
2042
+ assert "Multiple items:" in result
2043
+ assert "Item A, Item B" in result
2044
+
2045
+
2046
+ @pytest.mark.ai
2047
+ def test_get_sub_agent_answer_from_parts__empty_formatted_text__renders_empty() -> None:
2048
+ """
2049
+ Purpose: Verify parts with empty formatted_text render as empty.
2050
+ Why this matters: Edge case handling for empty content.
2051
+ Setup summary: Provide parts with empty formatted_text, assert minimal output.
2052
+ """
2053
+ # Arrange
2054
+ answer_parts = [
2055
+ SubAgentAnswerPart(matching_text="something", formatted_text=""),
2056
+ ]
2057
+ config = SubAgentDisplayConfig(
2058
+ mode=SubAgentResponseDisplayMode.PLAIN,
2059
+ )
2060
+
2061
+ # Act
2062
+ result = get_sub_agent_answer_from_parts(
2063
+ answer_parts=answer_parts,
2064
+ config=config,
2065
+ )
2066
+
2067
+ # Assert
2068
+ # Default template renders empty string for empty formatted_text
2069
+ assert result.strip() == ""
2070
+
2071
+
2072
+ @pytest.mark.ai
2073
+ def test_get_sub_agent_answer_from_parts__integration__with_get_sub_agent_answer_parts() -> (
2074
+ None
2075
+ ):
2076
+ """
2077
+ Purpose: Verify integration between get_sub_agent_answer_parts and get_sub_agent_answer_from_parts.
2078
+ Why this matters: These functions work together in the display pipeline.
2079
+ Setup summary: Use get_sub_agent_answer_parts output as input, assert complete workflow.
2080
+ """
2081
+ # Arrange
2082
+ answer = "Contact: john@example.com or call 555-1234"
2083
+ config = SubAgentDisplayConfig(
2084
+ mode=SubAgentResponseDisplayMode.PLAIN,
2085
+ answer_substrings_config=[
2086
+ SubAgentAnswerSubstringConfig(
2087
+ regexp=r"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b",
2088
+ display_template="Email: {}",
2089
+ ),
2090
+ SubAgentAnswerSubstringConfig(
2091
+ regexp=r"\d{3}-\d{4}",
2092
+ display_template="Phone: {}",
2093
+ ),
2094
+ ],
2095
+ )
2096
+
2097
+ # Act
2098
+ parts = get_sub_agent_answer_parts(answer=answer, display_config=config)
2099
+ result = get_sub_agent_answer_from_parts(answer_parts=parts, config=config)
2100
+
2101
+ # Assert
2102
+ assert "Email: john@example.com" in result
2103
+ assert "Phone: 555-1234" in result
@@ -231,25 +231,6 @@ class _ToolManager(Generic[_ApiMode]):
231
231
  self,
232
232
  tool_calls: list[LanguageModelFunction],
233
233
  ) -> list[ToolCallResponse]:
234
- tool_calls = tool_calls
235
-
236
- tool_calls = self.filter_duplicate_tool_calls(
237
- tool_calls=tool_calls,
238
- )
239
- num_tool_calls = len(tool_calls)
240
-
241
- if num_tool_calls > self._config.max_tool_calls:
242
- self._logger.warning(
243
- (
244
- "Number of tool calls %s exceeds the allowed maximum of %s."
245
- "The tool calls will be reduced to the first %s."
246
- ),
247
- num_tool_calls,
248
- self._config.max_tool_calls,
249
- self._config.max_tool_calls,
250
- )
251
- tool_calls = tool_calls[: self._config.max_tool_calls]
252
-
253
234
  tool_call_responses = await self._execute_parallelized(tool_calls)
254
235
  return tool_call_responses
255
236
 
@@ -358,6 +339,22 @@ class _ToolManager(Generic[_ApiMode]):
358
339
  )
359
340
  return unique_tool_calls
360
341
 
342
+ def filter_tool_calls_by_max_tool_calls_allowed(
343
+ self, tool_calls: list[LanguageModelFunction]
344
+ ) -> list[LanguageModelFunction]:
345
+ if len(tool_calls) > self._config.max_tool_calls:
346
+ self._logger.warning(
347
+ (
348
+ "Number of tool calls %s exceeds the allowed maximum of %s."
349
+ "The tool calls will be reduced to the first %s."
350
+ ),
351
+ len(tool_calls),
352
+ self._config.max_tool_calls,
353
+ self._config.max_tool_calls,
354
+ )
355
+ return tool_calls[: self._config.max_tool_calls]
356
+ return tool_calls
357
+
361
358
  @overload
362
359
  def get_tool_by_name(
363
360
  self: "_ToolManager[Literal['completions']]", name: str
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: unique_toolkit
3
- Version: 1.31.1
3
+ Version: 1.32.0
4
4
  Summary:
5
5
  License: Proprietary
6
6
  Author: Cedric Klinkert
@@ -121,6 +121,12 @@ All notable changes to this project will be documented in this file.
121
121
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
122
122
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
123
123
 
124
+ ## [1.32.0] - 2025-11-28
125
+ - Add option to filter duplicate sub agent answers.
126
+
127
+ ## [1.31.2] - 2025-11-27
128
+ - Added the function `filter_tool_calls_by_max_tool_calls_allowed` in `tool_manager` to limit the number of parallel tool calls permitted per loop iteration.
129
+
124
130
  ## [1.31.1] - 2025-11-27
125
131
  - Various fixes to sub agent answers.
126
132
 
@@ -82,12 +82,13 @@ unique_toolkit/agentic/tools/a2a/evaluation/evaluator.py,sha256=AJvXu0UJKHe72nRm
82
82
  unique_toolkit/agentic/tools/a2a/evaluation/summarization_user_message.j2,sha256=acP1YqD_sCy6DT0V2EIfhQTmaUKeqpeWNJ7RGgceo8I,271
83
83
  unique_toolkit/agentic/tools/a2a/manager.py,sha256=pk06UUXKQdIUY-PyykYiItubBjmIydOaqWvBBDwhMN4,1939
84
84
  unique_toolkit/agentic/tools/a2a/postprocessing/__init__.py,sha256=aVtUBPN7kDrqA6Bze34AbqQpcBBqpvfyJG-xF65w7R0,659
85
- unique_toolkit/agentic/tools/a2a/postprocessing/_display_utils.py,sha256=cM5EpIFKMNjMfjmOwFfxFxz3KF8iEtY6mdmt-UaJtW4,6879
86
- unique_toolkit/agentic/tools/a2a/postprocessing/_ref_utils.py,sha256=E3KybH9SX5oOkh14sSaIaLnht4DhKVrHAiUkoACNBsg,2430
85
+ unique_toolkit/agentic/tools/a2a/postprocessing/_display_utils.py,sha256=eL_5bkud6aPCKGER705ZQkNttrUZEs-zco83SfbffDQ,7107
86
+ unique_toolkit/agentic/tools/a2a/postprocessing/_ref_utils.py,sha256=tfH3Bhx67uQtH3fYoUr2Zp45HVw7hV_N-5F_qRwiOas,2727
87
87
  unique_toolkit/agentic/tools/a2a/postprocessing/config.py,sha256=nYH1otBrVGHq1Y2i1KII3pb1IVE0efwmOwhOLLsv1qU,2841
88
- unique_toolkit/agentic/tools/a2a/postprocessing/display.py,sha256=L1YFwAvnjNfbG2fxKSLk9wCFcfagq1gtQXucS_kZBeg,7172
88
+ unique_toolkit/agentic/tools/a2a/postprocessing/display.py,sha256=e8R92XJHwyVI8UxVqCG_cTzensHSfGOIfDe1nfGcDoE,9058
89
89
  unique_toolkit/agentic/tools/a2a/postprocessing/references.py,sha256=DGiv8WXMjIwumI7tlpWRgV8wSxnE282ryxEf03fgck8,3465
90
- unique_toolkit/agentic/tools/a2a/postprocessing/test/test_display_utils.py,sha256=v4P0fi7iKKaU050WxxLGjXG4RUEw6r7kQCRlj9Vu59g,52065
90
+ unique_toolkit/agentic/tools/a2a/postprocessing/test/test_display.py,sha256=pP7fjvCm4aamtizs4viZSwsrw4Vb4kMxwDPEEx8GI98,14676
91
+ unique_toolkit/agentic/tools/a2a/postprocessing/test/test_display_utils.py,sha256=5d67L4msesDENsNhgeoDTH6pjw_Z4FUUC1lRM9j4PlI,63608
91
92
  unique_toolkit/agentic/tools/a2a/postprocessing/test/test_ref_utils.py,sha256=u-eNrHjsRFcu4TmzkD5XfFrxvaIToB42YGyXZ-RpsR0,17830
92
93
  unique_toolkit/agentic/tools/a2a/prompts.py,sha256=0ILHL_RAcT04gFm2d470j4Gho7PoJXdCJy-bkZgf_wk,2401
93
94
  unique_toolkit/agentic/tools/a2a/response_watcher/__init__.py,sha256=fS8Lq49DZo5spMcP8QGTMWwSg80rYSr2pTfYDbssGYs,184
@@ -112,10 +113,9 @@ unique_toolkit/agentic/tools/openai_builtin/code_interpreter/service.py,sha256=X
112
113
  unique_toolkit/agentic/tools/openai_builtin/manager.py,sha256=QeDVgLfnCXrSmXI3b9bgQa9oyfQe_L15wa_YfhfNe9E,2633
113
114
  unique_toolkit/agentic/tools/schemas.py,sha256=TXshRvivr2hD-McXHumO0bp-Z0mz_GnAmQRiVjT59rU,5025
114
115
  unique_toolkit/agentic/tools/test/test_mcp_manager.py,sha256=VpB4k4Dh0lQWakilJMQSzO8sBXapuEC26cub_lorl-M,19221
115
- unique_toolkit/agentic/tools/test/test_tool_manager.py,sha256=eO7BSCRrw8iiPhrVL348Ch_yOobc6dUEqK_3OZ5heDw,48298
116
116
  unique_toolkit/agentic/tools/test/test_tool_progress_reporter.py,sha256=XHNezB8itj9KzpQgD0cwRtp2AgRUfUkQsHc3bTyPj6c,15801
117
117
  unique_toolkit/agentic/tools/tool.py,sha256=YmhGZ-NkPlgQ4X1hA6IVod10LNM5YErzbd0Zn6ANA98,6529
118
- unique_toolkit/agentic/tools/tool_manager.py,sha256=zOshUjQYuZe-_lN7DgPCT8UgXK-V34CzVBgF7f7XsWg,17549
118
+ unique_toolkit/agentic/tools/tool_manager.py,sha256=ZwzCcjzHYZgB1FxrpKRmarepfaZknIhLilxeyKoe4BY,17541
119
119
  unique_toolkit/agentic/tools/tool_progress_reporter.py,sha256=GaR0oqDUJZvBB9WCUVYYh0Zvs6U-LMygJCCrqPlitgA,10296
120
120
  unique_toolkit/agentic/tools/utils/__init__.py,sha256=s75sjY5nrJchjLGs3MwSIqhDW08fFXIaX7eRQjFIA4s,346
121
121
  unique_toolkit/agentic/tools/utils/execution/__init__.py,sha256=OHiKpqBnfhBiEQagKVWJsZlHv8smPp5OI4dFIexzibw,37
@@ -189,7 +189,7 @@ unique_toolkit/short_term_memory/service.py,sha256=5PeVBu1ZCAfyDb2HLVvlmqSbyzBBu
189
189
  unique_toolkit/smart_rules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
190
190
  unique_toolkit/smart_rules/compile.py,sha256=Ozhh70qCn2yOzRWr9d8WmJeTo7AQurwd3tStgBMPFLA,1246
191
191
  unique_toolkit/test_utilities/events.py,sha256=_mwV2bs5iLjxS1ynDCjaIq-gjjKhXYCK-iy3dRfvO3g,6410
192
- unique_toolkit-1.31.1.dist-info/LICENSE,sha256=GlN8wHNdh53xwOPg44URnwag6TEolCjoq3YD_KrWgss,193
193
- unique_toolkit-1.31.1.dist-info/METADATA,sha256=xnIZXap3GPV6kt0ML-vhtAoFiSI4JVU5RWtt_qLNgtw,44716
194
- unique_toolkit-1.31.1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
195
- unique_toolkit-1.31.1.dist-info/RECORD,,
192
+ unique_toolkit-1.32.0.dist-info/LICENSE,sha256=GlN8wHNdh53xwOPg44URnwag6TEolCjoq3YD_KrWgss,193
193
+ unique_toolkit-1.32.0.dist-info/METADATA,sha256=w-7NUQhIQPdLlOXStTABVEF5PrLskDfNucF5zLc7yeM,44978
194
+ unique_toolkit-1.32.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
195
+ unique_toolkit-1.32.0.dist-info/RECORD,,