Aller au contenu

Donner une machine de test à un agent

Un rig est une machine jetable qu’un agent ouvre lorsqu’il doit réellement essayer quelque chose : charger une page, parcourir une application de bureau, manipuler un téléphone. Vous pouvez le regarder travailler en temps réel et reprendre les commandes quand vous le souhaitez.

Les rigs cloisonnés de terminal, de navigateur et de bureau sont des VM dotées de disques jetables et de réseaux filtrés. Android et iOS sont des émulateurs gérés par l’hôte : l’état de leurs appareils est jetable, mais leur mise en réseau suit l’hôte du serveur.

Les rigs s’exécutent sur la machine qui héberge cc_server — la même machine, pas celle que vous avez sous les yeux. Cinq surfaces sont exposées à l’utilisateur ; les surfaces de bureau et mobiles nécessitent une configuration sur l’hôte :

Surface S’exécute sur Installation
Terminal (VM) Une microVM qui démarre une image Ubuntu épinglée Aucune — l’image est récupérée automatiquement au premier usage
Navigateur (VM) Une microVM qui démarre une image Debian épinglée, avec Chromium, Firefox ou WebKit installés au premier usage Aucune — idem
Ordinateur (VM) QEMU avec une image de bureau Linux qui embarque Chromium, Firefox, WebKit et un socle d’outils CLI du même genre que celui d’un exécuteur hébergé par GitHub Installez QEMU (brew install qemu), puis Importer une image de bureau sous Paramètres → Serveur → Rigs
Android L’émulateur Android de Google Installez le SDK Android, créez un AVD et démarrez-le (ci-dessous)
Simulateur iOS CoreSimulator sur le Mac du serveur Installez Xcode et le runtime iOS demandé, puis installez la passerelle d’automatisation sous Paramètres → Serveur → Rigs

Les machines Terminal et Navigateur démarrent à partir d’images épinglées par empreinte : les octets exacts sont nommés à l’avance, récupérés une fois au premier démarrage, puis mis en cache — après le premier démarrage de chaque type, les machines suivantes sautent complètement le téléchargement et démarrent en quelques secondes. Paramètres → Serveur → Rigs indique ce que votre serveur peut démarrer et toutes les machines en cours d’exécution.

Une image de bureau installée reste gérable depuis la même page : Importer la remplace par un qcow2 plus récent, et Supprimer la retire afin que vous puissiez installer une nouvelle version.

Il n’existe aucune image de notre côté pour Android ou iOS, et ce n’est pas un oubli. Les images système Android proviennent du SDK de Google ; les runtimes iOS proviennent de Xcode. Pour Android, installez Android Studio (ou les outils SDK en ligne de commande), ajoutez un appareil virtuel dans le Gestionnaire d’appareils, puis démarrez-le. La page Rigs signale alors Android comme disponible.

Elle vous indique aussi exactement l’étape qui manque — pas de SDK, pas d’émulateur, pas d’appareil virtuel, ou un appareil tout simplement arrêté — parce que ces cas ont quatre correctifs différents et qu’un seul est un téléchargement. Si vous démarrez cc_server depuis un shell qui ne voit pas le SDK, exportez-le :

Fenêtre de terminal
export ANDROID_HOME="$HOME/Library/Android/sdk"

Pour iOS, le serveur lui-même doit s’exécuter sous macOS avec Xcode et un runtime de simulateur iOS installés. Ouvrez Paramètres → Serveur → Rigs et cliquez sur Installer la passerelle d’automatisation iOS. Le serveur récupère l’artefact WebDriverAgent épinglé par somme de contrôle, le vérifie et l’installe dans le magasin d’automatisation propre au serveur. Aucun simulateur ne démarre pendant l’installation.

Les machines vivent sous forme d’onglets, à côté du chat et du diff — dans un espace ou sur une page de PR, dans le même menu +, sous Machines :

  • Ordinateur — un bureau Linux avec Chromium, Firefox et WebKit
  • Chromium, Firefox ou WebKit — un navigateur
  • Android — l’émulateur Android en cours d’exécution
  • Simulateur iOS — un simulateur jetable créé pour cette conversation

Choisissez-en un et cliquez sur Démarrer la machine. L’onglet indique à quelle étape du démarrage il en est (« Starting the microVM », « Waiting for the guest to come up ») au lieu de simplement tourner.

