Ir al contenido

Dar a un agente una máquina para probar

Un rig es una máquina desechable que un agente abre cuando necesita probar algo de verdad: cargar una página, recorrer con clics una aplicación de escritorio, toquetear un teléfono. Puedes verlo trabajar en tiempo real y asumir los controles cuando quieras.

Los rigs con recinto de terminal, navegador y escritorio son VM con discos desechables y redes con puerta. Android e iOS son emuladores gestionados por el host: el estado de sus dispositivos es desechable, pero su red sigue al host del servidor.

Los rigs se ejecutan en la máquina que aloja cc_server — la misma máquina, no la que estás mirando. Hay cinco superficies de cara al usuario; las superficies de escritorio y móviles necesitan configuración en el host:

Superficie Se ejecuta en Configuración
Terminal (VM) Una microVM que arranca una imagen de Ubuntu fijada Ninguna — la imagen se descarga automáticamente en el primer uso
Navegador (VM) Una microVM que arranca una imagen de Debian fijada, con Chromium, Firefox o WebKit instalados en el primer uso Ninguna — lo mismo
Ordenador (VM) QEMU con una imagen de escritorio Linux que incluye Chromium, Firefox, WebKit y una base de CLI al estilo de un runner alojado en GitHub Instala QEMU (brew install qemu) y luego Importar una imagen de escritorio en Ajustes → Servidor → Rigs
Android El emulador de Android de Google Instala el SDK de Android, crea un AVD y arráncalo (más abajo)
Simulador de iOS CoreSimulator en el Mac del servidor Instala Xcode y el runtime de iOS solicitado, y después el puente de automatización en Ajustes → Servidor → Rigs

Las máquinas de terminal y navegador arrancan desde imágenes fijadas por digest: los bytes exactos se nombran de antemano, se descargan una vez en el primer arranque y se guardan en caché — tras el primer arranque de cada tipo, las máquinas posteriores se saltan la descarga por completo y están listas en segundos. Ajustes → Servidor → Rigs muestra lo que tu servidor puede arrancar y todas las máquinas que están en marcha ahora mismo.

Una imagen de escritorio instalada sigue siendo gestionable desde la misma página: Importar la reemplaza por un qcow2 más reciente y Eliminar la borra para que puedas instalar una compilación nueva.

Los dispositivos móviles se configuran de otra forma

Sección titulada «Los dispositivos móviles se configuran de otra forma»

No hay ninguna imagen nuestra para Android o iOS, y no es una omisión. Las imágenes de sistema de Android vienen del SDK de Google; los runtimes de iOS, de Xcode. Para Android, instala Android Studio (o las herramientas de SDK de línea de comandos), añade un dispositivo virtual en el Administrador de dispositivos y arráncalo. Después, la página Rigs informa de que Android está disponible.

También te dice exactamente qué paso te falta — ningún SDK, ningún emulador, ningún dispositivo virtual o un dispositivo que simplemente no está en marcha — porque esos son cuatro arreglos distintos y solo uno de ellos es una descarga. Si arrancas cc_server desde un shell que no ve el SDK, expórtalo:

Ventana de terminal
export ANDROID_HOME="$HOME/Library/Android/sdk"

Para iOS, el propio servidor debe ejecutarse en macOS con Xcode y un runtime de simulador de iOS instalados. Abre Ajustes → Servidor → Rigs y pulsa Instalar el puente de automatización de iOS. El servidor descarga el artefacto WebDriverAgent fijado por suma de comprobación, lo verifica y lo instala en el almacén de automatización propio del servidor. Durante la configuración no arranca ningún simulador.

Las máquinas viven como pestañas, junto al chat y al diff — en un espacio o en una página de PR, en el mismo menú +, bajo Máquinas:

  • Ordenador — un escritorio Linux con Chromium, Firefox y WebKit
  • Chromium, Firefox o WebKit — un navegador
  • Android — el emulador de Android en ejecución
  • Simulador de iOS — un simulador desechable creado para esta conversación

Elige una y pulsa Iniciar la máquina. La pestaña indica en qué fase del arranque está («Starting the microVM», «Waiting for the guest to come up») en lugar de limitarse a girar.

