コンテンツにスキップ

リグ

ここには事実だけを記します。その背後にあるモデルについてはリグとエンクロージャーを、マシンを開く方法についてはガイドを参照してください。

サーフェス 駆動対象 バックエンド 値 エグレスの隔離
ターミナル(exec) VM の exec チャネル越しのシェル microVM smolvm はい
ブラウザ ヘッドレス Chromium(CDP)、Firefox(WebDriver BiDi)、または WebKit(W3C WebDriver) microVM smolvm はい
コンピュータ X11 デスクトップ: 入力はハイパーバイザー経由、キャプチャはゲストエージェント経由 QEMU qemu-hvf(macOS)、qemu-kvm(Linux)、qemu-tcg(アクセラレーションなしのフォールバック。自動で選ばれることはない) はい
Android ADB 経由の Android Google のエミュレータ android-emulator いいえ — エミュレータが自身のネットワークを管理する
iOS WebDriverAgent 経由の iOS Simulator CoreSimulator ios-simulator いいえ — ネットワークはホストの Mac に従う

ターミナルと computer_use サーフェスは同じ computer サーフェス値を共有します。 ターミナルは exec イメージマーカーで区別され、操作可能なデスクトップとして再利用される ことはありません(その逆も同様です)。1 つの会話は 1 台のターミナルマシンを再利用します。

エンジン 値 プロトコル ライブビュー 静止画
Chromium chromium(既定) Chrome DevTools Protocol スクリーンキャスト — ページが再描画されるとブラウザがフレームをプッシュする JPEG
Firefox firefox WebDriver BiDi ポーリングによる静止画(BiDi にスクリーンキャストはない)、上限 6 fps JPEG
WebKit webkit W3C WebDriver(クラシック) ポーリングによる静止画。ホストの ffmpeg でトランスコードされる PNG

リグは生涯を通じて 1 つ のエンジンだけを実行します。1 つの会話はエンジンごとに 1 つのリグを保持でき、これが並べて比較できる理由です。「Firefox (VM)」を 「Chromium (VM)」の隣で開くと 2 台のマシンになり、一方を閉じてももう一方は実行された ままです。

engine は rig.open または browser_use ツールに渡します。不明な名前は既定値に フォールバックされるのではなく拒否されます — ブラウザを要求して黙って別のものを 受け取ることは、互換性の問いに誤った答えを返すことだからです。

エンジン固有の制限は、回避するのではなく明示します:

  • Firefox にはキャッシュを迂回するリロードがありません(BiDi の ignoreCache を明確に拒否します)。そのためハードリロードは通常のリロードと同じです。
  • WebKit にもキャッシュを迂回するリロードがなく、コンソールフィードもありません (出力は各ナビゲーションの後に console.* をフックして取得するため、読み込み中に 記録されたものは失われます — コンソールの抽出はどれもそう述べます)。ライブビューには ホスト上の ffmpeg が必要です。
  • どちらも、そのプロトコル越しにプラットフォームのアクセシビリティツリーを公開しません。 そのため extract (a11y) は DOM から導出した近似を返し、近似であると明示されます。
  • どちらも実際のファイルドロップを受け取れません。ファイル入力には、それでも マシン内のパスを指定できます。
サーフェス イメージ 取得方法
ターミナル ubuntu:24.04、ダイジェスト固定 初回起動時に、マシン自身のゲートされたネットワーク経由で自動的に
ブラウザ(Chromium、Firefox、WebKit) debian:trixie-slim、ダイジェスト固定、およびエンジン自身のパッケージ 初回起動時に自動的に。その後はウォーム済みパックとしてキャッシュされる
コンピュータ Chromium、Firefox、WebKit と、ターミナルがウォームするのと同じ GitHub ホストのランナー相当の CLI ベースラインを備えた qcow2 デスクトップイメージ 設定 → サーバー → リグのインポート(公開されているものはチェックサム固定でダウンロード)
Android Google のシステムイメージ Android SDK 経由
iOS Xcode の Simulator ランタイムと、チェックサム固定の WebDriverAgent ランタイムは Xcode 経由。自動化ブリッジは設定 → サーバー → リグから

