from __future__ import annotations from collections.abc import Iterator from contextlib import contextmanager from ragcore_sdk import AnswerStreamEventType, RAGCoreClient from conftest import build_answer_app, run_app @contextmanager def _client(app: object) -> Iterator[RAGCoreClient]: with run_app(app) as base_url, RAGCoreClient(base_url=base_url, token="sdk-test-token") as client: # type: ignore[arg-type] # noqa: E501 yield client def test_answer_sync_returns_typed_response() -> None: fixture = build_answer_app() with _client(fixture.app) as client: response = client.answer(query="refund window", requested_space_ids=[fixture.space_id]) assert response.answer assert response.citations assert all(claim.citation_ids for claim in response.claims) def test_answer_stream_emits_metadata_then_done_in_order() -> None: fixture = build_answer_app() with _client(fixture.app) as client: events = list( client.answer_stream(query="refund window", requested_space_ids=[fixture.space_id]) ) assert [event.type for event in events] == [ AnswerStreamEventType.RETRIEVAL_METADATA, AnswerStreamEventType.DONE, ] done_answer = events[1].as_done_answer() assert done_answer is not None assert done_answer.citations assert "refund" in done_answer.answer.lower() assert events[0].as_done_answer() is None def test_answer_stream_reports_terminal_error_event_on_invalid_generation() -> None: fixture = build_answer_app(generator_responses=["not json", "still not json"]) with _client(fixture.app) as client: events = list( client.answer_stream(query="refund window", requested_space_ids=[fixture.space_id]) ) assert [event.type for event in events] == [ AnswerStreamEventType.RETRIEVAL_METADATA, AnswerStreamEventType.ERROR, ] assert events[1].data["code"] == "validation_retries_exhausted"