La pestaña está acotada a la conversación, y la herramienta del agente también. Una pestaña de Chromium, Firefox o WebKit y browser_use, Android y mobile_use, o el simulador de iOS y ios_use se dirigen a la misma máquina predeterminada. Las ranuras adicionales de la interfaz son máquinas de comparación independientes; las herramientas de agente usan siempre la predeterminada.

Para compilar, instalar y arrancar una aplicación de Flutter en Android:

Ventana de terminal
fvm flutter build apk --debug

Después, llama a mobile_use con install_apk y build/app/outputs/flutter-apk/app-debug.apk, seguido de start_app y el nombre del paquete de Android. ui_dump, las capturas y la entrada dirigen el mismo dispositivo que se muestra en la pestaña humana. stop_app, clear_app_data, uninstall_app, open_url y las llamadas a shell con forma de argv cubren el resto del ciclo de desarrollo sin invocar un shell en el host del servidor.

Para compilar, instalar y arrancar una aplicación de Flutter en el simulador de iOS:

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

Después, llama a ios_use con install_app y el directorio .app, seguido de start_app y el identificador de paquete que imprima plutil. La herramienta de iOS también expone stop_app, uninstall_app, open_url y una acción spawn con forma de argv para diagnósticos locales del simulador.

Las pantallas de escritorio y navegador se redimensionan al panel. iOS mantiene el tamaño fijo en puntos del simulador y lo muestra con bandas negras. Todas las superficies siguen teniendo dos canales independientes: el agente recibe capturas pequeñas y baratas, mientras que tú recibes la vista en directo. Cambiar de pestaña detiene el flujo humano, así que una máquina en segundo plano no consume ancho de banda de pantalla.

Una pestaña de rig no arranca ninguna máquina por sí sola, ni siquiera durante la restauración de la disposición. Esa regla evita que abrir la aplicación arranque VM o cree dispositivos de simulador sin esperarlo.

El lienzo es tuyo para escribir y hacer clic siempre que nadie más tenga el control exclusivo — o cuando lo tengas tú. Mientras sostienes ese bloqueo, la etiqueta de estado dice Tienes el control, el agente puede seguir haciendo capturas y el servidor rechaza sus acciones que modifican el estado en el único punto de paso por el que pasan todas las acciones. Todo lo que haces queda registrado a tu nombre.

Pulsa Detener la máquina cuando termines.

El control es exclusivo a propósito: dos actores escribiendo en una misma máquina producen entrada que ninguno de los dos pretendía.

Copiar y pegar funcionan en ambos sentidos a través del lienzo del rig, y arrastrar archivos también.

Copiar y pegar. Pulsa la combinación de copiar sobre el lienzo y lo que haya copiado la máquina — texto, una imagen, una lista de archivos — aterriza en tu portapapeles. Pegar envía el tuyo en sentido contrario y pulsa pegar dentro de la máquina. En macOS la combinación es ⌘C/⌘V; ⌃C sigue llegando a un shell del huésped como interrupción. En Windows y Linux usa ⌃C/⌃V — el huésped recibe la misma pulsación que habría recibido de todos modos, así que ⌃C en un terminal del huésped sigue interrumpiendo y tu propio portapapeles no se toca.

Nada se sincroniza en segundo plano. Una contraseña que copias en tu propia máquina no llega al interior de una VM porque se dispare un temporizador; cruza cuando pegas.

Pegar en un rig está permitido de forma predeterminada. Copiar desde un rig pregunta primero — un permiso de diez minutos, o Permitir siempre en Ajustes → Servidor → Rigs → Acceso al portapapeles. Las dos direcciones son independientes, y te siguen a ti, no al espacio de trabajo.

