Skip to main content

uriloop

AI Cost Tracking

PyPI Version Python License AI Cost Human Time Model

  • 🤖 LLM usage: $0.4811 (11 commits)
  • 👤 Human dev: ~$573 (5.7h @ $100/h, 30min dedup)

Generated on 2026-10-30 using openrouter/qwen/qwen3-coder-next


Wspólna płaszczyzna URI/URN do autonomicznego sterowania przeglądarką (CDP) i pulpitem (noVNC/VNC) przez MCP, z warstwową analizą ekranu, pętlą zwrotną nad TODO.md i wzorcem CQRS + Event Sourcing (logs.jsonl → chat.jsonl, PostgreSQL).

Zgodność z wytycznymi wellmanifest: nl-uri-dsl-llm (NUL-001…009, 015), logs (hash-chain JSONL, runbooki), poa (typowane procesy, kwity, fail-closed), ssot (ssot.json), reuse (rejestr deklaratywny, fasady), dsl (dsl-manifest.json).

AI: decyzje, generowanie procesów, wizja

Rola Model (domyślnie) Co robi
Decyzje Liquid d1 d1:3b przez Ollama /v1/systemone wybiera Action URI z katalogu (2..255 kandydatów, także elementy ekranu po URN), ocenia ryzyko 1..3 i zgodę na wykonanie; widzi zrzut ekranu
Generator qwen3:8b (GPU 8 GB) · qwen3.8:27b-q4_K_M (≥ 20 GB) · DeepSeek deepseek-v4-flash/pro · proxy subllm tworzy proces złożony proc://uriloop/<nazwa> z kroków rejestru, z pętlą poprawek po walidacji
Wizja YOLO (ultralytics lub onnxruntime) detekcje z URN i akcjami kliknięcia na pulpicie i stronie
make ollama-pull                                   # natywnie: modele dobrane do VRAM (np. d1:3b + qwen3:8b)
make models                                        # telemetria GPU i wybrane profile
make decide Q='kliknij Powitanie' X=1              # decyzja d1 (+ wykonanie, jeśli polityka pozwala)
make generate G='wyszukaj uriloop, a następnie otwórz drugą stronę' R=1
make generate G='…' P=deepseek                     # z DEEPSEEK_API_KEY
make detect SRC=desktop                            # YOLO

W pętli: zadanie bez kroków → NL → decyzja d1 → (gdy wieloetapowe lub niepewne) generator → proc:// → weryfikacja. Zablokowane przez politykę (URILOOP_AUTONOMY, negacja „nie klikaj…”) dostaje [?] i czeka na człowieka. Szczegóły: docs/AI.md.

Szybki start

Granica wdrożenia: Ollama (d1, qwen), YOLO i ciężkie pakiety (onnxruntime, ultralytics/torch) działają natywnie na hoście — z bezpośrednim dostępem do GPU i bez wielogigabajtowych obrazów. Docker uruchamia tylko lekką infrastrukturę: Postgres, Chrome (CDP), pulpit (VNC/noVNC), stronę demo i projektor CQRS.

make host-setup    # .venv + uriloop[pg,vnc,onnx] + sprawdzenie Ollamy + `ollama pull` modeli dobranych do VRAM
                   #   INSTALL_OLLAMA=1 make host-setup — instalacja Ollamy oficjalnym skryptem
                   #   WITH_YOLO=1 make host-setup       — ultralytics (torch zainstaluj wcześniej z właściwym CUDA)
source .venv/bin/activate  # udostępnia uriloop w bieżącej powłoce, także po pracy w conda (base)
export URILOOP_ROOT="$PWD/workspace"
make up            # docker: postgres, chrome (CDP 127.0.0.1:9222), desktop (VNC :5901, noVNC :6901), demo (:8088), projektor
make doctor        # host: Ollama, modele, GPU, pakiety · docker: CDP, VNC, Postgres
make run-dry       # plan: TODO.md → Action URI (bez wykonania)
make run           # pętla autonomiczna na hoście; obserwuj workspace/TODO.md i workspace/chat.jsonl
make tail          # zdarzenia
make verify        # łańcuch hashy
make db-shell      # select * from chat_view; select * from elements_view;

