uriloop 0.3.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- uriloop-0.3.1/LICENSE +11 -0
- uriloop-0.3.1/PKG-INFO +307 -0
- uriloop-0.3.1/README.md +282 -0
- uriloop-0.3.1/pyproject.toml +42 -0
- uriloop-0.3.1/setup.cfg +4 -0
- uriloop-0.3.1/src/uriloop/__init__.py +2 -0
- uriloop-0.3.1/src/uriloop/__main__.py +5 -0
- uriloop-0.3.1/src/uriloop/ai/__init__.py +0 -0
- uriloop-0.3.1/src/uriloop/ai/decision.py +305 -0
- uriloop-0.3.1/src/uriloop/ai/generator.py +153 -0
- uriloop-0.3.1/src/uriloop/ai/http.py +35 -0
- uriloop-0.3.1/src/uriloop/ai/router.py +129 -0
- uriloop-0.3.1/src/uriloop/ai/vision.py +181 -0
- uriloop-0.3.1/src/uriloop/analysis/__init__.py +0 -0
- uriloop-0.3.1/src/uriloop/analysis/dom_probe.js +108 -0
- uriloop-0.3.1/src/uriloop/analysis/file_transfer.js +53 -0
- uriloop-0.3.1/src/uriloop/analysis/layers.py +211 -0
- uriloop-0.3.1/src/uriloop/cli.py +247 -0
- uriloop-0.3.1/src/uriloop/composites.py +150 -0
- uriloop-0.3.1/src/uriloop/doctor.py +111 -0
- uriloop-0.3.1/src/uriloop/drivers/__init__.py +0 -0
- uriloop-0.3.1/src/uriloop/drivers/cdp.py +234 -0
- uriloop-0.3.1/src/uriloop/drivers/vnc.py +227 -0
- uriloop-0.3.1/src/uriloop/eventstore.py +236 -0
- uriloop-0.3.1/src/uriloop/files.py +76 -0
- uriloop-0.3.1/src/uriloop/loop.py +188 -0
- uriloop-0.3.1/src/uriloop/mcp/__init__.py +0 -0
- uriloop-0.3.1/src/uriloop/mcp/server.py +191 -0
- uriloop-0.3.1/src/uriloop/nl.py +127 -0
- uriloop-0.3.1/src/uriloop/privacy.py +55 -0
- uriloop-0.3.1/src/uriloop/projector.py +147 -0
- uriloop-0.3.1/src/uriloop/registry.py +93 -0
- uriloop-0.3.1/src/uriloop/runtime.py +675 -0
- uriloop-0.3.1/src/uriloop/scenarios.py +240 -0
- uriloop-0.3.1/src/uriloop/shell.py +102 -0
- uriloop-0.3.1/src/uriloop/suites.py +96 -0
- uriloop-0.3.1/src/uriloop/tabs.py +102 -0
- uriloop-0.3.1/src/uriloop/targeting.py +67 -0
- uriloop-0.3.1/src/uriloop/todo.py +104 -0
- uriloop-0.3.1/src/uriloop/uri.py +124 -0
- uriloop-0.3.1/src/uriloop.egg-info/PKG-INFO +307 -0
- uriloop-0.3.1/src/uriloop.egg-info/SOURCES.txt +60 -0
- uriloop-0.3.1/src/uriloop.egg-info/dependency_links.txt +1 -0
- uriloop-0.3.1/src/uriloop.egg-info/entry_points.txt +3 -0
- uriloop-0.3.1/src/uriloop.egg-info/requires.txt +20 -0
- uriloop-0.3.1/src/uriloop.egg-info/top_level.txt +1 -0
- uriloop-0.3.1/tests/test_ai.py +222 -0
- uriloop-0.3.1/tests/test_boundary.py +76 -0
- uriloop-0.3.1/tests/test_concurrency.py +35 -0
- uriloop-0.3.1/tests/test_core.py +205 -0
- uriloop-0.3.1/tests/test_e2e_browser.py +479 -0
- uriloop-0.3.1/tests/test_eventstore_boundaries.py +39 -0
- uriloop-0.3.1/tests/test_execution.py +144 -0
- uriloop-0.3.1/tests/test_files.py +101 -0
- uriloop-0.3.1/tests/test_layers.py +68 -0
- uriloop-0.3.1/tests/test_mcp.py +54 -0
- uriloop-0.3.1/tests/test_pg_mirror.py +84 -0
- uriloop-0.3.1/tests/test_privacy.py +107 -0
- uriloop-0.3.1/tests/test_shell.py +99 -0
- uriloop-0.3.1/tests/test_suites.py +74 -0
- uriloop-0.3.1/tests/test_tabs.py +133 -0
- uriloop-0.3.1/tests/test_vnc.py +126 -0
uriloop-0.3.1/LICENSE
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Copyright 2026 uriloop contributors
|
|
2
|
+
|
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
you may not use this project except in compliance with the License.
|
|
5
|
+
You may obtain a copy of the License at
|
|
6
|
+
|
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
|
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
uriloop-0.3.1/PKG-INFO
ADDED
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: uriloop
|
|
3
|
+
Version: 0.3.1
|
|
4
|
+
Summary: Wspólna płaszczyzna URI/URN do autonomicznego sterowania przeglądarką (CDP) i pulpitem (noVNC) z pętlą zwrotną CQRS+ES i serwerami MCP
|
|
5
|
+
License-Expression: Apache-2.0
|
|
6
|
+
Requires-Python: >=3.11
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Requires-Dist: websockets>=12
|
|
10
|
+
Requires-Dist: jsonschema>=4.18
|
|
11
|
+
Requires-Dist: pillow>=10
|
|
12
|
+
Provides-Extra: pg
|
|
13
|
+
Requires-Dist: psycopg[binary]>=3.1; extra == "pg"
|
|
14
|
+
Provides-Extra: vnc
|
|
15
|
+
Requires-Dist: pycryptodome>=3.19; extra == "vnc"
|
|
16
|
+
Provides-Extra: onnx
|
|
17
|
+
Requires-Dist: onnxruntime>=1.18; extra == "onnx"
|
|
18
|
+
Requires-Dist: numpy>=1.26; extra == "onnx"
|
|
19
|
+
Provides-Extra: yolo
|
|
20
|
+
Requires-Dist: ultralytics>=8.3; extra == "yolo"
|
|
21
|
+
Provides-Extra: test
|
|
22
|
+
Requires-Dist: pyyaml>=6; extra == "test"
|
|
23
|
+
Requires-Dist: onnx>=1.15; extra == "test"
|
|
24
|
+
Dynamic: license-file
|
|
25
|
+
|
|
26
|
+
# uriloop
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
## AI Cost Tracking
|
|
30
|
+
|
|
31
|
+
   
