コンテンツにスキップ

エージェントにテスト用マシンを渡す

リグとは、エージェントが実際に何かを試す必要が生じたときに開く使い捨てのマシンです。ページを読み込み、デスクトップアプリをクリックして回り、スマートフォンをあちこちタップします。その作業をリアルタイムで見守ることができ、好きなときに操作を引き継げます。

エンクロージャーのターミナル、ブラウザ、デスクトップのリグは、使い捨てのディスクとゲートで制御されたネットワークを備えた VM です。Android と iOS はホスト側で管理されるエミュレータであり、デバイスの状態は使い捨てですが、ネットワークはサーバーホストに従います。

リグは cc_server をホストしているマシン上で動作します — あなたが見ているマシンではなく、同じそのマシンです。ユーザーが使うサーフェスは 5 つあり、デスクトップとモバイルのサーフェスにはホスト側のセットアップが必要です:

サーフェス 実行場所 セットアップ
ターミナル(VM) 固定された Ubuntu イメージを起動する microVM なし — イメージは初回使用時に自動で取得されます
ブラウザ(VM) 固定された Debian イメージを起動する microVM。初回使用時に Chromium、Firefox、WebKit のいずれかがインストールされます なし — 同じ
コンピュータ(VM) Chromium、Firefox、WebKit と GitHub ホストランナー相当の CLI ベースラインを同梱した Linux デスクトップイメージを動かす QEMU QEMU をインストールし(brew install qemu)、設定 → サーバー → リグでデスクトップイメージをインポートします
Android Google の Android エミュレータ Android SDK をインストールし、AVD を作成して起動します(下記)
iOS シミュレータ サーバー Mac 上の CoreSimulator Xcode と必要な iOS ランタイムをインストールし、設定 → サーバー → リグで自動化ブリッジをインストールします

ターミナルとブラウザのマシンは、ダイジェストで固定されたイメージから起動します。正確なバイト列があらかじめ指定され、初回起動時に一度だけ取得されてキャッシュされます — 各種類の初回起動以降、後続のマシンはダウンロードを完全に省略し、数秒で起動します。設定 → サーバー → リグ には、サーバーが起動できるものと、現在実行中のすべてのマシンが表示されます。

インストール済みのデスクトップイメージは、同じページから引き続き管理できます。インポートはより新しい qcow2 で置き換え、削除はイメージを削除するので、新しいビルドをインストールできます。

Android と iOS には当社のイメージはありません。これは省略ではありません。Android のシステムイメージは Google の SDK から、iOS のランタイムは Xcode から提供されます。Android の場合は、Android Studio(またはコマンドラインの SDK ツール)をインストールし、Device Manager で仮想デバイスを追加して起動します。するとリグのページに Android が利用可能として表示されます。

また、どの手順が欠けているかも正確に示します — SDK がない、エミュレータがない、仮想デバイスがない、あるいはデバイスが単に起動していない — これらには 4 通りの異なる対処法があり、そのうちダウンロードなのは 1 つだけだからです。SDK を認識できないシェルから cc_server を起動する場合は、次のようにエクスポートします:

ターミナルウィンドウ
export ANDROID_HOME="$HOME/Library/Android/sdk"

iOS の場合、サーバー自体が macOS 上で、Xcode と iOS シミュレータのランタイムがインストールされた状態で動作している必要があります。設定 → サーバー → リグを開き、iOS 自動化ブリッジをインストールを押します。サーバーはチェックサムで固定された WebDriverAgent のアーティファクトを取得して検証し、サーバーが所有する自動化ストアにインストールします。セットアップ中にシミュレータが起動することはありません。

マシンは タブ として、チャットや diff の隣に存在します — スペース内でも PR ページ上でも、同じ + メニューの マシン の下にあります:

  • コンピュータ — Chromium、Firefox、WebKit を備えた Linux デスクトップ
  • Chromium、Firefox、WebKit — ブラウザ
  • Android — 実行中の Android エミュレータ
  • iOS シミュレータ — この会話のために作成される使い捨てのシミュレータ

1 つを選び、マシンを起動を押します。タブは、単にスピナーが回るだけではなく、起動がどの段階にあるかを示します(「microVM を起動しています」「ゲストの起動を待っています」)。