Ollama działa jak zwykle na hoście (ollama serve lub usługa systemowa) pod http://127.0.0.1:11434. Usługi docker są wystawione tylko na 127.0.0.1. Opcjonalny kontener agent (make agent-docker A='todo') nie zawiera AI; jeśli ma korzystać z Ollamy hosta, ustaw URILOOP_AI_IN_DOCKER=on i uruchom Ollamę z OLLAMA_HOST=0.0.0.0.

Katalog workspace/ jest współdzielony: projektor w kontenerze działa z UID/GID użytkownika (eksportuje je make), więc pliki projekcji pozostają zapisywalne dla procesów hosta. Na macOS (Docker Desktop) blokady plików między hostem a kontenerem bywają zawodne — tam uruchom projektor natywnie (make follow) zamiast usługi projector.

Podgląd pulpitu: http://localhost:6901/vnc.html?password=vncpassword.

Interaktywny shell i przykłady

make shell uruchamia terminal ze stałym Runtime oraz bramą narzędzi MCP. Analiza i kliknięcie po URN zachowują wspólną sesję. make mcp nadal udostępnia serwer stdio dla zewnętrznego klienta MCP.

uriloop> help
uriloop> tools
uriloop> scenarios
uriloop> scenario-plan demo-complex
uriloop> scenario demo-complex http://127.0.0.1:18089/
uriloop> do browser://page/analyze
uriloop> call chat_message_post {"text":"Sprawdzenie zakończone"}
uriloop> quit

Dostępne przykłady: demo-search, demo-data, demo-complex, demo-form, demo-table, demo-files, demo-tabs, demo-auth. Wykonują analizę przed kliknięciem, wybierają bieżący URN, sprawdzają wyniki pośrednie i zapisują raport jako artefakt. Błąd zatrzymuje scenariusz; nie ma automatycznych ponowień efektów. URL wskazuje serwer demo widoczny dla sterowanej przeglądarki. Można też użyć make scenarios oraz make scenario NAME=demo-complex URL=http://127.0.0.1:18089/.

Terminal przyjmuje Action URI, nl TEKST, plan CEL i call NAZWA JSON. plan zapisuje plan do osobnego późniejszego wykonania przez proc://uriloop/run?name=.... help, tools i quit sterują terminalem; działania systemu przechodzą przez rejestr i MCP. Shell obsługuje lokalny katalog uriloop; nie jest klientem dowolnego zewnętrznego serwera MCP.

Seria scenariuszy i CI

make suite wykonuje wszystkie osiem gotowych scenariuszy, każdy w oddzielnej sesji i katalogu. Całość wymaga grantów i fikcyjnych danych do logowania:

URILOOP_GRANTS=browser.upload,browser.tabs.close,browser.secrets \
URILOOP_SECRET_DEMO_PASSWORD=uriloop-demo-only \
URILOOP_SECRET_DEMO_BAD_PASSWORD=wrong-demo-password \
make suite URL=http://127.0.0.1:18089/

W shellu uruchomionym z tymi ustawieniami odpowiednikiem jest suite http://127.0.0.1:18089/. Akcja scenario://suite/run zapisuje raport JSON, JUnit XML, kwity i logi; błąd dowolnego scenariusza daje exit 1. Można wybrać podzbiór parametrem names i limit czasu jednego przypadku parametrem timeout.

make suite-local OUT=/tmp/nowe-wyniki CHROME_BIN=/sciezka/do/chrome uruchamia własne Chromium i serwer demo na wolnych portach. Wymaga pustego katalogu wyników. Workflow GitHub Actions sprawdza Python 3.11 i 3.13 i zachowuje raporty nawet po niepowodzeniu. Szczegóły: docs/CI.md.

