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?” (API v1: 4 ścieżki wdrożone · API v2: 6 ścieżek w kontrakcie)
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.
Ścieżki wdrożone (API v1)
| 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)
| Endpoint | Metody | Dostęp | Opis działania i parametry |
|---|---|---|---|
/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. |
/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=…). |
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 15 wdrożonych ścieżek API (11 dla Lunety i 4 dla Companiona v1) oraz 7 ścieżek kontraktu Companion API v2, które czekają na otwarcie bram w capabilities. 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?