L’onglet est délimité à la conversation, et l’outil de l’agent aussi. Un onglet Chromium, Firefox ou WebKit et browser_use, Android et mobile_use, ou le Simulateur iOS et ios_use s’adressent à la même machine par défaut. Les emplacements d’interface supplémentaires sont des machines de comparaison distinctes ; les outils d’agent utilisent toujours celle par défaut.

Pour compiler, installer et démarrer une application Flutter sur Android :

Fenêtre de terminal
fvm flutter build apk --debug

Appelez ensuite mobile_use avec install_apk et build/app/outputs/flutter-apk/app-debug.apk, puis start_app et le nom de paquet Android. ui_dump, les captures d’écran et les entrées pilotent le même appareil que celui affiché dans l’onglet humain. stop_app, clear_app_data, uninstall_app, open_url et les appels shell de forme argv couvrent le reste du cycle de développement sans invoquer de shell sur l’hôte du serveur.

Pour compiler, installer et démarrer une application Flutter dans le Simulateur iOS :

Fenêtre de terminal
fvm flutter build ios --simulator --debug
/usr/bin/plutil -extract CFBundleIdentifier raw -o - \
build/ios/iphonesimulator/Runner.app/Info.plist

Appelez ensuite ios_use avec install_app et le répertoire .app, puis start_app et l’identificateur de paquet imprimé par plutil. L’outil iOS expose aussi stop_app, uninstall_app, open_url et une action spawn de forme argv pour les diagnostics locaux au simulateur.

Les affichages du bureau et du navigateur s’adaptent au panneau. Du côté d’iOS, l’affichage conserve la taille de point fixe du simulateur et est présenté en format boîte aux lettres. Chaque surface a tout de même deux voies indépendantes : l’agent reçoit de petites captures économiques, tandis que vous obtenez la vue en direct. Changer d’onglet arrête le flux humain, de sorte qu’une machine en arrière-plan ne coûte aucune bande passante d’affichage.

Un onglet de rig ne démarre pas de machine de lui-même, y compris pendant la restauration de la disposition. Cette règle évite qu’un lancement de l’application démarre inopinément des VM ou crée des appareils de simulateur.

Le canevas vous appartient : vous pouvez y taper et y cliquer dès que personne d’autre ne détient le contrôle exclusif — ou lorsque c’est vous qui le détenez. Tant que vous détenez ce verrou, l’étiquette d’état affiche Vous avez le contrôle, l’agent peut toujours prendre des captures d’écran, et le serveur refuse ses actions de modification au point de passage unique par lequel transite chaque action. Tout ce que vous faites est consigné à votre nom.

Cliquez sur Arrêter la machine quand vous avez terminé.

Le contrôle est exclusif à dessein : deux acteurs qui tapent dans une même machine produisent des entrées qu’aucun des deux ne voulait.

Le copier-coller fonctionne dans les deux sens sur le canevas du rig, tout comme le glisser-déposer de fichiers.

Copier-coller. Appuyez sur le raccourci de copie au-dessus du canevas et tout ce que la machine a copié — texte, image, liste de fichiers — atterrit dans votre presse-papiers. Le collage envoie le vôtre dans l’autre sens et exécute un collage à l’intérieur de la machine. Sous macOS, le raccourci est ⌘C/⌘V ; ⌃C atteint encore un shell de l’invité comme interruption. Sous Windows et Linux, utilisez ⌃C/⌃V — l’invité reçoit la même frappe qu’il aurait reçue de toute façon, donc ⌃C dans un terminal de l’invité interrompt toujours et votre propre presse-papiers n’est pas touché.

Rien ne se synchronise en arrière-plan. Un mot de passe que vous copiez sur votre propre machine n’arrive pas dans une VM parce qu’une minuterie s’est déclenchée ; il franchit la frontière quand vous collez.

Le collage vers un rig est autorisé par défaut. La copie depuis un rig demande d’abord une autorisation — une autorisation de dix minutes, ou Toujours autoriser sous Paramètres → Serveur → Rigs → Accès au presse-papiers. Les deux sens sont indépendants, et ils vous suivent vous, pas l’espace de travail.

