← 返回首頁

Agent-Simulator推出,串流iOS模擬器至瀏覽器,支持Agent互動與React Native除錯

Jason Kneen
Jason Kneen
@jasonkneen
182🔁 16
𝕏 (Twitter)🔥🔥
AI 中文摘要Claude 生成

Agent-Simulator推出,串流iOS模擬器至瀏覽器,支持Agent互動與React Native除錯。

Agent-Simulator是一個開源工具,基於MCP協定,將iOS模擬器畫面串流至瀏覽器,讓使用者或AI Agent無需移動macOS游標,即可點擊、滑動、輸入,並檢視真實程式碼來源。開發者Jason Kneen強調其同時服務RN/Expo開發者、QA測試與AI Agent三類使用者,目前iOS版已可用,Android版開發中,呼籲星標、分享與貢獻,保持開源精神。

三大目標客群

  • RN/Expo開發者:提供類Figma「圖層面板」,點擊運行中的App.tsx:42即跳轉真實來源。
  • QA與示範流程:無XCUITest痛點的腳本化模擬,支持accessibility-label點擊、滑動、鍵盤輸入與截圖。
  • AI Agent(如Claude Desktop、OpenAI Agents SDK、Cursor):透過MCP暴露完整瀏覽器功能,讓Agent「看見」畫面並「行動」。

核心功能

  • 無游標輸入:透過axe → FBSimulatorHID → CoreSimulator,每個點擊/滑動/按鍵皆像素精準,無需Simulator.app焦點或macOS游標移動,支持任意縮放。
  • 驅動任意iOS App:點擊、拖曳、滑鼠滾輪滾動、多工切換、主畫面、鎖定、鍵盤直通,適用Settings、Maps、Messages等非RN App。
  • iOS無障礙樹:啟動即由axe describe-ui填充,每個畫面元素含label、role與frame,點擊前即可檢視。
  • React元件樹:RN App搭配metro plugin,檢視渲染元件獲完整fiber堆疊與真實來源路徑(React 19 _debugStack + Metro /symbolicate)。
  • 真實程式碼面板:選取元件後,屬性面板抓取實際檔案並高亮目標行,支持自訂程式碼、RN Libraries與Expo shims。
  • MCP橋接:15項工具如sim_tree、sim_tap_by_label、sim_swipe、sim_type、sim_inspect、sim_source等,將瀏覽器全功能暴露給Agent。

系統架構
工具分三層架構,驅動單一iOS模擬器:

瀏覽器UI ── WS + HTTP ── server.js (Node) ── WS/stdin ── sim-server (Rust) ── iOS Simulator (axe + simctl)
                          │                     │
                          └─ MCP client ── stdio ─┘
  • sim-server (Rust):經simctl io screenshot擷取畫面編碼MJPEG,提供/stream.mjpeg、/snapshot.jpg、/api/tree與/health,從stdin讀取指令並shell axe。
  • server.js (Node):協調sim-server,服務Vite UI,暴露/api/config、/api/tree、/api/source,橋接瀏覽器與MCP WebSocket客戶端,代理Metro /symbolicate。
  • web-app (React + shadcn + Tailwind):深色/淺色主題、可調整面板、鍵盤擷取、拖曳滑動、滾輪滾動。

觸控注入流程:瀏覽器點擊經WS → server.js → stdin → sim-server → exec axe tap -x… -y… → FBSimulatorHID,座標以[0,1]比例End to End傳遞,sim-server轉換為device points(基於axe describe-ui根AXFrame,5秒TTL,旋轉時失效)。

介面佈局

區域 內容
標頭 裝置晶片、串流+橋接狀態丸、Inspect切換、主畫面/多工/鎖定/旋轉、面板切換、主題選單。
圖層面板(左) 切換iOS無障礙樹(自動填充)與React元件樹(檢視時填充),點擊選取、懸停高亮、畫面內點擊自動展開祖先。
模擬器畫布 即時MJPEG,驅動模式隱藏原生游標換圓形指標,點擊現脈衝環、拖曳變滑動、滾輪滾動、鍵盤輸入焦點欄位;Inspect模式換十字準星與選取覆蓋。
屬性面板(右) 選取圖層無障礙屬性、React元件名+來源、高亮JSX呼叫點或元件定義程式碼視窗。
狀態列 UDID、模式旗標、上次檢視幀數、鍵盤快捷鍵提示。

