"""A real consult over the normalized route (L9). The point is the prompt-level contract: a live model must produce something that parses against our local schema, since no API-level enforcement exists. """ import io from pathlib import Path import pytest from nisse_core.loop.expert import BudgetExhausted, ExpertDesk from nisse_core.models.llm import LiteLLMClient, RoleMap from nisse_core.oplog import OpLog from nisse_dev.evals import collect from nisse_dev.state import StateStore pytestmark = pytest.mark.integration @pytest.fixture def desk(tmp_path: Path, litellm: LiteLLMClient, live_model: str): def make(budget: int = 2) -> tuple[ExpertDesk, StateStore]: model = live_model roles = RoleMap(driver=model, helper=model, expert=model) store = StateStore( tmp_path / "state.db", oplog=OpLog("nisse-dev", io.StringIO()) ) return ExpertDesk(litellm, roles, budget=budget), store return make def test_live_consult_parses_against_the_local_schema(desk) -> None: expert, store = desk() answer = expert.ask( store.transcript("t", "expert"), "For a single-process agent storing a few thousand rows of task state, " "is SQLite sufficient, or is PostgreSQL warranted? Answer briefly.", ) assert answer.confidence in {"high", "medium", "low"} assert len(answer.answer) > 20 # The consult is captured for L9 without any extra bookkeeping. [record] = collect(store) assert record.role == "expert" assert record.exit_status == "answered" def test_live_budget_stops_a_circling_caller(desk) -> None: expert, store = desk(budget=1) expert.ask( store.transcript("t", "expert"), "Name one advantage of WAL mode in SQLite. Be brief.", ) with pytest.raises(BudgetExhausted): expert.ask(store.transcript("t", "expert"), "And another?")