Rzeczywisty VNC i PostgreSQL są sprawdzane osobnym jobem real-infrastructure: tekst jest wpisywany do aplikacji xterm i weryfikowany w pliku, a lustro bazy porównywane z logiem także po awarii połączenia i replay. Lokalne uruchomienie opisuje docs/CI.md. Synchronizacja bazy ma teraz Action URI log://mirror/sync.

Nowe strony demo: formularz kontaktu (forms.html) i lista zamówień (table.html). Scenariusze otwierają je względem bazowego URL demo. Dane pozostają w pamięci strony do jej przeładowania.

uriloop> scenario demo-form http://demo/
uriloop> scenario demo-table http://demo/

demo-form sprawdza pola wymagane, niepoprawny e-mail, zastąpienie tekstu i checkbox. demo-table sprawdza filtr, sortowanie, anulowanie i potwierdzenie modala oraz odmowę kliknięcia zasłoniętej kontrolki. Polecenie browser://page/type przyjmuje clear=true, aby zastąpić zawartość wskazanego pola; wymaga wtedy URN lub selektora.

Scenariusz plikowy wymaga grantu operatora:

URILOOP_GRANTS=browser.upload ./uriloop shell
# W terminalu uriloop:
# scenario demo-files http://demo/

demo-files pobiera raport UTF-8, sprawdza nazwę, MIME, bajty i SHA-256, wykrywa HTTP 404, załącza niewłaściwy typ, czyści wybór i zapisuje poprawny załącznik dokładnie raz w atrapie. Plik jest odczytywany w formularzu lokalnie; atrapa nie wysyła go do serwera. Runner make suite-local sam przyznaje potrzebne granty i ustawia jawne dane fikcyjnego konta dla własnego Chromium i lokalnych stron demo.

browser://file/fetch?urn=… pobiera zawartość linku przez Fetch w przeglądarce do artefaktu w katalogu roboczym. Obsługuje HTTP(S) tej samej domeny, bez przekierowań, maksymalnie 5 MiB i z ograniczonym czasem. Kwit zwraca metadane pliku i artefakt; błąd, timeout lub niekompletny transfer nie tworzy artefaktu plikowego. To ścieżka pobierania przez Fetch; natywny menedżer pobierania i dialog zapisu wymagają osobnych testów.

browser://page/attach?urn=…&artifact=artifacts/…&name=raport.txt&mime=text/plain wybiera jeden artefakt we wskazanym polu plikowym. clear=true czyści wybór. Wymaga grantu browser.upload, aktualnego celu i zgodnego hasha pliku; nie odczytuje dowolnych ścieżek hosta. Transfer bajtów przez CDP działa także wtedy, gdy Chromium jest w innym kontenerze. Używa File/DataTransfer; formularze wymagające zaufanych zdarzeń systemowych lub natywnego dialogu nie są jeszcze obsługiwane.

Scenariusz kart otwiera dwie kopie tej samej strony i sprawdza oddzielny stan notatek, odrzucenie URN z innej karty oraz zachowanie po zamknięciu wybranej karty:

URILOOP_GRANTS=browser.tabs.close ./uriloop shell
# W terminalu uriloop:
# scenario demo-tabs http://demo/

browser://tabs/list zwraca URN, URL, tytuł i informację o karcie wybranej w Runtime. browser://tabs/open przyjmuje albo url, albo URN linku z analizy; otwiera i wybiera nową kartę. browser://tabs/switch?urn=… wybiera wskazaną kartę. browser://tabs/close?urn=… wymaga grantu browser.tabs.close. Po zamknięciu wybranej karty trzeba jawnie wskazać kolejną przez switch; zwykła akcja strony nie wybiera automatycznie sąsiedniej karty. Zamknięcie karty w tle zachowuje wybraną kartę i jej indeks.