各 microVM 種別の初回起動後、サーバーは展開済みのコピーをデータディレクトリ配下に キャッシュし、以降のマシンはすべてそこから起動します — パッケージがインストール済みの ウォーム済みイメージも含みます。ターミナルは GitHub ホストのランナー相当の CLI ツールセット(git、gcc、python3、jq、rsync、アーカイブツール、および apt ベースラインの残り。Docker や言語のツールキャッシュは含みません)をウォームします。 コンピュータの qcow2 は、イメージビルド時に同じ CLI 群を、XFCE と 3 つのブラウザと 並べて焼き込みます。各ブラウザは自身のエンジンをウォームします。3 つのエンジンは Debian ベースを共有しますが、パックを共有することは決してありません。キャッシュの キーはイメージ、エンジン、および音声リビジョン(audio-v1-<engine>)です。 1 つのエンジンのためにウォームしたマシン — あるいは PulseAudio と ffmpeg が ワークロードの一部になる前にウォームしたマシン — には、他のエンジンのものが何も 入っていないからです。ターミナルのパックも同じ理由でツールセットのリビジョン (tools-v1)をキーにします。コンパイラがイメージの一部になる前にウォームした パックが、コンパイラを持つはずのマシンに提供されてはなりません。

採用する価値のある焼き込み済みの自動化イメージはありません — Chromium の chromedp/headless-shell は ALSA と PulseAudio の両方をビルドから外しているため、 音を出すことができません。唯一メンテナンスされている Firefox 用のものは Debian ベースの 33 倍のサイズで、しかも socat を同梱していません。WebKit 用には メンテナンスされたものが一切ありません。そのため各エンジンは初回起動時に インストールされ(chromium、firefox-esr、または webkit2gtk-driver)、その処理の 間に Debian のアーカイブ(deb.debian.org、security.debian.org、 cloudfront.debian.net)に到達します。Chromium はディストリビューションのバイナリで あり、chromium --headless=new として起動されます。

設定キー 上書きする対象
rigs.smolvm.execImage ターミナル(VM)のイメージ
rigs.smolvm.browserImage Chromium ブラウザ(VM)のイメージ

管理者権限で保護されたワークスペース設定ストア(設定 → サーバー → リグ → カスタムイメージ(このワークスペース))を通じて書き込まれます。値はレジストリ参照で なければなりません — ローカルパス、アーカイブ、フラグのような文字列は、入力フィールドで も起動時にも拒否されます。保存された値が無効な場合は明示的に警告されたうえで無視され、 代わりに既定のイメージが起動します。そのイメージ自身のレジストリ(および Docker Hub、 GHCR、Quay、GitLab、GCR の既知の blob CDN の随伴ホスト)が、プルのためにエグレス ゲートを通じて許可されます。

ターミナルイメージの契約 — bash が存在すること。git、curl、socat が プリインストールされているまたは Debian/Ubuntu の apt ベースであること (エンクロージャーは初回起動時にこの 3 つに加え、GitHub ホストのランナー相当の CLI ツールセットをインストールします: コンパイラ、Python 3、jq、アーカイブツール、 rsync。言語のツールキャッシュと Docker はインストールされません)。

ブラウザイメージの契約 — bash と socat を備えた Debian/Ubuntu の apt ベース (またはすでにインストール済みのパッケージ)。加えて、サーバー自身が chromium --headless=new として起動する chromium バイナリがあり、DevTools は ゲストのループバック 9223 で待ち受け、ゲストのポート 9222 に中継されます。 音声レーン用に、初回起動時に PulseAudio と ffmpeg がインストールされます。 FROM chromedp/headless-shell でビルドしないでください。上流の headless.gn は ALSA と PulseAudio の両方をビルドから外しているため、そのバイナリは音を出せません。 この上書きが適用されるのは Chromium のリグだけです — 起動するワークロードコマンドは Chromium のものであり、それを Firefox や WebKit に渡すと存在しないバイナリを起動する ことになります。Firefox や WebKit のリグでは、この設定は明示的に警告されたうえで 無視され、固定されたイメージで起動します。

自動化ポート — すべてのブラウザマシンは、ホストのループバックポートをちょうど 1 つ、 ゲストの 9222 に転送します。その背後では、Chromium の DevTools と Firefox の リモートエージェントがゲストのループバック 9223 にあり、その手前に socat リレーが 置かれます(どちらも無条件にループバックへバインドします)。WebKit のドライバーは --host を受け取り、ゲストの NIC に自身でバインドします。さらに Firefox は Host ヘッダーを自身のポートと照合して検証するため、クライアントは接続先に指定した authority ではなく、ゲスト側の authority を送ります。