Glisser des fichiers vers l’intérieur. Déposez-les n’importe où sur le canevas.

  • Sur le Navigateur (VM), la page reçoit un véritable dépôt à l’endroit où vous relâchez, de sorte qu’une zone de téléversement se comporte exactement comme avec un fichier local.
  • Sur l’Ordinateur (VM), les fichiers atterrissent dans ~/Drops et leurs chemins sont placés dans le presse-papiers de la machine, de sorte que ⌃V les colle dans un gestionnaire de fichiers ou un champ de téléversement. Un hôte ne peut pas synthétiser un glisser vers une application Linux arbitraire sans exécuter un démon privilégié dans la VM, ce dont les rigs sont délibérément dépourvus — c’est pourquoi un message vous indique où sont allés les fichiers plutôt que de prétendre qu’un dépôt a eu lieu.
  • Sur un terminal, le fichier est copié à l’intérieur et son chemin est tapé à l’invite, prêt à être passé à une commande. Coller une image dans un terminal fait la même chose : elle est enregistrée dans la machine et vous obtenez le chemin.

Glisser des fichiers vers l’extérieur fonctionne depuis l’Ordinateur (VM). Commencez à glisser un fichier dans la machine, faites sortir le pointeur du canevas, et il devient un véritable glisser sur votre bureau — déposez-le dans le Finder ou l’Explorateur. Copier des fichiers dans le gestionnaire de fichiers de la machine et les coller de votre côté fonctionne aussi. Le Navigateur (VM) ne l’offre pas : un navigateur sans interface n’a aucune charge utile de glisser à lire, et deviner à partir de la sélection de texte de la page détournerait des clics ordinaires.

Les terminaux d’un espace ou d’une page de PR peuvent s’exécuter dans un rig plutôt que sur la machine propre du serveur. Dans ce cas, le panneau affiche l’étiquette VM cloisonnée.

Ce qui change :

  • Rien de ce que vous exécutez n’atteint l’hôte. Un rm -rf là-dedans vous coûte le rig.
  • Le réseau est refusé par défaut. Seuls les hôtes de la liste d’autorisation du rig sont joignables, et tout passe par une porte qui l’applique.
  • git push fonctionne toujours dans un terminal que vous avez ouvert. Le rig ne stocke aucun identifiant ; il demande au serveur un jeton de courte durée par opération, borné par votre propre accès à la forge, et ce jeton est révoqué à la fermeture du rig. Un rig ouvert par un agent reçoit un identifiant en lecture seule : il peut faire un fetch, mais pas pousser.