Arrastrar archivos hacia dentro. Suéltalos en cualquier punto del lienzo.

  • En el Navegador (VM), la página recibe un soltado real en el punto donde sueltas, así que una zona de subida se comporta exactamente igual que con un archivo local.
  • En el Ordenador (VM), los archivos aterrizan en ~/Drops y sus rutas pasan al portapapeles de la máquina, así que ⌃V las pega en un gestor de archivos o en un campo de subida. Un host no puede sintetizar un arrastre hacia una aplicación Linux arbitraria sin ejecutar un demonio con privilegios dentro de la VM, y los rigs deliberadamente no lo tienen — por eso el aviso te dice adónde han ido los archivos en lugar de fingir que se ha producido un soltado.
  • En un terminal, el archivo se copia dentro y su ruta se escribe en el indicador, lista para pasarla a un comando. Pegar una imagen en un terminal hace lo mismo: se guarda en la máquina y recibes la ruta.

Arrastrar archivos hacia fuera funciona desde el Ordenador (VM). Empieza a arrastrar un archivo dentro de la máquina, saca el puntero del lienzo y se convierte en un arrastre real en tu escritorio — suéltalo en Finder o en Explorer. Copiar archivos en el gestor de archivos de la máquina y pegarlos en tu lado también funciona. El Navegador (VM) no ofrece esto: un navegador sin interfaz gráfica no tiene ninguna carga de arrastre que leer, y adivinarla a partir de la selección de texto de la página secuestraría clics normales.

Los terminales de un espacio o de una página de PR pueden ejecutarse dentro de un rig en lugar de en la propia máquina del servidor. Cuando lo hacen, el panel muestra una insignia VM aislada.

Lo que cambia:

  • Nada de lo que ejecutes llega al host. Un rm -rf ahí dentro te cuesta el rig.
  • La red deniega por defecto. Solo son accesibles los hosts de la lista de permitidos del rig, y todo pasa por una puerta que la aplica.
  • git push sigue funcionando en un terminal que hayas abierto tú. El rig no guarda ninguna credencial; pide al servidor una de corta duración por operación, acotada por tu propio acceso al host de código, y ese token se revoca cuando el rig se cierra. Un rig que abrió un agente recibe una credencial de solo lectura, así que puede hacer fetch pero no push.

