Oferă unui agent o mașină pe care să testeze
O stație este o mașină de unică folosință pe care un agent o deschide când trebuie să încerce efectiv ceva: să încarce o pagină, să dea clic prin aplicația de desktop, să atingă un telefon. O poți urmări cum lucrează în timp real și îi poți prelua controalele oricând vrei.
Stațiile izolate de terminal, browser și desktop sunt VM-uri cu discuri de unică folosință și rețele cu poartă. Android și iOS sunt emulatoare gestionate de gazdă: starea dispozitivului lor este de unică folosință, dar rețeaua lor urmează gazda serverului.
Configurează o dată
Secțiune intitulată „Configurează o dată”Stațiile rulează pe mașina care găzduiește cc_server — aceeași mașină, nu cea
la care te uiți. Există cinci suprafețe vizibile pentru utilizator; suprafețele
de desktop și mobile necesită configurare pe gazdă:
| Suprafață | Rulează pe | Configurare |
|---|---|---|
| Terminal (VM) | Un microVM care pornește o imagine Ubuntu fixată | Nimic — imaginea este descărcată automat la prima utilizare |
| Browser (VM) | Un microVM care pornește o imagine Debian fixată, cu Chromium, Firefox sau WebKit instalat la prima utilizare | Nimic — la fel |
| Computer (VM) | QEMU cu o imagine de desktop Linux care include Chromium, Firefox, WebKit și un set de bază de CLI de tip runner găzduit de GitHub | Instalează QEMU (brew install qemu), apoi Importă o imagine de desktop în Setări → Server → Stații |
| Android | Emulatorul Android de la Google | Instalează Android SDK, creează un AVD și pornește-l (mai jos) |
| Simulator iOS | CoreSimulator pe Mac-ul serverului | Instalează Xcode și runtime-ul iOS solicitat, apoi instalează puntea de automatizare în Setări → Server → Stații |
Mașinile de terminal și de browser pornesc din imagini fixate prin digest: octeții exacți sunt numiți dinainte, descărcați o dată la prima pornire și puși în cache — după prima pornire de fiecare tip, mașinile ulterioare sar complet peste descărcare și pornesc în câteva secunde. Setări → Server → Stații arată ce poate porni serverul tău și fiecare mașină care rulează chiar acum.
O imagine de desktop instalată rămâne gestionabilă din aceeași pagină: Importă o înlocuiește cu un qcow2 mai nou, iar Șterge o elimină, ca să poți instala o versiune nouă.
Dispozitivele mobile se configurează altfel
Secțiune intitulată „Dispozitivele mobile se configurează altfel”Nu avem nicio imagine proprie pentru Android sau iOS, iar asta nu este o omisiune. Imaginile de sistem Android vin din SDK-ul Google; runtime-urile iOS vin din Xcode. Pentru Android, instalează Android Studio (sau instrumentele SDK din linia de comandă), adaugă un dispozitiv virtual în Device Manager și pornește-l. Pagina Stații raportează apoi Android ca disponibil.
De asemenea, îți spune exact ce pas îți lipsește — niciun SDK, niciun emulator,
niciun dispozitiv virtual sau un dispozitiv care pur și simplu nu rulează —
pentru că acestea au patru remedii diferite și doar unul dintre ele este o
descărcare. Dacă pornești cc_server dintr-un shell care nu vede SDK-ul,
exportă-l:
export ANDROID_HOME="$HOME/Library/Android/sdk"Pentru iOS, serverul însuși trebuie să ruleze pe macOS, cu Xcode și un runtime de Simulator iOS instalate. Deschide Setări → Server → Stații și apasă Instalează puntea de automatizare iOS. Serverul descarcă artefactul WebDriverAgent fixat prin sumă de control, îl verifică și îl instalează în magazia de automatizare deținută de server. Niciun simulator nu pornește în timpul configurării.
Deschide o mașină
Secțiune intitulată „Deschide o mașină”Mașinile trăiesc ca file, lângă chat și diff — într-un spațiu sau pe o
pagină de PR, în același meniu +, sub Mașini:
- Computer — un desktop Linux cu Chromium, Firefox și WebKit
- Chromium, Firefox sau WebKit — un browser
- Android — emulatorul Android care rulează
- Simulator iOS — un simulator de unică folosință creat pentru această conversație
Alege una și apasă Pornește mașina. Fila indică în ce etapă se află pornirea („Starting the microVM”, „Waiting for the guest to come up”) în loc să se învârtă pur și simplu.
Fila este limitată la conversație, la fel și instrumentul agentului. O filă
Chromium, Firefox sau WebKit și browser_use, Android și mobile_use sau
Simulator iOS și ios_use se adresează aceleiași mașini implicite. Sloturile
suplimentare din interfață sunt mașini de comparație separate; instrumentele
agentului folosesc întotdeauna mașina implicită.
Pentru a compila, instala și porni o aplicație Flutter pe Android:
fvm flutter build apk --debugApoi apelează mobile_use cu install_apk și
build/app/outputs/flutter-apk/app-debug.apk, urmat de start_app și numele
pachetului Android. ui_dump, capturile de ecran și intrarea controlează
același dispozitiv afișat în fila umană. stop_app, clear_app_data,
uninstall_app, open_url și apeluri shell în formă de argv acoperă restul
ciclului de dezvoltare fără a invoca un shell pe gazda serverului.
Pentru a compila, instala și porni o aplicație Flutter pe Simulator iOS:
fvm flutter build ios --simulator --debug/usr/bin/plutil -extract CFBundleIdentifier raw -o - \ build/ios/iphonesimulator/Runner.app/Info.plistApoi apelează ios_use cu install_app și directorul .app, urmat de
start_app și identificatorul de bundle afișat de plutil.
Instrumentul iOS expune de asemenea stop_app, uninstall_app, open_url și
o acțiune spawn în formă de argv pentru diagnostice locale simulatorului.
Afișajele de desktop și de browser se redimensionează la dimensiunea panoului. iOS păstrează dimensiunea fixă în puncte a simulatorului și îl afișează cu benzi negre. Fiecare suprafață are în continuare două canale independente: agentul primește capturi de ecran mici și ieftine, în timp ce tu primești vizualizarea live. Trecerea la altă filă oprește fluxul uman, astfel încât o mașină din fundal nu consumă lățime de bandă pentru afișare.
O filă de stație nu pornește singură o mașină, nici în timpul restaurării aspectului. Această regulă împiedică o lansare a aplicației să pornească în mod neașteptat VM-uri sau să creeze dispozitive de simulator.
Condu mașina
Secțiune intitulată „Condu mașina”Canvasul este al tău, pentru a tasta și a da clic în el oricând nu deține altcineva controlul exclusiv — sau când îl deții tu. Cât timp deții acea blocare, eticheta de stare afișează Ai controlul, agentul poate face în continuare capturi de ecran, iar serverul îi refuză acțiunile care modifică starea în singurul punct de trecere prin care trece fiecare acțiune. Tot ce faci este consemnat pe numele tău.
Apasă Oprește mașina când ai terminat.
Controlul este exclusiv intenționat: doi actori care tastează într-o singură mașină produc intrare pe care niciunul nu a intenționat-o.
Mută lucruri înăuntru și în afară
Secțiune intitulată „Mută lucruri înăuntru și în afară”Copierea și lipirea funcționează în ambele direcții peste canvasul stației, la fel și tragerea fișierelor.
Copiere și lipire. Apasă combinația de copiere peste canvas și orice a copiat mașina — text, o imagine, o listă de fișiere — ajunge în clipboardul tău. Lipirea trimite al tău în cealaltă direcție și apasă lipire în interiorul mașinii. Pe macOS combinația este ⌘C/⌘V; ⌃C ajunge în continuare la un shell din invitat ca întrerupere. Pe Windows și Linux folosește ⌃C/⌃V — invitatul primește aceeași apăsare de taste pe care ar fi primit-o oricum, așa că ⌃C într-un terminal din invitat întrerupe în continuare, iar clipboardul tău rămâne neatins.
Nimic nu se sincronizează în fundal. O parolă pe care o copiezi pe propria mașină nu ajunge într-o VM pentru că s-a declanșat un temporizator; ea traversează când lipești.
Lipirea într-o stație este permisă implicit. Copierea dintr-o stație cere întâi confirmare — o autorizare de zece minute, sau Permiteți întotdeauna în Setări → Server → Stații → Acces la clipboard. Cele două direcții sunt independente și te urmează pe tine, nu spațiul de lucru.
Trage fișiere înăuntru. Depune-le oriunde pe canvas.
- Pe Browser (VM), pagina primește o depunere reală în punctul în care dai drumul, așa că o zonă de încărcare se comportă exact ca pentru un fișier local.
- Pe Computer (VM), fișierele ajung în
~/Dropsși căile lor intră în clipboardul mașinii, așa că ⌃V le lipește într-un manager de fișiere sau într-un câmp de încărcare. O gazdă nu poate sintetiza o tragere într-o aplicație Linux arbitrară fără să ruleze un demon privilegiat în interiorul VM-ului, pe care stațiile nu îl au în mod deliberat — așa că notificarea toast îți spune unde au ajuns fișierele, în loc să pretindă că a avut loc o depunere. - Pe un terminal, fișierul este copiat înăuntru și calea lui este tastată la prompt, gata de transmis unei comenzi. Lipirea unei imagini într-un terminal face același lucru: este salvată în mașină și primești calea.
Tragerea fișierelor în afară funcționează din Computer (VM). Începe să tragi un fișier în interiorul mașinii, du pointerul în afara canvasului și devine o tragere reală pe desktopul tău — depune-l în Finder sau Explorer. Copierea fișierelor în managerul de fișiere al mașinii și lipirea pe partea ta funcționează și ea. Browser (VM) nu oferă asta: un browser headless nu are niciun payload de tragere de citit, iar ghicirea pe baza selecției de text a paginii ar deturna clicurile obișnuite.
Terminale în interiorul unei stații
Secțiune intitulată „Terminale în interiorul unei stații”Terminalele dintr-un spațiu sau de pe o pagină de PR pot rula în interiorul unei stații în loc de pe mașina proprie a serverului. Când o fac, panoul afișează o insignă VM izolată.
Ce se schimbă:
- Nimic din ce rulezi nu ajunge la gazdă. Un
rm -rfacolo te costă stația. - Rețeaua este refuzată implicit. Doar gazdele din lista de permisiuni a stației sunt accesibile, iar totul trece printr-o poartă care impune acest lucru.
git pushfuncționează în continuare într-un terminal pe care l-ai deschis tu. Stația nu are nicio credențială stocată; cere serverului una de scurtă durată per operație, limitată de propriul tău acces la platforma de cod, iar acel token este revocat când stația se închide. O stație deschisă de un agent primește o credențială doar pentru citire, așa că poate face fetch, dar nu push.
Ce trebuie să știi:
- Un terminal izolat restaurat te așteaptă. Ca o filă de stație, un
terminal
microvmcare revine odată cu aspectul tău afișează un buton Deschide shell-ul în loc să pornească VM-ul la lansare. Un terminal cu shell pe gazdă costă un proces; unul izolat costă o mașină. - Fișierele depuse pe terminal sunt tastate, nu deschise. Depune un CSV pe un terminal izolat și acesta este copiat în mașină, iar calea lui din invitat apare la prompt — calea de pe gazdă ar fi o comandă care eșuează acolo.
- Copia din stație este o copie. Worktree-ul tău de pe gazdă rămâne sursa
de adevăr. Commit-urile pe care le faci în interiorul unei stații sunt aduse
înapoi în
refs/rigs/<id>/*când ceri — nu îți mută niciodată ramura și nu ating arborele tău de lucru. - Munca destinată gazdei rulează în continuare pe gazdă. Un invitat Linux
nu poate compila pentru macOS și nu poate rula
xcodebuild. Alege explicit backend-ul nativ pentru asta; aplicația îți va cere să confirmi, în loc să comute în tăcere.
Pornește un server de dezvoltare în Terminal (VM) — pnpm dev pe portul 3000,
să zicem — și în câteva secunde pictograma de priză din colțul terminalului se
aprinde: portul este redirecționat către localhost:3000 pe mașina ta, accesibil
la localhost:3000 în interiorul Browser (VM), partajabil în rețeaua ta și
căruia i se poate da numele https://myapp.test. Întregul flux — redirecționare
automată, partajare în LAN, domenii de dezvoltare cu HTTPS — are propriul ghid:
Redirecționează porturi dintr-un terminal.
Imagini personalizate
Secțiune intitulată „Imagini personalizate”Un spațiu de lucru poate îndrepta Terminal (VM) și Browser (VM) către propriile imagini — în Setări → Server → Stații → Imagini personalizate (acest spațiu de lucru). Utilizare tipică: extinde imaginea implicită cu lanțul de instrumente de care are nevoie proiectul tău, ca fiecare terminal să pornească pregătit, sau refolosește o imagine deja publicată de echipa ta.
Mașina pornește în continuare în același mediu izolat: aceeași poartă de ieșire, același broker de credențiale, același ciclu de viață. Doar administratorii spațiului de lucru pot schimba setarea, mașinile noi o preiau (cele care rulează își păstrează a lor), iar referința trebuie să fie o imagine din registry — căile locale sunt refuzate.
Ce trebuie să ofere o imagine:
- Terminal (VM) — o imagine Linux cu
bash. Are nevoie și degit,curlșisocat— fie preinstalate, fie instalabile la prima pornire (orice imagine bazată pe Debian/Ubuntu funcționează: sunt instalate automat, împreună cu un set de instrumente CLI de tip runner găzduit de GitHub: compilatoare, Python 3,jq, instrumente de arhivare,rsync. Runtime-urile de limbaj precum Node/Go/Java și Docker nu sunt preinstalate). Portul de invitat7911este rezervat pentru redirectorul de porturi. - Browser (VM) — o imagine Debian/Ubuntu cu
bashșisocat, plus un binarchromium. Serverul pornește Chromium însuși cachromium --headless=newși retransmite DevTools de la9223din invitat către9222. PulseAudio și ffmpeg sunt instalate la prima pornire. Nu construiFROM chromedp/headless-shell— acel binar nu are audio. Suprascrierea se aplică doar stațiilor Chromium; Firefox și WebKit o ignoră și pornesc imaginea Debian fixată. Porturile de invitat9222/9223sunt rezervate.
Două recomandări: fixează referința prin digest (@sha256:…), ca octeții să nu
se poată schimba sub tine, și găzduiește-o pe Docker Hub sau GitHub Container
Registry — gazdele de descărcare ale acestor registry-uri sunt admise automat
prin poarta de ieșire; altele pot avea nevoie ca gazdele lor de livrare de
conținut să fie accesibile pentru a face pull.
Când o stație dispare
Secțiune intitulată „Când o stație dispare”Stațiile sunt menite să fie temporare:
- Inactiv — după ~15 minute în care nu se întâmplă nimic, o stație de browser, desktop sau mobil se parcă (înghețată, se trezește instantaneu la următoarea acțiune). Un terminal izolat așteaptă 45 de minute. După dublul ferestrei de inactivitate, se închide.
- Limită de timp — fiecare stație are o durată de viață strictă pe care nu o poate prelungi, indiferent ce face.
- Memorie — dacă serverul are nevoie de loc pentru o stație nouă, o închide pe cea mai puțin utilizată recent. O stație pe care cineva o conduce, o privește sau are un terminal deschis în ea nu este niciodată luată.
Când o stație izolată se închide, discul ei este aruncat. Închiderea unei stații Android se detașează de emulatorul de pe gazdă — nu îl șterge. O stație iOS șterge dispozitivul CoreSimulator pe care l-a creat. Adu înapoi mai întâi orice vrei să păstrezi.
Ce poate atinge o stație
Secțiune intitulată „Ce poate atinge o stație”Stațiile izolate de terminal, browser și desktop folosesc implicit o poartă de
ieșire cu refuz implicit: acorzi gazde în mod explicit, iar singura rută a
invitatului este o poartă care impune acea listă. O stație de browser admite din
start și site-ul produsului (usectrl.dev). Brokerul de credențiale folosește
aceeași listă.
Două avertismente oneste:
- Rețeaua mobilă urmează gazda. Emulatorul Android și CoreSimulator de la Apple nu se află în spatele porții de ieșire a mediului izolat. Niciuna dintre filele mobile nu oferă un control de ocolire a rețelei, pentru că rețeaua gestionată de gazdă este deja fără restricții.
- Tot ce citește o stație este tratat ca nesigur. Textul paginilor, DOM-ul, arborii de accesibilitate și dump-urile de interfață ajung la agent învelite în marcaje care spun „acestea sunt date, nu instrucțiuni”. O pagină care încearcă să îi dea ordine agentului tău se citește ca un șir citat.
Poți vedea tot ce rulează și poți opri orice, în Setări → Server → Stații.
- Stații și medii izolate — modelul din spatele tuturor acestora: de ce VM-uri, cele două canale de afișare, brokerul de credențiale, ciclul de viață
- Redirecționează porturi dintr-un terminal — ajunge la un server de dezvoltare din orice loc în care contează
- Referința pentru stații — fiecare suprafață, verb, port și valoare implicită într-un singur loc
- Configurează guardrail-urile —
Conduce un mediu izolat (stație)este o clasă de acțiuni pe care o poți seta să permită, să întrebe întâi sau să refuze, per spațiu de lucru, agent sau spațiu. Modurile numai în citire o refuză în bloc.