65de90114a
Der Compliance-Check streamt jetzt progressive Events; der Impressum-Tab
erscheint, sobald das Thema fertig ist, statt am Ende alles auf einmal.
Additiv — das Polling fürs finale Ergebnis bleibt.
- backend: _sse.py (Queue/emit/event_generator) + Endpoint
/compliance-check/{id}/stream; _update emittiert progress,
run_agent_outputs emittiert topic (laeuft jetzt frueh nach Phase B),
Orchestrator emittiert complete/error.
- frontend: SSE-Proxy-Route + EventSource in ComplianceCheckTab merged
topic-Events in agent_outputs -> Tab erscheint progressiv.
- Tests: backend 5 passed (SSE + agent_outputs); tsc 0 neue Fehler,
vitest 2 passed, check-loc 0.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
51 lines
1.5 KiB
Python
51 lines
1.5 KiB
Python
"""Phase 2: SSE-Plumbing für den Compliance-Check.
|
|
|
|
Deckt emit (Queue-Push), _format_sse (SSE-Zeilenformat) und den
|
|
event_generator (hello → Events → stream_close bei 'complete') ab.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import asyncio
|
|
|
|
from compliance.api.agent_check import _sse
|
|
|
|
|
|
def test_emit_pushes_and_format():
|
|
cid = "sse-test-1"
|
|
_sse.new_queue(cid)
|
|
_sse.emit(cid, {"type": "topic", "topic": "impressum", "output": {"x": 1}})
|
|
q = _sse._check_queues[cid]
|
|
assert q.qsize() == 1
|
|
ev = q.get_nowait()
|
|
assert ev["type"] == "topic" and ev["topic"] == "impressum"
|
|
line = _sse._format_sse(ev)
|
|
assert line.startswith("data: ") and line.endswith("\n\n")
|
|
assert '"impressum"' in line
|
|
|
|
|
|
def test_emit_is_noop_without_queue():
|
|
# Kein new_queue → emit darf nicht crashen (best-effort).
|
|
_sse.emit("does-not-exist-xyz", {"type": "topic"})
|
|
|
|
|
|
def test_event_generator_streams_topic_then_closes_on_complete():
|
|
cid = "sse-test-gen"
|
|
_sse.new_queue(cid)
|
|
_sse.emit(cid, {"type": "topic", "topic": "impressum", "output": {}})
|
|
_sse.emit(cid, {"type": "complete", "status": "completed"})
|
|
|
|
async def collect():
|
|
out = []
|
|
async for line in _sse.event_generator(cid):
|
|
out.append(line)
|
|
if len(out) > 12: # safety
|
|
break
|
|
return out
|
|
|
|
blob = "".join(asyncio.run(collect()))
|
|
assert '"type": "hello"' in blob
|
|
assert '"topic": "impressum"' in blob
|
|
assert '"type": "complete"' in blob
|
|
assert '"type": "stream_close"' in blob
|