鍵盤快捷鍵

  • I:切換Inspect(無RN橋接時停用)。
  • Esc:取消Inspect/解除選取固定。
  • 其他按鍵(畫布焦點時):直送模擬器(適用任意文字欄位)。

MCP橋接細節
mcp/server.mjs為獨立Model Context Protocol伺服器,經stdio與MCP主機溝通,WebSocket橋接agent-simulator伺服器,暴露15工具:

工具 用途
sim_info 裝置UDID/名稱/串流URL/裝置點尺寸。
sim_tree 完整iOS無障礙樹,flat: true回傳標籤元素清單供LLM低成本脈絡。
sim_tap 點擊(x, y)模擬器比例座標。
sim_tap_by_label 依label/value(選type篩選)查AX元素並點中心,抗佈局變動。
sim_swipe 單呼叫原生滑動,含durationMs。
sim_type 輸入可印文字至焦點TextField。
sim_key 按USB-HID鍵碼(Return=40、Backspace=42、Esc=41、箭頭80–83)。
sim_button home/lock/power/side-button/siri/apple-pay。
sim_multitask 開啟App切換器。
sim_screenshot 回傳當前幀為MCP image內容。
sim_inspect 檢視(x, y) RN元件,回傳來源symbolicate堆疊。
sim_source 讀取file:line周圍程式碼視窗(絕對路徑)。
sim_select_by_source 給fileName+line,網格探測匹配渲染元件。
sim_subscribe_selections 串流inspectResult事件為MCP記錄通知。
sim_unsubscribe_selections 停止上述。

MCP客戶端設定範例
Claude Desktop於~/Library/Application Support/Claude/claude_desktop_config.json新增:

{
  "mcpServers": {
    "agent-simulator": {
      "command": "node",
      "args": ["/absolute/path/to/agent-simulator/mcp/server.mjs"],
      "env": { "SIM_PREVIEW_URL": "http://localhost:3200" }
    }
  }
}

其他MCP主機(如OpenAI Agents SDK、Cursor)spawn node /path/to/mcp/server.mjs,設SIM_PREVIEW_URL指向運行伺服器。

Agent流程範例

  1. sim_tree flat:true → 看畫面所有元素。
  2. sim_tap_by_label "+" → 點擊計數器加號。
  3. sim_tap_by_label "Your name" type:"TextField"。
  4. sim_type "hello agent"。
  5. sim_key 40 → Return。
  6. sim_inspect x:0.86 y:0.24 → 回傳App.tsx:42。
  7. sim_source file:".../App.tsx" line:42 → 讀JSX。

快速啟動(1分鐘)

git clone https://github.com/jkneen/agent-simulator
cd agent-simulator
bun install
(cd sim-server && cargo build --release)
(cd web-app && bun install && bun run build)
xcrun simctl boot "iPhone 17 Pro" || true
open -a Simulator
bun start
open http://localhost:3200

UI自動附加已啟動模擬器,開Settings/Maps等即可驅動;左側iOS圖層樹由無障礙API填充,RN App載入inspector bridge後React樹才激活。

一指令示範(最有趣)

bun demo

自動:啟動iPhone模擬器、Metro於examples/expo-demo:8081、Expo Go載入exp://127.0.0.1:8081、agent-simulator:3200、開瀏覽器。Ctrl-C清理。操作:點擊預覽驅動(脈衝環+圖層展開)、I鍵Inspect(懸停/點擊React元件填屬性面板)、點+開examples/expo-demo/App.tsx:42高亮+

旗標:--no-open跳瀏覽器、--port=3300改端口、--metro-port=8082改Metro、--device=指定模擬器。

整合至自有RN/Expo App
metro.config.js:

const { getDefaultConfig } = require("expo/metro-config");
const { withAgentSimulator } = require("agent-simulator/runtime/metro-plugin");
module.exports = withAgentSimulator(getDefaultConfig(__dirname));

bun add -D agent-simulator。或index.ts匯入前registerRootComponent:

import "agent-simulator/runtime/inspector-bridge";

App啟動後,工具列BRIDGE丸轉綠,檢視點擊產生完整堆疊+來源。

串流品質與FPS上限
工具列Quality下拉,五預設+FPS/JPEG品質/縮放/擷取模式滑桿。切換經WS setCapture重啟sim-server,半秒內瀏覽器重訂閱。

