Přeskočit na obsah

Stanice

Jen fakta. Model za nimi je ve Stanicích a izolovaných prostředích; stroj otevřeš podle návodu.

Plocha Řídí Backend Hodnota Uzavřený odchozí provoz
Terminál (exec) Shell přes exec kanál VM microVM smolvm Ano
Prohlížeč Bezhlavý Chromium (CDP), Firefox (WebDriver BiDi) nebo WebKit (W3C WebDriver) microVM smolvm Ano
Počítač Plocha X11: vstup přes hypervisor, záznam přes agenta hosta QEMU qemu-hvf (macOS), qemu-kvm (Linux), qemu-tcg (nezrychlený záložní režim, nikdy se nevybere sám) Ano
Android Android přes ADB Emulátor Googlu android-emulator Ne — síť si řídí emulátor
iOS Simulátor iOS přes WebDriverAgent CoreSimulator ios-simulator Ne — síť sleduje hostitelský Mac

Terminál a plocha computer_use sdílejí hodnotu plochy computer; terminál se pozná podle značky exec obrazu a nikdy se znovu nepoužije jako plocha, kterou jde řídit (ani naopak). Jedna konverzace znovu použije jeden stroj terminálu.

Engine Hodnota Protokol Živý náhled Snímky
Chromium chromium (výchozí) Chrome DevTools Protocol Screencast — prohlížeč tlačí snímky, jak se stránka překresluje JPEG
Firefox firefox WebDriver BiDi Dotazované snímky (BiDi screencast nemá), strop 6 fps JPEG
WebKit webkit W3C WebDriver (klasický) Dotazované snímky, překódované ffmpeg hostitele PNG

Stanice běží celý život na jednom enginu. Jedna konverzace unese jednu stanici na engine, a právě proto jde srovnání vedle sebe: otevření „Firefox (VM)“ vedle „Chromium (VM)“ jsou dva stroje a zavření jednoho nechá druhý běžet.

engine se předává rig.open nebo nástroji browser_use. Neznámé jméno se odmítne, místo aby se dosadilo výchozí — žádat prohlížeč a potichu dostat jiný odpovídá na otázku kompatibility špatnou odpovědí.

Limity konkrétních enginů, pojmenované, ne obcházené:

  • Firefox nemá znovunačtení, které obchází cache (ignoreCache z BiDi rovnou odmítne), takže tvrdé znovunačtení je obyčejné znovunačtení.
  • WebKit taky nemá znovunačtení, které obchází cache, nemá kanál konzole (výstup se chytá zaháknutím console.* až po každé navigaci, takže cokoli zapsané během načítání chybí — každý výpis konzole to říká) a na živý náhled potřebuje na hostiteli ffmpeg.
  • Ani jeden nevystaví přes svůj protokol platformní strom přístupnosti, takže extract (a11y) vrací aproximaci odvozenou z DOM a tak ji i označí.
  • Ani jeden neumí skutečné puštění souboru; vstup souboru se pořád dá namířit na cesty uvnitř stroje.
Plocha Obraz Získání
Terminál ubuntu:24.04, připnutý digestem Automaticky při prvním startu, přes vlastní hradlovanou síť stroje
Prohlížeč (Chromium, Firefox, WebKit) debian:trixie-slim, připnutý digestem, plus vlastní balíčky enginu Automaticky při prvním startu, pak v cache jako zahřátý balík
Počítač Obraz plochy qcow2 s Chromium, Firefox, WebKit a stejnou základní sadou CLI runneru hostovaného na GitHubu, kterou zahřívá terminál Importovat v Nastavení → Server → Stanice (stažení připnutá kontrolním součtem, kde jsou publikovaná)
Android Systémové obrazy Googlu Přes Android SDK
iOS Runtime simulátoru Xcode plus WebDriverAgent připnutý kontrolním součtem Runtime přes Xcode; automatizační most z Nastavení → Server → Stanice

