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ściedwadzieścia jeden ś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?” (API v1:v1 4i ścieżkiv2: wdrożone10 ścieżek wdrożonych · API v2: 6 ścieżek1 w kontrakcie)kontrakcie rozbudowy)
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). Od wersji 0.5.0 telefon obsługuje również kontrakt Companion API v2 — przed wywołaniem nowych tras odpytuje /api/companion/capabilities, a dopóki dana funkcja nie jest ogłoszona na serwerze, trzyma zdarzenia w kolejce bez ich porzucania. Wraz z wdrożeniem API v2 na serwerze otworzyły się bramy dla pobierania zadań, kolejki notatek z załącznikami, śledzenia progresji oraz modułu Życie.
Ścieżki wdrożone (Companion API v1)v1 i v2)
| 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). W API v2 obsługuje także akcje RESCHEDULE (zmiana terminu z zapisem zwrotnym do Vikunji), DELETE (odwracalne porzucenie i zamknięcie w Vikunji z etykietą porzucone) oraz REOPEN. Odmowa silnika 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. |
Ścieżki kontraktu rozbudowy (API v2 i podział zadań — klient gotowy w telefonie)
/api/companion/splitPOSTcompanionCalleraq:<id>{ questUid, requestId, steps: [{ title, estimateMin }] }{ ok, duplicate, created, xp }requestId/api/companion/capabilities
GET
companionCaller
Ogłasza wersję kontraktu (version: 2), aktywne funkcje (items, inbox, inboxFiles, progress, life), obsługiwane akcje decyzyjne (RESCHEDULE, DELETE, REOPEN) oraz limity (inboxFileMaxBytes).
/api/companion/progress
GET
companionCaller
Zwraca pełny stan trzech ścieżek progresji właściciela (Esper, Adept wraz z dziennym limitem XP za tekst oraz Majster) na klucz urządzenia.
/api/companion/items
GET
companionCaller
Stronicowana lista zadań z serwera (?filter=overdue|open|nodate&limit=100&cursor=…), pozwalająca telefonowi pobrać wszystkie zaległości do przeglądu hurtowego (do 500 pozycji).
/api/companion/inbox
POST, GET
companionCaller
Kolejka luźnych notatek z telefonu (dom, projekty, praca, pomysly). POST zapisuje notatkę idempotentnie po clientId, a GET ?since=<ISO> zwraca zmiany statusów (new, accepted, rejected, done) oraz powiązany questUid po przekształceniu notatki w zadanie.
/api/companion/inbox/{id}/files
PUT
companionCaller
Strumieniowe przesyłanie załączników do notatki (zdjęcia, wideo, nagrania głosowe, PDF do inboxFileMaxBytes) z nagłówkami Content-Type, X-File-Name oraz X-Client-File-Id zapewniającym idempotencję.
/api/companion/life
POST, DELETE
companionCaller
Dzienne podsumowanie z modułu „Życie” przesyłane wyłącznie za zgodą per kategoria (sleep, steps, mood, places, calls). Odrzuca kodem 422 wszelkie dane surowe (współrzędne, numery telefonów, treści wiadomości, nagrania). DELETE usuwa zapisane agregaty wszystkie lub dla wybranej kategorii (?category=…).
Ścieżki kontraktu rozbudowy (podział zadań — klient gotowy w telefonie)
/api/companion/split
POST
companionCaller
Ręczny podział zadania aq:<id> z telefonu ({ questUid, requestId, steps: [{ title, estimateMin }] }). Tworzy 1–6 kroków (po 5–60 min) i zwraca { ok, duplicate, created, xp }, zachowując idempotencję po requestId.
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 1521 wdrożonych ścieżek API (11 dla Lunety i 410 dla Companiona v1)z API v1 i v2) oraz 71 ścieżekścieżkę kontraktu Companionrozbudowy API v2(/api/companion/split), którektóra czekajączeka na otwarciedołączenie bramdo w capabilities.silnika. 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?