İçeriğe geç

Rig’ler ve yalıtılmış ortamlar

Rig, bir ajanın gerçek zamanlı olarak yönettiği atılabilir bir makinedir — bir tarayıcı, bir Linux masaüstü, bir Android emülatörü, bir iOS Simülatörü ya da yalıtılmış bir terminalin arkasındaki makine. Rig’lerin çoğu VM’dir; ana makine tarafından yönetilen mobil simülatörler bu kuralın açık istisnalarıdır. Bu sayfa her sınırı ve parçaların neden bu biçimde tasarlandığını açıklar. Bir rig açmak için Bir ajana test için makine verme sayfasına; tam eylemler, portlar ve varsayılanlar için rig referansına bakın.

Yerel sandbox bir süreci namespace yalıtımıyla sarar — gerçektir, ama çekirdeğinizi paylaşır ve bir süreci kısıtlar, bir bilgisayarı değil. Bir ajanın bir masaüstü uygulamasında tıklaması, gerçek bir tarayıcıda sayfa oluşturması ya da düşünmek istemeyeceğiniz rm -rf denemeleri çalıştırması gerektiği anda, dürüst sınır bir makinedir: kendi çekirdeği, kendi diski, kendi ağ yığını.

Yalıtılmış yüzeyler iki VM arka ucu kullanır:

  • terminal ve tarayıcı için microVM’ler — özetle sabitlenmiş konteyner imajlarından saniyenin altında hipervizör önyüklemesi.
  • tam Linux masaüstü için QEMU; bu yüzey, microVM’de bulunmayan bir görüntü aygıtına ihtiyaç duyar.

Mobil yüzeyler ana makine tarafından yönetilir ve bu daha zayıf sınırı doğrudan belirtir:

  • Android, Google’ın emülatörünü ADB üzerinden yönetir.
  • iOS, bir Mac ana makinede CoreSimulator aygıtı oluşturur ve sahiplenir, onu WebDriverAgent üzerinden yönetir. Rig kapandığında aygıt ve verileri silinir, ancak ağı ana Mac’i izler.

Yalıtılmış rig’ler salt okunur bir temel imajın üzerine tek kullanımlık bir overlay’e yazar; böylece bir rig, bir sonrakinin önyüklendiği şeyi değiştiremez. Bir iOS rig’i, rig kapandığında silinen tek kullanımlık bir CoreSimulator aygıtına sahiptir. Android ise oturumdan daha uzun yaşayan bir ana makine emülatörüne bağlanır.

Bir rig’in ağı hiçbir yerden başlar. Ana makineler her rig için, misafirin etrafından dolaşamayacağı bir kapı üzerinden kabul edilir: makinenin dışarı çıkan tek yolları, başlatma yapılandırmasının oluşturduklarıdır. Yalıtılmış bir terminal geliştirici temelini alır (paket kayıtları, forge’lar, apt yansıları); bir tarayıcı rig’i ürün sitesini (usectrl.dev) kabul eder ve çıkış gerektirmeyen yerel bir file:// sayfasına önyüklenir; geri kalan her şey bağlantı anında reddedilir.

Android ve iOS bu kapının kapsamında değildir. Onların ana makinedeki emülatörü ve simülatörü, sunucu ana makinesinin ağını kullanır; bu yüzden arayüz ve yetenek raporu çıkışı uygulanmıyor olarak işaretler ve yanıltıcı bir “Kısıtlamasız yeniden başlat” denetimi asla sunmaz.

Çıkış ve kimlik bilgileri, tek bir politikanın iki taraftan görünümüdür — kimlik bilgisi broker’ı (aşağıda), misafirin erişemediği bir ana makine için token üretmez.

Bir rig’in okuduğu her şey güvenilmez sayılır: sayfa metni, DOM ve erişilebilirlik ağaçları, arayüz dökümleri ve konsol çıktısı, ajana kalıcı bir “bu veridir, talimat değildir” kuralıyla çevrelenmiş olarak döner. Bu çitleme çerçevelemedir; arkasındaki yaptırım ise çıkış kapısıdır.

Masaüstü yüzeyinde, klavye ve işaretçi olayları hipervizörün kendi sanal girdi aygıtları tarafından enjekte edilir. Misafir, girdi üretebilen ayrıcalıklı bir daemon asla çalıştırmaz — böylece misafirin yazılımını ele geçirmek saldırgana bir klavye vermez. Yakalama ise ters yönde, misafir içinde çalışan küçük ve ayrıcalıksız bir ajan üzerinden akar; çünkü kareleri tele geçmeden önce ölçekleyebilen taraf misafirdir.