|
|
32
|
+
  
|
|
33
|
+
|
|
34
|
+
- 🤖 **LLM usage:** $0.4811 (11 commits)
|
|
35
|
+
- 👤 **Human dev:** ~$573 (5.7h @ $100/h, 30min dedup)
|
|
36
|
+
|
|
37
|
+
Generated on 2026-10-30 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
Wspólna płaszczyzna **URI/URN** do autonomicznego sterowania **przeglądarką (CDP)** i **pulpitem (noVNC/VNC)**
|
|
44
|
+
przez **MCP**, z warstwową analizą ekranu, pętlą zwrotną nad `TODO.md` i wzorcem **CQRS + Event Sourcing**
|
|
45
|
+
(`logs.jsonl` → `chat.jsonl`, PostgreSQL).
|
|
46
|
+
|
|
47
|
+
Zgodność z wytycznymi wellmanifest: `nl-uri-dsl-llm` (NUL-001…009, 015), `logs` (hash-chain JSONL, runbooki),
|
|
48
|
+
`poa` (typowane procesy, kwity, fail-closed), `ssot` (`ssot.json`), `reuse` (rejestr deklaratywny, fasady), `dsl` (`dsl-manifest.json`).
|
|
49
|
+
|
|
50
|
+
## AI: decyzje, generowanie procesów, wizja
|
|
51
|
+
|
|
52
|
+
| Rola | Model (domyślnie) | Co robi |
|
|
53
|
+
|---|---|---|
|
|
54
|
+
| 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 |
|
|
55
|
+
| 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 |
|
|
56
|
+
| Wizja | YOLO (`ultralytics` lub `onnxruntime`) | detekcje z URN i akcjami kliknięcia na pulpicie i stronie |
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
make ollama-pull # natywnie: modele dobrane do VRAM (np. d1:3b + qwen3:8b)
|
|
60
|
+
make models # telemetria GPU i wybrane profile
|
|
61
|
+
make decide Q='kliknij Powitanie' X=1 # decyzja d1 (+ wykonanie, jeśli polityka pozwala)
|
|
62
|
+
make generate G='wyszukaj uriloop, a następnie otwórz drugą stronę' R=1
|
|
63
|
+
make generate G='…' P=deepseek # z DEEPSEEK_API_KEY
|
|
64
|
+
make detect SRC=desktop # YOLO
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
W pętli: zadanie bez kroków → NL → decyzja d1 → (gdy wieloetapowe lub niepewne) generator → `proc://` → weryfikacja.
|
|
68
|
+
Zablokowane przez politykę (`URILOOP_AUTONOMY`, negacja „nie klikaj…”) dostaje `[?]` i czeka na człowieka.
|
|
69
|
+
Szczegóły: [docs/AI.md](docs/AI.md).
|
|
70
|
+
|
|
71
|
+
## Szybki start
|
|
72
|
+
|
|
73
|
+
**Granica wdrożenia:** Ollama (d1, qwen), YOLO i ciężkie pakiety (onnxruntime, ultralytics/torch) działają
|
|
74
|
+
**natywnie na hoście** — z bezpośrednim dostępem do GPU i bez wielogigabajtowych obrazów. Docker uruchamia tylko
|
|
75
|
+
lekką infrastrukturę: Postgres, Chrome (CDP), pulpit (VNC/noVNC), stronę demo i projektor CQRS.
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
make host-setup # .venv + uriloop[pg,vnc,onnx] + sprawdzenie Ollamy + `ollama pull` modeli dobranych do VRAM
|
|
79
|
+
# INSTALL_OLLAMA=1 make host-setup — instalacja Ollamy oficjalnym skryptem
|
|
80
|
+
# WITH_YOLO=1 make host-setup — ultralytics (torch zainstaluj wcześniej z właściwym CUDA)
|
|
81
|
+
source .venv/bin/activate # udostępnia uriloop w bieżącej powłoce, także po pracy w conda (base)
|
|
82
|
+
export URILOOP_ROOT="$PWD/workspace"
|
|
83
|
+
make up # docker: postgres, chrome (CDP 127.0.0.1:9222), desktop (VNC :5901, noVNC :6901), demo (:8088), projektor
|
|
84
|
+
make doctor # host: Ollama, modele, GPU, pakiety · docker: CDP, VNC, Postgres
|
|
85
|
+
make run-dry # plan: TODO.md → Action URI (bez wykonania)
|
|
86
|
+
make run # pętla autonomiczna na hoście; obserwuj workspace/TODO.md i workspace/chat.jsonl
|
|
87
|
+
make tail # zdarzenia
|
|
88
|
+
make verify # łańcuch hashy
|
|
89
|
+
make db-shell # select * from chat_view; select * from elements_view;
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Ollama działa jak zwykle na hoście (`ollama serve` lub usługa systemowa) pod `http://127.0.0.1:11434`.
|
|
93
|
+
Usługi docker są wystawione tylko na `127.0.0.1`. Opcjonalny kontener `agent` (`make agent-docker A='todo'`)
|
|
94
|
+
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`.
|
|
95
|
+
|
|
96
|
+
Katalog `workspace/` jest współdzielony: projektor w kontenerze działa z UID/GID użytkownika (eksportuje je `make`),
|
|
97
|
+
więc pliki projekcji pozostają zapisywalne dla procesów hosta. Na macOS (Docker Desktop) blokady plików między
|
|
98
|
+
hostem a kontenerem bywają zawodne — tam uruchom projektor natywnie (`make follow`) zamiast usługi `projector`.
|
|
99
|
+
|
|
100
|
+
Podgląd pulpitu: `http://localhost:6901/vnc.html?password=vncpassword`.
|
|
101
|
+
|
|
102
|
+
## Interaktywny shell i przykłady
|
|
103
|
+
|
|
104
|
+
`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.
|
|
105
|
+
|
|
106
|
+
```text
|
|
107
|
+
uriloop> help
|
|
108
|
+
uriloop> tools
|
|
109
|
+
uriloop> scenarios
|
|
110
|
+
uriloop> scenario-plan demo-complex
|
|
111
|
+
uriloop> scenario demo-complex http://127.0.0.1:18089/
|
|
112
|
+
uriloop> do browser://page/analyze
|
|
113
|
+
uriloop> call chat_message_post {"text":"Sprawdzenie zakończone"}
|
|
114
|
+
uriloop> quit
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
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/`.
|
|
118
|
+
|
|
119
|
+
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.
|
|
120
|
+
|
|
121
|
+
## Seria scenariuszy i CI
|
|
122
|
+
|
|
123
|
+
`make suite` wykonuje wszystkie osiem gotowych scenariuszy, każdy w oddzielnej sesji i katalogu. Całość wymaga grantów i fikcyjnych danych do logowania:
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
URILOOP_GRANTS=browser.upload,browser.tabs.close,browser.secrets \
|
|
127
|
+
URILOOP_SECRET_DEMO_PASSWORD=uriloop-demo-only \
|
|
128
|
+
URILOOP_SECRET_DEMO_BAD_PASSWORD=wrong-demo-password \
|
|
129
|
+
make suite URL=http://127.0.0.1:18089/
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
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`.
|
|
133
|
+
|
|
134
|
+
`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](docs/CI.md).
|
|
135
|
+
|
|
136
|
+
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](docs/CI.md). Synchronizacja bazy ma teraz Action URI `log://mirror/sync`.
|
|
137
|
+
|
|
138
|
+
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.
|
|
139
|
+
|
|
140
|
+
```text
|
|
141
|
+
uriloop> scenario demo-form http://demo/
|
|
142
|
+
uriloop> scenario demo-table http://demo/
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
`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.
|
|
146
|
+
|
|
147
|
+
Scenariusz plikowy wymaga grantu operatora:
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
URILOOP_GRANTS=browser.upload ./uriloop shell
|
|
151
|
+
# W terminalu uriloop:
|
|
152
|
+
# scenario demo-files http://demo/
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
`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.
|
|
156
|
+
|
|
157
|
+
`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.
|
|
158
|
+
|
|
159
|
+
`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.
|
|
160
|
+
|
|
161
|
+
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:
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
URILOOP_GRANTS=browser.tabs.close ./uriloop shell
|
|
165
|
+
# W terminalu uriloop:
|
|
166
|
+
# scenario demo-tabs http://demo/
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
`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.
|
|
170
|
+
|
|
171
|
+
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.
|
|
172
|
+
|
|
173
|
+
Logowanie demonstracyjne:
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
URILOOP_GRANTS=browser.secrets \
|
|
177
|
+
URILOOP_SECRET_DEMO_PASSWORD=uriloop-demo-only \
|
|
178
|
+
URILOOP_SECRET_DEMO_BAD_PASSWORD=wrong-demo-password \
|
|
179
|
+
./uriloop shell
|
|
180
|
+
# W terminalu uriloop:
|
|
181
|
+
# scenario demo-auth http://demo/
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
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.
|
|
185
|
+
|
|
186
|
+
`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.
|
|
187
|
+
|
|
188
|
+
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.
|
|
189
|
+
|
|
190
|
+
## Dostęp do polecenia uriloop
|
|
191
|
+
|
|
192
|
+
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`.
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
./uriloop --help
|
|
196
|
+
./uriloop nl 'wpisz „uriloop” ' --dry
|
|
197
|
+
./uriloop shell
|
|
198
|
+
# Alternatywnie, w bieżącym terminalu:
|
|
199
|
+
source .venv/bin/activate
|
|
200
|
+
export URILOOP_ROOT="$PWD/workspace"
|
|
201
|
+
uriloop --help
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
`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`.
|
|
205
|
+
|
|
206
|
+
## Goal: dostarczenie zmian do prywatnego repozytorium
|
|
207
|
+
|
|
208
|
+
Do commitu i push bez wydania pakietu użyj:
|
|
209
|
+
|
|
210
|
+
```bash
|
|
211
|
+
make deliver
|
|
212
|
+
# To samo bez Make:
|
|
213
|
+
goal -a --no-publish push --no-version-sync --no-tag --no-changelog
|
|
214
|
+
# Podgląd bez wykonywania zmian:
|
|
215
|
+
goal -a --no-publish --dry-run push --no-version-sync --no-tag --no-changelog
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
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.
|
|
219
|
+
|
|
220
|
+
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`.
|
|
221
|
+
|
|
222
|
+
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.
|
|
223
|
+
|
|
224
|
+
## Pojedyncze polecenia
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
uriloop do 'browser://page/navigate?url=http://demo/'
|
|
228
|
+
uriloop do 'browser://page/analyze?format=webp' # zwraca URN elementów + gotowe akcje
|
|
229
|
+
uriloop do 'browser://page/click?urn=urn:uriloop:el:3f9c0a1b2c4d'
|
|
230
|
+
uriloop nl 'wpisz „uriloop” ' # NL → browser://page/type?text=uriloop
|
|
231
|
+
uriloop do 'desktop://keyboard/key?key=ctrl+l'
|
|
232
|
+
uriloop do 'desktop://screen/analyze?grid=12'
|
|
233
|
+
uriloop snapshot # NUL-009: stan rozmowy, procesów, zadań
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
## MCP
|
|
237
|
+
|
|
238
|
+
Narzędzia są generowane z `registry/processes.json` (nazwa = URI: `browser://page/click` → `browser_page_click`),
|
|
239
|
+
plus `uri_execute` (dowolne URI) i `nl_execute` (polecenie w języku naturalnym). Zrzuty wracają jako treść `image`.
|
|
240
|
+
Zasoby: `TODO.md`, `chat.jsonl`, `state.json`, `logs.jsonl`, `uriloop://registry/gbnf`.
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
make mcp-browser # profil CDP (natywnie, stdio)
|
|
244
|
+
make mcp-desktop # profil noVNC (natywnie, stdio)
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
Konfiguracja klienta: `.mcp.json` uruchamia serwery z `.venv` na hoście (ustaw `URILOOP_HOME` na katalog projektu).
|
|
248
|
+
|
|
249
|
+
## TODO.md — kolejka zadań
|
|
250
|
+
|
|
251
|
+
```markdown
|
|
252
|
+
- [ ] Wyszukaj frazę formularzem
|
|
253
|
+
- `browser://page/type?selector=%23q&text=uriloop&submit=true`
|
|
254
|
+
- expect: url~search.html?q=uriloop
|
|
255
|
+
- expect: text~Fraza: uriloop
|
|
256
|
+
- [ ] przejdź do http://demo/page2.html ← bez kroków: NL → URI
|
|
257
|
+
- expect: text~Nawigacja zakończona sukcesem
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
Statusy `[~]` w toku, `[x]` wykonane, `[!]` nieudane ustawia projektor ze zdarzeń; dopisuje też `<!-- urn:uriloop:task:… -->`.
|
|
261
|
+
|
|
262
|
+
## Pliki robocze (`workspace/`)
|
|
263
|
+
|
|
264
|
+
| Plik | Rola |
|
|
265
|
+
|---|---|
|
|
266
|
+
| `logs.jsonl` | Event store: append-only, `prev`/`hash` SHA-256, jedyne źródło prawdy |
|
|
267
|
+
| `chat.jsonl` | Projekcja rozmowy: wiadomości + zwięzłe powiadomienia procesów z URI/URN |
|
|
268
|
+
| `state.json` | Projekcja zasobów po URN (elementy, żądania, artefakty, procesy, zadania) |
|
|
269
|
+
| `TODO.md` | Zadania (pisze człowiek) + statusy (pisze projektor) |
|
|
270
|
+
| `artifacts/` | PNG/WebP, Set-of-Mark, JSON warstw — adresowane treścią |
|
|
271
|
+
|
|
272
|
+
## Struktura
|
|
273
|
+
|
|
274
|
+
```
|
|
275
|
+
registry/processes.json SSOT akcji (URI, schematy, aliasy NL, efekty)
|
|
276
|
+
src/uriloop/uri.py Action URI / URN, stable_urn
|
|
277
|
+
src/uriloop/runtime.py szyna komend + handlery (CQRS write)
|
|
278
|
+
src/uriloop/eventstore.py logs.jsonl + lustro PostgreSQL + artefakty
|
|
279
|
+
src/uriloop/projector.py projekcje (CQRS read), follow/rebuild
|
|
280
|
+
src/uriloop/loop.py pętla autonomiczna z expect i ponowieniami
|
|
281
|
+
src/uriloop/analysis/ warstwy L0–L4, sonda DOM, Set-of-Mark
|
|
282
|
+
src/uriloop/drivers/ cdp.py, vnc.py (RFB 3.8, TCP lub WebSocket noVNC)
|
|
283
|
+
src/uriloop/mcp/server.py serwer MCP stdio
|
|
284
|
+
src/uriloop/ai/ router (NUL-022), decision (d1/System One), generator (qwen/DeepSeek), vision (YOLO)
|
|
285
|
+
src/uriloop/composites.py procesy złożone proc://uriloop/<nazwa>, katalog DockURI
|
|
286
|
+
registry/models.json SSOT modeli i profili
|
|
287
|
+
db/init.sql tabela events (append-only) + widoki read-modeli
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
Szczegóły: [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md), zasady dla agentów: [AGENTS.md](AGENTS.md), runbooki: [errors/](errors/README.md).
|
|
291
|
+
|
|
292
|
+
## Testy
|
|
293
|
+
|
|
294
|
+
`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),
|
|
295
|
+
warstwy analizy, kontrakt MCP oraz E2E z prawdziwym Chromium (pętla nad TODO.md, MCP po stdio), uruchamiane gdy przeglądarka jest dostępna.
|
|
296
|
+
|
|
297
|
+
## Ograniczenia i dalsze kroki
|
|
298
|
+
|
|
299
|
+
- Analiza pulpitu jest pikselowa (siatka, zmiany); rozpoznawanie tekstu/ikon (OCR, VLM na Set-of-Mark) to następny krok.
|
|
300
|
+
- Klient VNC obsługuje kodowania Raw/CopyRect; dla wolnych łączy warto dodać Tight/ZRLE.
|
|
301
|
+
- Klienci d1, qwen i DeepSeek są przetestowani na atrapach zgodnych z opublikowanymi kontraktami API, nie na prawdziwych modelach.
|
|
302
|
+
- Format katalogu DockURI jest własnym profilem — repozytorium dockuri/dockuri było niedostępne.
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
## License
|
|
306
|
+
|
|
307
|
+
Licensed under Apache-2.0.
|
uriloop-0.3.1/README.md
ADDED
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
# uriloop
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
## AI Cost Tracking
|
|
5
|
+
|
|
6
|
+
   
