Rigs
Лише факти. Про модель, що за ними стоїть, читайте Rigs та ізольовані середовища; щоб відкрити машину, дотримуйтеся посібника.
Поверхні та бекенди
Розділ із назвою «Поверхні та бекенди»| Поверхня | Керує | Бекенд | Значення | Обмежений вихід |
|---|---|---|---|---|
| Термінал (exec) | Оболонка через канал exec ВМ | мікроВМ | smolvm |
Так |
| Браузер | Headless Chromium (CDP), Firefox (WebDriver BiDi) або WebKit (W3C WebDriver) | мікроВМ | smolvm |
Так |
| Комп’ютер | Робочий стіл X11: введення через гіпервізор, захоплення через агент гостя | QEMU | qemu-hvf (macOS), qemu-kvm (Linux), qemu-tcg (неприскорений запасний варіант, ніколи не вибирається автоматично) |
Так |
| Android | Android через ADB | Емулятор Google | android-emulator |
Ні — емулятор керує власною мережею |
| iOS | Симулятор iOS через WebDriverAgent | CoreSimulator | ios-simulator |
Ні — мережа йде за хостом Mac |
Термінал і поверхня computer_use поділяють значення поверхні computer;
термінал розрізняють за маркером образу exec, і його ніколи не використовують
повторно як керований робочий стіл (чи навпаки). Одна розмова повторно
використовує одну термінальну машину.
Браузерні рушії
Розділ із назвою «Браузерні рушії»| Рушій | Значення | Протокол | Живий перегляд | Нерухомі знімки |
|---|---|---|---|---|
| Chromium | chromium (типово) |
Chrome DevTools Protocol | Скринкаст — браузер надсилає кадри, коли сторінка перемальовується | JPEG |
| Firefox | firefox |
WebDriver BiDi | Опитувані нерухомі знімки (у BiDi немає скринкасту), обмежено 6 fps | JPEG |
| WebKit | webkit |
W3C WebDriver (класичний) | Опитувані нерухомі знімки, транскодовані ffmpeg хоста | PNG |
Rig виконує один рушій протягом усього свого життя. Одна розмова може містити один rig на рушій — саме це уможливлює порівняння пліч-о-пліч: відкрити «Firefox (VM)» поруч із «Chromium (VM)» — це дві машини, і закриття однієї лишає іншу працювати.
Передайте engine у rig.open або в інструмент browser_use. Невідому назву
відхиляють, а не підставляють типову, — просити браузер і тихо отримувати
інший означає відповідати на питання про сумісність неправильною відповіддю.
Обмеження, властиві рушіям, названі прямо, а не обійдені:
- Firefox не має перезавантаження з обходом кешу (він відхиляє
ignoreCacheу BiDi цілком), тож жорстке перезавантаження — це звичайне перезавантаження. - WebKit також не має перезавантаження з обходом кешу й не має потоку
консолі (вивід захоплюють, перехоплюючи
console.*після кожного переходу, тож усе, залоговане під час завантаження, пропускається — кожен видобуток консолі про це каже), а для живого перегляду йому потрібенffmpegна хості. - Жоден із них не надає дерева доступності платформи через свій протокол,
тож
extract (a11y)повертає наближення, похідне від DOM, і позначене як таке. - Жоден із них не може прийняти справжнє перекидання файлу; поле вибору файлу все одно можна спрямувати на шляхи всередині машини.
Образи машин
Розділ із назвою «Образи машин»| Поверхня | Образ | Звідки беруться |
|---|---|---|
| Термінал | ubuntu:24.04, закріплений за дайджестом |
Автоматично під час першого завантаження, через власну гейтовану мережу машини |
| Браузер (Chromium, Firefox, WebKit) | debian:trixie-slim, закріплений за дайджестом, плюс власні пакети рушія |
Автоматично під час першого завантаження, потім кешуються як прогрітий пак |
| Комп’ютер | Образ робочого столу qcow2 з Chromium, Firefox, WebKit і тим самим базовим набором CLI, як у ранера, розміщеного на GitHub, який прогріває термінал | Імпортувати в Налаштування → Сервер → Rigs (завантаження, закріплені контрольною сумою, де вони опубліковані) |
| Android | Системні образи Google | Через Android SDK |
| iOS | Середовище виконання Xcode Simulator плюс закріплений за контрольною сумою WebDriverAgent | Середовище виконання через Xcode; місток автоматизації з Налаштування → Сервер → Rigs |
Після першого завантаження кожного різновиду мікроВМ сервер кешує попередньо
розпаковану копію в каталозі даних і завантажує кожну наступну машину з неї —
зокрема попередньо прогріті образи з уже встановленими пакетами. Термінал
прогріває набір CLI-інструментів у стилі ранера, розміщеного на GitHub (git,
gcc, python3, jq, rsync, архівні утиліти та решту базового набору apt;
не Docker і не мовні toolcache). Образ qcow2 для Комп’ютера вбудовує ті самі
назви CLI під час збірки образу, поруч із XFCE і трьома браузерами. Кожен
браузер прогріває свій рушій. Усі три рушії поділяють основу Debian, але
ніколи не поділяють пак: кеш має ключ з образу, рушія і ревізії аудіо
(audio-v1-<engine>), бо машина, прогріта для одного рушія — або до того, як
PulseAudio і ffmpeg увійшли до складу робочого навантаження, — не має в собі
нічого з іншого. Пак термінала має ключ з ревізії набору інструментів
(tools-v1) з тієї самої причини: пак, прогрітий до того, як компілятор
увійшов до образу, не повинен обслуговувати машину, у якій він має бути.
Немає готового образу автоматизації, вартого того, щоб його брати, — Chromium із
chromedp/headless-shell компілює і ALSA, і PulseAudio геть, тож він ніколи не
може видати звук; єдиний підтримуваний образ Firefox у 33× більший за основу
Debian і все одно не містить socat; підтримуваного образу WebKit немає
взагалі. Тож кожен рушій встановлюється під час першого запуску (chromium,
firefox-esr або webkit2gtk-driver) і під час цього звертається до архівів
Debian (deb.debian.org, security.debian.org, cloudfront.debian.net).
Chromium — це пакунковий бінарник, який запускають як chromium --headless=new.
Власні образи для робочого простору
Розділ із назвою «Власні образи для робочого простору»| Ключ налаштування | Що перекриває |
|---|---|
rigs.smolvm.execImage |
Образ Terminal (VM) |
rigs.smolvm.browserImage |
Образ Browser (VM) |
Записують через сховище налаштувань робочого простору, доступне лише адмінам (Налаштування → Сервер → Rigs → Власні образи (цей робочий простір)). Значення має бути посиланням на реєстр — локальні шляхи, архіви та рядки, схожі на прапорці, відхиляють і на полі, і знову під час завантаження. Недійсне збережене значення ігнорують гучно, і натомість завантажується типове. Власний реєстр образу (плюс відомі супутні blob-CDN для Docker Hub, GHCR, Quay, GitLab і GCR) допускають через шлюз виходу для витягування.
Контракт образу термінала — наявний bash; git, curl, socat
попередньо встановлені або основа apt Debian/Ubuntu (ізольоване середовище
встановлює ці три плюс набір CLI-інструментів у стилі ранера, розміщеного на
GitHub, під час першого запуску: компілятори, Python 3, jq, архівні утиліти,
rsync. Мовні toolcache і Docker не встановлюються).
Контракт образу браузера — основа apt Debian/Ubuntu (або вже встановлені
пакети) з bash і socat, плюс бінарник chromium, який сервер запускає сам
як chromium --headless=new з DevTools на гостьовому loopback 9223,
переспрямованому на гостьовий порт 9222. PulseAudio і ffmpeg встановлюються
під час першого запуску для аудіоканалу. Не збирайте
FROM chromedp/headless-shell: headless.gn угорі компілює і ALSA, і
PulseAudio геть, тож цей бінарник не може видавати звук. Перекриття
застосовується лише до rig Chromium — команда робочого навантаження, яку він
завантажує, належить Chromium, і передати її Firefox чи WebKit означало б
запустити бінарник, якого там немає. Rig Firefox або WebKit ігнорує його гучно
й завантажує свій закріплений образ.
Порти автоматизації — кожна браузерна машина переадресовує рівно один порт
loopback хоста на гостьовий 9222. За ним: DevTools Chromium і віддалений агент
Firefox сидять на гостьовому loopback 9223 із реле socat попереду (обидва
безумовно прив’язуються до loopback); драйвер WebKit приймає --host і сам
прив’язується до гостьового NIC. Firefox додатково перевіряє заголовок Host
проти власного порту, тож клієнт надсилає авторитет гостьової сторони, а не
той, до якого звертався.
Дієслова дій
Розділ із назвою «Дієслова дій»Кожну дію розбирають повністю: некоректне навантаження повертає повідомлення з назвою поля, а ніколи не виняток. Дієслова спостереження (позначені ○) лишаються дозволеними, поки керування утримує людина; дієслова, що змінюють стан, відхиляються.
computer_use
Розділ із назвою «computer_use»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 с), type, wait○ (0–60 с), set_display,
clipboard_read○, clipboard_write.
Координати — це гостьові пікселі в поточному режимі гостя; кожен знімок екрана
зазначає розмір дисплея. Сполучення клавіш використовують написання X11
(ctrl+s, alt+Tab, Return).
clipboard_read приймає selection: clipboard (те, що заповнює ctrl+C,
типове), primary (виділення-копіювання в X11) або xdnd (перетягування
в польоті). Порожній результат — нормальна відповідь для всіх трьох.
clipboard_write приймає лише text — зображення й файли їдуть файловим
каналом, бо аргументи дії зберігаються в журнал аудиту, і байтам зображень там
не місце. Вміст буфера обміну повертається в огорожі як ненадійні дані.
browser_use
Розділ із назвою «browser_use»navigate (лише http/https), reload (hard необов’язковий), stop_loading,
click (селектор або координата), fill, type, key (назви клавіш DOM),
scroll, mouse_move, drag, left_mouse_down, left_mouse_up,
extract○ (a11y | dom | console), screenshot○ (full_page
необов’язковий), set_viewport (мін. 320×240), history, wait_for○ (селектор,
0.1–30 с), clipboard_read○, clipboard_write.
Видобутий вміст сторінки повертається в огорожі як ненадійні дані.
У браузера рівно один буфер обміну, тож clipboard_read не приймає
selection. Обидва дієслова буфера обміну потребують захищеного контексту:
сторінка, віддана звичайним http://, взагалі не має API буфера обміну, і
дієслово каже про це, а не повідомляє порожній, — там використовуйте type,
який вставляє в місці каретки, не проходячи через буфер обміну.
mobile_use
Розділ із назвою «mobile_use»tap, swipe (50–5000 мс), type, key (псевдоніми back, home,
recents, enter, delete, backspace, tab, escape, search,
menu, volume_up, volume_down, power або будь-який KEYCODE_*),
screenshot○, ui_dump○, install_apk
(обмежено worktree rig і каталогом даних сервера), start_app,
stop_app, clear_app_data, uninstall_app, open_url і shell.
shell приймає список argv і виконується всередині Android, ніколи через
оболонку хоста; він покриває діагностику для розробників, як-от logcat,
dumpsys і pm grant.
mobile_use не має дієслів буфера обміну. Від Android 10 читати буфер обміну
може лише застосунок у фокусі.
ios_use
Розділ із назвою «ios_use»tap, swipe (50–5000 мс), type, key (enter, backspace, tab,
escape, клавіші зі стрілками або один друкований символ; необов’язкові
модифікатори command, control, option і shift), home, lock,
unlock, screenshot○, ui_dump○, install_app (каталог .app симулятора,
обмежений worktree rig або каталогом даних сервера), start_app, stop_app,
uninstall_app, open_url і spawn. spawn приймає argv і виконується
всередині симулятора через simctl; він ніколи не викликає оболонку хоста.
Координати — це точки екрана iOS, а не пікселі знімка екрана. Живий потік тримає фіксований розмір симулятора й додає до нього рамку (letterbox), а не змінює розмір пристрою. Передавання тексту буфера обміну з хоста в симулятор і з симулятора в хост використовує ту саму політику дозволів для кожного користувача й кожного напрямку, що й інші rig; файли та зображення канал буфера обміну iOS не приймає.
Кожен rig створює власний пристрій CoreSimulator і сеанс WebDriverAgent. Його закриття зупиняє WebDriverAgent, вимикає й видаляє цей пристрій і прибирає його запис із реєстру. Rig iOS працюють лише на сервері macOS із Xcode, встановленим середовищем виконання iOS і закріпленим містком автоматизації. Вони не надають звуку, мікрофона, перекидання файлів, оболонки хоста чи гарантії ізольованої мережі.
Інструменти керування
Розділ із назвою «Інструменти керування»| Інструмент | Опис |
|---|---|
rig_list |
Показати rig робочого простору з поверхнею, статусом, дисплеєм і контролером |
rig_close |
Знищити rig і відкинути його диск |
Життєвий цикл
Розділ із назвою «Життєвий цикл»| Фаза | Значення |
|---|---|
provisioning |
Завантажується; деталь статусу дослівно передає поточний крок |
ready |
Доступний і приймає дії |
parked |
Припаркований за простоєм: vCPU зупинено, RAM усе ще резидентна; наступна дія його пробуджує |
closing |
Завершує роботу |
closed |
Зник; рядок лишається для журналу аудиту |
failed |
Загинув або так і не піднявся; його можна відрізнити, щоб інтерфейс міг запропонувати повтор |
| Причина закриття | Спрацьовує, коли |
|---|---|
requested |
Попросила людина або агент |
idleTimeout |
Простій понад 2× вікна простою або витіснення через пам’ять |
ttlExpired |
Вичерпався жорсткий час життя |
conversationEnded |
Розмова-власник завершилася |
workspaceGone |
Робочий простір видалено або втрачено членство |
serverShutdown |
Сервер зупиняється |
backendFailure |
Гіпервізор під ним загинув |
Типові значення та межі
Розділ із назвою «Типові значення та межі»| Значення | Термінал | Браузер | Комп’ютер | Мобільні |
|---|---|---|---|---|
| Пам’ять | 512 MB | 2048 MB (Chromium); 2560 MB (Firefox, WebKit) | 4096 MB | 4096 MB |
| vCPU | 2 | 2 | 4 | 4 |
| Жорсткий TTL | 8 год | 2 год | 2 год | 2 год |
| Вікно простою | 45 хв | 15 хв | 15 хв | 15 хв |
| Екран під час завантаження | — | 1280×800 | 1280×800 | 1080×1920 |
- Нерухомі знімки каналу агента обмежено 1280×800; людський канал узгоджує до 2560×1600.
- Типовий бюджет резидентної пам’яті хоста для всіх rig — 12 GB, рахований у резидентних мегабайтах (припаркована ВМ усе одно тримає свою RAM). Витіснення — за найдавнішим використанням, і воно ніколи не забирає машину, якою хтось керує, за якою спостерігає або в якій має відкритий термінал.
- Відкритий термінал або канал спостереження закріплює rig проти паркування та прибирання за простоєм; жорсткий TTL усе одно діє.
Порти й dev-домени
Розділ із назвою «Порти й dev-домени»| Порт | Де | Зарезервовано для |
|---|---|---|
7911 |
Гостьовий термінал | Мультиплексор портів, яким їде кожна переадресація |
9222, 9223 |
Гостьовий браузер | Реле й кінцева точка автоматизації (WebKit прив’язується до 9222 напряму й не використовує реле) |
80, 443 |
Гостьовий loopback браузера | HTTP/HTTPS-канали dev-домену |
- Виявлення опитує TCP-порти, які слухає гостьовий термінал, приблизно кожні ~4 с, на боці сервера.
- Щонайбільше 16 портів переадресовують автоматично на кожен rig; більше — лише згадують у журналі, не переадресовують.
- Переадресація на боці хоста прив’язується до loopback, віддаючи перевагу власному номеру порту гостя; Поділитися в локальній мережі додає порт LAN, призначений ОС.
- Dev-домени мають відповідати
name.testабоname.localhost(нижній регістр, мітка до 63 символів). Один домен відображається на один порт. - HTTPS для dev-домену використовує локальний для сервера CA (EC P-256, під
<dataDir>/rigs/tls/, ключі 0600 і ніколи не в гості) з одним кінцевим wildcard-сертифікатом для*.test/*.localhost. Немаєopensslна хості — немає каналу HTTPS; звичайний HTTP усе одно маршрутизується.
Типові значення виходу
Розділ із назвою «Типові значення виходу»| Поверхня | Типовий список дозволених хостів |
|---|---|
| Термінал | Базова лінія розробника пісочниці (хостинги коду, реєстри пакетів, провайдери моделей) + дзеркала apt Ubuntu + власний хост хостингу коду з worktree |
| Браузер | usectrl.dev (сайт продукту) — плюс архіви Debian під час першого завантаження кожного рушія, поки він встановлює свої пакети. Домашня сторінка — це локальний документ file://, і виходу їй не потрібно |
| Комп’ютер | Порожній — заборонено все — доки виклик не надасть хости |
| Мобільні | Не застосовується (мережею керує емулятор) |
Кожен мікроВМ додатково отримує хости реєстру свого образу — лише для витягування. Набір дозволених хостів брокера облікових даних виводять із того самого списку: для хоста, до якого гість не може дістатися, токен не випускають.
Буфер обміну та передавання файлів
Розділ із назвою «Буфер обміну та передавання файлів»Обидва напрямки копіювання й вставлення, а також перетягування файлів усередину й назовні. Доступно людині, яка керує rig; агент отримує буфер обміну через дієслова вище й жодного передавання файлів (у нього вже є оболонка всередині ізольованого середовища).
Перетинання буфера обміну — для кожного користувача й кожного напрямку. Вставлення з хоста в rig дозволене за замовчуванням; копіювання з rig у хост запитує підтвердження (дозвіл на десять хвилин або завжди дозволяти в Налаштування → Сервер → Rigs → Доступ до буфера обміну). Обидва вибори незалежні й ніколи не є налаштуванням робочого простору.
| Канал | Маршрут | Переносить |
|---|---|---|
| Буфер обміну | GET/POST /rig/clipboard/<rigId> |
Текст, один PNG/JPEG (≤16 MB) і гостьові шляхи файлів у буфері обміну |
| Файли | POST /rig/files/<rigId> |
До 64 файлів, ≤256 MB кожен і ≤512 MB на перекидання, з необов’язковою точкою перекидання в гостьових пікселях |
| Файли | GET /rig/files/<rigId>?p=<base64url path> |
Байти одного файлу, назад назовні |
- HTTP, не RPC. RPC-сокет закриває з’єднання на вхідному фреймі понад 256 KB — це захист від DoS, який правильний для команд JSON і фатальний для вставленого знімка екрана. Байти їдуть таким самим маршрутом, яким уже їдуть кадри rig і аудіо зустрічей.
- Автентифікація — це підписана ціль
rig-files:<workspaceId>/<rigId>плюс членство в робочому просторі — окрема ціль, тож URL, випущений, щоб спостерігати машину, не може також записувати в неї файли. - Перехоплення застосовується. Запис у буфер обміну й перекидання файлів змінюють стан, і їх відхиляють, поки керування утримує хтось інший; читання буфера обміну й вичитування файлу назовні — це спостереження, і їх не відхиляють.
- Куди потрапляють перекинуті файли:
~/Drops(робочий стіл),~/drops(термінал — поряд із worktree, ніколи всередині нього, тож перекинутий файл ніколи не з’являється як незафіксована зміна),/tmp/cc-drops(браузер). Каталог вибирає сервер; той, хто викликає, не може його назвати. Наявні файли ніколи не перезаписують — ім’я, що збігається, лягає як2-name.ext. - Що кажуть гостю: сторінка браузера отримує справжню подію перекидання в
запитаній точці (
Input.dispatchDragEvent); робочий стіл отримує файли разом з їхніми URI у своєму буфері обміну, бо жоден хост не може синтезувати перетягування XDND у довільний інструментарій без привілейованого демона всередині гостя. Відповідь каже, який із двох варіантів стався. - Перетягування назовні працює лише на робочому столі й читає
XdndSelectionгостя, поки перетягування триває. Навантаження, ідентичне тому, яке гість уже тримав на момент початку натискання, вважають застарілим виділенням із завершеного перетягування, а не новим, — у X немає кроку «перетягування завершено». - Вимоги до образу: образ робочого столу має бути протоколу 2 або новішого (зібраний після появи підтримки буфера обміну). Старіший образ відповідає 404, і застосунок каже перезібрати його, а не повідомляє про зламану машину.
- Журнал аудиту записує форму, ніколи вміст: рядки
clipboard_read,clipboard_write,drop_filesіread_fileмістять кількості, розміри та шляхи. Буфер обміну — це місце, де облікові дані живуть по кілька секунд за раз, і ніщо з цього не записується.
Обмеження, події, сховище
Розділ із назвою «Обмеження, події, сховище»- Інструменти rig оголошують клас дій
enclosureControl(плюсnetworkEgressіprocessSpawnв інструментах використання;mobile_useтаios_useтакож оголошуютьpackageInstall).rig_closeоголошуєenclosureControl;rig_listне оголошує жодного. Дозволено за замовчуванням; режими лише для читання забороняють його цілком; регулятор автономності для кожного простору може знизити його до рівня «спершу запитати». - Доменні події:
RigClosedEvent(з її причиною закриття),RigControlChanged(перехоплення / повернення керування),RigReaped(простій, TTL або витіснення за пам’яттю, з агентом, який керував). Відкриття rig не є подією. Див. Доменні події. - Сховище:
rig_sessionsіrig_action_logу базі даних кожного робочого простору. Журнал дій записує кожну подію введення з її суб’єктом і монотонною послідовністю для кожного rig; набраний текст редагують до довжини та хешу, перш ніж записати. - Каталог даних:
rigs/images/(імпортовані образи qcow2),rigs/smolvm/(стан середовища виконання кожного rig),rigs/smolvm-packs/(попередньо розпаковані пакети машин),rigs/tls/(CA dev-домену),rigs/run/(оверлеї та сіди QEMU). - Маршрути: живий перегляд — це вкладка в просторі або на сторінці PR;
/settings/server/rigs— екран налаштувань Rigs.