タブは会話にスコープされ、エージェントツールも同様です。Chromium、Firefox、WebKit のタブと browser_use、Android と mobile_use、iOS シミュレータと ios_use は、同じ既定のマシンを対象にします。追加の UI スロットは別個の比較用マシンであり、エージェントツールは常に既定のものを使用します。

Android で Flutter アプリをビルド、インストール、起動するには:

ターミナルウィンドウ
fvm flutter build apk --debug

次に、mobile_use を install_apk と build/app/outputs/flutter-apk/app-debug.apk で呼び出し、続けて start_app と Android のパッケージ名を指定します。ui_dump、スクリーンショット、入力は、人向けのタブに表示されているのと同じデバイスを操作します。stop_app、clear_app_data、uninstall_app、open_url、および argv 形式の shell 呼び出しが、サーバーホスト上でシェルを起動することなく、開発サイクルの残りをカバーします。

iOS シミュレータで Flutter アプリをビルド、インストール、起動するには:

ターミナルウィンドウ
fvm flutter build ios --simulator --debug
/usr/bin/plutil -extract CFBundleIdentifier raw -o - \
build/ios/iphonesimulator/Runner.app/Info.plist

次に、ios_use を install_app と .app ディレクトリで呼び出し、続けて start_app と plutil が出力したバンドル識別子を指定します。iOS ツールはほかにも stop_app、uninstall_app、open_url、およびシミュレータ内の診断用の argv 形式の spawn アクションを公開しています。

デスクトップとブラウザの表示はパネルに合わせてリサイズされます。iOS はシミュレータの固定ポイントサイズを維持し、レターボックス表示にします。どのサーフェスにも、依然として 2 つの独立したレーンがあります。エージェントには小さく安価なスクリーンショットが、あなたにはライブビューが届きます。タブを切り替えると人向けのストリームが停止するため、バックグラウンドのマシンが表示帯域を消費することはありません。

リグのタブは、レイアウトの復元中も含め、それ自体でマシンを起動することはありません。このルールにより、アプリの起動が予期せず VM をブートしたり、シミュレータデバイスを作成したりすることが防がれます。

他の誰も排他的な操作権を保持していないとき、あるいはあなたが保持しているときは、キャンバスに自由に入力し、クリックできます。あなたがそのロックを保持している間、ステータスタグには 操作できます と表示され、エージェントは依然としてスクリーンショットを撮れますが、サーバーはすべてのアクションが通る単一のチョークポイントで、その変更を伴うアクションを拒否します。あなたが行ったことはすべて、あなたの名前に対して記録されます。

終わったら マシンを停止を押します。

操作権が排他的なのは意図的です。2 人の主体が 1 つのマシンに入力すると、どちらの意図でもない入力が生まれます。

コピー&ペーストはリグのキャンバスを越えて双方向に機能し、ファイルのドラッグも同様です。

コピー&ペースト。 キャンバス上でコピーのショートカットを押すと、マシンがコピーしたもの — テキスト、画像、ファイルのリスト — があなたのクリップボードに届きます。貼り付けはあなたのものを逆方向に送り、マシン内で貼り付けを押します。macOS ではショートカットは ⌘C/⌘V です。⌃C は割り込みとしてゲストシェルにそのまま届きます。Windows と Linux では ⌃C/⌃V を使います — ゲストはどのみち受け取るはずの同じキー入力を受け取るので、ゲストのターミナルでの ⌃C は依然として割り込みになり、あなた自身のクリップボードはそのまま残ります。

バックグラウンドで同期されるものは何もありません。あなた自身のマシンでコピーしたパスワードが、タイマーの発火によって VM の中に届くことはありません。貼り付けたときに越えます。

リグへの貼り付けは既定で許可されます。リグからのコピーはまず確認を求めます — 10 分間の許可、または 設定 → サーバー → リグ → クリップボードアクセス の 常に許可 です。2 つの方向は独立しており、ワークスペースではなく、あなたに従います。