すべてのアクションは網羅的に解析されます。不正な形式のペイロードは、例外ではなく、 問題のフィールド名を示すメッセージを返します。観察系の動詞(○ 印)は、人が操作権を 保持している間も許可されたままです。変更を伴う動詞は拒否されます。

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 s), type, wait○ (0–60 s), set_display, clipboard_read○, clipboard_write.

座標は、ゲストの現在のモードにおけるゲストのピクセルです。スクリーンショットはどれも 表示サイズを明示します。キーの組み合わせは X11 の表記(ctrl+s、alt+Tab、 Return)を使います。

clipboard_read は selection を受け取ります: clipboard(ctrl+C が埋めるもの。 既定)、primary(X11 の選択によるコピー)、xdnd(進行中のドラッグ)。空の結果は 3 つすべてにとって正常な答えです。clipboard_write は text だけを受け取ります — 画像とファイルはファイルレーンを通ります。アクションの引数は監査ログに保存されるため、 画像のバイト列がそこにあるべきではないからです。クリップボードの内容は、信頼できない データとしてフェンスされた状態で返ります。

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 s), clipboard_read○, clipboard_write.

抽出されたページの内容は、信頼できないデータとしてフェンスされて返ります。

ブラウザのクリップボードは 1 つだけなので、clipboard_read は selection を 取りません。クリップボード関連の 2 つの動詞にはセキュアコンテキストが必要です — 平文の http:// で配信されたページにはクリップボード API がまったくなく、動詞は空の クリップボードを報告するのではなく、その旨を述べます — その場合は type を使って ください。クリップボードを経由せず、キャレット位置に挿入します。

tap, swipe(50–5000 ms), type, key(別名 back, home, recents, enter, delete, backspace, tab, escape, search, menu, volume_up, volume_down, power、または任意の KEYCODE_*), screenshot○, ui_dump○, install_apk(リグのワークツリーとサーバーの データディレクトリに限定), start_app, stop_app, clear_app_data, uninstall_app, open_url、および shell. shell は argv のリストを受け取り、Android の中で実行されます。ホストのシェルを 通ることは決してありません。logcat、dumpsys、pm grant のような開発者向けの 診断を担います。

mobile_use にクリップボード系の動詞はありません。Android 10 以降、クリップボードを 読み取れるのはフォーカス中のアプリだけです。

tap, swipe(50–5000 ms), type, key(enter, backspace, tab, escape、矢印キー、または印刷可能な 1 文字。任意で command, control, option, shift 修飾子), home, lock, unlock, screenshot○, ui_dump○, install_app(リグのワークツリーまたはサーバーの データディレクトリに限定されたシミュレータの .app ディレクトリ), start_app, stop_app, uninstall_app, open_url、および spawn. spawn は argv を受け取り、simctl を 通じてシミュレータの中で実行します。ホストのシェルを呼び出すことは決してありません。

座標は、スクリーンショットのピクセルではなく iOS 画面のポイントです。 ライブストリームはシミュレータの固定サイズを保ち、デバイスをリサイズするのではなく レターボックス表示します。ホストからシミュレータへ、およびシミュレータからホストへの テキストのクリップボード転送は、他のリグと同じユーザーごと・方向ごとの権限ポリシーに 従います。iOS のペーストボードレーンはファイルと画像を受け付けません。

各リグは、所有する CoreSimulator デバイスと WebDriverAgent セッションを作成します。 リグを閉じると WebDriverAgent が停止し、そのデバイスがシャットダウンされて削除され、 レジストリのエントリも削除されます。iOS のリグは、Xcode、インストール済みの iOS ランタイム、固定された自動化ブリッジを備えた macOS サーバーでのみ実行されます。 音声、マイク、ファイルドロップ、ホストシェル、エンクロージャーによるネットワーク保証の いずれも提供しません。

