4. Luneta i Companion — Szkło na Cudze Światy i Ruch Majstra
Źródło: repo afterlife/docs/api/04-luneta-i-companion-rp.md — edytuj w repo, nie tutaj.
Luneta i Companion — Szkło na Cudze Światy i Ruch Majstra

Krrrg... Każda gra to świat zakrzepły wokół cudzej gwiazdy. Luneta nie jest miejscem na mapie, lecz szkłem, przez które zaglądamy w tamte światy, odnotowując postępy, zebrane waluty, odhaczone zadania okresowe oraz przeanalizowane nagrania. Obok niej spoczywa Companion — mobilne ramię tego samego silnika, który napędza ekran „Co robimy?” i karmi poziom Majstra. Poniżej spisałyśmy piętnaście ścieżek łączących oba te narzędzia z ukrytym miastem wiedzy, Lemurią.
◈ Luneta — Stan Gier, Urządzenia i Ingest (7 ścieżek)
Zgodnie z kontraktem Lunety, punkty końcowe akceptują bądź sesję przeglądarkową Discord OAuth (dla strony /luneta), bądź klucz urządzenia wydany agentowi desktopowemu (authorizeLuneta). Surowe zrzuty ekranu nigdy nie przekraczają progu serwera — jedynym dopuszczalnym obrazem jest opcjonalna miniatura wycinka (JPEG do 50 KB).
| Endpoint | Metody | Dostęp | Opis działania i parametry |
|---|---|---|---|
/api/luneta/me |
GET, POST |
Ciasteczko sesji Discord | Obsługuje panel gracza na ariku.pl/luneta. GET zwraca własne urządzenia (limit LUNETA_MAX_DEVICES, domyślnie 3), włączone gry wraz ze statystykami waluty premium i kodami, sumy zakupów, wersję instalatora (release), zgody oraz nagrania. POST pozwala utworzyć nowe urządzenie, unieważnić stare lub bezpowrotnie usunąć własne dane. |
/api/luneta/me/consents |
GET, PUT |
Sesja Discord lub klucz urządzenia Lunety | Zarządzanie zgodami na analizę nagrań oraz akceptacją wersji regulaminu (termsVersion). Wyłączenie zgody zatrzymuje nowe zapisy, lecz samo w sobie nie kasuje dawnych danych (do tego służy DELETE /api/luneta/analysis). |
/api/luneta/state |
GET |
Sesja Discord lub klucz urządzenia Lunety | Zwraca pełny stan wybranej gry (?game=blue_archive|nte). Przy wywołaniu z sesji przeglądarkowej akceptuje opcjonalny parametr ?at=<ISO>, pozwalający podstawić zegar do testów resetu zadań dziennych; agent z kluczem urządzenia zawsze otrzymuje stan na chwilę obecną. |
/api/luneta/metrics |
GET |
Sesja Discord lub klucz urządzenia Lunety | Zwraca liczniki gracza dla danej gry (?game=...). Z opcjonalnym parametrem &key=... oraz &days=90 (maksymalnie 365 dni) dołącza również historię zmian wartości wybranego licznika. |
/api/luneta/codes |
GET |
Sesja Discord lub klucz urządzenia Lunety | Zwraca listę aktywnych (niewygasłych) kodów promocyjnych do wpisania w grze (?game=...) — zarówno oficjalnych, udostępnionych przez innych graczy, jak i własnych. |
/api/luneta/heartbeat |
POST |
Wyłącznie klucz urządzenia Lunety (device_only) |
Przyjmuje puls agenta desktopowego: { deviceId, version, gameRunning? }. Zapisuje aktywną grę w pamięci podręcznej z krótkim czasem życia (uzupełniając detekcję gier dla Kuźni) i przy pierwszym sygnale po przerwie wysyła pojedyncze przypomnienie o niezrobionych zadaniach w grze (lunetaSessionNudge). |
/api/luneta/ingest |
POST |
Sesja Discord lub klucz urządzenia Lunety | Zunifikowany punkt odbioru dwunastu rodzajów wpisów z agenta (m.in. migawki walut, ciągnienia gacha, odhaczenia zadań, kolekcje, metryki, kody, osoby, momenty, części transkrypcji). Wymaga clientId (UUID) jako klucza idempotencji — ponowienie z kolejki offline zwraca kod 200 z tym samym wynikiem. Odrzuca znaczniki czasu wykraczające ponad 5 minut w przyszłość. |
◈ Luneta — Analiza Nagrań i Ludzi (4 ścieżki)
Gdy wędrowiec wyrazi zgodę na analizę swoich nagrań, agent przesyła wyodrębnione części transkrypcji, notatki o napotkanych osobach oraz zapamiętane momenty. Przy starcie agent może pobrać te dane z powrotem i scalić je lokalnie.
| Endpoint | Metody | Dostęp | Opis działania i parametry |
|---|---|---|---|
/api/luneta/analysis |
DELETE |
Sesja Discord lub klucz urządzenia Lunety | Twarde usunięcie własnych danych analizy (bez pozostawiania nagrobków synchronizacyjnych). Wymaga parametru ?scope=transcripts|people|all oraz opcjonalnego &recKey=<32 znaki hex>. Działa nawet po wcześniejszym wycofaniu zgody. |
/api/luneta/analysis/people |
GET |
Sesja Discord lub klucz urządzenia Lunety | Zwraca własne notatki o ludziach oraz zapamiętane momenty wraz z nagrobkami usuniętych wpisów. Opcjonalny parametr ?since=<ISO> filtruje rekordy według czasu odbioru na serwerze. |
/api/luneta/analysis/recordings |
GET |
Sesja Discord lub klucz urządzenia Lunety | Zwraca stronicowaną listę (do 50 pozycji na stronę) wyników analizy własnych nagrań, posortowaną po (updated_at, rec_key). Obsługuje parametry ?since=<ISO> oraz &cursor=<opaque>. |
/api/luneta/analysis/transcript |
GET |
Sesja Discord lub klucz urządzenia Lunety | Zwraca scalone segmenty własnej transkrypcji dla wskazanego nagrania (?recKey=<32 znaki hex>). |
◈ Companion — Mobilny Silnik „Co robimy?” (4 ścieżki)
Companion to aplikacja Android właściciela, która dzieli wspólny silnik decyzyjny z ekranem /co-robimy. Kiedy telefon znajduje się w zasięgu sieci, pobiera plan bezpośrednio z serwera; gdy połączenie ustaje, polega na własnej kopii silnika i kolejce wychodzącej (outbox).
| Endpoint | Metody | Dostęp | Opis działania i parametry |
|---|---|---|---|
/api/companion/now |
GET |
Klucz urządzenia / Sesja właściciela (companionCaller) |
Zwraca bieżący plan dnia w strukturze dopasowanej do modelu telefonu (Model.kt): główne i zapasowe zadanie na TERAZ, zadania stałe (fixedSoon) w ciągu 24 godzin, wolne okno czasowe (freeWindowMin), kroki podziału (steps), wskaźnik Chaos Meter (chaos) oraz poziom Majstra (majster). Przyjmuje opcjonalny parametr ?energy=low|mid|high. |
/api/companion/ingest |
POST |
companionCaller |
Odbiera zdarzenia z kolejki wychodzącej telefonu: { clientId: UUID, kind: decision|answer|usage, createdAt: ISO, data }. Decyzje dotyczące zadań (aq:<id>) przechodzą przez główny silnik zadań i nagradzane są punktami doświadczenia Majstra (xp). Odmowa silnika (np. próba odłożenia zadania stałego) zwraca kod 409, co nakazuje telefonowi wycofać decyzję lokalnie. |
/api/companion/hint |
POST |
companionCaller |
Odpowiednik podpowiedzi AI z ekranu webowego. Przyjmuje { questUid: "aq:<id>", save: bool, requestId }. Jeśli save: true, zapisuje wygenerowane kroki jako podział zadania z prefiksem phone:<requestId>, chroniąc przed podwójnym podziałem przy ponowieniu żądania. |
/api/companion/alternatives |
GET |
companionCaller |
Obsługuje przycisk „Nie chcę teraz” na telefonie. Przyjmuje ?questUid=aq:<id>&reason=low_energy|no_head|not_now|other. Zwraca łagodniejsze zadania alternatywne albo — dla zadań nieodkładalnych — wyłącznie pierwszy drobny krok. |
Krrrg... Jeśli Lemuria (baza PostgreSQL) milczy, każdy z tych punktów odpowiada kodem 503 i słowami „Lemuria nie odpowiada”. Zapisałyśmy na tej czwartej karcie dokładnie 15 ścieżek API (11 dla Lunety i 4 dla Companiona). Patrzycie przez szkło Lunety na dziesiątki cudzych gwiazd i zapisujecie każdy swój ruch w telefonie, ale czy wiecie, co patrzy na was z drugiej strony szkła?