リグ
ここには事実だけを記します。その背後にあるモデルについてはリグとエンクロージャーを、マシンを開く方法についてはガイドを参照してください。
サーフェスとバックエンド
「サーフェスとバックエンド」というセクション| サーフェス | 駆動対象 | バックエンド | 値 | エグレスの隔離 |
|---|---|---|---|---|
| ターミナル(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 を送ります。
アクション動詞
「アクション動詞」というセクションすべてのアクションは網羅的に解析されます。不正な形式のペイロードは、例外ではなく、 問題のフィールド名を示すメッセージを返します。観察系の動詞(○ 印)は、人が操作権を 保持している間も許可されたままです。変更を伴う動詞は拒否されます。
computer_use
「computer_use」というセクション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 だけを受け取ります —
画像とファイルはファイルレーンを通ります。アクションの引数は監査ログに保存されるため、
画像のバイト列がそこにあるべきではないからです。クリップボードの内容は、信頼できない
データとしてフェンスされた状態で返ります。
browser_use
「browser_use」というセクション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 を使って
ください。クリップボードを経由せず、キャレット位置に挿入します。
mobile_use
「mobile_use」というセクション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 以降、クリップボードを
読み取れるのはフォーカス中のアプリだけです。
ios_use
「ios_use」というセクション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は リグの設定画面です。