Po prvním startu každého druhu microVM si server do datového adresáře uloží předem rozbalenou kopii a z ní bootuje každý další stroj — včetně předehřátých obrazů, které už mají balíčky nainstalované. Terminál zahřeje sadu CLI ve stylu runneru hostovaného na GitHubu (git, gcc, python3, jq, rsync, nástroje na archivy a zbytek základní sady apt; ne Docker ani jazykový toolcache). Obraz Počítač zapeče stejná jména CLI už při sestavení, vedle XFCE a tří prohlížečů. Každý prohlížeč zahřeje svůj engine. Všechny tři enginy sdílejí základ Debianu, ale balík nesdílejí nikdy: cache se klíčuje obrazem, enginem a revizí zvuku (audio-v1-<engine>), protože stroj zahřátý pro jeden engine — nebo dřív, než byly PulseAudio a ffmpeg součástí zátěže — v sobě nic z toho druhého nemá. Balík terminálu se ze stejného důvodu klíčuje revizí sady nástrojů (tools-v1): balík zahřátý dřív, než byl překladač součástí obrazu, nesmí obsloužit stroj, který ho má mít.

Neexistuje zapečený automatizační obraz, který by stálo za to vzít — chromedp/headless-shell od Chromia se překládá bez ALSA i bez PulseAudio, takže zvuk vydat neumí; jediný udržovaný od Firefoxu je 33× větší než základ Debianu a pořád neobsahuje socat; udržovaný obraz WebKitu neexistuje vůbec. Každý engine se proto nainstaluje při prvním startu (chromium, firefox-esr nebo webkit2gtk-driver) a přitom sahá do archivů Debianu (deb.debian.org, security.debian.org, cloudfront.debian.net). Chromium je distribuční binárka spouštěná jako chromium --headless=new.

Vlastní obrazy po pracovních prostorech

Sekce “Vlastní obrazy po pracovních prostorech”
Klíč nastavení Přepisuje
rigs.smolvm.execImage Obraz Terminal (VM)
rigs.smolvm.browserImage Obraz Chromium Browser (VM)

Zapisuje se přes úložiště nastavení pracovního prostoru za branou správce (Nastavení → Server → Stanice → Vlastní obrazy (tento pracovní prostor)). Hodnota musí být odkaz na registr — místní cesty, archivy a řetězce ve tvaru přepínače se odmítnou, u pole i znovu při startu. Neplatná uložená hodnota se ignoruje a ohlásí; nabootuje výchozí. Vlastní registr obrazu (plus známé doprovodné blob-CDN pro Docker Hub, GHCR, Quay, GitLab a GCR) se na dobu stažení pustí branou odchozího provozu.

Kontrakt obrazu terminálu — přítomný bash; git, curl a socat předinstalované nebo apt základ Debian/Ubuntu (izolované prostředí při prvním startu doinstaluje ty tři plus sadu CLI ve stylu runneru hostovaného na GitHubu: překladače, Python 3, jq, nástroje na archivy, rsync. Jazykový toolcache a Docker se neinstalují).

Kontrakt obrazu prohlížeče — apt základ Debian/Ubuntu (nebo už nainstalované balíčky) s bash a socat, plus binárka chromium, kterou server sám spouští jako chromium --headless=new s DevTools na loopbacku hosta 9223, předávaným na port hosta 9222. PulseAudio a ffmpeg se kvůli zvukovému kanálu nainstalují při prvním startu. Nestav FROM chromedp/headless-shell: upstream headless.gn se překládá bez ALSA i bez PulseAudio, takže tahle binárka zvuk vydat neumí. Přepis platí jen pro stanice Chromium — příkaz zátěže, se kterým se bootuje, patří Chromiu, a předat ho Firefoxu nebo WebKitu by spustilo binárku, která tam není. Stanice Firefoxu nebo WebKitu ho ignoruje a ohlásí to; nabootuje svůj připnutý obraz.

Automatizační porty — každý stroj prohlížeče předává přesně jeden loopbackový port hostitele na 9222 hosta. Za ním: DevTools Chromia a vzdálený agent Firefoxu sedí na loopbacku hosta 9223 a před nimi je relé socat (oba se bezpodmínečně vážou na loopback); ovladač WebKitu bere --host a sám se váže na síťové rozhraní hosta. Firefox navíc ověřuje hlavičku Host proti vlastnímu portu, takže klient posílá autoritu ze strany hosta, ne tu, kterou vytočil.

Každá akce se parsuje beze zbytku: poškozený payload vrátí zprávu, která pojmenuje pole, nikdy výjimku. Pozorovací slovesa (označená ○) zůstávají povolená, dokud řízení drží člověk; měnící slovesa se odmítnou.