ツール 説明
rig_list ワークスペースのリグを、サーフェス、ステータス、ディスプレイ、操作者とともに一覧する
rig_close リグを破棄し、そのディスクを捨てる
フェーズ 意味
provisioning 起動中。ステータスの詳細に現在のステップがそのまま表示される
ready 到達可能で、アクションを受け付ける
parked アイドルによるパーク: vCPU は停止しているが RAM は常駐したまま。次のアクションで復帰する
closing シャットダウン中
closed 消滅済み。監査証跡のために行は残る
failed 停止したか、起動しなかった。UI が再試行を提示できるよう区別されている
クローズ理由 発生する条件
requested 人またはエージェントが要求した
idleTimeout アイドル期間の 2 倍を超えてアイドルだった、またはメモリのために退避された
ttlExpired ハードな寿命が尽きた
conversationEnded 所有元の会話が終了した
workspaceGone ワークスペースが削除された、またはメンバーシップを失った
serverShutdown サーバーが停止している
backendFailure その下のハイパーバイザーが落ちた
項目 ターミナル ブラウザ コンピュータ モバイル
メモリ 512 MB 2048 MB(Chromium)。2560 MB(Firefox、WebKit) 4096 MB 4096 MB
vCPUs 2 2 4 4
ハード TTL 8 時間 2 時間 2 時間 2 時間
アイドル期間 45 分 15 分 15 分 15 分
起動時のディスプレイ — 1280×800 1280×800 1080×1920
  • エージェントレーンの静止画は 1280×800 に制限されます。ヒューマンレーンは 2560×1600 までネゴシエートします。
  • すべてのリグに対するホストの常駐メモリ予算は既定で 12 GB で、常駐メガバイト単位で 数えます(パークした VM も RAM を保持したままです)。退避は最も長く使われていない ものから順に行われ、誰かが操作している、視聴している、またはターミナルを開いている マシンが退避されることは決してありません。
  • 開いているターミナルまたは視聴レーンは、そのリグをパークとアイドル回収の対象から 外します。ハード TTL は引き続き適用されます。
ポート 場所 用途
7911 ターミナルのゲスト すべての転送が乗るポートマルチプレクサ
9222, 9223 ブラウザのゲスト 自動化のリレーとエンドポイント(WebKit は 9222 に直接バインドし、リレーを使わない)
80, 443 ブラウザのゲストループバック 開発ドメインの HTTP/HTTPS レーン
  • 検出は、サーバー側で約 4 秒ごとにターミナルゲストのリッスン中 TCP ポートを ポーリングします。
  • リグごとに自動転送されるポートは最大 16 個です。それを超えるものはログに 表示され、転送はされません。
  • ホスト側の転送はループバックにバインドし、ゲスト自身のポート番号を優先します。 ローカルネットワークで共有は、OS が割り当てる LAN ポートを追加します。
  • 開発ドメインは name.test または name.localhost(小文字、ラベルは最大 63 文字)に 一致しなければなりません。1 つのドメインは 1 つのポートに対応します。
  • 開発ドメインの HTTPS はサーバーローカルの CA(EC P-256、<dataDir>/rigs/tls/ 配下、 鍵は 0600 でゲストには決して置かれません)を使い、*.test / *.localhost 用の ワイルドカードリーフを 1 つ持ちます。ホストに openssl がなければ HTTPS レーンは ありません。平文の HTTP は引き続きルーティングされます。
サーフェス 既定の許可リスト
ターミナル サンドボックスの開発者ベースライン(フォージ、パッケージレジストリ、モデルプロバイダー)+ Ubuntu の apt ミラー + ワークツリー自身のフォージホスト
ブラウザ usectrl.dev(製品サイト) — 加えて、各エンジンの初回起動時に、パッケージをインストールしている間の Debian のアーカイブ。ホームページはローカルの file:// ドキュメントで、エグレスを必要としない
コンピュータ 空 — すべて拒否 — 呼び出し元がホストを許可するまで
モバイル 適用されない(エミュレータが管理するネットワーク)

さらにすべての microVM は、プルのためだけに、自身のイメージのレジストリホストを 取得します。認証情報ブローカーの許可ホスト集合は同じ許可リストから導出されます。 ゲストが到達できないホストに対してトークンが発行されることはありません。

コピー&ペーストの両方向、およびファイルのドラッグイン・ドラッグアウトです。リグを 操作する人に利用できます。エージェントは上記の動詞を通じてクリップボードを利用でき、 ファイル転送はまったく利用できません(すでにエンクロージャー内にシェルを持っている ためです)。

クリップボードの越境はユーザーごと、方向ごとです。リグへの貼り付けは既定で許可されます。 リグからのコピーは確認を求めます(10 分間の許可、または設定 → サーバー → リグ → クリップボードアクセスの常に許可)。この 2 つの選択肢は独立しており、ワークスペース 設定になることは決してありません。