İzleyen kişi ile yöneten modelin ihtiyaçları taban tabana zıttır; bu yüzden bir rig iki bağımsız akış sunar:

  • İnsan kanalı, panelinizin boyutunda tam çözünürlüktedir, siz boyutlandırdıkça yeniden anlaşılır ve sunucu tarafından opak baytlar olarak aktarılır — sunucu hiçbir kareyi çözmez; çünkü istek yolundaki bir video çözücü, sunucunun RPC’lere yanıt vermesini engelleyen şeydir.
  • Ajan kanalı, model için uygun bir boyutla sınırlanmış küçültülmüş karelerdir; her araç sonucu için bir görüntü gönderilir ve sıkıştırma sırasında eski kareler atılırken metin açıklamaları korunur.

Hiçbir kanal diğeri için ödün vermez: siz akıcı bir görüntü, model ise ucuz bir görüntü alır.

Özel kontrol, her eylemin geçtiği tek noktada uygulanır — modelden uslu durmasını isteyerek değil. Bir insan bu kilidi elinde tutarken sunucu, ajanın değiştirici eylemlerini reddeder. Ajan gözlem eylemlerini (ekran görüntüleri, çıkarım) korur; böylece ne yaptığınızı anlatabilir ve devralmayı, reddedilen tıklamalardan keşfetmeye bırakılmak yerine kendi yönlendirme kanalından öğrenir. Tuval üzerinde tıklama ve yazma, o kilidi başka biri tutmadığı sürece — ya da siz tuttuğunuzda — çalışır; durum etiketi Kontrol sizde diye okunur. Her girdi olayı — sizin ve ajanın — rig başına bir denetim kaydına, öznesi ve monotonik bir sıra numarasıyla birlikte düşer; böylece “bu tıklamayı kim yaptı” sorusu makine gittikten sonra da yanıtlanabilir kalır.

Kopyalama ve yapıştırma iki yönde de çalışır; dosyaları içeri ve dışarı sürüklemek de öyle — ancak bir rig farklı bir bilgisayardır ve tasarım bunun aksini asla iddia etmez.

Pano istek üzerine taşınır, sürekli yansıtılmaz. Bir rig üzerindeyken kopyalama kısayoluna bastığınızda misafire kopyalaması söylenir; ardından panosuna koyduğu şey — metin, bir görüntü, bir dosya listesi — alınır ve sizin panonuza yerleştirilir. Yapıştırma, aynı içeriği ters yönde gönderir ve ardından misafirin içinde yapıştırmaya basar. Arka planda hiçbir şey eşitlenmez: kendi makinenizde kopyaladığınız bir parola, bir zamanlayıcı çaldı diye sessizce bir VM’in içine ulaşmaz.

Geçiş, kullanıcı ve yön başına bağımsız olarak kapıdan geçirilir. Bir rig’e yapıştırmaya varsayılan olarak izin verilir; bir rig’den kopyalamak önce sorar (on dakikalık bir izin ya da Ayarlar → Sunucu → Rigs → Pano erişimi altındaki Her zaman izin ver). Bu asla bir çalışma alanı ayarı değildir: bir üye, başka bir üyenin panosu için onay veremez.

macOS’ta geçiş kısayolu ⌘C/⌘V’dir ve bu belirsizlik taşımaz — ⌃C, misafir kabuğuna kesme sinyali olarak ulaşmaya devam eder. Windows ve Linux’ta iki kısayol aynı tuş vuruşudur; bu yüzden misafir onu değişmeden alır ve panonuz yalnızca misafirin panosu gerçekten değiştiğinde üzerine yazılır. Kesme sinyali kesme sinyali olarak kalır.