screenshot○, cursor_position○, mouse_move, left_click, right_click, middle_click, double_click, triple_click, left_mouse_down, left_mouse_up, left_click_drag, scroll, key, hold_key (0–60 s), type, wait○ (0–60 s), set_display, clipboard_read○, clipboard_write.

Souřadnice jsou pixely hosta v jeho aktuálním režimu; každý snímek uvede velikost displeje. Kombinace kláves používají zápisy X11 (ctrl+s, alt+Tab, Return).

clipboard_read bere selection: clipboard (to, co naplní ctrl+C, výchozí), primary (výběr ke kopírování v X11) nebo xdnd (probíhající přetažení). Prázdný výsledek je u všech tří normální odpověď. clipboard_write bere jen text — obrázky a soubory jedou po souborovém kanálu, protože argumenty akce se ukládají do auditního záznamu a bajty obrázku tam nemají co dělat. Obsah schránky se vrací ohrazený jako nedůvěryhodná data.

navigate (jen http/https), reload (hard volitelně), stop_loading, click (selektor nebo souřadnice), fill, type, key (jména kláves DOM), scroll, mouse_move, drag, left_mouse_down, left_mouse_up, extract○ (a11y | dom | console), screenshot○ (full_page volitelně), set_viewport (nejméně 320×240), history, wait_for○ (selektor, 0.1–30 s), clipboard_read○, clipboard_write.

Extrahovaný obsah stránky se vrací ohrazený jako nedůvěryhodná data.

Prohlížeč má právě jednu schránku, takže clipboard_read nebere selection. Obě slovesa schránky potřebují zabezpečený kontext: stránka podávaná přes holé http:// nemá API schránky vůbec a sloveso to řekne, místo aby hlásilo prázdnou — tam použij type, které vloží text ke kurzoru a přes schránku nejde.

tap, swipe (50–5000 ms), type, key (aliasy back, home, recents, enter, delete, backspace, tab, escape, search, menu, volume_up, volume_down, power, nebo libovolný KEYCODE_*), screenshot○, ui_dump○, install_apk (omezené na worktree stanice a datový adresář serveru), start_app, stop_app, clear_app_data, uninstall_app, open_url a shell. shell bere seznam argv a běží uvnitř Androidu, nikdy přes shell hostitele; pokryje vývojářskou diagnostiku jako logcat, dumpsys a pm grant.

mobile_use nemá slovesa schránky. Od Androidu 10 smí schránku číst jen aplikace, která má fokus.

tap, swipe (50–5000 ms), type, key (enter, backspace, tab, escape, šipky nebo jeden tisknutelný znak; volitelné modifikátory command, control, option a shift), home, lock, unlock, screenshot○, ui_dump○, install_app (adresář simulátoru .app omezený na worktree stanice nebo datový adresář serveru), start_app, stop_app, uninstall_app, open_url a spawn. spawn bere argv a spouští se uvnitř simulátoru přes simctl; shell hostitele nespouští nikdy.

Souřadnice jsou body obrazovky iOS, ne pixely snímku. Živý proud drží pevnou velikost simulátoru a letterboxuje ji, místo aby měnil velikost zařízení. Přenos textu schránky z hostitele do simulátoru a ze simulátoru na hostitele používá stejnou politiku oprávnění po uživateli a po směru jako ostatní stanice; soubory a obrázky kanál pasteboardu iOS nepřijímá.

Každá stanice si vytvoří vlastní zařízení CoreSimulator a relaci WebDriverAgent. Zavření zastaví WebDriverAgent, zařízení vypne a smaže a odstraní jeho záznam v registru. Stanice iOS běží jen na serveru s macOS, s Xcode, nainstalovaným runtime iOS a připnutým automatizačním mostem. Nevystavují zvuk, mikrofon, puštění souboru, shell hostitele ani záruku uzavřené sítě.

Nástroj Popis
rig_list Vypíše stanice pracovního prostoru s plochou, stavem, displejem a tím, kdo je řídí
rig_close Zničí stanici a zahodí její disk
Fáze Význam
provisioning Bootuje se; detail stavu nese aktuální krok doslova
ready Dosažitelná a přijímá akce
parked Zaparkovaná za nečinnost: vCPU zastavené, RAM pořád rezidentní; další akce ji probudí
closing Vypíná se
closed Pryč; řádek zůstane kvůli auditní stopě
failed Spadla, nebo vůbec nenaběhla; jde to rozlišit, aby rozhraní mohlo nabídnout opakování
Důvod zavření Kdy se spustí
requested Požádal o to člověk nebo agent
idleTimeout Nečinnost delší než 2× okno nečinnosti, nebo vyhození kvůli paměti
ttlExpired Vypršela tvrdá životnost
conversationEnded Skončila vlastnící konverzace
workspaceGone Pracovní prostor se smazal, nebo se ztratilo členství
serverShutdown Server se zastavuje
backendFailure Hypervisor pod ní spadl