預設 目標FPS 解析度 模式 備註
Eco 2 300×650 MJPEG 省電背景監控。
Balanced 3 400×870 MJPEG 預設,匹配CSS渲染尺寸。
Smooth 最高10 400×870 MJPEG 適合滾動。
Max 最高30 400×870 MJPEG MJPEG路徑上限。
Fluid 最高60 400×870 BGRA + keepalive 實驗性,見限制。

點擊精度獨立於解析度,皆用[0,1]比例伺服器轉device points,低解析僅損畫面像素,非瞄準。

真實FPS數據(iPhone 17 Pro模擬器,M系列Mac)

路徑 要求 實際
axe screenshot(單張) 280–370 ms/張,~3 fps上限。
axe stream-video --format raw --fps 30 30 ~5–10 fps(axe截圖迴圈瓶頸)。
axe stream-video --format bgra 60 首幀後停滯,FBVideoStreamConfiguration硬編framesPerSecond: nil,iOS sim IOSurface回呼沉默。

Fluid 60 fps為願景,架構就位,但axe當前無法達標。解法:(1) fork axe傳framesPerSecond至BGRA;(2) Swift helper直連FBSimulatorControl.xcframework驅SimDevice/SimDeviceIOClient,皆半日工程,後端換入即替換。

Fluid keepalive:BGRA單幀後無更新,sim-server並行axe screenshot,300 ms無幀即PNG解碼→JPEG廣播,避免空白。閒置~3 fps,滾動BGRA貢獻,keepalive沉默。最差不掉0 fps。

環境變數:SP_FPS=10 SP_QUALITY=60 SP_SCALE=0.33 SP_CAPTURE=mjpeg bun start;SP_CAPTURE=bgra強制BGRA。

需求與安裝

  • macOS + Xcode + 至少一iOS模擬器。
  • Node ≥18(或Bun)。
  • Rust toolchain(建sim-server一次)。
  • axe:brew install cameroncooke/axe/axe。
  • RN/Expo App僅React檢視需agent-simulator metro plugin,其他功能通用任意iOS App。

開發提示

  • Agent腳本直用axe裝置點座標,UI處理比例轉換。
  • axe describe-ui參考:axe describe-ui --udid | jq '.[0]'。
  • inspector-bridge.js改動無效Metro快取,重啟expo start --clear。
  • SP_FPS/SP_QUALITY調MJPEG(預設fps=3 q=55)。

開發指令

(cd sim-server && cargo build --release)  # Rust改動後
(cd web-app && bun run build)             # UI改動後
bun mcp                                   # 獨立MCP伺服器
npx @modelcontextprotocol/inspector node mcp/server.mjs  # 監控MCP流量

專案佈局:

agent-simulator/
├── server.js              Node協調、WS橋接、HTTP
├── scripts/demo.mjs       一鍵示範啟動
├── sim-server/            Rust MJPEG + axe驅動
├── runtime/               RN metro plugin + inspector bridge
├── web-app/               Vite + React + shadcn UI
├── web/                   舊單檔UI (/classic)
├── mcp/                   MCP伺服器 (15工具)
├── examples/expo-demo/    預配plugin Expo App
└── LICENSE                AGPL-3.0-or-later

React來源解析(React 19)
纖維._debugSource移除,來源藏_fiber._debugStack(Error堆疊字串指bundle-URL行/欄)。檢視時:

  1. inspector-bridge解析_debugStack,收集每纖維最多12候選bundleFrames。
  2. server.js批POST至localhost:8081/symbolicate,一次往返挑非React createElement/jsxDEV內第一候選。
  3. UI收stack[i].source為真實絕對檔案路徑,涵蓋使用者元件、RN內部(RCTView、ScrollView)、Expo shim。

API細節

  • GET /api/tree:代理axe describe-ui --udid,UI啟動/刷新拉取,MCP sim_tree包裝。
  • GET /api/source?file=ABS&line=N&context=M:讀line周圍M行,回{file, lines, startLine0, endLine0, targetLine0, language},驅UI程式碼面板與sim_source。

授權與未來
AGPL-3.0-or-later。若嵌入商業產品或需其他授權,開issue討論雙授權。Android版開發中,需整理包裝成CodeSurf等擴充套件。