URN elementów i formularzy uwzględnia kartę, także przy identycznym URL. Przełączenie czyści indeks, poprzedni obraz i obserwację; nowa sesja CDP ma osobną historię żądań. open otwiera adres linku bez wykonywania jego handlera JavaScript. Okna popup, iframe, pobieranie danych między formularzami i odzyskiwanie niezapisanej pracy wymagają dalszych scenariuszy.

Logowanie demonstracyjne:

URILOOP_GRANTS=browser.secrets \
URILOOP_SECRET_DEMO_PASSWORD=uriloop-demo-only \
URILOOP_SECRET_DEMO_BAD_PASSWORD=wrong-demo-password \
./uriloop shell
# W terminalu uriloop:
# scenario demo-auth http://demo/

To jawne dane fikcyjnego konta. demo-auth sprawdza niepoprawne dane, zalogowanie, odświeżenie, odmowę dostępu, wygaśnięcie i wylogowanie. Kody 200/401/403 są komunikatami lokalnej symulacji w sessionStorage; nie są odpowiedziami serwera uwierzytelniania. Backend, ciasteczka, SSO i MFA wymagają kolejnych testów.

browser://page/secret?urn=…&env=URILOOP_SECRET_PASSWORD odczytuje wartość z otoczenia procesu operatora i wpisuje ją wyłącznie do wskazanego pola hasła. Wymaga grantu browser.secrets, świeżego URN, poprawnego fokusu i nazwy zmiennej zaczynającej się od URILOOP_SECRET_. Nie zatwierdza formularza. W URI, kwicie i błędzie sterownika pozostaje referencja, bez wartości ani jej długości. Zwykłe browser://page/type odrzuca pole hasła; tekst tej komendy jest maskowany w publicznym URI także przy błędzie kontraktu. URI z maską jest dowodem audytu, a nie sposobem odtworzenia wpisanej treści.

Sekrety przekazuj przez referencję środowiskową, również w procesach złożonych. Nie umieszczaj ich w NL, TODO, kodzie procesu, eval ani innych parametrach URI. Ochrona dotyczy tej ścieżki wprowadzania i standardowych pól hasła; nie zapewnia maskowania dowolnych danych widocznych na ekranie ani treści, którą strona sama ujawni poza polem hasła.

Dostęp do polecenia uriloop

Instalacja znajduje się w .venv. Skrypt make host-setup aktywuje ją tylko wewnątrz swojego procesu. W nowym terminalu aktywuj środowisko przez source .venv/bin/activate, aby używać polecenia uriloop. W katalogu projektu można od razu używać ./uriloop albo .venv/bin/uriloop bez aktywacji. Launcher ./uriloop wybiera Python projektu i domyślnie zapisuje zdarzenia do workspace/; respektuje jawne URILOOP_ROOT i --root.

./uriloop --help
./uriloop nl 'wpisz „uriloop” ' --dry
./uriloop shell
# Alternatywnie, w bieżącym terminalu:
source .venv/bin/activate
export URILOOP_ROOT="$PWD/workspace"
uriloop --help

nl 'wpisz …' wpisuje do pola, które ma fokus. Do przykładu z wyszukiwaniem i weryfikacją wyniku użyj w shellu scenario demo-search http://demo/. Samo uruchomienie CLI nie wymaga goal -a.

Goal: dostarczenie zmian do prywatnego repozytorium

Do commitu i push bez wydania pakietu użyj:

make deliver
# To samo bez Make:
goal -a --no-publish push --no-version-sync --no-tag --no-changelog
# Podgląd bez wykonywania zmian:
goal -a --no-publish --dry-run push --no-version-sync --no-tag --no-changelog