レーン ルート 運ぶもの
クリップボード GET/POST /rig/clipboard/<rigId> テキスト、PNG/JPEG を 1 つ(≤16 MB)、およびクリップボード上のファイルのゲスト側パス
ファイル POST /rig/files/<rigId> 最大 64 ファイル、1 つあたり ≤256 MB、1 回のドロップあたり ≤512 MB。任意でゲストのピクセル座標のドロップ位置を指定
ファイル GET /rig/files/<rigId>?p=<base64url path> 1 つのファイルのバイト列を外へ取り出す
  • RPC ではなく HTTP。 RPC ソケットは 256 KB を超える受信フレームで接続を閉じます — JSON コマンドには正しく、貼り付けられたスクリーンショットには致命的な DoS ガードです。 バイト列は、リグのフレームやミーティングの音声がすでに使っているのと同じ種類のルートを 通ります。
  • 認証は、署名されたターゲット rig-files:<workspaceId>/<rigId> とワークスペースの メンバーシップです — 独立したターゲットなので、マシンを視聴するために発行された URL で、そのマシンにファイルを書き込むことはできません。
  • テイクオーバーが適用されます。 クリップボードへの書き込みとファイルのドロップは 変更を伴うため、他の誰かが操作権を保持している間は拒否されます。クリップボードの 読み取りとファイルの読み出しは観察であり、拒否されません。
  • ドロップの着地点: ~/Drops(デスクトップ)、~/drops(ターミナル — ワークツリーの 隣であり、決してその中ではないため、ドロップが未追跡の変更として現れることは ありません)、/tmp/cc-drops(ブラウザ)。ディレクトリを選ぶのはサーバーであり、 呼び出し元が名前を指定することはできません。既存のファイルが上書きされることは ありません — 名前が衝突したものは 2-name.ext として配置されます。
  • ゲストに伝えられる内容: ブラウザのページは、要求された位置で本物のドロップ イベントを受け取ります(Input.dispatchDragEvent)。デスクトップは、ファイルとその URI を自身のクリップボードに受け取ります。特権を持つゲスト内デーモンなしに、任意の ツールキットへの XDND ドラッグをホストが合成することはできないからです。どちらが 起きたかは応答が明示します。
  • ドラッグアウトはデスクトップ専用で、ドラッグが進行している間にゲストの XdndSelection を読み取ります。押下が始まった時点でゲストがすでに保持していたものと 同一のペイロードは、新しい選択ではなく、終了したドラッグの古い選択として扱われます — X には「ドラッグが終わった」というステップがないからです。
  • イメージの要件: デスクトップイメージはプロトコル 2 以降(クリップボード対応が 入った後にビルドされたもの)でなければなりません。古いイメージは 404 を返し、アプリは マシンが壊れていると報告するのではなく、イメージを再ビルドするよう伝えます。
  • 監査ログは形を記録し、内容は決して記録しません: clipboard_read、 clipboard_write、drop_files、read_file の行が持つのは件数、サイズ、パスです。 クリップボードは資格情報が数秒単位で居座る場所であり、そのどれも書き留められません。
  • リグのツールは enclosureControl アクションクラスを宣言します(use 系ツールでは networkEgress と processSpawn も宣言します。mobile_use と ios_use は packageInstall も宣言します)。rig_close は enclosureControl を宣言し、 rig_list は何も宣言しません。既定では許可されます。読み取り専用モードはこれを 全面的に拒否します。スペースごとの自律性ダイヤルで、承認を先に求める形へ格下げ できます。
  • ドメインイベント: RigClosedEvent(クローズ理由を伴う)、RigControlChanged (テイクオーバー / 返却)、RigReaped(アイドル、TTL、メモリ退避のいずれか。 操作中のエージェントを伴う)。リグを開くことはイベントではありません。 ドメインイベントを参照してください。
  • ストレージ: 各ワークスペースデータベースの rig_sessions と rig_action_log。 アクションログはすべての入力イベントを、その主体とリグごとの単調増加するシーケンスと ともに記録します。入力されたテキストは、書き込まれる前に長さとハッシュに伏せられます。
  • データディレクトリ: rigs/images/(インポートされた qcow2 イメージ)、 rigs/smolvm/(リグごとのランタイム状態)、rigs/smolvm-packs/(展開済みの マシンパック)、rigs/tls/(開発ドメインの CA)、rigs/run/(QEMU のオーバーレイと シード)。
  • ルート: ライブビューはスペースまたは PR ページのタブです。/settings/server/rigs は リグの設定画面です。