|
|
7
|
+
  
|
|
8
|
+
|
|
9
|
+
- 🤖 **LLM usage:** $0.4811 (11 commits)
|
|
10
|
+
- 👤 **Human dev:** ~$573 (5.7h @ $100/h, 30min dedup)
|
|
11
|
+
|
|
12
|
+
Generated on 2026-10-30 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
Wspólna płaszczyzna **URI/URN** do autonomicznego sterowania **przeglądarką (CDP)** i **pulpitem (noVNC/VNC)**
|
|
19
|
+
przez **MCP**, z warstwową analizą ekranu, pętlą zwrotną nad `TODO.md` i wzorcem **CQRS + Event Sourcing**
|
|
20
|
+
(`logs.jsonl` → `chat.jsonl`, PostgreSQL).
|
|
21
|
+
|
|
22
|
+
Zgodność z wytycznymi wellmanifest: `nl-uri-dsl-llm` (NUL-001…009, 015), `logs` (hash-chain JSONL, runbooki),
|
|
23
|
+
`poa` (typowane procesy, kwity, fail-closed), `ssot` (`ssot.json`), `reuse` (rejestr deklaratywny, fasady), `dsl` (`dsl-manifest.json`).
|
|
24
|
+
|
|
25
|
+
## AI: decyzje, generowanie procesów, wizja
|
|
26
|
+
|
|
27
|
+
| Rola | Model (domyślnie) | Co robi |
|
|
28
|
+
|---|---|---|
|
|
29
|
+
| 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 |
|
|
30
|
+
| 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 |
|
|
31
|
+
| Wizja | YOLO (`ultralytics` lub `onnxruntime`) | detekcje z URN i akcjami kliknięcia na pulpicie i stronie |
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
make ollama-pull # natywnie: modele dobrane do VRAM (np. d1:3b + qwen3:8b)
|
|
35
|
+
make models # telemetria GPU i wybrane profile
|
|
36
|
+
make decide Q='kliknij Powitanie' X=1 # decyzja d1 (+ wykonanie, jeśli polityka pozwala)
|
|
37
|
+
make generate G='wyszukaj uriloop, a następnie otwórz drugą stronę' R=1
|
|
38
|
+
make generate G='…' P=deepseek # z DEEPSEEK_API_KEY
|
|
39
|
+
make detect SRC=desktop # YOLO
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
W pętli: zadanie bez kroków → NL → decyzja d1 → (gdy wieloetapowe lub niepewne) generator → `proc://` → weryfikacja.
|
|
43
|
+
Zablokowane przez politykę (`URILOOP_AUTONOMY`, negacja „nie klikaj…”) dostaje `[?]` i czeka na człowieka.
|
|
44
|
+
Szczegóły: [docs/AI.md](docs/AI.md).
|
|
45
|
+
|
|
46
|
+
## Szybki start
|
|
47
|
+
|
|
48
|
+
**Granica wdrożenia:** Ollama (d1, qwen), YOLO i ciężkie pakiety (onnxruntime, ultralytics/torch) działają
|
|
49
|
+
**natywnie na hoście** — z bezpośrednim dostępem do GPU i bez wielogigabajtowych obrazów. Docker uruchamia tylko
|
|
50
|
+
lekką infrastrukturę: Postgres, Chrome (CDP), pulpit (VNC/noVNC), stronę demo i projektor CQRS.
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
make host-setup # .venv + uriloop[pg,vnc,onnx] + sprawdzenie Ollamy + `ollama pull` modeli dobranych do VRAM
|
|
54
|
+
# INSTALL_OLLAMA=1 make host-setup — instalacja Ollamy oficjalnym skryptem
|
|
55
|
+
# WITH_YOLO=1 make host-setup — ultralytics (torch zainstaluj wcześniej z właściwym CUDA)
|
|
56
|
+
source .venv/bin/activate # udostępnia uriloop w bieżącej powłoce, także po pracy w conda (base)
|
|
57
|
+
export URILOOP_ROOT="$PWD/workspace"
|
|
58
|
+
make up # docker: postgres, chrome (CDP 127.0.0.1:9222), desktop (VNC :5901, noVNC :6901), demo (:8088), projektor
|
|
59
|
+
make doctor # host: Ollama, modele, GPU, pakiety · docker: CDP, VNC, Postgres
|
|
60
|
+
make run-dry # plan: TODO.md → Action URI (bez wykonania)
|
|
61
|
+
make run # pętla autonomiczna na hoście; obserwuj workspace/TODO.md i workspace/chat.jsonl
|
|
62
|
+
make tail # zdarzenia
|
|
63
|
+
make verify # łańcuch hashy
|
|
64
|
+
make db-shell # select * from chat_view; select * from elements_view;
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Ollama działa jak zwykle na hoście (`ollama serve` lub usługa systemowa) pod `http://127.0.0.1:11434`.
|
|
68
|
+
Usługi docker są wystawione tylko na `127.0.0.1`. Opcjonalny kontener `agent` (`make agent-docker A='todo'`)
|
|
69
|
+
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`.
|
|
70
|
+
|
|
71
|
+
Katalog `workspace/` jest współdzielony: projektor w kontenerze działa z UID/GID użytkownika (eksportuje je `make`),
|
|
72
|
+
więc pliki projekcji pozostają zapisywalne dla procesów hosta. Na macOS (Docker Desktop) blokady plików między
|
|
73
|
+
hostem a kontenerem bywają zawodne — tam uruchom projektor natywnie (`make follow`) zamiast usługi `projector`.
|
|
74
|
+
|
|
75
|
+
Podgląd pulpitu: `http://localhost:6901/vnc.html?password=vncpassword`.
|
|
76
|
+
|
|
77
|
+
## Interaktywny shell i przykłady
|
|
78
|
+
|
|
79
|
+
`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.
|
|
80
|
+
|
|
81
|
+
```text
|
|
82
|
+
uriloop> help
|
|
83
|
+
uriloop> tools
|
|
84
|
+
uriloop> scenarios
|
|
85
|
+
uriloop> scenario-plan demo-complex
|
|
86
|
+
uriloop> scenario demo-complex http://127.0.0.1:18089/
|
|
87
|
+
uriloop> do browser://page/analyze
|
|
88
|
+
uriloop> call chat_message_post {"text":"Sprawdzenie zakończone"}
|
|
89
|
+
uriloop> quit
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
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/`.
|
|
93
|
+
|
|
94
|
+
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.
|
|
95
|
+
|
|
96
|
+
## Seria scenariuszy i CI
|
|
97
|
+
|
|
98
|
+
`make suite` wykonuje wszystkie osiem gotowych scenariuszy, każdy w oddzielnej sesji i katalogu. Całość wymaga grantów i fikcyjnych danych do logowania:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
URILOOP_GRANTS=browser.upload,browser.tabs.close,browser.secrets \
|
|
102
|
+
URILOOP_SECRET_DEMO_PASSWORD=uriloop-demo-only \
|
|
103
|
+
URILOOP_SECRET_DEMO_BAD_PASSWORD=wrong-demo-password \
|
|
104
|
+
make suite URL=http://127.0.0.1:18089/
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
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`.
|
|
108
|
+
|
|
109
|
+
`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](docs/CI.md).
|
|
110
|
+
|
|
111
|
+
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](docs/CI.md). Synchronizacja bazy ma teraz Action URI `log://mirror/sync`.
|
|
112
|
+
|
|
113
|
+
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.
|
|
114
|
+
|
|
115
|
+
```text
|
|
116
|
+
uriloop> scenario demo-form http://demo/
|
|
117
|
+
uriloop> scenario demo-table http://demo/
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
`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.
|
|
121
|
+
|
|
122
|
+
Scenariusz plikowy wymaga grantu operatora:
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
URILOOP_GRANTS=browser.upload ./uriloop shell
|
|
126
|
+
# W terminalu uriloop:
|
|
127
|
+
# scenario demo-files http://demo/
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
`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.
|
|
131
|
+
|
|
132
|
+
`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.
|
|
133
|
+
|
|
134
|
+
`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.
|
|
135
|
+
|
|
136
|
+
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:
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
URILOOP_GRANTS=browser.tabs.close ./uriloop shell
|
|
140
|
+
# W terminalu uriloop:
|
|
141
|
+
# scenario demo-tabs http://demo/
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
`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.
|
|
145
|
+
|
|
146
|
+
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.
|
|
147
|
+
|
|
148
|
+
Logowanie demonstracyjne:
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
URILOOP_GRANTS=browser.secrets \
|
|
152
|
+
URILOOP_SECRET_DEMO_PASSWORD=uriloop-demo-only \
|
|
153
|
+
URILOOP_SECRET_DEMO_BAD_PASSWORD=wrong-demo-password \
|
|
154
|
+
./uriloop shell
|
|
155
|
+
# W terminalu uriloop:
|
|
156
|
+
# scenario demo-auth http://demo/
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
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.
|
|
160
|
+
|
|
161
|
+
`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.
|
|
162
|
+
|
|
163
|
+
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.
|
|
164
|
+
|
|
165
|
+
## Dostęp do polecenia uriloop
|
|
166
|
+
|
|
167
|
+
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`.
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
./uriloop --help
|
|
171
|
+
./uriloop nl 'wpisz „uriloop” ' --dry
|
|
172
|
+
./uriloop shell
|
|
173
|
+
# Alternatywnie, w bieżącym terminalu:
|
|
174
|
+
source .venv/bin/activate
|
|
175
|
+
export URILOOP_ROOT="$PWD/workspace"
|
|
176
|
+
uriloop --help
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
`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`.
|
|
180
|
+
|
|
181
|
+
## Goal: dostarczenie zmian do prywatnego repozytorium
|
|
182
|
+
|
|
183
|
+
Do commitu i push bez wydania pakietu użyj:
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
make deliver
|
|
187
|
+
# To samo bez Make:
|
|
188
|
+
goal -a --no-publish push --no-version-sync --no-tag --no-changelog
|
|
189
|
+
# Podgląd bez wykonywania zmian:
|
|
190
|
+
goal -a --no-publish --dry-run push --no-version-sync --no-tag --no-changelog
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
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.
|
|
194
|
+
|
|
195
|
+
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`.
|
|
196
|
+
|
|
197
|
+
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.
|
|
198
|
+
|
|
199
|
+
## Pojedyncze polecenia
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
uriloop do 'browser://page/navigate?url=http://demo/'
|
|
203
|
+
uriloop do 'browser://page/analyze?format=webp' # zwraca URN elementów + gotowe akcje
|
|
204
|
+
uriloop do 'browser://page/click?urn=urn:uriloop:el:3f9c0a1b2c4d'
|
|
205
|
+
uriloop nl 'wpisz „uriloop” ' # NL → browser://page/type?text=uriloop
|
|
206
|
+
uriloop do 'desktop://keyboard/key?key=ctrl+l'
|
|
207
|
+
uriloop do 'desktop://screen/analyze?grid=12'
|
|
208
|
+
uriloop snapshot # NUL-009: stan rozmowy, procesów, zadań
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
## MCP
|
|
212
|
+
|
|
213
|
+
Narzędzia są generowane z `registry/processes.json` (nazwa = URI: `browser://page/click` → `browser_page_click`),
|
|
214
|
+
plus `uri_execute` (dowolne URI) i `nl_execute` (polecenie w języku naturalnym). Zrzuty wracają jako treść `image`.
|
|
215
|
+
Zasoby: `TODO.md`, `chat.jsonl`, `state.json`, `logs.jsonl`, `uriloop://registry/gbnf`.
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
make mcp-browser # profil CDP (natywnie, stdio)
|
|
219
|
+
make mcp-desktop # profil noVNC (natywnie, stdio)
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Konfiguracja klienta: `.mcp.json` uruchamia serwery z `.venv` na hoście (ustaw `URILOOP_HOME` na katalog projektu).
|
|
223
|
+
|
|
224
|
+
## TODO.md — kolejka zadań
|
|
225
|
+
|
|
226
|
+
```markdown
|
|
227
|
+
- [ ] Wyszukaj frazę formularzem
|
|
228
|
+
- `browser://page/type?selector=%23q&text=uriloop&submit=true`
|
|
229
|
+
- expect: url~search.html?q=uriloop
|
|
230
|
+
- expect: text~Fraza: uriloop
|
|
231
|
+
- [ ] przejdź do http://demo/page2.html ← bez kroków: NL → URI
|
|
232
|
+
- expect: text~Nawigacja zakończona sukcesem
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
Statusy `[~]` w toku, `[x]` wykonane, `[!]` nieudane ustawia projektor ze zdarzeń; dopisuje też `<!-- urn:uriloop:task:… -->`.
|
|
236
|
+
|
|
237
|
+
## Pliki robocze (`workspace/`)
|
|
238
|
+
|
|
239
|
+
| Plik | Rola |
|
|
240
|
+
|---|---|
|
|
241
|
+
| `logs.jsonl` | Event store: append-only, `prev`/`hash` SHA-256, jedyne źródło prawdy |
|
|
242
|
+
| `chat.jsonl` | Projekcja rozmowy: wiadomości + zwięzłe powiadomienia procesów z URI/URN |
|
|
243
|
+
| `state.json` | Projekcja zasobów po URN (elementy, żądania, artefakty, procesy, zadania) |
|
|
244
|
+
| `TODO.md` | Zadania (pisze człowiek) + statusy (pisze projektor) |
|
|
245
|
+
| `artifacts/` | PNG/WebP, Set-of-Mark, JSON warstw — adresowane treścią |
|
|
246
|
+
|
|
247
|
+
## Struktura
|
|
248
|
+
|
|
249
|
+
```
|
|
250
|
+
registry/processes.json SSOT akcji (URI, schematy, aliasy NL, efekty)
|
|
251
|
+
src/uriloop/uri.py Action URI / URN, stable_urn
|
|
252
|
+
src/uriloop/runtime.py szyna komend + handlery (CQRS write)
|
|
253
|
+
src/uriloop/eventstore.py logs.jsonl + lustro PostgreSQL + artefakty
|
|
254
|
+
src/uriloop/projector.py projekcje (CQRS read), follow/rebuild
|
|
255
|
+
src/uriloop/loop.py pętla autonomiczna z expect i ponowieniami
|
|
256
|
+
src/uriloop/analysis/ warstwy L0–L4, sonda DOM, Set-of-Mark
|
|
257
|
+
src/uriloop/drivers/ cdp.py, vnc.py (RFB 3.8, TCP lub WebSocket noVNC)
|
|
258
|
+
src/uriloop/mcp/server.py serwer MCP stdio
|
|
259
|
+
src/uriloop/ai/ router (NUL-022), decision (d1/System One), generator (qwen/DeepSeek), vision (YOLO)
|
|
260
|
+
src/uriloop/composites.py procesy złożone proc://uriloop/<nazwa>, katalog DockURI
|
|
261
|
+
registry/models.json SSOT modeli i profili
|
|
262
|
+
db/init.sql tabela events (append-only) + widoki read-modeli
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
Szczegóły: [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md), zasady dla agentów: [AGENTS.md](AGENTS.md), runbooki: [errors/](errors/README.md).
|
|
266
|
+
|
|
267
|
+
## Testy
|
|
268
|
+
|
|
269
|
+
`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),
|
|
270
|
+
warstwy analizy, kontrakt MCP oraz E2E z prawdziwym Chromium (pętla nad TODO.md, MCP po stdio), uruchamiane gdy przeglądarka jest dostępna.
|
|
271
|
+
|
|
272
|
+
## Ograniczenia i dalsze kroki
|
|
273
|
+
|
|
274
|
+
- Analiza pulpitu jest pikselowa (siatka, zmiany); rozpoznawanie tekstu/ikon (OCR, VLM na Set-of-Mark) to następny krok.
|
|
275
|
+
- Klient VNC obsługuje kodowania Raw/CopyRect; dla wolnych łączy warto dodać Tight/ZRLE.
|
|
276
|
+
- Klienci d1, qwen i DeepSeek są przetestowani na atrapach zgodnych z opublikowanymi kontraktami API, nie na prawdziwych modelach.
|
|
277
|
+
- Format katalogu DockURI jest własnym profilem — repozytorium dockuri/dockuri było niedostępne.
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
## License
|
|
281
|
+
|
|
282
|
+
Licensed under Apache-2.0.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "uriloop"
|
|
7
|
+
version = "0.3.1"
|
|
8
|
+
description = "Wspólna płaszczyzna URI/URN do autonomicznego sterowania przeglądarką (CDP) i pulpitem (noVNC) z pętlą zwrotną CQRS+ES i serwerami MCP"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.11"
|
|
11
|
+
license = "Apache-2.0"
|
|
12
|
+
dependencies = ["websockets>=12", "jsonschema>=4.18", "pillow>=10"]
|
|
13
|
+
|
|
14
|
+
[project.optional-dependencies]
|
|
15
|
+
pg = ["psycopg[binary]>=3.1"]
|
|
16
|
+
vnc = ["pycryptodome>=3.19"]
|
|
17
|
+
onnx = ["onnxruntime>=1.18", "numpy>=1.26"]
|
|
18
|
+
yolo = ["ultralytics>=8.3"]
|
|
19
|
+
test = ["pyyaml>=6", "onnx>=1.15"]
|
|
20
|
+
|
|
21
|
+
[project.scripts]
|
|
22
|
+
uriloop = "uriloop.cli:main"
|
|
23
|
+
uriloop-mcp = "uriloop.mcp.server:main"
|
|
24
|
+
|
|
25
|
+
[tool.setuptools.packages.find]
|
|
26
|
+
where = ["src"]
|
|
27
|
+
|
|
28
|
+
[tool.setuptools.package-data]
|
|
29
|
+
uriloop = ["analysis/*.js"]
|
|
30
|
+
|
|
31
|
+
[tool.costs]
|
|
32
|
+
# AI Cost tracking configuration
|
|
33
|
+
badge = true
|
|
34
|
+
update_readme = true
|
|
35
|
+
readme_path = "README.md"
|
|
36
|
+
default_model = "openrouter/qwen/qwen3-coder-next"
|
|
37
|
+
analysis_mode = "byok"
|
|
38
|
+
full_history = true
|
|
39
|
+
max_commits = 500
|
|
40
|
+
|
|
41
|
+
# Cost thresholds for badge colors (USD)
|
|
42
|
+
badge_color_thresholds = { low = 1.0, medium = 5.0, high = 10.0, critical = 50.0 }
|
uriloop-0.3.1/setup.cfg
ADDED