feat(assistant): #91 etapes enrichies (sous-sections Reflechon/Sources, chevrons, indicateur anime, suppression barre de chargement)
CI / lint (push) Successful in 1m23s
CI / security (push) Successful in 58s
CI / test (push) Successful in 2m43s
CI / build (push) Successful in 55s
CI / e2e (push) Successful in 11m8s

This commit is contained in:
2026-09-15 22:53:15 -04:00
parent 431fb5626d
commit f630771150
13 changed files with 477 additions and 80 deletions
+51
View File
@@ -1024,3 +1024,54 @@ class TestEffectiveModel:
assert _effective_model("nope-not-a-provider", None) == ""
assert _effective_model(None, None) == ""
class TestToolEventSources:
"""Web sources surfaced in the « sources » section of the steps block."""
@staticmethod
def _record(name, result):
from backend.agent.loop import ToolCallRecord
return ToolCallRecord(name=name, arguments={}, ok=True, result=result)
def test_web_search_results_become_sources(self):
from backend.bookslm_routes import _tool_sources
rec = self._record("web_search", {"results": [
{"title": "Météo Paris", "url": "https://exemple.fr/meteo"},
{"title": "Sans URL", "url": ""},
{"title": "", "url": "https://exemple.fr/b"},
]})
sources = _tool_sources(rec)
assert sources == [
{"title": "Météo Paris", "url": "https://exemple.fr/meteo"},
{"title": "https://exemple.fr/b", "url": "https://exemple.fr/b"},
]
def test_fetch_url_yields_one_source(self):
from backend.bookslm_routes import _tool_sources
rec = self._record("fetch_url", {"url": "https://exemple.fr/a", "title": "Titre"})
assert _tool_sources(rec) == [{"title": "Titre", "url": "https://exemple.fr/a"}]
def test_other_tools_yield_no_sources(self):
from backend.bookslm_routes import _tool_sources
assert _tool_sources(self._record("read_file", {"content": "x"})) == []
assert _tool_sources(self._record("web_search", {"error": "boom"})) == []
assert _tool_sources(self._record("fetch_url", "not-a-dict")) == []
def test_sse_payload_carries_the_sources(self):
import json as _json
from backend.bookslm_routes import _tool_event_sse
rec = self._record("web_search", {"results": [{"title": "T", "url": "https://exemple.fr/t"}]})
payload = _tool_event_sse(rec)
assert payload.startswith("event: tool\ndata: ")
data = _json.loads(payload.split("data: ", 1)[1])
assert data["name"] == "web_search"
assert data["sources"] == [{"title": "T", "url": "https://exemple.fr/t"}]
# Non-web tools keep the key, empty, so the UI never guesses.
assert _json.loads(_tool_event_sse(self._record("read_file", {})).split("data: ", 1)[1])["sources"] == []