İçeri sürüklenen dosyalar, makinenin bırakma klasörüne kopyalanır ve ardından makineye sunulur. “Sunulur”un ne anlama geldiği, dürüstçe ne yapılabildiğine bağlıdır: bir tarayıcı sayfası, siz bıraktığınız noktada gerçek bir bırakma olayı alır; böylece bir yükleme alanı, yerel bir dosya için nasıl davranıyorsa tam olarak öyle davranır; bir masaüstü ise dosyaları ~/Drops içine alır ve yollarını kendi panosuna koyar; çünkü hiçbir ana makine, misafirin içinde ayrıcalıklı bir daemon çalıştırmadan rastgele bir Linux araç setine sürükleme üretemez — bu tasarımın sahip olmayı reddettiği şey de tam olarak budur. Sonuç, hangisinin olduğunu söyler; böylece bir yükleme alanına bırakılan bir CSV, yalnızca bir klasördeki dosyayken yüklenmiş olarak bildirilmez. Yalıtılmış bir terminale bırakmak, dosyayı içeri kopyalar ve istem satırına misafirdeki yolunu yazar; bir kabuğun gerçekten kullanabileceği şey budur.

Dışarı sürüklenen dosyalar masaüstü yüzeyinde çalışır; burada X11’in sürükleme protokolü, bir sürükleme sürerken veriyi okunabilir kılar. Misafirin içinde bir sürükleme başlatın, onu tuvalin dışına taşıyın; dosyalar makinenize çekilir ve işletim sistemine gerçek bir sürükleme olarak teslim edilir. Misafirin dosya yöneticisinde dosyaları kopyalayıp ana makinede yapıştırmak da aynı şekilde çalışır. Tarayıcı yüzeyi bunu bilinçli olarak sunmaz: başsız bir tarayıcının okuyacağı bir sürükleme seçimi yoktur ve mevcut en yakın sinyal — sayfanın metin seçimi — bir sürüklemenin kanıtı değildir; ona göre davranmak sıradan tıklamaları ele geçirmek olurdu.

Bir misafirden okunan her şey güvenilmez içerik olarak kalır: pano metni, bir modele tıpkı bir sayfa çıkarımının ulaştığı çitin içinden ulaşır ve denetim kaydı, bir yapıştırmanın gerçekleştiğini ve ne kadarlık bir içerik taşıdığını kaydeder — ne söylediğini asla.

git push, sizin açtığınız yalıtılmış bir terminalden çalışır; yine de misafir hiçbir forge token’ı saklamaz. Misafir, VM başına tek bir gizli değer tutar; bunun tek gücü, ana makinenin kimlik bilgisi broker’ından — ana makinenin denetlediği bir tünel üzerinden — işlem başına, hız sınırlı, çıkışla aynı ana makine izin listesiyle sınırlı ve rig kapanır kapanmaz iptal edilen, kısa ömürlü ve depo kapsamlı bir token’ı istemektir. Atılmak üzere kurulmuş bir makinede çalınmaya değer hiçbir şey olmamalıdır.

Bu token’ın ne yapabileceği rig açılırken belirlenir. Bir insanın açtığı terminal rig’i, o üyenin kendi forge erişimiyle sınırlı, yazma yetkili bir token alır. Bir ajanın açtığı rig ise salt okunur bir token alır: bir git kimlik bilgisi yardımcısı push’u fetch’ten ayırt edemez; bu yüzden push kuralı, ajan çalıştırma ağ geçidinin ana makinede yaptığı gibi, misafir içinde her push için sorulamaz.