W Goal 2.2.4 samo -a włącza również --force-publish. Przy czystym drzewie i braku bazowej wersji z tagów, rejestru lub historii Goal proponuje normal-bump, po czym odmawia publikacji: clean --force-publish requires an already synchronized, pre-bumped release version. To konflikt w przebiegu wydania Goal; ponowienie tego samego polecenia nie przygotuje wydania. Linie VERSION ... -> ... w tym komunikacie opisują plan, a nie wykonany zapis.

Samo --no-publish pomija publikację pakietu; pozostałe flagi w make deliver wyłączają także synchronizację wersji, tagowanie i generowanie changeloga. Podgląd Goal 2.2.4 może nadal wyświetlić hipotetyczne podbicie wersji mimo tych flag; wykonanie korzysta ze ścieżki commitu bez wydania. Goal nadal może przygotować środowisko oraz zmienić pliki konfiguracyjne, utworzyć commit i wykonać push bieżącej gałęzi. Do uruchomienia aplikacji wystarczy ./uriloop shell, a do lokalnej kontroli make test i make verify.

Ostrzeżenie AI badge generation failed pochodzi z dodatkowego mechanizmu szacowania kosztów i jest oddzielne od błędu wydania. Nie wymaga dodawania klucza OpenRouter do uruchamiania CLI ani deterministycznych scenariuszy. Wydanie do rejestru pakietów jest osobnym procesem: wymaga świadomego wyboru wersji, jej synchronizacji i konfiguracji docelowego rejestru.

Pojedyncze polecenia

uriloop do 'browser://page/navigate?url=http://demo/'
uriloop do 'browser://page/analyze?format=webp'          # zwraca URN elementów + gotowe akcje
uriloop do 'browser://page/click?urn=urn:uriloop:el:3f9c0a1b2c4d'
uriloop nl 'wpisz „uriloop” '                             # NL → browser://page/type?text=uriloop
uriloop do 'desktop://keyboard/key?key=ctrl+l'
uriloop do 'desktop://screen/analyze?grid=12'
uriloop snapshot                                          # NUL-009: stan rozmowy, procesów, zadań

MCP

