fix: retain last non-empty result set in search polling loop

DSM sends files=[] on the final finished=True poll even when results
exist in earlier rounds. Overwriting files each iteration discarded
the real results, producing a false "No files found" response.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-14 09:48:05 +02:00
parent c47221dc8f
commit 544cfb8b06
2 changed files with 38 additions and 1 deletions
+35
View File
@@ -502,6 +502,41 @@ async def test_search_polls_until_finished(config: AppConfig) -> None:
assert "1 match(es) found" in result
@pytest.mark.asyncio
async def test_search_empty_final_poll(config: AppConfig) -> None:
"""search returns results from an earlier poll when the final finished=True poll is empty.
DSM can return files=[]] on the finishing poll even when results exist — the tool
must retain the last non-empty result set rather than overwriting with [].
"""
client = MagicMock()
poll_calls = 0
async def _request(api, method, **kwargs):
nonlocal poll_calls
if method == "start":
return {"taskid": "t_empty_final"}
if method == "list":
poll_calls += 1
if poll_calls == 1:
# First poll: results available, not yet finished
return {"files": [_SEARCH_FILE], "finished": False, "total": 1}
# Second poll: finished, but DSM returns empty files
return {"files": [], "finished": True, "total": 1}
return {}
client.request = AsyncMock(side_effect=_request)
tools = _make_mcp_and_tools(config, client)
with patch("asyncio.sleep", new_callable=AsyncMock):
result = await tools["search"](path="/docker", pattern="*.yaml")
# Must surface the result from the first poll, not treat the empty final as "no results"
assert "1 match(es) found" in result
assert "/docker/app/compose.yaml" in result
@pytest.mark.asyncio
async def test_search_no_results(config: AppConfig) -> None:
"""search returns a friendly message when no files are found."""