Výchozí hodnoty a stropy

Sekce “Výchozí hodnoty a stropy”
Hodnota Terminál Prohlížeč Počítač Mobil
Paměť 512 MB 2048 MB (Chromium); 2560 MB (Firefox, WebKit) 4096 MB 4096 MB
vCPUs 2 2 4 4
Tvrdé TTL 8 h 2 h 2 h 2 h
Okno nečinnosti 45 min 15 min 15 min 15 min
Displej při startu — 1280×800 1280×800 1080×1920
  • Snímky kanálu agenta mají strop 1280×800; lidský kanál vyjedná až 2560×1600.
  • Rozpočet rezidentní paměti hostitele na všechny stanice je ve výchozím stavu 12 GB, počítaný v rezidentních megabajtech (zaparkované VM pořád drží svou RAM). Vyhazuje se stroj, který se nepoužíval nejdéle, a nikdy ten, který někdo řídí, sleduje, nebo v něm má otevřený terminál.
  • Otevřený terminál nebo kanál sledování drží stanici proti parkování a uzavření za nečinnost; tvrdé TTL pořád platí.

Porty a vývojové domény

Sekce “Porty a vývojové domény”
Port Kde Vyhrazeno pro
7911 Host terminálu Multiplexor portů, po kterém jede každé předání
9222, 9223 Host prohlížeče Relé a koncový bod automatizace (WebKit váže 9222 přímo a relé nepoužívá)
80, 443 Loopback hosta prohlížeče Kanály HTTP/HTTPS vývojové domény
  • Zjišťování se na straně serveru každých ~4 s ptá na naslouchající TCP porty hosta terminálu.
  • Automaticky se předá nejvýš 16 portů na stanici; další se jen zapíšou do logu.
  • Předání na straně hostitele se váže na loopback a dává přednost vlastnímu číslu portu hosta; Sdílet v místní síti přidá port v LAN, který přidělí operační systém.
  • Vývojové domény musí sedět na name.test nebo name.localhost (malá písmena, návěští nejvýš 63 znaků). Jedna doména patří jednomu portu.
  • HTTPS vývojové domény používá CA místní pro server (EC P-256, pod <dataDir>/rigs/tls/, klíče 0600 a nikdy v hostu) s jedním wildcard listem pro *.test / *.localhost. Není-li na hostiteli openssl, není ani kanál HTTPS; holé HTTP se pořád směruje.

Výchozí odchozí provoz

Sekce “Výchozí odchozí provoz”
Plocha Výchozí seznam povolených
Terminál Vývojářská základní sada sandboxu (forge, registry balíčků, poskytovatelé modelů) + zrcadla apt Ubuntu + vlastní hostitel forge daného worktree
Prohlížeč usectrl.dev (web produktu) — plus archivy Debianu při prvním startu každého enginu, dokud instaluje své balíčky. Domovská stránka je místní dokument file:// a odchozí provoz nepotřebuje
Počítač Prázdný — odmítnout vše — dokud volající nepovolí cílové hostitele
Mobil Nevynucuje se (síť řídí emulátor)

Každé microVM navíc dostane hostitele registru svého obrazu, jen na stažení. Množina povolených hostitelů u brokeru přihlašovacích údajů se odvozuje ze stejného seznamu: token se nevystaví pro hostitele, na kterého host nedosáhne.

Schránka a přenos souborů

Sekce “Schránka a přenos souborů”

Kopírování a vkládání oběma směry a přetahování souborů dovnitř i ven. Má to člověk, který stanici řídí; agent dostane schránku přes slovesa výše a přenos souborů vůbec ne (shell uvnitř izolovaného prostředí už má).

Přechod schránky je po uživateli a po směru. Vložení z hostitele do stanice je ve výchozím stavu povolené; kopírování ze stanice na hostitele se nejdřív zeptá (povolení na deset minut, nebo Vždy povolit v Nastavení → Server → Stanice → Přístup ke schránce). Obě volby jsou nezávislé a nikdy to není nastavení pracovního prostoru.

