unique_toolkit 2026.42.0.dev6__py3-none-any.whl → 2026.42.0.dev7__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.
@@ -1,6 +1,9 @@
1
1
  import logging
2
+ from collections.abc import Sequence
2
3
  from typing import Unpack
3
4
 
5
+ from openai.types.responses import ToolParam, response_create_params
6
+
4
7
  from unique_toolkit.agentic.loop_runner._responses_stream_handler_utils import (
5
8
  responses_stream_response,
6
9
  )
@@ -9,12 +12,44 @@ from unique_toolkit.agentic.loop_runner.base import (
9
12
  )
10
13
  from unique_toolkit.language_model.schemas import (
11
14
  LanguageModelTokenUsage,
15
+ LanguageModelToolDescription,
12
16
  ResponsesLanguageModelStreamResponse,
13
17
  )
14
18
 
15
19
  _LOGGER = logging.getLogger(__name__)
16
20
 
17
21
 
22
+ def _is_forced_function_choice(
23
+ tool_choice: response_create_params.ToolChoice,
24
+ ) -> bool:
25
+ return isinstance(tool_choice, dict) and tool_choice.get("type") == "function"
26
+
27
+
28
+ def _is_hosted_tool(tool: LanguageModelToolDescription | ToolParam) -> bool:
29
+ """Return whether OpenAI executes the tool."""
30
+ if isinstance(tool, LanguageModelToolDescription):
31
+ return False
32
+ return tool.get("type") != "function"
33
+
34
+
35
+ def _tools_for_forced_choice(
36
+ tools: Sequence[LanguageModelToolDescription | ToolParam] | None,
37
+ tool_choice: response_create_params.ToolChoice,
38
+ ) -> list[LanguageModelToolDescription | ToolParam] | None:
39
+ """Drop hosted tools from requests that force a function tool."""
40
+ if tools is None or not _is_forced_function_choice(tool_choice):
41
+ return list(tools) if tools is not None else None
42
+
43
+ remaining = [tool for tool in tools if not _is_hosted_tool(tool)]
44
+ dropped = len(tools) - len(remaining)
45
+ if dropped > 0:
46
+ _LOGGER.info(
47
+ "Dropped %d hosted tool(s) from the forced function request.",
48
+ dropped,
49
+ )
50
+ return remaining
51
+
52
+
18
53
  async def handle_responses_last_iteration(
19
54
  **kwargs: Unpack[_ResponsesLoopIterationRunnerKwargs],
20
55
  ) -> ResponsesLanguageModelStreamResponse:
@@ -47,9 +82,16 @@ async def handle_responses_forced_tools_iteration(
47
82
  responses: list[ResponsesLanguageModelStreamResponse] = []
48
83
 
49
84
  for opt in tool_choices:
50
- responses.append(
51
- await responses_stream_response(loop_runner_kwargs=kwargs, tool_choice=opt)
52
- )
85
+ tools = _tools_for_forced_choice(kwargs.get("tools"), opt)
86
+ if tools is None:
87
+ response = await responses_stream_response(
88
+ loop_runner_kwargs=kwargs, tool_choice=opt
89
+ )
90
+ else:
91
+ response = await responses_stream_response(
92
+ loop_runner_kwargs=kwargs, tool_choice=opt, tools=tools
93
+ )
94
+ responses.append(response)
53
95
 
54
96
  # Merge responses and refs:
55
97
  tool_calls = []
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: unique-toolkit
3
- Version: 2026.42.0.dev6
3
+ Version: 2026.42.0.dev7
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>
@@ -120,7 +120,7 @@ unique_toolkit/agentic/history_manager/settings.py,sha256=Lrx3a8yXeU0MXrWlV6RZSH
120
120
  unique_toolkit/agentic/history_manager/utils.py,sha256=DiBip8xtah3I9-G-_Ul3OjlYKunrXR-5RJtzREHWV_0,6579
121
121
  unique_toolkit/agentic/loop_runner/__init__.py,sha256=bhwOIloPn2MZyCw60FkHy330twCCRovg3bgye9OjZRE,1496
122
122
  unique_toolkit/agentic/loop_runner/_iteration_handler_utils.py,sha256=y3tjTAtpkyL_Y7279_3v0fGaq9FUYN3UquwdIB3ZhgI,3831
123
- unique_toolkit/agentic/loop_runner/_responses_iteration_handler_utils.py,sha256=DuQRsToV0KLs7YcFjJVnEmrryhlX5q4isztx2jUxZcI,2064
123
+ unique_toolkit/agentic/loop_runner/_responses_iteration_handler_utils.py,sha256=SbfV5KCZ-3QiMRYjaDDUnY0JuBtfBCSBofF6sxTOugI,3615
124
124
  unique_toolkit/agentic/loop_runner/_responses_stream_handler_utils.py,sha256=6HXpSPGUp096a175-NvXqU2Gw7e8Msjo60CP4wGFOoM,2340
125
125
  unique_toolkit/agentic/loop_runner/_stream_handler_utils.py,sha256=ERk-qS8MG8FM2F2AEzaub_XsuZQD1tsD8-li692LKp0,1708
126
126
  unique_toolkit/agentic/loop_runner/base.py,sha256=OddFwxT7zOOLd2MlAef63BNhzH-NNET8RAsfaMcsHQE,3307
@@ -426,6 +426,6 @@ unique_toolkit/short_term_memory/service.py,sha256=2JMBEBn6GoyK-a0xvdcWpPft-3C74
426
426
  unique_toolkit/smart_rules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
427
427
  unique_toolkit/smart_rules/compile.py,sha256=vRe0aMJWuVIK-VsqomgxQImzke7MDmwgSxxJfYCa7zw,1386
428
428
  unique_toolkit/test_utilities/events.py,sha256=FLrhMh0A_mQutAUjoD0FdMcVQ4Gq31r35OVGzRjvLro,6760
429
- unique_toolkit-2026.42.0.dev6.dist-info/WHEEL,sha256=eh7sammvW2TypMMMGKgsM83HyA_3qQ5Lgg3ynoecH3M,79
430
- unique_toolkit-2026.42.0.dev6.dist-info/METADATA,sha256=9WKUOCtvXNQS7Svf4qdFEfym23otCvkrLHRhQscwag0,7821
431
- unique_toolkit-2026.42.0.dev6.dist-info/RECORD,,
429
+ unique_toolkit-2026.42.0.dev7.dist-info/WHEEL,sha256=eh7sammvW2TypMMMGKgsM83HyA_3qQ5Lgg3ynoecH3M,79
430
+ unique_toolkit-2026.42.0.dev7.dist-info/METADATA,sha256=lerw6mdP9Cp9f4mxf3nMFsJEZg9R_iak69i2o-uZcwU,7821
431
+ unique_toolkit-2026.42.0.dev7.dist-info/RECORD,,