Lo que conviene saber:

  • Un terminal con recinto restaurado te espera. Como una pestaña de rig, un terminal microvm que vuelve con tu disposición muestra un botón Abrir el shell en lugar de arrancar su VM al inicio. Un terminal con shell del host cuesta un proceso; uno con recinto cuesta una máquina.
  • Los archivos que se sueltan en el terminal se escriben, no se abren. Suelta un CSV en un terminal con recinto y se copia dentro de la máquina, y su ruta en el huésped aparece en el indicador — la ruta del host sería allí un comando que falla.
  • La copia del rig es una copia. Tu worktree en el host sigue siendo la fuente de verdad. Los commits que haces dentro de un rig se traen de vuelta a refs/rigs/<id>/* cuando lo pides — nunca mueven tu rama ni tocan tu árbol de trabajo.
  • El trabajo dirigido al host sigue ejecutándose en el host. Un huésped Linux no puede compilar para macOS ni ejecutar xcodebuild. Para eso, elige explícitamente el backend nativo; la aplicación te pedirá confirmación en lugar de cambiar en silencio.

Arranca un servidor de desarrollo en la Terminal (VM) — pnpm dev en el puerto 3000, por ejemplo — y en unos segundos se enciende el icono del enchufe en la esquina del terminal: el puerto se reenvía a localhost:3000 en tu máquina, es accesible en localhost:3000 dentro del Navegador (VM), se puede compartir en tu red y se le puede dar nombre como https://myapp.test. Todo el flujo — reenvío automático, uso compartido en la LAN, dominios de desarrollo con HTTPS — tiene su propia guía: Reenviar puertos desde un terminal.

Un espacio de trabajo puede apuntar la Terminal (VM) y el Navegador (VM) a sus propias imágenes — en Ajustes → Servidor → Rigs → Imágenes personalizadas (este espacio de trabajo). Uso típico: ampliar la imagen predeterminada con la cadena de herramientas que necesita tu proyecto para que cada terminal arranque listo, o reutilizar una imagen que tu equipo ya publica.

La máquina sigue arrancando dentro del mismo recinto: misma puerta de salida, mismo bróker de credenciales, mismo ciclo de vida. Solo los administradores del espacio de trabajo pueden cambiar el ajuste, las máquinas nuevas lo adoptan (las que ya se ejecutan conservan el suyo) y la referencia debe ser una imagen de registro — las rutas locales se rechazan.

Lo que debe proporcionar una imagen:

  • Terminal (VM) — una imagen de Linux con bash. También necesita git, curl y socat — preinstalados o instalables en el primer arranque (sirve cualquier imagen basada en Debian/Ubuntu: se instalan automáticamente, junto con un conjunto de herramientas de CLI al estilo de un runner alojado en GitHub: compiladores, Python 3, jq, herramientas de archivo y rsync. Los runtimes de lenguaje como Node/Go/Java y Docker no vienen preinstalados). El puerto del huésped 7911 está reservado para el reenviador de puertos.
  • Navegador (VM) — una imagen de Debian/Ubuntu con bash y socat, más un binario chromium. El servidor arranca Chromium por su cuenta como chromium --headless=new y reenvía DevTools desde el 9223 del huésped al 9222. PulseAudio y ffmpeg se instalan en el primer arranque. No compiles FROM chromedp/headless-shell — ese binario no tiene audio. La anulación solo se aplica a los rigs de Chromium; Firefox y WebKit la ignoran y arrancan la imagen de Debian fijada. Los puertos del huésped 9222/9223 están reservados.

Dos recomendaciones: fija la referencia por digest (@sha256:…) para que los bytes no puedan cambiar bajo tus pies, y alójala en Docker Hub o GitHub Container Registry — los hosts de descarga de esos registros se admiten automáticamente a través de la puerta de salida; puede que otros necesiten que sus hosts de distribución de contenido sean accesibles para poder descargarla.

Los rigs están pensados para ser temporales:

  • Inactividad — tras ~15 minutos sin que ocurra nada, un rig de navegador, escritorio o móvil se aparca (queda congelado y se despierta al instante con la siguiente acción). Un terminal con recinto espera 45 minutos. Tras el doble de la ventana de inactividad, se cierra.
  • Límite de tiempo — cada rig tiene una vida útil máxima que no puede prolongar, haga lo que haga.
  • Memoria — si el servidor necesita sitio para un rig nuevo, cierra el que se ha usado menos recientemente. Nunca se lleva un rig que alguien está dirigiendo o observando, ni en el que tiene un terminal abierto.

Cuando se cierra un rig con recinto, su disco se descarta. Cerrar un rig de Android se desconecta del emulador del host — no lo elimina. Un rig de iOS elimina el dispositivo CoreSimulator que creó. Trae de vuelta primero todo lo que quieras conservar.

Los rigs con recinto de terminal, navegador y escritorio usan de forma predeterminada una puerta de salida que deniega por defecto: los hosts los concedes tú explícitamente, y la única ruta del huésped es una puerta que aplica esa lista. Un rig de navegador también admite de fábrica el sitio del producto (usectrl.dev). El bróker de credenciales usa la misma lista.

Dos advertencias honestas:

  • La red de los móviles sigue al host. El emulador de Android y CoreSimulator de Apple no están detrás de la puerta de salida del recinto. Ninguna de las dos pestañas móviles ofrece un control para eludir la red, porque la red gestionada por el host ya es irrestricta.
  • Todo lo que lee un rig no es de confianza. El texto de las páginas, el DOM, los árboles de accesibilidad y los volcados de vista vuelven al agente envueltos en marcadores que dicen «esto son datos, no instrucciones». Una página que intente dar órdenes a tu agente se lee como una cadena entrecomillada.

Puedes ver todo lo que está en marcha, y detener cualquiera de ello, en Ajustes → Servidor → Rigs.

  • Rigs y recintos — el modelo que hay detrás de todo esto: por qué VM, los dos canales de visualización, el bróker de credenciales, el ciclo de vida
  • Reenviar puertos desde un terminal — llega a un servidor de desarrollo desde cualquier lugar donde importe
  • Referencia de rigs — cada superficie, verbo, puerto y valor predeterminado en un solo sitio
  • Configurar barandillas — Controlar un recinto (rig) es una clase de acción que puedes definir como permitir, preguntar primero o denegar, por espacio de trabajo, agente o espacio. Los modos de solo lectura la deniegan directamente.