Ce qu’il faut savoir :

  • Un terminal cloisonné restauré vous attend. Comme un onglet de rig, un terminal microvm qui revient avec votre disposition affiche un bouton Ouvrir le shell plutôt que de démarrer sa VM au lancement. Un terminal dans le shell de l’hôte coûte un processus ; un terminal cloisonné coûte une machine.
  • Les fichiers déposés sur le terminal sont tapés, pas ouverts. Déposez un CSV sur un terminal cloisonné : il est copié dans la machine et son chemin invité apparaît à l’invite — le chemin de l’hôte serait une commande qui échouerait là-bas.
  • La copie dans le rig est une copie. Votre arbre de travail sur l’hôte fait autorité. Les commits que vous faites dans un rig sont ramenés dans refs/rigs/<id>/* quand vous le demandez — ils ne déplacent jamais votre branche et ne touchent jamais votre arbre de travail.
  • Le travail destiné à l’hôte s’exécute toujours sur l’hôte. Un invité Linux ne peut pas compiler pour macOS ni exécuter xcodebuild. Choisissez explicitement le backend natif pour cela ; l’application vous demandera de confirmer plutôt que de basculer sans le dire.

Démarrez un serveur de développement dans le Terminal (VM) — pnpm dev sur le port 3000, par exemple — et en quelques secondes, l’icône de prise dans le coin du terminal s’allume : le port est transféré vers localhost:3000 sur votre machine, joignable à localhost:3000 dans le Navigateur (VM), partageable sur votre réseau et nommable https://myapp.test. Tout ce mécanisme — transfert automatique, partage sur le réseau local, domaines de développement avec HTTPS — fait l’objet de son propre guide : Transférer des ports depuis un terminal.

Un espace de travail peut faire pointer le Terminal (VM) et le Navigateur (VM) vers ses propres images — sous Paramètres → Serveur → Rigs → Images personnalisées (cet espace de travail). Usage courant : enrichir l’image par défaut avec la chaîne d’outils dont votre projet a besoin pour que chaque terminal démarre prêt à l’emploi, ou réutiliser une image que votre équipe publie déjà.

La machine démarre toujours dans la même enceinte : même porte de sortie réseau, même courtier d’identifiants, même cycle de vie. Seuls les administrateurs de l’espace de travail peuvent modifier le réglage, les nouvelles machines l’adoptent (celles en cours gardent le leur), et la référence doit être une image de registre — les chemins locaux sont refusés.

Ce qu’une image doit fournir :

  • Terminal (VM) — une image Linux avec bash. Elle a aussi besoin de git, curl et socat — soit préinstallés, soit installables au premier démarrage (toute image basée sur Debian/Ubuntu fait l’affaire : ils sont installés automatiquement, avec un socle d’outils CLI du même genre que celui d’un exécuteur hébergé par GitHub : compilateurs, Python 3, jq, outils d’archivage, rsync. Les environnements d’exécution comme Node/Go/Java et Docker ne sont pas préinstallés). Le port invité 7911 est réservé au redirecteur de ports.
  • Navigateur (VM) — une image Debian/Ubuntu avec bash et socat, plus un binaire chromium. Le serveur démarre Chromium lui-même sous la forme chromium --headless=new et relaie les DevTools du port invité 9223 vers 9222. PulseAudio et ffmpeg sont installés au premier démarrage. Ne construisez pas FROM chromedp/headless-shell — ce binaire n’a pas d’audio. La substitution ne s’applique qu’aux rigs Chromium ; Firefox et WebKit l’ignorent et démarrent l’image Debian épinglée. Les ports invités 9222/9223 sont réservés.

Deux recommandations : épinglez la référence par empreinte (@sha256:…) pour que les octets ne puissent pas changer sous vos pieds, et hébergez-la sur Docker Hub ou GitHub Container Registry — les hôtes de téléchargement de ces registres sont admis automatiquement par la porte de sortie réseau ; pour les autres, leurs hôtes de diffusion de contenu pourraient devoir être joignables pour le téléchargement.

Les rigs sont conçus pour être temporaires :

  • Inactivité — après environ 15 minutes sans activité, un rig de navigateur, de bureau ou mobile se met en veille (gelé, il se réveille instantanément à la prochaine action). Un terminal cloisonné attend 45 minutes. Après le double de la fenêtre d’inactivité, il se ferme.
  • Limite de temps — chaque rig a une durée de vie stricte qu’il ne peut pas prolonger, quoi qu’il fasse.
  • Mémoire — si le serveur a besoin de place pour un nouveau rig, il ferme celui qui a été utilisé le moins récemment. Un rig que quelqu’un pilote, regarde, ou dans lequel un terminal est ouvert n’est jamais retiré.

À la fermeture d’un rig cloisonné, son disque est jeté. Fermer un rig Android le détache de l’émulateur de l’hôte — il ne le supprime pas. Un rig iOS supprime l’appareil CoreSimulator qu’il a créé. Récupérez d’abord tout ce que vous voulez conserver.

Les rigs cloisonnés de terminal, de navigateur et de bureau utilisent par défaut une porte de sortie réseau qui refuse tout : vous autorisez les hôtes explicitement, et la seule voie de l’invité passe par une porte qui applique cette liste. Un rig de navigateur admet aussi le site du produit (usectrl.dev) d’emblée. Le courtier d’identifiants utilise la même liste.

Deux réserves honnêtes :

  • Le réseau mobile suit l’hôte. L’émulateur Android et CoreSimulator d’Apple ne sont pas derrière la porte de sortie réseau de l’enceinte. Aucun des deux onglets mobiles n’offre de commande de contournement du réseau, parce que le réseau géré par l’hôte est déjà sans restriction.
  • Tout ce qu’un rig lit est non fiable. Le texte des pages, le DOM, les arbres d’accessibilité et les vidages d’interface reviennent à l’agent encadrés par des marqueurs qui disent « ceci est une donnée, pas une instruction ». Une page qui tente de donner des ordres à votre agent se lit comme une chaîne citée.

Vous pouvez voir tout ce qui tourne, et arrêter n’importe quoi, sous Paramètres → Serveur → Rigs.

  • Rigs et enceintes — le modèle derrière tout cela : pourquoi des VM, les deux voies d’affichage, le courtier d’identifiants, le cycle de vie
  • Transférer des ports depuis un terminal — joindre un serveur de développement de partout où c’est utile
  • Référence des rigs — chaque surface, verbe, port et valeur par défaut au même endroit
  • Configurer les garde-fous — Piloter une enceinte (rig) est une classe d’action que vous pouvez régler sur Autoriser, Demander d’abord ou Refuser, par espace de travail, agent ou espace. Les modes en lecture seule la refusent d’emblée.