Kanál Trasa Nese
Schránka GET/POST /rig/clipboard/<rigId> Text, jeden PNG/JPEG (≤16 MB) a cesty hosta k souborům na schránce
Soubory POST /rig/files/<rigId> Až 64 souborů, každý ≤256 MB a ≤512 MB na jedno puštění, s volitelným bodem puštění v pixelech hosta
Soubory GET /rig/files/<rigId>?p=<base64url path> Bajty jednoho souboru, ven
  • HTTP, ne RPC. Soket RPC zavře spojení na příchozím rámci nad 256 KB — ochrana proti DoS, která sedí na příkazy JSON a je smrtelná pro vložený snímek. Bajty jedou stejným druhem trasy, jakou už jedou snímky stanice a zvuk schůzky.
  • Ověření je podepsaný cíl rig-files:<workspaceId>/<rigId> plus členství v pracovním prostoru — vlastní cíl, takže URL vystavené ke sledování stroje do něj nemůže taky zapisovat soubory.
  • Převzetí platí. Zápis do schránky a puštění souborů jsou měnící a odmítnou se, dokud řízení drží někdo jiný; čtení schránky a čtení souboru ven jsou pozorování a neodmítnou se.
  • Kam puštění dopadne: ~/Drops (plocha), ~/drops (terminál — vedle worktree, nikdy uvnitř, takže se puštění nikdy neukáže jako nesledovaná změna), /tmp/cc-drops (prohlížeč). Adresář vybírá server; volající ho neumí pojmenovat. Existující soubory se nikdy nepřepíšou — kolidující jméno dopadne jako 2-name.ext.
  • Co se řekne hostu: stránka prohlížeče dostane v požadovaném bodě skutečnou událost puštění (Input.dispatchDragEvent); plocha dostane soubory a jejich URI na schránku, protože žádný hostitel neumí syntetizovat přetažení XDND do libovolného toolkitu bez privilegovaného démona v hostu. Odpověď řekne, která z těch dvou věcí nastala.
  • Tahání ven je jen na ploše a čte XdndSelection hosta, dokud přetažení běží. Payload shodný s tím, co host už držel na začátku stisku, se bere jako zastaralý výběr z dokončeného přetažení, ne jako nové — X nemá krok „přetažení skončilo“.
  • Požadavky na obraz: obraz plochy musí být protokol 2 nebo novější (sestavený až poté, co přistála podpora schránky). Starší obraz odpoví 404 a aplikace řekne, ať se sestaví znovu, místo aby hlásila rozbitý stroj.
  • Auditní záznam zapisuje tvar, nikdy obsah: řádky clipboard_read, clipboard_write, drop_files a read_file nesou počty, velikosti a cesty. Ve schránce žijí přihlašovací údaje vždy jen pár sekund a nic z toho se nezapisuje.

Guardraily, události, úložiště

Sekce “Guardraily, události, úložiště”
  • Nástroje stanic deklarují třídu akce enclosureControl (plus networkEgress a processSpawn u nástrojů použití; mobile_use a ios_use deklarují taky packageInstall). rig_close deklaruje enclosureControl; rig_list nedeklaruje nic. Ve výchozím stavu povolené; režimy jen pro čtení to odmítnou celé; volič autonomie na prostor to umí srazit na nejdřív se zeptat.
  • Doménové události: RigClosedEvent (s důvodem zavření), RigControlChanged (převzetí / vrácení), RigReaped (nečinnost, TTL nebo vyhození kvůli paměti, s řídícím agentem). Otevření stanice událost není. Viz doménové události.
  • Úložiště: rig_sessions a rig_action_log v databázi každého pracovního prostoru. Záznam akcí zapíše každou vstupní událost s jejím principálem a monotónní posloupností v rámci stanice; napsaný text se před zápisem nahradí délkou a hashem.
  • Datový adresář: rigs/images/ (importované obrazy qcow2), rigs/smolvm/ (běhový stav po stanicích), rigs/smolvm-packs/ (předem rozbalené balíky strojů), rigs/tls/ (CA vývojové domény), rigs/run/ (překryvy a seedy QEMU).
  • Trasy: živý náhled je karta v prostoru nebo na stránce PR; /settings/server/rigs je obrazovka nastavení Stanice.