Narzędzia są generowane z registry/processes.json (nazwa = URI: browser://page/click → browser_page_click), plus uri_execute (dowolne URI) i nl_execute (polecenie w języku naturalnym). Zrzuty wracają jako treść image. Zasoby: TODO.md, chat.jsonl, state.json, logs.jsonl, uriloop://registry/gbnf.

make mcp-browser   # profil CDP (natywnie, stdio)
make mcp-desktop   # profil noVNC (natywnie, stdio)

Konfiguracja klienta: .mcp.json uruchamia serwery z .venv na hoście (ustaw URILOOP_HOME na katalog projektu).

TODO.md — kolejka zadań

- [ ] Wyszukaj frazę formularzem
  - `browser://page/type?selector=%23q&text=uriloop&submit=true`
  - expect: url~search.html?q=uriloop
  - expect: text~Fraza: uriloop
- [ ] przejdź do http://demo/page2.html         ← bez kroków: NL → URI
  - expect: text~Nawigacja zakończona sukcesem

Statusy [~] w toku, [x] wykonane, [!] nieudane ustawia projektor ze zdarzeń; dopisuje też <!-- urn:uriloop:task:… -->.

Pliki robocze (workspace/)

Plik Rola
logs.jsonl Event store: append-only, prev/hash SHA-256, jedyne źródło prawdy
chat.jsonl Projekcja rozmowy: wiadomości + zwięzłe powiadomienia procesów z URI/URN
state.json Projekcja zasobów po URN (elementy, żądania, artefakty, procesy, zadania)
TODO.md Zadania (pisze człowiek) + statusy (pisze projektor)
artifacts/ PNG/WebP, Set-of-Mark, JSON warstw — adresowane treścią

Struktura

registry/processes.json   SSOT akcji (URI, schematy, aliasy NL, efekty)
src/uriloop/uri.py        Action URI / URN, stable_urn
src/uriloop/runtime.py    szyna komend + handlery (CQRS write)
src/uriloop/eventstore.py logs.jsonl + lustro PostgreSQL + artefakty
src/uriloop/projector.py  projekcje (CQRS read), follow/rebuild
src/uriloop/loop.py       pętla autonomiczna z expect i ponowieniami
src/uriloop/analysis/     warstwy L0–L4, sonda DOM, Set-of-Mark
src/uriloop/drivers/      cdp.py, vnc.py (RFB 3.8, TCP lub WebSocket noVNC)
src/uriloop/mcp/server.py serwer MCP stdio
src/uriloop/ai/           router (NUL-022), decision (d1/System One), generator (qwen/DeepSeek), vision (YOLO)
src/uriloop/composites.py procesy złożone proc://uriloop/<nazwa>, katalog DockURI
registry/models.json      SSOT modeli i profili
db/init.sql               tabela events (append-only) + widoki read-modeli

Szczegóły: docs/ARCHITECTURE.md, zasady dla agentów: AGENTS.md, runbooki: errors/.

Testy

make test — 110 testów, w tym kontrola granicy wdrożenia (brak Ollamy/GPU/torch w compose i obrazie, MCP natywnie, doctor), warstwa AI na atrapie Ollama/DeepSeek (router GPU 8 GB, kontrakt d1, polityki, pętla poprawek generatora, YOLO ONNX) i E2E zadania złożonego (d1 → generator → proc:// → weryfikacja na żywym Chromium). Pozostałe: URI/rejestr/NL, event store i projekcje, schematy, klient RFB vs atrapa serwera (TCP i WebSocket), warstwy analizy, kontrakt MCP oraz E2E z prawdziwym Chromium (pętla nad TODO.md, MCP po stdio), uruchamiane gdy przeglądarka jest dostępna.

Ograniczenia i dalsze kroki

  • Analiza pulpitu jest pikselowa (siatka, zmiany); rozpoznawanie tekstu/ikon (OCR, VLM na Set-of-Mark) to następny krok.
  • Klient VNC obsługuje kodowania Raw/CopyRect; dla wolnych łączy warto dodać Tight/ZRLE.
  • Klienci d1, qwen i DeepSeek są przetestowani na atrapach zgodnych z opublikowanymi kontraktami API, nie na prawdziwych modelach.
  • Format katalogu DockURI jest własnym profilem — repozytorium dockuri/dockuri było niedostępne.

License

Licensed under Apache-2.0.

Metadata

Release files for uriloop 0.3.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for uriloop 0.3.1
File Size Uploaded Provenance Actions
uriloop-0.3.1.tar.gz 117.3 kB Without provenance Details for uriloop-0.3.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for uriloop 0.3.1
File Interpreter ABI Platform Actions
uriloop-0.3.1-py3-none-any.whl Python 3 none any Details for uriloop-0.3.1-py3-none-any.whl

Total release size: 213.2 kB

Release files / uriloop-0.3.1.tar.gz

Download URL uriloop-0.3.1.tar.gz
Size 117.3 kB
Tags Source
SHA-256 checksum
How to use checksums
35372cbf43799ce99cf54bbf637cefa74c0c89c18d23e52c86d8569dcf4883a0
BLAKE2b-256 checksum
How to use checksums
8bb00a65ab2ea5855162c657df8f077d492faf5228e8b529f55142f611cdc902
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.7

Release files / uriloop-0.3.1-py3-none-any.whl

Download URL uriloop-0.3.1-py3-none-any.whl
Size 95.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a3f7c68b15786eeb1f36412ee3c1f79cae8b7061d47c1cafa9154efbdf9847ab
BLAKE2b-256 checksum
How to use checksums
bf1c8c76c2d89cd60ba96d3e69a95547d0a5989fa30f0decfdc3c56a88776148
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.7

Security for uriloop 0.3.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.3.1 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page