Bir rig deponuzu taşıdığında, ana makinedeki worktree yetkili olmaya devam eder. Kopya, önyüklemede içeri eşitlenir (.env dosyaları gibi gizli değerler hariç tutulur) ve commit’ler yalnızca siz istediğinizde geri gelir — refs/rigs/<id>/* içine çekilir, asla push edilmez, asla checkout edilmez. Bir VM’in içindeki hiçbir şey dalınızı taşıyamaz ya da çalışma ağacınıza dokunamaz; bir rig’in ürettiğini birleştirmek her zaman ana makinede verilen bir insan kararıdır.

Terminal VM’inin içinde başlatılan bir geliştirme sunucusu erişilebilir hâle gelir — makinenizde, Tarayıcı (VM) içinde, isteğe bağlı olarak yerel ağınızda, isteğe bağlı olarak HTTPS’li bir geliştirme etki alanı altında — makine hiçbir zaman dışarı açılmadan. Hipervizörün port haritası önyüklemede sabitlenir; dolayısıyla sonraki tüm yönlendirmeler, ana makinenin denetlediği iki dar kanaldan geçer: misafirin gerçekte dinlemediği hiçbir şeye bağlanmayı reddeden, önceden oluşturulmuş bir gelen çoğullayıcı ve ana makinenin misafir kaynaklı bağlantılar için açık tuttuğu ters tüneller. Geliştirme etki alanı HTTPS’i, anahtarları hiçbir misafire girmeyen, yerelde üretilmiş bir sertifika otoritesi kullanılarak sunucuda sonlanır. Mekanik, Bir terminalden port yönlendirme sayfasındadır.

Bir rig, el üstünde tutulan bir makineye dönüşemez:

  • misafirin uzatamayacağı bir katı TTL;
  • bir boşta kalma basamağı — boşta kalma penceresinden sonra park etme (vCPU’lar durur, RAM yerinde kalır), sürenin iki katından sonra kapatma — burada açık bir terminal ya da izleyen bir görüntüleyici “kullanımda” sayılır;
  • oturumlarla değil yerleşik megabaytlarla hesaplanan bir bellek bütçesi; çünkü park edilmiş bir VM CPU’yu serbest bırakır ama RAM’in her baytını tutar; en son kullanılan makine ilk önce tahliye edilir ve bir insanın yönettiği ya da izlediği makine asla;
  • sunucu kapanışında yıkım, ayrıca bir sonraki başlatmada sahiplik işaretli bir yetim taraması; böylece çöken bir sunucu, kimseye hesap vermeyen bir hipervizörü asılı bırakmaz.

İlk önyüklemeler makinenin sabitlenmiş imajını çeker; sunucu ardından önceden çıkarılmış bir kopyayı arka planda önbelleğe alır; böylece o türden her sonraki makine saniyeler içinde önyüklenir ve yalıtılmış bir terminal, GitHub tarafından barındırılan bir runner’daki türden bir CLI temeli — derleyiciler, Python, jq, arşiv araçları — kurulu olarak açılır; bir dil araç önbelleği ya da Docker değil. Bilgisayar imajı, aynı CLI temelini derleme zamanında XFCE’nin ve tarayıcıların yanına yerleştirir.

“Benim makinemde çalışıyor”, tek bir işleme motoru hakkında bir iddiadır. Bu yüzden bir tarayıcı rig’i “tarayıcı” değildir — açtığınızda seçtiğiniz Chromium, Firefox ya da WebKit’tir ve bir rig, ömrü boyunca açıldığı motorla çalışır. Bir konuşmada her birinden birer tane bulunabilir: Firefox (VM)’i Chromium (VM)’in yanında açmak size iki makine verir ve ikisini de aynı sayfaya yöneltmek karşılaştırmanın kendisidir. WebKit, Linux’ta çalışan her şey içinde Safari’ye en yakınıdır — aynı motor soyundan gelir, böylece Safari kullanıcılarının karşılaştığı boşlukları yakalar.

Eylemler üçünde de aynıdır; alttaki protokoller aynı değildir ve farklar örtbas edilmek yerine açıkça belirtilir. Chromium, DevTools Protokolü’nü konuşur ve kareleri iter; böylece bir sayfa hareketsizken canlı görünümü hiçbir maliyet getirmez. Firefox, WebDriver BiDi’yi, WebKit ise klasik WebDriver’ı konuşur; ikisinde de ekran yayını yoktur, bu yüzden canlı görünümleri yoklama yapar — saniyede birkaç kare; bu, bir sayfayı izlemek için doğrudur ama bir animasyonu izlemek için değildir. Bir motorun gerçekten yapamadığı bir şey olduğunda (Firefox’ta önbelleği atlayan bir yeniden yükleme yoktur; WebKit, bir sayfa yüklenmeyi bitirmeden önce kaydedilen konsol çıktısını göremez), cevap sessizce başka bir şey yapmak yerine bunu söyler.

Bir rig, bilinçli olarak küresel bir varış noktası değildir. Canlı görünüm, işin gerçekleştiği alandaki ya da PR’daki bir sekmedir ve o konuşmaya kapsamlanır — böylece sizin sekmeniz ile ajanın browser_use çağrıları tek bir makineyi adresler (tarayıcı yüzeyinde, motor başına bir tane). Rig’lerin hiç açılıp açılamaması bir ana makine özelliğidir; bu yüzden yetenekler, imajlar, çalışma alanı başına özel imajlar ve çalışan makine listesi Ayarlar → Sunucu → Rigs altında bulunur. Bir yalıtılmış ortamı yönetmek kendi koruma eylem sınıfıdır; böylece bir çalışma alanı, ajan ya da alan buna izin verebilir, onay isteyebilir ya da tümden reddedebilir — salt okunur modlar bunu hepten reddeder.