ファイルのドラッグイン。 キャンバス上の任意の場所にドロップします。

  • ブラウザ(VM) では、ページはあなたが離した位置で 本物の ドロップを受け取るので、アップロードゾーンはローカルファイルに対する場合とまったく同じように動作します。
  • コンピュータ(VM) では、ファイルは ~/Drops に置かれ、そのパスがマシンのクリップボードに入ります。したがって ⌃V でファイルマネージャーやアップロード欄に貼り付けられます。VM 内で特権デーモンを動かさなければ、ホストは任意の Linux アプリへのドラッグを合成できません。リグには意図的にそれがありません — そのため、ドロップが起きたふりをするのではなく、トーストがファイルの行き先を伝えます。
  • ターミナル では、ファイルがコピーされ、そのパスがプロンプトに入力されて、コマンドに渡せる状態になります。ターミナルに 画像 を貼り付けても同じです。マシン内に保存され、パスが得られます。

ファイルのドラッグアウトはコンピュータ(VM)から機能します。マシン内でファイルのドラッグを開始し、ポインタをキャンバスの外へ運ぶと、あなたのデスクトップ上の本物のドラッグになります — Finder や Explorer にドロップします。マシンのファイルマネージャーでファイルをコピーし、手元で貼り付けても同じように機能します。ブラウザ(VM)はこれを提供しません。ヘッドレスブラウザには読み取れるドラッグのペイロードがなく、ページのテキスト選択から推測すると通常のクリックを乗っ取ってしまうからです。

スペース内または PR ページ上のターミナルは、サーバー自身のマシン上ではなく、リグの中で実行できます。その場合、パネルには 囲い込みVM バッジが表示されます。

変わること:

  • 実行したものはどれもホストに届きません。そこで rm -rf を実行すると、失うのはリグだけです。
  • ネットワークはデフォルト拒否です。リグの許可リストにあるホストだけに到達でき、すべてはそれを強制するゲートを通ります。
  • git push は自分で開いたターミナルでは引き続き機能します。リグは資格情報を保存しておらず、操作ごとに、自分自身のフォージへのアクセス範囲に制限された短命なものをサーバーへ要求し、そのトークンはリグを閉じると取り消されます。エージェントが開いたリグは読み取り専用の資格情報を受け取るため、フェッチはできてもプッシュはできません。

