unique_orchestrator 1.11.1__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.
Potentially problematic release.
This version of unique_orchestrator might be problematic. Click here for more details.
- unique_orchestrator/config.py +401 -0
- unique_orchestrator/prompts/generic_reference_prompt.jinja2 +46 -0
- unique_orchestrator/prompts/system_prompt.jinja2 +166 -0
- unique_orchestrator/prompts/user_message_prompt.jinja2 +23 -0
- unique_orchestrator/tests/test_unique_ai_get_filtered_user_metadata.py +259 -0
- unique_orchestrator/tests/test_unique_ai_log_tool_calls.py +729 -0
- unique_orchestrator/tests/test_unique_ai_reference_order.py +134 -0
- unique_orchestrator/tests/test_unique_ai_update_debug_info_for_tool_control.py +339 -0
- unique_orchestrator/unique_ai.py +537 -0
- unique_orchestrator/unique_ai_builder.py +568 -0
- unique_orchestrator-1.11.1.dist-info/LICENSE +1 -0
- unique_orchestrator-1.11.1.dist-info/METADATA +199 -0
- unique_orchestrator-1.11.1.dist-info/RECORD +14 -0
- unique_orchestrator-1.11.1.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,729 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
from unittest.mock import MagicMock
|
|
5
|
+
|
|
6
|
+
import pytest
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from unique_orchestrator.unique_ai import UniqueAI
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class TestLogToolCalls:
|
|
13
|
+
"""Test suite for UniqueAI._log_tool_calls method"""
|
|
14
|
+
|
|
15
|
+
@pytest.fixture
|
|
16
|
+
def mock_unique_ai(self, monkeypatch):
|
|
17
|
+
"""Create a minimal UniqueAI instance with mocked dependencies"""
|
|
18
|
+
# Mock MessageStepLogger before importing UniqueAI to avoid import errors
|
|
19
|
+
mock_message_step_logger_class = MagicMock()
|
|
20
|
+
mock_service_module = MagicMock()
|
|
21
|
+
mock_service_module.MessageStepLogger = mock_message_step_logger_class
|
|
22
|
+
|
|
23
|
+
# Use monkeypatch to set the module in sys.modules before import
|
|
24
|
+
import sys
|
|
25
|
+
|
|
26
|
+
monkeypatch.setitem(
|
|
27
|
+
sys.modules,
|
|
28
|
+
"unique_toolkit.agentic.message_log_manager.service",
|
|
29
|
+
mock_service_module,
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
# Lazy import to avoid heavy dependencies at module import time
|
|
33
|
+
from unique_orchestrator.unique_ai import UniqueAI
|
|
34
|
+
|
|
35
|
+
mock_logger = MagicMock()
|
|
36
|
+
|
|
37
|
+
# Create minimal event structure
|
|
38
|
+
dummy_event = MagicMock()
|
|
39
|
+
dummy_event.payload.assistant_message.id = "assist_1"
|
|
40
|
+
dummy_event.payload.user_message.text = "query"
|
|
41
|
+
|
|
42
|
+
# Create minimal config structure
|
|
43
|
+
mock_config = MagicMock()
|
|
44
|
+
mock_config.agent.prompt_config.user_metadata = []
|
|
45
|
+
|
|
46
|
+
# Create minimal required dependencies
|
|
47
|
+
mock_chat_service = MagicMock()
|
|
48
|
+
mock_content_service = MagicMock()
|
|
49
|
+
mock_debug_info_manager = MagicMock()
|
|
50
|
+
mock_reference_manager = MagicMock()
|
|
51
|
+
mock_thinking_manager = MagicMock()
|
|
52
|
+
mock_tool_manager = MagicMock()
|
|
53
|
+
mock_history_manager = MagicMock()
|
|
54
|
+
mock_evaluation_manager = MagicMock()
|
|
55
|
+
mock_postprocessor_manager = MagicMock()
|
|
56
|
+
mock_streaming_handler = MagicMock()
|
|
57
|
+
mock_message_step_logger = MagicMock()
|
|
58
|
+
|
|
59
|
+
# Instantiate UniqueAI
|
|
60
|
+
ua = UniqueAI(
|
|
61
|
+
logger=mock_logger,
|
|
62
|
+
event=dummy_event,
|
|
63
|
+
config=mock_config,
|
|
64
|
+
chat_service=mock_chat_service,
|
|
65
|
+
content_service=mock_content_service,
|
|
66
|
+
debug_info_manager=mock_debug_info_manager,
|
|
67
|
+
streaming_handler=mock_streaming_handler,
|
|
68
|
+
reference_manager=mock_reference_manager,
|
|
69
|
+
thinking_manager=mock_thinking_manager,
|
|
70
|
+
tool_manager=mock_tool_manager,
|
|
71
|
+
history_manager=mock_history_manager,
|
|
72
|
+
evaluation_manager=mock_evaluation_manager,
|
|
73
|
+
postprocessor_manager=mock_postprocessor_manager,
|
|
74
|
+
message_step_logger=mock_message_step_logger,
|
|
75
|
+
mcp_servers=[],
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
return ua
|
|
79
|
+
|
|
80
|
+
@pytest.mark.ai
|
|
81
|
+
def test_log_tool_calls__creates_log_entry__with_single_tool_call(
|
|
82
|
+
self, mock_unique_ai: UniqueAI
|
|
83
|
+
) -> None:
|
|
84
|
+
"""
|
|
85
|
+
Purpose: Verify that _log_tool_calls creates a message log entry with the correct format when a single tool call is provided.
|
|
86
|
+
|
|
87
|
+
Why this matters: The logging of tool calls is critical for user visibility and debugging. The function must correctly format and log tool call information.
|
|
88
|
+
|
|
89
|
+
Setup summary: Create a UniqueAI instance with mocked dependencies, set up a tool manager with one available tool, and provide a single tool call.
|
|
90
|
+
"""
|
|
91
|
+
# Arrange
|
|
92
|
+
mock_tool = MagicMock(spec=["name", "display_name"])
|
|
93
|
+
mock_tool.name = "search_tool"
|
|
94
|
+
mock_tool.display_name.return_value = "Search Tool"
|
|
95
|
+
|
|
96
|
+
mock_unique_ai._tool_manager.available_tools = [mock_tool]
|
|
97
|
+
|
|
98
|
+
mock_tool_call = MagicMock(spec=["name"])
|
|
99
|
+
mock_tool_call.name = "search_tool"
|
|
100
|
+
|
|
101
|
+
tool_calls = [mock_tool_call]
|
|
102
|
+
|
|
103
|
+
# Act
|
|
104
|
+
mock_unique_ai._log_tool_calls(tool_calls)
|
|
105
|
+
|
|
106
|
+
# Assert
|
|
107
|
+
assert isinstance(mock_unique_ai._history_manager.add_tool_call.call_count, int)
|
|
108
|
+
assert mock_unique_ai._history_manager.add_tool_call.call_count == 1
|
|
109
|
+
mock_unique_ai._history_manager.add_tool_call.assert_called_once_with(
|
|
110
|
+
mock_tool_call
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
assert isinstance(
|
|
114
|
+
mock_unique_ai._message_step_logger.create_message_log_entry.call_count,
|
|
115
|
+
int,
|
|
116
|
+
)
|
|
117
|
+
assert (
|
|
118
|
+
mock_unique_ai._message_step_logger.create_message_log_entry.call_count == 1
|
|
119
|
+
)
|
|
120
|
+
mock_unique_ai._message_step_logger.create_message_log_entry.assert_called_once_with(
|
|
121
|
+
text="**Triggered Tool Calls:**\n \n• Search Tool", references=[]
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
@pytest.mark.ai
|
|
125
|
+
def test_log_tool_calls__creates_log_entry__with_multiple_tool_calls(
|
|
126
|
+
self, mock_unique_ai: UniqueAI
|
|
127
|
+
) -> None:
|
|
128
|
+
"""
|
|
129
|
+
Purpose: Verify that _log_tool_calls correctly formats and logs multiple tool calls in a single log entry.
|
|
130
|
+
|
|
131
|
+
Why this matters: Users may trigger multiple tools simultaneously, and all should be logged in a readable format.
|
|
132
|
+
|
|
133
|
+
Setup summary: Create a UniqueAI instance with mocked dependencies, set up a tool manager with multiple available tools, and provide multiple tool calls.
|
|
134
|
+
"""
|
|
135
|
+
# Arrange
|
|
136
|
+
mock_tool_1 = MagicMock(spec=["name", "display_name"])
|
|
137
|
+
mock_tool_1.name = "search_tool"
|
|
138
|
+
mock_tool_1.display_name.return_value = "Search Tool"
|
|
139
|
+
|
|
140
|
+
mock_tool_2 = MagicMock(spec=["name", "display_name"])
|
|
141
|
+
mock_tool_2.name = "web_search"
|
|
142
|
+
mock_tool_2.display_name.return_value = "Web Search"
|
|
143
|
+
|
|
144
|
+
mock_unique_ai._tool_manager.available_tools = [mock_tool_1, mock_tool_2]
|
|
145
|
+
|
|
146
|
+
mock_tool_call_1 = MagicMock(spec=["name"])
|
|
147
|
+
mock_tool_call_1.name = "search_tool"
|
|
148
|
+
|
|
149
|
+
mock_tool_call_2 = MagicMock(spec=["name"])
|
|
150
|
+
mock_tool_call_2.name = "web_search"
|
|
151
|
+
|
|
152
|
+
tool_calls = [mock_tool_call_1, mock_tool_call_2]
|
|
153
|
+
|
|
154
|
+
# Act
|
|
155
|
+
mock_unique_ai._log_tool_calls(tool_calls)
|
|
156
|
+
|
|
157
|
+
# Assert
|
|
158
|
+
assert isinstance(mock_unique_ai._history_manager.add_tool_call.call_count, int)
|
|
159
|
+
assert mock_unique_ai._history_manager.add_tool_call.call_count == 2
|
|
160
|
+
mock_unique_ai._history_manager.add_tool_call.assert_any_call(mock_tool_call_1)
|
|
161
|
+
mock_unique_ai._history_manager.add_tool_call.assert_any_call(mock_tool_call_2)
|
|
162
|
+
|
|
163
|
+
assert isinstance(
|
|
164
|
+
mock_unique_ai._message_step_logger.create_message_log_entry.call_count,
|
|
165
|
+
int,
|
|
166
|
+
)
|
|
167
|
+
assert (
|
|
168
|
+
mock_unique_ai._message_step_logger.create_message_log_entry.call_count == 1
|
|
169
|
+
)
|
|
170
|
+
mock_unique_ai._message_step_logger.create_message_log_entry.assert_called_once_with(
|
|
171
|
+
text="**Triggered Tool Calls:**\n \n• Search Tool\n• Web Search",
|
|
172
|
+
references=[],
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
@pytest.mark.ai
|
|
176
|
+
def test_log_tool_calls__uses_tool_name__when_tool_not_in_available_tools(
|
|
177
|
+
self, mock_unique_ai: UniqueAI
|
|
178
|
+
) -> None:
|
|
179
|
+
"""
|
|
180
|
+
Purpose: Verify that _log_tool_calls does not create a message log entry when the tool is not found in available_tools.
|
|
181
|
+
Setup summary: Create a UniqueAI instance with mocked dependencies, set up a tool manager with no matching tools, and provide a tool call with a name not in available_tools.
|
|
182
|
+
"""
|
|
183
|
+
# Arrange
|
|
184
|
+
mock_tool = MagicMock(spec=["name", "display_name"])
|
|
185
|
+
mock_tool.name = "other_tool"
|
|
186
|
+
mock_tool.display_name.return_value = "Other Tool"
|
|
187
|
+
|
|
188
|
+
mock_unique_ai._tool_manager.available_tools = [mock_tool]
|
|
189
|
+
|
|
190
|
+
mock_tool_call = MagicMock(spec=["name"])
|
|
191
|
+
mock_tool_call.name = "unknown_tool"
|
|
192
|
+
|
|
193
|
+
tool_calls = [mock_tool_call]
|
|
194
|
+
|
|
195
|
+
# Act
|
|
196
|
+
mock_unique_ai._log_tool_calls(tool_calls)
|
|
197
|
+
|
|
198
|
+
# Assert
|
|
199
|
+
assert isinstance(mock_unique_ai._history_manager.add_tool_call.call_count, int)
|
|
200
|
+
assert mock_unique_ai._history_manager.add_tool_call.call_count == 1
|
|
201
|
+
mock_unique_ai._history_manager.add_tool_call.assert_called_once_with(
|
|
202
|
+
mock_tool_call
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
assert isinstance(
|
|
206
|
+
mock_unique_ai._message_step_logger.create_message_log_entry.call_count,
|
|
207
|
+
int,
|
|
208
|
+
)
|
|
209
|
+
# Tool call not in available_tools should not create a log entry
|
|
210
|
+
assert (
|
|
211
|
+
mock_unique_ai._message_step_logger.create_message_log_entry.call_count == 0
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
@pytest.mark.ai
|
|
215
|
+
def test_log_tool_calls__uses_tool_name__when_display_name_is_falsy(
|
|
216
|
+
self, mock_unique_ai: UniqueAI
|
|
217
|
+
) -> None:
|
|
218
|
+
"""
|
|
219
|
+
Purpose: Verify that _log_tool_calls falls back to the tool call's name when display_name returns a falsy value.
|
|
220
|
+
|
|
221
|
+
Why this matters: The function must handle edge cases where display_name might return None or empty string, ensuring the log entry always contains meaningful information.
|
|
222
|
+
|
|
223
|
+
Setup summary: Create a UniqueAI instance with mocked dependencies, set up a tool manager with a tool that returns a falsy display_name, and provide a matching tool call.
|
|
224
|
+
"""
|
|
225
|
+
# Arrange
|
|
226
|
+
mock_tool = MagicMock(spec=["name", "display_name"])
|
|
227
|
+
mock_tool.name = "search_tool"
|
|
228
|
+
mock_tool.display_name.return_value = None
|
|
229
|
+
|
|
230
|
+
mock_unique_ai._tool_manager.available_tools = [mock_tool]
|
|
231
|
+
|
|
232
|
+
mock_tool_call = MagicMock(spec=["name"])
|
|
233
|
+
mock_tool_call.name = "search_tool"
|
|
234
|
+
|
|
235
|
+
tool_calls = [mock_tool_call]
|
|
236
|
+
|
|
237
|
+
# Act
|
|
238
|
+
mock_unique_ai._log_tool_calls(tool_calls)
|
|
239
|
+
|
|
240
|
+
# Assert
|
|
241
|
+
assert isinstance(mock_unique_ai._history_manager.add_tool_call.call_count, int)
|
|
242
|
+
assert mock_unique_ai._history_manager.add_tool_call.call_count == 1
|
|
243
|
+
mock_unique_ai._history_manager.add_tool_call.assert_called_once_with(
|
|
244
|
+
mock_tool_call
|
|
245
|
+
)
|
|
246
|
+
|
|
247
|
+
assert isinstance(
|
|
248
|
+
mock_unique_ai._message_step_logger.create_message_log_entry.call_count,
|
|
249
|
+
int,
|
|
250
|
+
)
|
|
251
|
+
assert (
|
|
252
|
+
mock_unique_ai._message_step_logger.create_message_log_entry.call_count == 1
|
|
253
|
+
)
|
|
254
|
+
# When display_name is falsy, should use tool_call.name
|
|
255
|
+
mock_unique_ai._message_step_logger.create_message_log_entry.assert_called_once_with(
|
|
256
|
+
text="**Triggered Tool Calls:**\n \n• search_tool", references=[]
|
|
257
|
+
)
|
|
258
|
+
|
|
259
|
+
@pytest.mark.ai
|
|
260
|
+
def test_log_tool_calls__handles_empty_list__without_error(
|
|
261
|
+
self, mock_unique_ai: UniqueAI
|
|
262
|
+
) -> None:
|
|
263
|
+
"""
|
|
264
|
+
Purpose: Verify that _log_tool_calls handles an empty tool_calls list without raising errors and does not create a log entry.
|
|
265
|
+
|
|
266
|
+
Why this matters: The function should be resilient to edge cases like empty input, ensuring the system continues to function even when no tool calls are present.
|
|
267
|
+
|
|
268
|
+
Setup summary: Create a UniqueAI instance with mocked dependencies, set up a tool manager with available tools, and provide an empty tool_calls list.
|
|
269
|
+
"""
|
|
270
|
+
# Arrange
|
|
271
|
+
mock_tool = MagicMock(spec=["name", "display_name"])
|
|
272
|
+
mock_tool.name = "search_tool"
|
|
273
|
+
mock_tool.display_name.return_value = "Search Tool"
|
|
274
|
+
|
|
275
|
+
mock_unique_ai._tool_manager.available_tools = [mock_tool]
|
|
276
|
+
|
|
277
|
+
tool_calls: list = []
|
|
278
|
+
|
|
279
|
+
# Act
|
|
280
|
+
mock_unique_ai._log_tool_calls(tool_calls)
|
|
281
|
+
|
|
282
|
+
# Assert
|
|
283
|
+
assert isinstance(mock_unique_ai._history_manager.add_tool_call.call_count, int)
|
|
284
|
+
assert mock_unique_ai._history_manager.add_tool_call.call_count == 0
|
|
285
|
+
|
|
286
|
+
assert isinstance(
|
|
287
|
+
mock_unique_ai._message_step_logger.create_message_log_entry.call_count,
|
|
288
|
+
int,
|
|
289
|
+
)
|
|
290
|
+
# Empty tool_calls list should not create a log entry
|
|
291
|
+
assert (
|
|
292
|
+
mock_unique_ai._message_step_logger.create_message_log_entry.call_count == 0
|
|
293
|
+
)
|
|
294
|
+
|
|
295
|
+
@pytest.mark.ai
|
|
296
|
+
def test_log_tool_calls__adds_all_tool_calls_to_history__regardless_of_availability(
|
|
297
|
+
self, mock_unique_ai: UniqueAI
|
|
298
|
+
) -> None:
|
|
299
|
+
"""
|
|
300
|
+
Purpose: Verify that _log_tool_calls adds all tool calls to history, even if they are not in the available_tools list.
|
|
301
|
+
|
|
302
|
+
Why this matters: History tracking should be complete and independent of whether tools are available for display name lookup.
|
|
303
|
+
|
|
304
|
+
Setup summary: Create a UniqueAI instance with mocked dependencies, set up a tool manager with some available tools, and provide tool calls including both available and unavailable tools.
|
|
305
|
+
"""
|
|
306
|
+
# Arrange
|
|
307
|
+
mock_tool = MagicMock(spec=["name", "display_name"])
|
|
308
|
+
mock_tool.name = "search_tool"
|
|
309
|
+
mock_tool.display_name.return_value = "Search Tool"
|
|
310
|
+
|
|
311
|
+
mock_unique_ai._tool_manager.available_tools = [mock_tool]
|
|
312
|
+
|
|
313
|
+
mock_tool_call_1 = MagicMock(spec=["name"])
|
|
314
|
+
mock_tool_call_1.name = "search_tool"
|
|
315
|
+
|
|
316
|
+
mock_tool_call_2 = MagicMock(spec=["name"])
|
|
317
|
+
mock_tool_call_2.name = "unknown_tool"
|
|
318
|
+
|
|
319
|
+
tool_calls = [mock_tool_call_1, mock_tool_call_2]
|
|
320
|
+
|
|
321
|
+
# Act
|
|
322
|
+
mock_unique_ai._log_tool_calls(tool_calls)
|
|
323
|
+
|
|
324
|
+
# Assert
|
|
325
|
+
assert isinstance(mock_unique_ai._history_manager.add_tool_call.call_count, int)
|
|
326
|
+
assert mock_unique_ai._history_manager.add_tool_call.call_count == 2
|
|
327
|
+
mock_unique_ai._history_manager.add_tool_call.assert_any_call(mock_tool_call_1)
|
|
328
|
+
mock_unique_ai._history_manager.add_tool_call.assert_any_call(mock_tool_call_2)
|
|
329
|
+
|
|
330
|
+
assert isinstance(
|
|
331
|
+
mock_unique_ai._message_step_logger.create_message_log_entry.call_count,
|
|
332
|
+
int,
|
|
333
|
+
)
|
|
334
|
+
assert (
|
|
335
|
+
mock_unique_ai._message_step_logger.create_message_log_entry.call_count == 1
|
|
336
|
+
)
|
|
337
|
+
|
|
338
|
+
@pytest.mark.ai
|
|
339
|
+
def test_log_tool_calls__excludes_deep_research_from_message_log__but_adds_to_history(
|
|
340
|
+
self, mock_unique_ai: UniqueAI
|
|
341
|
+
) -> None:
|
|
342
|
+
"""
|
|
343
|
+
Purpose: Verify that _log_tool_calls excludes "DeepResearch" from the message log entry but still adds it to history.
|
|
344
|
+
|
|
345
|
+
Why this matters: DeepResearch tool calls should be tracked in history for completeness but hidden from the user-facing message steps to avoid clutter or confusion.
|
|
346
|
+
|
|
347
|
+
Setup summary: Create a UniqueAI instance with mocked dependencies, set up a tool manager with "DeepResearch" and other tools, and provide tool calls including "DeepResearch".
|
|
348
|
+
"""
|
|
349
|
+
# Arrange
|
|
350
|
+
mock_tool_1 = MagicMock(spec=["name", "display_name"])
|
|
351
|
+
mock_tool_1.name = "DeepResearch"
|
|
352
|
+
mock_tool_1.display_name.return_value = "Deep Research"
|
|
353
|
+
|
|
354
|
+
mock_tool_2 = MagicMock(spec=["name", "display_name"])
|
|
355
|
+
mock_tool_2.name = "search_tool"
|
|
356
|
+
mock_tool_2.display_name.return_value = "Search Tool"
|
|
357
|
+
|
|
358
|
+
mock_unique_ai._tool_manager.available_tools = [mock_tool_1, mock_tool_2]
|
|
359
|
+
|
|
360
|
+
mock_tool_call_1 = MagicMock(spec=["name"])
|
|
361
|
+
mock_tool_call_1.name = "DeepResearch"
|
|
362
|
+
|
|
363
|
+
mock_tool_call_2 = MagicMock(spec=["name"])
|
|
364
|
+
mock_tool_call_2.name = "search_tool"
|
|
365
|
+
|
|
366
|
+
tool_calls = [mock_tool_call_1, mock_tool_call_2]
|
|
367
|
+
|
|
368
|
+
# Act
|
|
369
|
+
mock_unique_ai._log_tool_calls(tool_calls)
|
|
370
|
+
|
|
371
|
+
# Assert
|
|
372
|
+
# Both tool calls should be added to history
|
|
373
|
+
assert isinstance(mock_unique_ai._history_manager.add_tool_call.call_count, int)
|
|
374
|
+
assert mock_unique_ai._history_manager.add_tool_call.call_count == 2
|
|
375
|
+
mock_unique_ai._history_manager.add_tool_call.assert_any_call(mock_tool_call_1)
|
|
376
|
+
mock_unique_ai._history_manager.add_tool_call.assert_any_call(mock_tool_call_2)
|
|
377
|
+
|
|
378
|
+
# But only the non-DeepResearch tool should appear in the message log
|
|
379
|
+
assert isinstance(
|
|
380
|
+
mock_unique_ai._message_step_logger.create_message_log_entry.call_count,
|
|
381
|
+
int,
|
|
382
|
+
)
|
|
383
|
+
assert (
|
|
384
|
+
mock_unique_ai._message_step_logger.create_message_log_entry.call_count == 1
|
|
385
|
+
)
|
|
386
|
+
mock_unique_ai._message_step_logger.create_message_log_entry.assert_called_once_with(
|
|
387
|
+
text="**Triggered Tool Calls:**\n \n• Search Tool", references=[]
|
|
388
|
+
)
|
|
389
|
+
|
|
390
|
+
@pytest.mark.ai
|
|
391
|
+
def test_log_tool_calls__excludes_only_deep_research_when_present__with_multiple_tools(
|
|
392
|
+
self, mock_unique_ai: UniqueAI
|
|
393
|
+
) -> None:
|
|
394
|
+
"""
|
|
395
|
+
Purpose: Verify that _log_tool_calls only excludes "DeepResearch" and logs all other tools when multiple tools are called.
|
|
396
|
+
|
|
397
|
+
Why this matters: The exclusion logic should be precise, affecting only "DeepResearch" while allowing all other tools to be logged normally.
|
|
398
|
+
|
|
399
|
+
Setup summary: Create a UniqueAI instance with mocked dependencies, set up a tool manager with multiple tools including "DeepResearch", and provide multiple tool calls.
|
|
400
|
+
"""
|
|
401
|
+
# Arrange
|
|
402
|
+
mock_tool_1 = MagicMock(spec=["name", "display_name"])
|
|
403
|
+
mock_tool_1.name = "DeepResearch"
|
|
404
|
+
mock_tool_1.display_name.return_value = "Deep Research"
|
|
405
|
+
|
|
406
|
+
mock_tool_2 = MagicMock(spec=["name", "display_name"])
|
|
407
|
+
mock_tool_2.name = "search_tool"
|
|
408
|
+
mock_tool_2.display_name.return_value = "Search Tool"
|
|
409
|
+
|
|
410
|
+
mock_tool_3 = MagicMock(spec=["name", "display_name"])
|
|
411
|
+
mock_tool_3.name = "web_search"
|
|
412
|
+
mock_tool_3.display_name.return_value = "Web Search"
|
|
413
|
+
|
|
414
|
+
mock_unique_ai._tool_manager.available_tools = [
|
|
415
|
+
mock_tool_1,
|
|
416
|
+
mock_tool_2,
|
|
417
|
+
mock_tool_3,
|
|
418
|
+
]
|
|
419
|
+
|
|
420
|
+
mock_tool_call_1 = MagicMock(spec=["name"])
|
|
421
|
+
mock_tool_call_1.name = "search_tool"
|
|
422
|
+
|
|
423
|
+
mock_tool_call_2 = MagicMock(spec=["name"])
|
|
424
|
+
mock_tool_call_2.name = "DeepResearch"
|
|
425
|
+
|
|
426
|
+
mock_tool_call_3 = MagicMock(spec=["name"])
|
|
427
|
+
mock_tool_call_3.name = "web_search"
|
|
428
|
+
|
|
429
|
+
tool_calls = [mock_tool_call_1, mock_tool_call_2, mock_tool_call_3]
|
|
430
|
+
|
|
431
|
+
# Act
|
|
432
|
+
mock_unique_ai._log_tool_calls(tool_calls)
|
|
433
|
+
|
|
434
|
+
# Assert
|
|
435
|
+
# All tool calls should be added to history
|
|
436
|
+
assert isinstance(mock_unique_ai._history_manager.add_tool_call.call_count, int)
|
|
437
|
+
assert mock_unique_ai._history_manager.add_tool_call.call_count == 3
|
|
438
|
+
mock_unique_ai._history_manager.add_tool_call.assert_any_call(mock_tool_call_1)
|
|
439
|
+
mock_unique_ai._history_manager.add_tool_call.assert_any_call(mock_tool_call_2)
|
|
440
|
+
mock_unique_ai._history_manager.add_tool_call.assert_any_call(mock_tool_call_3)
|
|
441
|
+
|
|
442
|
+
# But only the non-DeepResearch tools should appear in the message log
|
|
443
|
+
assert isinstance(
|
|
444
|
+
mock_unique_ai._message_step_logger.create_message_log_entry.call_count,
|
|
445
|
+
int,
|
|
446
|
+
)
|
|
447
|
+
assert (
|
|
448
|
+
mock_unique_ai._message_step_logger.create_message_log_entry.call_count == 1
|
|
449
|
+
)
|
|
450
|
+
mock_unique_ai._message_step_logger.create_message_log_entry.assert_called_once_with(
|
|
451
|
+
text="**Triggered Tool Calls:**\n \n• Search Tool\n• Web Search",
|
|
452
|
+
references=[],
|
|
453
|
+
)
|
|
454
|
+
|
|
455
|
+
@pytest.mark.ai
|
|
456
|
+
def test_log_tool_calls__creates_no_log_entry__when_only_deep_research_called(
|
|
457
|
+
self, mock_unique_ai: UniqueAI
|
|
458
|
+
) -> None:
|
|
459
|
+
"""
|
|
460
|
+
Purpose: Verify that _log_tool_calls does not create a message log entry when only "DeepResearch" is called.
|
|
461
|
+
|
|
462
|
+
Why this matters: When only excluded tools are called, no message log entry should be created since there's nothing to display to the user.
|
|
463
|
+
|
|
464
|
+
Setup summary: Create a UniqueAI instance with mocked dependencies, set up a tool manager with "DeepResearch", and provide only a DeepResearch tool call.
|
|
465
|
+
"""
|
|
466
|
+
# Arrange
|
|
467
|
+
mock_tool = MagicMock(spec=["name", "display_name"])
|
|
468
|
+
mock_tool.name = "DeepResearch"
|
|
469
|
+
mock_tool.display_name.return_value = "Deep Research"
|
|
470
|
+
|
|
471
|
+
mock_unique_ai._tool_manager.available_tools = [mock_tool]
|
|
472
|
+
|
|
473
|
+
mock_tool_call = MagicMock(spec=["name"])
|
|
474
|
+
mock_tool_call.name = "DeepResearch"
|
|
475
|
+
|
|
476
|
+
tool_calls = [mock_tool_call]
|
|
477
|
+
|
|
478
|
+
# Act
|
|
479
|
+
mock_unique_ai._log_tool_calls(tool_calls)
|
|
480
|
+
|
|
481
|
+
# Assert
|
|
482
|
+
# DeepResearch should be added to history
|
|
483
|
+
assert isinstance(mock_unique_ai._history_manager.add_tool_call.call_count, int)
|
|
484
|
+
assert mock_unique_ai._history_manager.add_tool_call.call_count == 1
|
|
485
|
+
mock_unique_ai._history_manager.add_tool_call.assert_called_once_with(
|
|
486
|
+
mock_tool_call
|
|
487
|
+
)
|
|
488
|
+
|
|
489
|
+
# But no message log entry should be created since tool_string is empty
|
|
490
|
+
assert isinstance(
|
|
491
|
+
mock_unique_ai._message_step_logger.create_message_log_entry.call_count,
|
|
492
|
+
int,
|
|
493
|
+
)
|
|
494
|
+
assert (
|
|
495
|
+
mock_unique_ai._message_step_logger.create_message_log_entry.call_count == 0
|
|
496
|
+
)
|
|
497
|
+
|
|
498
|
+
@pytest.mark.ai
|
|
499
|
+
def test_log_tool_calls__displays_count__when_same_tool_called_multiple_times(
|
|
500
|
+
self, mock_unique_ai: UniqueAI
|
|
501
|
+
) -> None:
|
|
502
|
+
"""
|
|
503
|
+
Purpose: Verify that _log_tool_calls displays a count indicator when the same tool is called multiple times.
|
|
504
|
+
|
|
505
|
+
Why this matters: Users should see how many times each tool was invoked to understand the execution pattern. Multiple calls to the same tool should be aggregated with a count suffix.
|
|
506
|
+
|
|
507
|
+
Setup summary: Create a UniqueAI instance with mocked dependencies, set up a tool manager with one available tool, and provide multiple calls to the same tool.
|
|
508
|
+
"""
|
|
509
|
+
# Arrange
|
|
510
|
+
mock_tool = MagicMock(spec=["name", "display_name"])
|
|
511
|
+
mock_tool.name = "search_tool"
|
|
512
|
+
mock_tool.display_name.return_value = "Search Tool"
|
|
513
|
+
|
|
514
|
+
mock_unique_ai._tool_manager.available_tools = [mock_tool]
|
|
515
|
+
|
|
516
|
+
mock_tool_call_1 = MagicMock(spec=["name"])
|
|
517
|
+
mock_tool_call_1.name = "search_tool"
|
|
518
|
+
|
|
519
|
+
mock_tool_call_2 = MagicMock(spec=["name"])
|
|
520
|
+
mock_tool_call_2.name = "search_tool"
|
|
521
|
+
|
|
522
|
+
tool_calls = [mock_tool_call_1, mock_tool_call_2]
|
|
523
|
+
|
|
524
|
+
# Act
|
|
525
|
+
mock_unique_ai._log_tool_calls(tool_calls)
|
|
526
|
+
|
|
527
|
+
# Assert
|
|
528
|
+
assert isinstance(mock_unique_ai._history_manager.add_tool_call.call_count, int)
|
|
529
|
+
assert mock_unique_ai._history_manager.add_tool_call.call_count == 2
|
|
530
|
+
mock_unique_ai._history_manager.add_tool_call.assert_any_call(mock_tool_call_1)
|
|
531
|
+
mock_unique_ai._history_manager.add_tool_call.assert_any_call(mock_tool_call_2)
|
|
532
|
+
|
|
533
|
+
assert isinstance(
|
|
534
|
+
mock_unique_ai._message_step_logger.create_message_log_entry.call_count,
|
|
535
|
+
int,
|
|
536
|
+
)
|
|
537
|
+
assert (
|
|
538
|
+
mock_unique_ai._message_step_logger.create_message_log_entry.call_count == 1
|
|
539
|
+
)
|
|
540
|
+
# Should display "(2x)" for the tool called twice
|
|
541
|
+
mock_unique_ai._message_step_logger.create_message_log_entry.assert_called_once_with(
|
|
542
|
+
text="**Triggered Tool Calls:**\n \n• Search Tool (2x)", references=[]
|
|
543
|
+
)
|
|
544
|
+
|
|
545
|
+
@pytest.mark.ai
|
|
546
|
+
def test_log_tool_calls__displays_count__when_same_tool_called_three_times(
|
|
547
|
+
self, mock_unique_ai: UniqueAI
|
|
548
|
+
) -> None:
|
|
549
|
+
"""
|
|
550
|
+
Purpose: Verify that _log_tool_calls correctly displays count for tools called three or more times.
|
|
551
|
+
|
|
552
|
+
Why this matters: The counting logic should work for any number of duplicate calls, not just two.
|
|
553
|
+
|
|
554
|
+
Setup summary: Create a UniqueAI instance with mocked dependencies, set up a tool manager with one available tool, and provide three calls to the same tool.
|
|
555
|
+
"""
|
|
556
|
+
# Arrange
|
|
557
|
+
mock_tool = MagicMock(spec=["name", "display_name"])
|
|
558
|
+
mock_tool.name = "search_tool"
|
|
559
|
+
mock_tool.display_name.return_value = "Search Tool"
|
|
560
|
+
|
|
561
|
+
mock_unique_ai._tool_manager.available_tools = [mock_tool]
|
|
562
|
+
|
|
563
|
+
mock_tool_call_1 = MagicMock(spec=["name"])
|
|
564
|
+
mock_tool_call_1.name = "search_tool"
|
|
565
|
+
|
|
566
|
+
mock_tool_call_2 = MagicMock(spec=["name"])
|
|
567
|
+
mock_tool_call_2.name = "search_tool"
|
|
568
|
+
|
|
569
|
+
mock_tool_call_3 = MagicMock(spec=["name"])
|
|
570
|
+
mock_tool_call_3.name = "search_tool"
|
|
571
|
+
|
|
572
|
+
tool_calls = [mock_tool_call_1, mock_tool_call_2, mock_tool_call_3]
|
|
573
|
+
|
|
574
|
+
# Act
|
|
575
|
+
mock_unique_ai._log_tool_calls(tool_calls)
|
|
576
|
+
|
|
577
|
+
# Assert
|
|
578
|
+
assert isinstance(mock_unique_ai._history_manager.add_tool_call.call_count, int)
|
|
579
|
+
assert mock_unique_ai._history_manager.add_tool_call.call_count == 3
|
|
580
|
+
|
|
581
|
+
assert isinstance(
|
|
582
|
+
mock_unique_ai._message_step_logger.create_message_log_entry.call_count,
|
|
583
|
+
int,
|
|
584
|
+
)
|
|
585
|
+
assert (
|
|
586
|
+
mock_unique_ai._message_step_logger.create_message_log_entry.call_count == 1
|
|
587
|
+
)
|
|
588
|
+
# Should display "(3x)" for the tool called three times
|
|
589
|
+
mock_unique_ai._message_step_logger.create_message_log_entry.assert_called_once_with(
|
|
590
|
+
text="**Triggered Tool Calls:**\n \n• Search Tool (3x)", references=[]
|
|
591
|
+
)
|
|
592
|
+
|
|
593
|
+
@pytest.mark.ai
|
|
594
|
+
def test_log_tool_calls__displays_mixed_counts__with_some_tools_called_once_and_others_multiple_times(
|
|
595
|
+
self, mock_unique_ai: UniqueAI
|
|
596
|
+
) -> None:
|
|
597
|
+
"""
|
|
598
|
+
Purpose: Verify that _log_tool_calls correctly handles a mix of tools called once and tools called multiple times.
|
|
599
|
+
|
|
600
|
+
Why this matters: Real-world scenarios often involve calling different tools different numbers of times. The log should accurately reflect this with counts only shown for tools called more than once.
|
|
601
|
+
|
|
602
|
+
Setup summary: Create a UniqueAI instance with mocked dependencies, set up a tool manager with multiple available tools, and provide a mix of single and multiple calls.
|
|
603
|
+
"""
|
|
604
|
+
# Arrange
|
|
605
|
+
mock_tool_1 = MagicMock(spec=["name", "display_name"])
|
|
606
|
+
mock_tool_1.name = "search_tool"
|
|
607
|
+
mock_tool_1.display_name.return_value = "Search Tool"
|
|
608
|
+
|
|
609
|
+
mock_tool_2 = MagicMock(spec=["name", "display_name"])
|
|
610
|
+
mock_tool_2.name = "web_search"
|
|
611
|
+
mock_tool_2.display_name.return_value = "Web Search"
|
|
612
|
+
|
|
613
|
+
mock_tool_3 = MagicMock(spec=["name", "display_name"])
|
|
614
|
+
mock_tool_3.name = "file_reader"
|
|
615
|
+
mock_tool_3.display_name.return_value = "File Reader"
|
|
616
|
+
|
|
617
|
+
mock_unique_ai._tool_manager.available_tools = [
|
|
618
|
+
mock_tool_1,
|
|
619
|
+
mock_tool_2,
|
|
620
|
+
mock_tool_3,
|
|
621
|
+
]
|
|
622
|
+
|
|
623
|
+
mock_tool_call_1 = MagicMock(spec=["name"])
|
|
624
|
+
mock_tool_call_1.name = "search_tool"
|
|
625
|
+
|
|
626
|
+
mock_tool_call_2 = MagicMock(spec=["name"])
|
|
627
|
+
mock_tool_call_2.name = "web_search"
|
|
628
|
+
|
|
629
|
+
mock_tool_call_3 = MagicMock(spec=["name"])
|
|
630
|
+
mock_tool_call_3.name = "search_tool"
|
|
631
|
+
|
|
632
|
+
mock_tool_call_4 = MagicMock(spec=["name"])
|
|
633
|
+
mock_tool_call_4.name = "file_reader"
|
|
634
|
+
|
|
635
|
+
mock_tool_call_5 = MagicMock(spec=["name"])
|
|
636
|
+
mock_tool_call_5.name = "search_tool"
|
|
637
|
+
|
|
638
|
+
tool_calls = [
|
|
639
|
+
mock_tool_call_1,
|
|
640
|
+
mock_tool_call_2,
|
|
641
|
+
mock_tool_call_3,
|
|
642
|
+
mock_tool_call_4,
|
|
643
|
+
mock_tool_call_5,
|
|
644
|
+
]
|
|
645
|
+
|
|
646
|
+
# Act
|
|
647
|
+
mock_unique_ai._log_tool_calls(tool_calls)
|
|
648
|
+
|
|
649
|
+
# Assert
|
|
650
|
+
assert isinstance(mock_unique_ai._history_manager.add_tool_call.call_count, int)
|
|
651
|
+
assert mock_unique_ai._history_manager.add_tool_call.call_count == 5
|
|
652
|
+
|
|
653
|
+
assert isinstance(
|
|
654
|
+
mock_unique_ai._message_step_logger.create_message_log_entry.call_count,
|
|
655
|
+
int,
|
|
656
|
+
)
|
|
657
|
+
assert (
|
|
658
|
+
mock_unique_ai._message_step_logger.create_message_log_entry.call_count == 1
|
|
659
|
+
)
|
|
660
|
+
# Should display:
|
|
661
|
+
# - "Search Tool (3x)" for search_tool (called 3 times)
|
|
662
|
+
# - "Web Search" for web_search (called once, no count)
|
|
663
|
+
# - "File Reader" for file_reader (called once, no count)
|
|
664
|
+
mock_unique_ai._message_step_logger.create_message_log_entry.assert_called_once_with(
|
|
665
|
+
text="**Triggered Tool Calls:**\n \n• Search Tool (3x)\n• Web Search\n• File Reader",
|
|
666
|
+
references=[],
|
|
667
|
+
)
|
|
668
|
+
|
|
669
|
+
@pytest.mark.ai
|
|
670
|
+
def test_log_tool_calls__excludes_deep_research_from_count__when_called_multiple_times(
|
|
671
|
+
self, mock_unique_ai: UniqueAI
|
|
672
|
+
) -> None:
|
|
673
|
+
"""
|
|
674
|
+
Purpose: Verify that _log_tool_calls excludes "DeepResearch" from message log even when it's called multiple times, but still adds all instances to history.
|
|
675
|
+
|
|
676
|
+
Why this matters: The exclusion of DeepResearch should work consistently regardless of how many times it's called.
|
|
677
|
+
|
|
678
|
+
Setup summary: Create a UniqueAI instance with mocked dependencies, set up a tool manager with "DeepResearch" and other tools, and provide multiple DeepResearch calls along with other tool calls.
|
|
679
|
+
"""
|
|
680
|
+
# Arrange
|
|
681
|
+
mock_tool_1 = MagicMock(spec=["name", "display_name"])
|
|
682
|
+
mock_tool_1.name = "DeepResearch"
|
|
683
|
+
mock_tool_1.display_name.return_value = "Deep Research"
|
|
684
|
+
|
|
685
|
+
mock_tool_2 = MagicMock(spec=["name", "display_name"])
|
|
686
|
+
mock_tool_2.name = "search_tool"
|
|
687
|
+
mock_tool_2.display_name.return_value = "Search Tool"
|
|
688
|
+
|
|
689
|
+
mock_unique_ai._tool_manager.available_tools = [mock_tool_1, mock_tool_2]
|
|
690
|
+
|
|
691
|
+
mock_tool_call_1 = MagicMock(spec=["name"])
|
|
692
|
+
mock_tool_call_1.name = "DeepResearch"
|
|
693
|
+
|
|
694
|
+
mock_tool_call_2 = MagicMock(spec=["name"])
|
|
695
|
+
mock_tool_call_2.name = "search_tool"
|
|
696
|
+
|
|
697
|
+
mock_tool_call_3 = MagicMock(spec=["name"])
|
|
698
|
+
mock_tool_call_3.name = "DeepResearch"
|
|
699
|
+
|
|
700
|
+
mock_tool_call_4 = MagicMock(spec=["name"])
|
|
701
|
+
mock_tool_call_4.name = "search_tool"
|
|
702
|
+
|
|
703
|
+
tool_calls = [
|
|
704
|
+
mock_tool_call_1,
|
|
705
|
+
mock_tool_call_2,
|
|
706
|
+
mock_tool_call_3,
|
|
707
|
+
mock_tool_call_4,
|
|
708
|
+
]
|
|
709
|
+
|
|
710
|
+
# Act
|
|
711
|
+
mock_unique_ai._log_tool_calls(tool_calls)
|
|
712
|
+
|
|
713
|
+
# Assert
|
|
714
|
+
# All tool calls should be added to history
|
|
715
|
+
assert isinstance(mock_unique_ai._history_manager.add_tool_call.call_count, int)
|
|
716
|
+
assert mock_unique_ai._history_manager.add_tool_call.call_count == 4
|
|
717
|
+
|
|
718
|
+
# But only the non-DeepResearch tool should appear in the message log, with correct count
|
|
719
|
+
assert isinstance(
|
|
720
|
+
mock_unique_ai._message_step_logger.create_message_log_entry.call_count,
|
|
721
|
+
int,
|
|
722
|
+
)
|
|
723
|
+
assert (
|
|
724
|
+
mock_unique_ai._message_step_logger.create_message_log_entry.call_count == 1
|
|
725
|
+
)
|
|
726
|
+
# DeepResearch should be excluded, only Search Tool (2x) should appear
|
|
727
|
+
mock_unique_ai._message_step_logger.create_message_log_entry.assert_called_once_with(
|
|
728
|
+
text="**Triggered Tool Calls:**\n \n• Search Tool (2x)", references=[]
|
|
729
|
+
)
|