"""A real consult over the normalized route (A14). 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 import os from pathlib import Path import pytest from nisse_dev.envfile import load_env_file from nisse_dev.evals import collect from nisse_dev.expert import BudgetExhausted, ExpertDesk from nisse_dev.llm import LiteLLMClient, RoleMap from nisse_dev.oplog import OpLog from nisse_dev.state import StateStore load_env_file(Path(__file__).resolve().parents[2] / ".env") SENTINEL = "NISSE_LIVE_PLANNER_MODEL" pytestmark = [ pytest.mark.integration, pytest.mark.skipif( not os.environ.get(SENTINEL), reason=f"no live frontier route configured ({SENTINEL} unset)", ), ] def desk(tmp_path: Path, budget: int = 2) -> tuple[ExpertDesk, StateStore]: model = os.environ[SENTINEL] roles = RoleMap(executor=model, planner=model, delegate=model, consultant=model) store = StateStore(tmp_path / "state.db", oplog=OpLog("nisse-dev", io.StringIO())) return ExpertDesk(LiteLLMClient.from_env(), store, roles, budget=budget), store def test_live_consult_parses_against_the_local_schema(tmp_path: Path) -> None: expert, store = desk(tmp_path) answer = expert.ask( "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 A16 without any extra bookkeeping. [record] = collect(store) assert record.role == "consultant" assert record.exit_status == "answered" def test_live_budget_stops_a_circling_caller(tmp_path: Path) -> None: expert, _ = desk(tmp_path, budget=1) expert.ask("Name one advantage of WAL mode in SQLite. Be brief.") with pytest.raises(BudgetExhausted): expert.ask("And another?")