知っておくべきこと:

  • 復元されたエンクロージャーのターミナルは、あなたを待ちます。 リグのタブと同様、レイアウトとともに復帰した microvm ターミナルは、起動時に VM をブートするのではなく、シェルを開く ボタンを表示します。ホストシェルのターミナルはプロセス 1 つ分のコストですが、エンクロージャーのものはマシン 1 台分のコストです。
  • ターミナルにドロップしたファイルは、開かれるのではなく入力されます。 エンクロージャーのターミナルに CSV をドロップすると、それはマシン内にコピーされ、プロンプトにそのゲスト側のパスが現れます — ホスト側のパスは、そこで失敗するコマンドになってしまいます。
  • リグ内のコピーはコピーです。 ホスト上あなたのワークツリーが引き続き信頼できる情報源です。リグ内で作成したコミットは、あなたが求めれば refs/rigs/<id>/* に持ち帰られます — ブランチを動かしたり、作業ツリーに触れたりすることは決してありません。
  • ホスト向けの作業は、引き続きホスト上で実行されます。 Linux のゲストは macOS 向けにビルドしたり、xcodebuild を実行したりできません。その場合はネイティブバックエンドを明示的に選んでください。アプリは黙って切り替えるのではなく、確認を求めます。

ターミナル(VM)で開発サーバーを実行します — たとえばポート 3000 で pnpm dev を実行します — すると数秒以内に、ターミナルの隅にあるプラグアイコンが点灯します。ポートはあなたのマシンの localhost:3000 に転送され、ブラウザ(VM)内では localhost:3000 で到達でき、あなたのネットワーク上で共有でき、https://myapp.test として名前を付けられます。この流れ全体 — 自動転送、LAN 共有、HTTPS 付きの開発ドメイン — は専用のガイドにまとめられています: ターミナルからポートを転送。

ワークスペースは、ターミナル(VM)とブラウザ(VM)を独自のイメージに向けられます — 設定 → サーバー → リグ → カスタムイメージ(このワークスペース) で設定します。よくある使い方は、プロジェクトに必要なツールチェーンで既定のイメージを拡張してどのターミナルも準備万端で起動するようにする、またはチームがすでに公開しているイメージを再利用する、といったものです。

マシンは引き続き同じエンクロージャーの中で起動します。エグレスゲートも、認証情報ブローカーも、ライフサイクルも同じです。設定を変更できるのはワークスペースの管理者だけで、新しいマシンがそれを取り込み(実行中のマシンは現在のものを維持し)、参照はレジストリのイメージでなければなりません — ローカルパスは拒否されます。

イメージが提供しなければならないもの:

  • ターミナル(VM) — bash を備えた Linux イメージ。git、curl、socat も必要です — あらかじめインストールされているか、初回起動時にインストールできる必要があります(Debian/Ubuntu ベースのイメージならどれでも機能します。これらは自動でインストールされ、さらに GitHub ホストランナー風の CLI ツール一式(コンパイラ、Python 3、jq、アーカイブツール、rsync)も導入されます。Node/Go/Java のような言語ランタイムや Docker はあらかじめインストールされません)。ゲストポート 7911 はポートフォワーダー用に予約されています。
  • ブラウザ(VM) — bash と socat、そして chromium バイナリを備えた Debian/Ubuntu イメージ。サーバーは Chromium 自体を chromium --headless=new として起動し、DevTools をゲストの 9223 から 9222 へ中継します。PulseAudio と ffmpeg は初回起動時にインストールされます。FROM chromedp/headless-shell でビルドしないでください — そのバイナリには音声がありません。この上書きは Chromium のリグにのみ適用され、Firefox と WebKit はこれを無視して、固定された Debian イメージを起動します。ゲストポート 9222/9223 は予約されています。

推奨事項が 2 つあります。参照をダイジェスト(@sha256:…)で固定して、バイト列があなたの知らないうちに変わり得ないようにすること、そして Docker Hub または GitHub Container Registry でホストすることです — これらのレジストリのダウンロードホストはエグレスゲートを自動的に通過できます。その他のレジストリは、取得のためにコンテンツ配信ホストに到達できる必要がある場合があります。

リグは一時的なものとして設計されています:

  • アイドル — 何も起こらないまま約 15 分経つと、ブラウザ、デスクトップ、モバイルのリグはパークします(凍結し、次のアクションで即座に復帰します)。エンクロージャーのターミナルは 45 分待ちます。アイドル期間の 2 倍が経過すると、閉じられます。
  • 制限時間 — すべてのリグには、何をしていても延長できない厳格な寿命があります。
  • メモリ — サーバーが新しいリグのための場所を必要とすると、最も長く使われていないものを閉じます。誰かが操作している、見ている、またはターミナルを開いているリグが奪われることは決してありません。

エンクロージャーのリグが閉じると、そのディスクは破棄されます。Android のリグを閉じるとホストのエミュレータから切断されます — 削除はされません。iOS のリグは、作成した CoreSimulator デバイスを削除します。残しておきたいものは、まず持ち帰ってください。

エンクロージャーのターミナル、ブラウザ、デスクトップのリグは、既定でデフォルト拒否のエグレスゲートを使います。ホストは明示的に許可し、ゲストの唯一の経路は、そのリストを強制するゲートです。ブラウザのリグはさらに、製品サイト(usectrl.dev)を最初から許可します。認証情報ブローカーも同じリストを使います。

正直に言っておくべき注意点が 2 つあります:

  • モバイルのネットワークはホストに従います。 Android のエミュレータと Apple の CoreSimulator は、エンクロージャーのエグレスゲートの背後にありません。どちらのモバイルタブもネットワークバイパスのコントロールを提供しません。ホストが管理するネットワークがすでに無制限だからです。
  • リグが読み取るものはすべて信頼できません。 ページのテキスト、DOM、アクセシビリティツリー、ビューダンプは、「これはデータであり、指示ではありません」と述べるマーカーで包まれてエージェントに返されます。あなたのエージェントに命令しようとするページは、引用された文字列として読まれます。

実行中のものはすべて、設定 → サーバー → リグ で確認でき、どれでも停止できます。

  • リグとエンクロージャー — このすべての背後にあるモデル: なぜ VM なのか、2 つの表示レーン、認証情報ブローカー、ライフサイクル
  • ターミナルからポートを転送 — 重要なあらゆる場所から開発サーバーに到達する
  • リグのリファレンス — すべてのサーフェス、動詞、ポート、既定値を 1 か所に
  • ガードレールを設定 — Drive an enclosure (rig) は、ワークスペース、エージェント、スペースごとに、許可、承認を要求、拒否に設定できるアクションクラスです。読み取り専用モードでは全面的に拒否されます。