"""Trasy wnoszone przez moduł. Bez tego katalogu w obrazie nie istnieją.""" from __future__ import annotations import json from typing import Any import httpx from fastapi import Form from fastapi.responses import JSONResponse, StreamingResponse from app.moduly.dodatki import katalog, klient _logic: Any = None _szablony: Any = None _buduj_utc: Any = None _blad: Any = None def zamontuj(app, *, logic: Any, templates: Any, buduj_utc: Any, blad: Any, **_reszta) -> None: """Podpięcie tras i przekazanie modułowi tego, czego potrzebuje. Zależności przychodzą z zewnątrz, zamiast być importowane: moduł nie może importować `app.main`, bo to cykl — a przede wszystkim dlatego, że zależność ma iść w JEDNĄ stronę. Aplikacja wie o istnieniu modułów opcjonalnych (przez neutralny most), moduł nie wie nic o aplikacji. """ # `**_reszta` CELOWO: most podaje wszystkim modułom ten sam zestaw zależności, # a każdy bierze z niego to, czego potrzebuje. Bez tego dołożenie zależności # dla jednego modułu wywracałoby pozostałe. global _logic, _szablony, _buduj_utc, _blad _logic, _szablony, _buduj_utc, _blad = logic, templates, buduj_utc, blad katalog.ustaw_zaleznosci(logic=logic, templates=templates) @app.post("/horoscope/stream") def horoscope_stream( # noqa: ANN202 profile: str = Form("natal"), date: str = Form(...), time: str = Form(...), tz_offset: float = Form(0.0), lat: float = Form(0.0), lon: float = Form(0.0), prompt_budget: str = Form("medium"), llm_provider: str = Form("local"), llm_model: str = Form(""), from_date: str = Form(""), to_date: str = Form(""), ): """Przekazuje strumień postępu z logiki i DOKLEJA gotowy HTML wyniku. Dzięki temu okno postępu wstawia dokładnie ten sam widok, który wyrenderowałoby przeładowanie strony — jedno źródło prawdy dla wyglądu. """ try: iso_utc, _ = _buduj_utc(date, time, tz_offset) except ValueError as e: return JSONResponse({"detail": f"Niepoprawne dane wejściowe: {e}"}, status_code=422) payload: dict = { "profile": profile, "when_utc": iso_utc, "lat": lat, "lon": lon, "budget": prompt_budget, "provider": llm_provider, "model": llm_model, } if profile == "period" and from_date and to_date: payload["from_date"], payload["to_date"] = from_date, to_date def relay(): try: for raw in klient.strumien(_logic, payload): try: event = json.loads(raw) except ValueError: continue if event.get("type") == "result": event["html"] = _szablony.get_template("_prompt_result.html").render( prompt_result=event.get("result") or {} ) yield json.dumps(event, ensure_ascii=False) + "\n" except httpx.HTTPError as e: yield json.dumps({"type": "error", "message": _blad(e)}, ensure_ascii=False) + "\n" return StreamingResponse(relay(), media_type="application/x-ndjson", headers={"Cache-Control": "no-store", "X-Accel-Buffering": "no"})