Skip to content

Commit 9c6aa18

Browse files
Brian KrafftCopilot
andcommitted
fix(4.5): address review findings from /8eyes + /collab Round 1
- Add docstring note on intentional param asymmetry in create_tool_retrieval() - Add empty-string model test (M1: treats '' same as None) - Add create_tool_retrieval twice test (M2: idempotency) - Add constructor exception test (C2: propagates, client stays None) - Fix fragile call_args unpacking (use .kwargs) Tests: 12 → 16 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 0f16a9f commit 9c6aa18

2 files changed

Lines changed: 39 additions & 1 deletion

File tree

openspace/llm_factory.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ def create_tool_retrieval(self) -> Optional[LLMClient]:
5151
5252
Inherits llm_kwargs (api_key, api_base, etc.) so credentials
5353
from the host agent are shared across all internal LLM clients.
54+
55+
Note: intentionally omits ``enable_thinking`` and ``rate_limit_delay``
56+
since tool retrieval is a simple selection task, not a reasoning task.
5457
"""
5558
if not self._config.tool_retrieval_model:
5659
return None

tests/test_llm_factory.py

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,10 +161,45 @@ def test_inherits_llm_kwargs(self, config):
161161
factory = LLMFactory(config=config)
162162
factory.create_tool_retrieval()
163163

164-
_, kwargs = MockLLM.call_args
164+
kwargs = MockLLM.call_args.kwargs
165165
assert kwargs["api_key"] == "sk-shared"
166166
assert kwargs["api_base"] == "https://custom"
167167

168+
def test_returns_none_when_empty_string_model(self, config):
169+
"""Empty string model treated as unconfigured."""
170+
config.tool_retrieval_model = ""
171+
factory = LLMFactory(config=config)
172+
result = factory.create_tool_retrieval()
173+
assert result is None
174+
assert factory.tool_retrieval_llm is None
175+
176+
def test_create_tool_retrieval_twice_replaces(self, config):
177+
"""Second call replaces the tool retrieval client."""
178+
with patch("openspace.llm_factory.LLMClient") as MockLLM:
179+
first, second = MagicMock(), MagicMock()
180+
MockLLM.side_effect = [first, second]
181+
182+
factory = LLMFactory(config=config)
183+
factory.create_tool_retrieval()
184+
assert factory.tool_retrieval_llm is first
185+
factory.create_tool_retrieval()
186+
assert factory.tool_retrieval_llm is second
187+
188+
189+
# ---------------------------------------------------------------------------
190+
# Error handling
191+
# ---------------------------------------------------------------------------
192+
193+
class TestErrorHandling:
194+
195+
def test_create_main_exception_propagates(self, config):
196+
"""LLMClient constructor failure propagates, client stays None."""
197+
with patch("openspace.llm_factory.LLMClient", side_effect=RuntimeError("boom")):
198+
factory = LLMFactory(config=config)
199+
with pytest.raises(RuntimeError, match="boom"):
200+
factory.create_main()
201+
assert factory.llm_client is None
202+
168203

169204
# ---------------------------------------------------------------------------
170205
# OpenSpace backward compatibility

0 commit comments

Comments
 (0)