"""The storyteller, run as a real OS process for `test_process_restart.py`. Not a test module, and named so pytest does not collect it: it is the program the test starts, twice, against one database file. The model is replaced with a deterministic fake before the app is imported, so the process needs no Ollama, no network and no configuration. Everything else — the engine, the migrations, the routers, the session lifecycle — is the real application, which is the whole point of spawning a process at all. python _restart_server.py """ import itertools import os import sys from pathlib import Path HERE = Path(__file__).resolve().parent sys.path.insert(0, str(HERE.parent)) # backend/, so `app` imports sys.path.insert(0, str(HERE)) # tests/, so `fakes` imports db_path, port = sys.argv[1], int(sys.argv[2]) os.environ["AIDND_DB_PATH"] = db_path # A developer's shell may point these at Postgres, and `app.database` prefers # either over the SQLite path. The suite's conftest clears them for the same # reason; a spawned process does not inherit that, so clear them here too. os.environ.pop("AIDND_DATABASE_URL", None) os.environ.pop("DATABASE_URL", None) from fakes import TALLY_PER_TURN, tally_reply # noqa: E402 _turn = itertools.count(1) class DeterministicProvider: """Records a running tally per reply, numbered so the text is checkable. The same instrumentation `test_head_cursor.py` and `test_save_points.py` use, for the same reason: it makes "the state at this position" a number the test can assert rather than a paragraph it has to interpret. M5 replaces the machinery underneath; what this measures is where the story is being read. """ last_usage = None def __init__(self, *a, **k): pass async def generate(self, parts, *, temperature, max_tokens): n = next(_turn) # An absolute running total (M5, ADR 010): turn n states n * 10, so the # value a position holds is a fact about that position rather than about # how many times something was added. yield ("text", tally_reply(f"Beat {n}.", n * TALLY_PER_TURN)) from app.routers.adventures import turns # noqa: E402 turns.OpenAICompatibleProvider = DeterministicProvider from app.main import app # noqa: E402 if __name__ == "__main__": import uvicorn # Loopback only, as every supported start path does. uvicorn.run(app, host="127.0.0.1", port=port, log_level="warning")