在对话里直接操作 iOS 模拟器或 USB 连接的 iPhone:22 个 Agent 工具用于启动、构建、按无障碍标识或 OCR 文本驱动 UI、列表行操作与 SwiftUI 预览热重载,并附带可点击拖拽的流式侧边栏面板。
安装
# npm 包(预构建)
dsh plugin --profile web add @zseven-w/dsh-ios
# GitHub 源码(首次需按提示配置 allowBuilds 构建授权后重试)
dsh plugin --profile web add github:ZSeven-W/dsh-ios
装任何插件都等于在你的机器上跑第三方代码,权限和你本人一样大——能读你的文件、用你的凭据、访问网络,工具审批管不到它。GitHub 来源的插件还会在安装时执行构建脚本——pnpm 默认拦截,所以安装可能停在 ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED 或 ERR_PNPM_IGNORED_BUILDS;dsh 会打印出需要添加的确切键名,把它加进该 profile 的 pnpm-workspace.yaml 的 allowBuilds 下,重跑一次即可装上。放行构建本身就是一次信任判断:请只安装可信来源,并尽量锁定 commit(github:owner/repo#sha)。
README
為什麼選擇 DSH iOS 模擬器
DSH iOS 模擬器讓智慧代理在對話裡擁有一台真正的 iOS 模擬器,也讓你親眼看到畫面。智慧代理可以啟動裝置、用 Xcode 專案或 Swift 套件建置並執行 App、按無障礙身份或 OCR 文字驅動介面、讀取統一記錄檔,還能檢查處理程序、呼叫堆疊與記憶體洩漏;與此同時,裝置的即時畫面會渲染在常駐的側邊欄面板裡,你可以在影片上直接點按、拖曳、旋轉、按 Home 鍵。同樣的操作也能作用於 USB 連接的真機 iPhone:外掛程式會在手機上建置並啟動 WebDriverAgent,把控制與畫面連接埠經回送通道轉送,把裝置畫面投進同一套面板、卡片與工具。整個過程不用圖片內容塊,也沒有錄影檔案——視覺資料只會透過 DSH webserver 簽章的限時 URL 進入介面。
| 🖥️ 對話裡的即時模擬器 | 已啟動裝置的 serve-sim MJPEG 畫面,經簽章後的 /_dsh/dsh-ios/* 路由代理進常駐的右側面板——瀏覽器永遠不會接觸 serve-sim 的連接埠。 |
| 📱 USB 真機 iPhone | ios_real_start_wda 在已連接的手機上建置並啟動 WebDriverAgent,把控制(REST)與畫面(MJPEG)連接埠經回送通道轉送;同一套面板、工具、卡片與狀態膠囊即可驅動真機。裝置必須處於解鎖狀態,真機帳號上的每一次點按都受外掛程式的「先識別、再點按」規則約束。 |
| 🛠️ 22 個智慧代理工具 | 裝置清單、啟動/關閉、截圖、互動、建置執行、統一記錄檔、基於 AXe 的 UI 樹與按元素點擊、清單/資訊流列級操作、Vision OCR 找字/點字、SwiftUI 預覽熱重載、處理程序清單、呼叫堆疊、洩漏分析、App 資訊。 |
| 👆 可互動面板 | 在即時畫面上點按、拖曳;Home / 旋轉 / 截圖 / 重新整理圖示工具列(懸停提示);尺寸模式(适应 · 50–125% · S/M/L);外框樣式(无框 / 边框 / 真机框);拖曳調寬上限 960px、雙擊重設;橫向畫面自動加寬。 |
| 🧾 清單與資訊流列 | ios_sim_ui_rows 把深層無障礙快照轉成帶索引、標籤與通用解析計數器的列;ios_sim_tap_row 在列內按相對座標點按,並用計數器符合預期的 ±1 變化驗證操作是否生效——這是清單類 App 唯一可靠的確認方式。 |
| 🔐 僅回送的傳輸 | serve-sim 只綁定 127.0.0.1 的專屬連接埠段;每條路由都要求回送對端、回送 Host 與 Fetch-Metadata/Origin 驗證;HMAC 能力權杖 10 分鐘內過期。。 |
| ⚡ SwiftUI 預覽熱重載 | ios_sim_preview 在套件之外產生一次性宿主 App,把你的預覽編譯成 dylib,編輯後無需重啟即可熱替換進正在執行的模擬器(約 2–5 秒)。 |
| 🧭 語意化 UI 自動化 | ios_sim_ui_tree 匯出無障礙元素樹(基於 AXe),ios_sim_tap_element 按標籤或識別碼點擊;當元素樹為空或退化時,ios_sim_find_text 直接對螢幕做 OCR,ios_sim_tap_text 點擊命中的文字——按身份或按文字點擊,而不是猜座標。 |
工具
全部 22 個工具在任何主機上都會註冊,且只回傳純 JSON——視覺資料只透過 presentationMeta + 簽章路由進入介面,絕不以圖片塊形式回傳。模擬器 udid 自動走 simctl/serve-sim,真機 udid 自動走 WebDriverAgent。非 macOS 主機(或 serve-sim 無法解析)上工具仍然註冊,但呼叫時會回傳明確的錯誤;唯一的例外是 ios_sim_preview 的 status,它在任何主機上都會如實回傳 { running: false }。
核心模擬器工具
| 工具 | 作用 | 關鍵參數 |
|---|---|---|
ios_sim_devices |
列出這台 Mac 上可用的 iOS 模擬器裝置(udid、名稱、執行時期、狀態)以及哪些已啟動,另外在 realDevices 裡列出 USB 連接的真機 iPhone(udid、名稱、osVersion、model、state、developerMode)。先用它發現要傳給其他工具的 udid 或名稱。 |
— |
ios_sim_boot |
啟動指定裝置並開始其 serve-sim 即時推流;推流在對話期間保持存活,面板可以即時顯示模擬器。 | udid(必填——udid 或裝置名稱) |
ios_sim_shutdown |
關閉指定裝置;若推流目標正是該裝置,則同時停止推流。 | udid(必填) |
ios_sim_screenshot |
擷取一張 PNG,回傳簡短的 JSON 摘要(路徑、位元組數、尺寸、裝置);圖片在卡片/面板中渲染,絕不會以圖片塊形式回傳。正在推流的模擬器與 USB 連接的真機(經 WebDriverAgent)都可以截。 | udid(可選——預設取正在推流的裝置,其次取第一個已啟動的模擬器) |
ios_sim_interact |
與正在推流的裝置互動——模擬器或 USB 真機均可:在 0..1 歸一化座標上點按、輸入文字(模擬器為美式鍵盤)、按下硬體按鍵(home、lock、volumeUp…)、捲動或傳送觸控手勢;操作穩定後(約 300 毫秒)附帶一張新截圖展示效果。 |
action(必填——tap/type/button/gesture/scroll),x/y、text、name、json |
ios_sim_list_apps |
列出模擬器或已連接真機上已安裝的 App(bundle id、顯示名稱、版本、是否系統 App)——第三方 App 的 bundle id 無法猜測,先列出它,或給 ios_sim_launch_app 傳 name。列舉失敗會拋錯(例如「裝置目前無法透過 CoreDevice 存取」)而不是回傳空清單,所以 count: 0 一定意味著裝置上確實沒有匹配的 App。 |
udid(可選)、query(對顯示名稱與 bundle id 同時做不區分大小寫的子字串匹配,支援中文)、include_system(預設 false) |
ios_sim_launch_app |
啟動已安裝的 App(模擬器或已連接真機均可):既可以傳 bundleId,也可以傳 name(對顯示名稱做不區分大小寫的子字串匹配,走同一套列舉邏輯,支援中文)。兩者只能給其一;啟動失敗或名稱有歧義時,錯誤裡會直接給出下一步該怎麼做(從原始碼建置請用 ios_sim_build_run)。 |
bundleId 或 name(二選一)、udid、relaunch |
ios_sim_build_run |
為模擬器建置 .xcodeproj、.xcworkspace 或 Swift 套件,安裝產生的 .app 並啟動;真機 udid 則改為在手機上建置、安裝並啟動(需要 Apple Development 簽章)。建置失敗時回傳過濾後的 xcodebuild 報錯尾部。完整建置通常需要幾分鐘。 |
projectPath(必填)、scheme、udid(推流裝置 → 已啟動裝置 → 最新執行時期 iPhone,會自動啟動)、configuration(預設 Debug) |
ios_real_start_wda |
在 USB 連接的真機 iPhone 上啟動 WebDriverAgent(WDA)——僅限真機,絕不用於模擬器。若已有 WDA 在回應則直接接管,否則執行 xcodebuild 建置/啟動(冷建置可能耗時數分鐘),然後等待 WDA 就緒並回傳即時面板所用的控制/MJPEG 連接埠。當 ios_sim_screenshot / ios_sim_interact / ios_sim_ui_tree / ios_sim_tap_element 報告該裝置 WDA 未執行時,先呼叫本工具。 |
udid(必填——來自 ios_sim_devices.realDevices 的真機 udid) |
UI 樹工具(基於 AXe)
| 工具 | 作用 | 關鍵參數 |
|---|---|---|
ios_sim_ui_tree |
匯出最前方 App 的無障礙元素樹(標籤、識別碼、取值、以點為單位的 frame)以及螢幕尺寸(點)——模擬器走 AXe,USB 真機走 WebDriverAgent(真機預設限制快照深度:繁忙 App 的不限深快照實測約 32 秒 / 751 KB,限深後約 2 秒);輸出上限約 40 KB(超出時裁掉最深層級,並置 truncated + 提示)。 |
udid(可選)、max_depth、filter(對標籤/識別碼/類型做不區分大小寫的子字串匹配) |
ios_sim_tap_element |
按身份點擊元素——先精確匹配,再做不區分大小寫的子字串匹配(identifier/label);巢狀重複元素摺疊為同一個目標,若有多個不同元素匹配則逐一列出候選。點擊落在元素中心(模擬器走 AXe HID,真機走 WebDriverAgent),隨後約 300 毫秒截一張效果圖;傳 expect_text / expect_gone 則點擊與驗證合併為一次往返(expected.matched)。 |
udid(可選)、identifier、label、expect_text、expect_gone |
清單與資訊流列
清單/資訊流類 App 把每條內容聚合進一個無障礙 Cell——標籤裡包含整條摘要與全部計數器(「57 回复。18 喜欢。592 次查看」),沒有可以匹配的逐控制項子按鈕,而且這些列只有在深層快照裡才會出現。下面兩個工具把這種結構暴露為「列」,並在列內操作。
| 工具 | 作用 | 關鍵參數 |
|---|---|---|
ios_sim_ui_rows |
把最前方 App 可見的清單/資訊流列讀成「列」而不是原始樹:每一列包含索引、以點為單位的 frame、聚合標籤,以及從標籤裡通用解析出的計數器(數字 + 分類詞,如 57 回复 → 回复=57,中文或英文——不內建任何 App 詞彙)。列只有在深層快照裡才出現:真機上預設 max_depth 為 60,每次呼叫約 15–25 秒 / ~0.5 MB(WDA 序列處理請求)——先考慮廉價的觀察手段(ios_sim_find_text / ios_sim_ui_tree)。計數器按啟發式解析、鍵值可原樣回傳:給 ios_sim_tap_row.expect_count 傳鍵時務必與清單完全一致。找不到列時結果會說明原因(深度太淺 / 不是清單頁 / 深度讀取後確實沒有無障礙資訊)——淺讀絕不會被報告成「該 App 沒有無障礙資訊」;螢幕外的列會被排除並計入 omittedOffscreen。 |
udid(可選)、max_depth(僅真機生效;預設 60) |
ios_sim_tap_row |
在一條可見清單列內按相對位置點按(列由 ios_sim_ui_rows 報告:0 基索引;x/y 為該列 frame 的比例——0 = 左/上邊緣,1 = 右/下邊緣,預設 0.5 = 中心),模擬器走 AXe、USB 真機走 WebDriverAgent。列的 frame 來自一次全新的樹讀取,絕不猜測絕對螢幕座標;索引越界直接失敗(絕不截斷收攏)。安全閘:傳 expect_count={key,delta} 時工具會重新讀取列標籤,校驗計數器恰好變化 +1/−1(countCheck.verified);若鍵不在該列解析出的計數器裡,點按會在執行前被拒絕——真機上的點按絕不是試探。不傳 expect_count 時點按仍會執行(明確的相對位置本身就是定位),但不會有任何驗證。 |
udid(可選)、index(必填)、x、y(0..1 比例)、max_depth、expect_count({key, delta}) |
OCR 工具(Vision)
| 工具 | 作用 | 關鍵參數 |
|---|---|---|
ios_sim_find_text |
用外掛程式編譯的 Vision 助手對已啟動模擬器或 USB 真機的目前螢幕做 OCR(識別準確,zh-Hans + en-US,首次使用由 swiftc 編譯進 ~/Library/Caches/dsh-ios/bin/ocr)。適用於無障礙樹為空或退化、文字以圖形渲染(角標數字、嵌進圖片的價格)或需要獨立核對螢幕內容的場景。先擷取一張新截圖,再回傳 {device, size, items:[{text, confidence, rect}]}——rect 是以裝置點為單位的框(原點在左上),按信心度排序,輸出上限約 40 KB(truncated 表示丟掉了信心度最低的尾部;可用 query 收窄或調高 min_confidence)。 |
udid(可選)、query(不區分大小寫的子字串)、min_confidence(預設 0.3) |
ios_sim_tap_text |
對目前螢幕做 OCR 並點按最佳文字匹配的中心——沿用與 ios_sim_tap_element 相同的「先精確、再忽略大小寫包含、多候選報歧義」規則,適用於無障礙樹看不到的文字(無 a11y 的 App、角標數字、嵌進圖片的文字)。真機上透過 WebDriverAgent 落在裝置絕對座標;模擬器上經 serve-sim 控制以歸一化座標下發(先呼叫 ios_sim_boot)。約 300 毫秒後附一張新截圖展示效果;傳 expect_text / expect_gone 則點擊與驗證合併為一次往返(expected.matched)。在真機上每一次點按都有真實後果——絕不靠點按來試探一個未識別的控制項。 |
udid(可選)、query(必填)、min_confidence、expect_text、expect_gone |
ios_sim_wait_for |
等待某段文字在螢幕上出現或消失:重用 ios_sim_find_text 的截圖+OCR 流程輪詢,直到條件成立或逾時(預設 8 秒,上限 60 秒)。逾時是正常的 matched:false 結果,絕不擲錯——一次呼叫取代手動循環 find_text(實機上每輪約 1.2 秒)。命中時 item 帶回 OCR 文字、信心值與裝置點座標框。 |
udid(選填)、text(必填)、mode(appear/disappear)、timeout_ms、min_confidence |
記錄檔工具
| 工具 | 作用 | 關鍵參數 |
|---|---|---|
ios_sim_logs |
從裝置統一記錄檔讀取 App 執行時期的輸出:snapshot(log show --last <duration>,預設 2m)或 follow(有界即時擷取 duration_seconds,預設 10 秒、上限 60——絕不會掛起不回傳)。輸出上限約 300 行 / 30 KB,並附收窄提示。 |
udid(可選)、mode(snapshot/follow)、duration、duration_seconds、bundle_id、predicate(原始 NSPredicate,優先於 bundle_id)、level(default/info/debug)、grep |
預覽工具
| 工具 | 作用 | 關鍵參數 |
|---|---|---|
ios_sim_preview |
在模擬器裡即時熱重載 SwiftUI 預覽:start(預設)驗證套件、在外掛程式快取裡產生一次性宿主 App(絕不會寫進你的套件)、把套件編譯為模擬器 dylib、安裝並啟動宿主、然後監聽原始碼——每次編輯都會重新建置並熱替換,無需重啟(約 2–5 秒)。編譯錯誤不會殺死工作階段:宿主保留最後一次成功的預覽,錯誤尾部透過 status 回傳;同一時間只能執行一個預覽工作階段。 |
packagePath(start 時必填)、udid、action(start/status/stop)、previewFilter(對預覽名稱做不區分大小寫的子字串匹配) |
偵錯工具
| 工具 | 作用 | 關鍵參數 |
|---|---|---|
ios_sim_processes |
從模擬器自身的 launchd 列出其執行中的 App 處理程序(主機可見的 pid、處理程序名稱、bundle id)——backtrace/leaks 的 pid 來源;真機 udid 則改經 devicectl 列出手機上的處理程序。 | udid(可選)、filter(對處理程序名稱/bundle id 做不區分大小寫的子字串匹配) |
ios_sim_backtrace |
一次性批次 LLDB(attach → thread backtrace → detach,絕非常駐工作階段);輸出上限約 200 行、主執行緒在前,目標處理程序必定被驗證已恢復執行。當 macOS 拒絕 attach(開發者模式未開啟)時,回退到 Xcode 的 sample 引擎(不掛起處理程序)並給出開啟提示。僅支援模擬器——真機會被明確拒絕並說明原因。 |
udid(可選)、pid / bundle_id、all_threads(預設 true) |
ios_sim_leaks |
用 Xcode 的 leaks 工具分析洩漏:summary(洩漏數、洩漏總位元組、前約 30 種洩漏類型)或 memgraph(產生 .memgraph 工件,用 Xcode Instruments 開啟,外掛程式絕不解析)。掃描期間 App 會被掛起,但之後必定恢復。僅支援模擬器。 |
udid(可選)、pid / bundle_id、mode(summary/memgraph) |
ios_sim_app_info |
讀取已安裝 App 的資訊:App 套件路徑、可寫資料容器、Info.plist 關鍵欄位——模擬器走 simctl appinfo(附 get_app_container 回退),USB 真機走 devicectl;未安裝時回傳 installed: false,並在 note 中提示改用 ios_sim_list_apps。 |
udid(可選)、bundle_id(必填) |
顯示面
- 側邊欄面板——「iOS 模拟器」。 即時畫面位於常駐的右側面板(固定停靠、把對話區讓開;窄視窗下退化為居中浮層)。面板渲染即時 MJPEG 畫面,支援在影片上直接點按、拖曳手勢,並有圖示工具列(Home、截圖、旋轉、重新整理),按鈕帶懸停提示。尺寸控制提供适应(鋪滿面板寬度)、50–125%(按裝置邏輯寬度縮放)以及 S / M / L 預設(按裝置短邊定尺寸;橫向時按顯示比例縮放,保持裝置實體大小)。外框樣式為无框 / 边框 / 真机框(frameless / bezel / 逼真的裝置外殼),圓角按比例計算。裝置旋轉為橫向時面板自動加寬到舒適尺寸,轉回直向時恢復你原來的寬度——橫向期間你手動拖過寬度則以你的選擇為準。左側邊緣的把手可以拖寬/收窄面板(上限 960px;雙擊恢復預設寬度)。當推流目標是 USB 連接的 iPhone 時,同一個面板顯示手機經 WebDriverAgent 的 MJPEG 畫面,操作方式完全一致。
- 緊湊對話卡片。 工具結果渲染為單列卡片,不含任何內聯圖片:統一的**「iOS 模拟器」**標題 + 操作副標籤(啟動 / 截圖 / 互動 / 建置執行 / 啟動 WebDriverAgent)+ 裝置名稱 + 狀態徽章 + 「在側邊欄開啟」提示。點擊卡片所在列即可開啟面板;點擊按鈕、連結或即時畫面本身不會觸發。
- 輸入框上方的狀態膠囊。 面板關閉且推流線上時,輸入框上方會出現一個綠點小膠囊(
<裝置名稱> · 实时),點擊即可開啟面板。它受工作階段門控:只有當目前工作階段裡掛載著模擬器結果時才渲染並輪詢,切換到沒有結果的工作階段即自動隱藏。 - 標準模式與 Code 模式。 標準工作階段使用主機下發的
presentationMeta;Code 模式(PTC)的巢狀呼叫不會攜帶 meta,用戶端會從結果中的完整 JSON 重建出完全一致的 meta——面板、卡片和狀態膠囊在兩種模式下都能工作。
安全
- 瀏覽器永遠不會接觸 serve-sim 的連接埠。所有流量都經由 DSH webserver 源站上的
/_dsh/dsh-ios/*路由:/stream/<token>(MJPEG 代理)、/screenshot/<token>(快取 PNG)、/ws?token=…(HID 控制轉送),以及/grant、/capture、/status端點。 - 權杖是 HMAC-SHA256 能力憑證(
base64url(payload).base64url(mac)),10 分鐘內過期,用每個 DSH 主目錄私有的金鑰簽章(<DSH_HOME>/cache/dsh-ios/stream-access.key,0600,原子建立)。 - 每條路由在檢查任何能力之前先套用回送/可信傳輸圍欄:回送對端位址、回送
Host(拒絕 DNS 重綁定)、Fetch-Metadata/Origin 驗證。截圖路由只提供外掛程式快取目錄內的檔案(拒絕符號連結,並做realpath包含性驗證)。 - serve-sim 以前景子處理程序方式執行,僅綁定回送位址的專屬連接埠段(3181–3244),絕不會動使用者自己在 3100 連接埠上的 serve-sim;從不使用
--host。。 - 孤兒處理程序收養/回收——若上一個 DSH 主機被異常殺死、其 serve-sim 子處理程序存活了下來:同一裝置會被直接收養(孤兒處理程序的握手資訊視為權威);若殘留處理程序占用槽位卻服務著別的裝置,則透過
serve-sim -k回收並重試一次。 - 保活與閒置停止——推流崩潰後約 5 秒會在背景自動重啟;當沒有消費者時,閒置 5 分鐘自動停止。主動停止絕不會被保活邏輯對抗。(真機 runner 有意豁免閒置回收:重啟它意味著一次數分鐘的
xcodebuild重新建置。)
環境需求
- macOS + 完整版 Xcode——僅裝 Command Line Tools 不夠。
xcodebuild、xcrun simctl和模擬器執行時期都隨 Xcode 提供。 - Xcode 中至少安裝一個 iOS 模擬器執行時期。
- DSH ≥ 0.1.0-rc.6 且使用 Web 版,才能顯示面板。無頭(headless)設定下外掛程式同樣可用:22 個工具照常工作,只是沒有即時畫面。
- 非 macOS 主機:外掛程式依然能載入,22 個工具也會註冊,但每次呼叫都會回傳明確的錯誤訊息(
iOS Simulator requires macOS with Xcode …)。 - serve-sim 作為本外掛程式的 npm 依賴隨套件安裝,正式安裝時會從本地解析;開發目錄則回退到
npx -y serve-sim(首次使用需要連網)。 - AXe(可選——只有基於 AXe 的工具需要:
ios_sim_ui_tree/ios_sim_tap_element,以及模擬器上的ios_sim_ui_rows/ios_sim_tap_row):brew install cameroncooke/axe/axe,或讓外掛程式自動下載固定版本(v1.8.0,驗證 SHA-256)到~/Library/Caches/dsh-ios/bin。DSHPLUGIN_IOS_AXE_BIN可覆蓋解析結果;DSHPLUGIN_IOS_AXE_OFFLINE=1可停用下載。 - Vision OCR(可選——只有
ios_sim_find_text/ios_sim_tap_text需要):外掛程式首次使用時用swiftc把內建的assets/ocr.swift編譯到~/Library/Caches/dsh-ios/bin/ocr(識別 zh-Hans + en-US)。 - lldb attach 需要 macOS 開發者模式:執行一次
sudo DevToolsSecurity -enable。在此之前ios_sim_backtrace會改用 Xcode 的sample引擎(不掛起處理程序),ios_sim_leaks會帶著開啟提示降級執行。。首次 WDA 建置會安裝簽章的 WebDriverAgentRunner:按提示在裝置上信任其憑證;免費團隊簽章描述檔 7 天過期後需重新執行ios_real_start_wda。
安裝到 DSH
dsh plugin --profile web add @zseven-w/dsh-ios@latest
dsh web
快速開始
一次典型的對話流程:
- 發現裝置——「列出可用的模擬器。」 →
ios_sim_devices。 - 啟動——「啟動 iPhone 17 Pro。」 →
ios_sim_boot。推流開始,「iOS 模拟器」面板隨之開啟:裝置在側邊欄裡即時顯示。(點擊任意模擬器卡片所在列,或輸入框上方的狀態膠囊,即可重新開啟。) - 在畫面上點按——直接在面板上點按、拖曳;或讓智慧代理驅動介面:「開啟設定,然後點 General。」 →
ios_sim_interact(按元素身份點擊用ios_sim_ui_tree+ios_sim_tap_element;按文字點擊用ios_sim_find_text+ios_sim_tap_text;清單/資訊流 App 用ios_sim_ui_rows+ios_sim_tap_row)。 - 建置並執行你的 App——「建置並執行 /path/to/MyApp.xcodeproj。」 →
ios_sim_build_run。完整建置需要幾分鐘;完成後 App 會在模擬器裡啟動,你可以在面板裡即時觀看。 - 預覽熱重載——「顯示 /path/to/MyPackage 的 SwiftUI 預覽。」 →
ios_sim_preview start。修改原始碼後,預覽會在約 2–5 秒內熱替換進正在執行的模擬器——無需重啟。 - 驅動真機 iPhone——用 USB 資料傳輸線連接手機並解鎖,然後說「在手機上啟動 WebDriverAgent。」 →
ios_real_start_wda。面板切到手機的即時畫面,所有工具都接受其realDevices裡的 udid;呼叫失敗時讀面板狀態裡的編碼原因(device-locked、cert-untrusted、profile-expired、tunnel-failed、device-unplugged)。
疑難排解
- backtrace 用的是
sample而不是 lldb,或 leaks 提示受限檢查——macOS 開發者模式未開啟。執行一次sudo DevToolsSecurity -enable後重試。在此之前工具會平滑降級:ios_sim_backtrace回退到 Xcode 的sample(已符號化、不掛起處理程序),ios_sim_leaks會給出開啟提示。 ios_sim_ui_tree/ios_sim_tap_element需要 AXe——用brew install cameroncooke/axe/axe安裝,或讓外掛程式在首次使用時自動下載固定版本(需要能存取 github.com)。錯誤訊息裡始終附帶完整的安裝提示;DSHPLUGIN_IOS_AXE_BIN=/path/to/axe可覆蓋解析結果。列工具(ios_sim_ui_rows/ios_sim_tap_row)在模擬器上同樣需要 AXe。ios_sim_find_text/ios_sim_tap_text報告缺少 OCR 助手——首次使用會用swiftc(需要 Xcode)把內建的assets/ocr.swift編譯到~/Library/Caches/dsh-ios/bin/ocr;錯誤訊息裡帶具體路徑與提示。ios_sim_ui_rows找不到列——結果會說明原因:深度太淺(調大max_depth;真機上每次更深快照約 15–25 秒)、不是清單頁,或深度讀取後確實沒有無障礙資訊。淺讀絕不會被誤報為「缺少無障礙支援」。- iOS 26.2 模擬器上的
ios_sim_leaks怪癖——在 iOS 26.2 執行時期上,即使開發者模式已開啟,Xcode 的leaks也可能無法分析模擬器處理程序,報出Failed to get DYLD info或 minimal-corpse 之類的致命診斷。工具會平滑降級:你能看到原始診斷,目標處理程序必定被驗證恢復,不會卡住。外掛程式側沒有修復辦法——遇到時試試mode: "memgraph"或換一個執行時期。。 - 推流自己停了——這是閒置策略,不是崩潰:沒有消費者(面板關閉、沒有掛載的卡片、沒有活躍路由)時,推流會在 5 分鐘後停止,並在下一次工具呼叫或開啟面板時重啟。崩潰的推流則會在約 5 秒內於背景自動重啟。
開發
pnpm install
pnpm run build # 主機 tsc + 用戶端打包 → lib/
pnpm run typecheck
scripts/ 下的煙霧測試會驗證編譯產物 lib/(需要啟動模擬器或連接真機 USB 的部分僅限 macOS;設定 DSH_IOS_SMOKE_SKIP_SIM=1 可跳過這些部分):
| 腳本 | 覆蓋內容 |
|---|---|
node scripts/dev-smoke.mjs |
模擬器主機:二進位解析、推流啟動、控制、保活、dispose。 |
node scripts/dev-tools-smoke.mjs [--full-build] |
在真實模擬器上驗證核心工具(加 --full-build 還會執行一次真實建置)。 |
node scripts/dev-routes-smoke.mjs |
簽章 Web 路由:grant、推流代理、截圖、ws 轉送、圍欄、過期。 |
node scripts/dev-card-smoke.mjs |
用戶端卡片:靜態 SSR(斷言無 <img>)、status/capture 契約、近即時的網路部分。 |
node scripts/dev-panel-smoke.mjs |
面板元件、尺寸模式、外框樣式、停靠/觸發/膠囊邏輯(純靜態)。 |
node scripts/dev-logs-smoke.mjs |
ios_sim_logs 的 snapshot/follow、篩選器、上限、處理程序回收。 |
node scripts/dev-uitree-smoke.mjs |
UI 樹工具:AXe 解析/下載管線、選擇器、真實模擬器上的樹與點擊。 |
node scripts/dev-debug-smoke.mjs |
偵錯工具:處理程序、呼叫堆疊(lldb + sample)、洩漏、App 資訊。 |
node scripts/dev-preview-smoke.mjs |
預覽熱重載:啟動、編輯 → 不重啟的熱替換、錯誤恢復、停止。 |
node scripts/dev-orphan-smoke.mjs |
主機被異常殺死後孤兒 serve-sim 的收養/回收。 |
node scripts/dev-ocr-smoke.mjs |
Vision-OCR 工具:助手解析、swiftc 編譯快取、識別管線、tap-text 路由。 |
node scripts/dev-wda-smoke.mjs |
WebDriverAgent 主機:ServerURLHere 解析、失敗分類、通道、保活(mock;可選實測)。 |
node scripts/dev-realdevice-smoke.mjs |
對 USB 連接的 iPhone 執行 xcrun devicectl——工具所用的真實程式碼路徑。 |
node scripts/dev-realstart-smoke.mjs |
/real-start 路由:圍欄、編碼拒絕、建置/啟動門控(純靜態)。 |
node scripts/dev-realtools-smoke.mjs |
ios_sim_screenshot / ios_sim_interact / ios_sim_ui_tree / ios_sim_tap_element 的真機後端,以及 ios_real_start_wda。 |
生態
- DSH Android — 在對話中執行 Android 模擬器或 USB 實機,全部由 adb 驅動
- DSH Crew — 從 Claude Code / Codex 把任務派給 DSH agent
- DSH Noema — DSH 的長期記憶
- DSH OpenPencil — 在對話中檢視與編輯
.op設計文件
致謝與授權
- serve-sim —— Evan Bacon —— 模擬器推流引擎(Apache-2.0;隨套件安裝的執行時期依賴)。
- AXe —— Cameron Cooke —— UI 樹工具所依賴的無障礙 CLI(MIT)。
- WebDriverAgent —— 外掛程式在真機上建置並啟動的 WebDriver 伺服器(BSD 授權)。
- 架構受 Codex 的「Build iOS Apps」外掛啟發;SwiftUI 預覽引擎是對其公開文件所述方案的潔淨室(clean-room)重實作,未複製任何 Codex 程式碼。
- 完整聲明見 THIRD_PARTY_NOTICES.md。
授權條款:MIT
链接
同类插件
zhu1090093659/dsh-web#packages/dsh-remote-web-ui★ 8405
手机/PC 远程操控 dsh web 工作区:扫码配对、令牌门控通道、SSE 实时同步,提供移动端与完整桌面 GUI 两种远程形态。
zhu1090093659/dsh-web#packages/dsh-ssh★ 8405
SSH 远程运维面板:Web 终端、SFTP 传输、本地端口转发与一条命令并发集群执行,Agent 与面板共用同一份主机配置。
saya-ch/dsh-mobile★ 380
通过 Android App 或手机浏览器访问 DeepSeek Harness,支持安全局域网连接、远程访问、持久设备配对和可自定义移动界面。
liguobao/ds-harness-remote★ 270
DeepSeek Harness 多端远程访问:从手机、平板、浏览器或另一台电脑继续进行中的会话,端到端加密通道(Noise IK + 自适应 Relay/WebRTC 传输),设备授权管理;远程端仅开放 ApiProxy 能力,支持 dsh-file-viewer 只读文件预览,不提供 Shell、远程桌面或写入权限。
wenbin-wb/dsh-bridge★ 185
DeepSeek Harness 远程与移动端接入插件:提供局域网扫码直连、Cloudflare 与自建公网隧道,以及微信、QQ、飞书、Telegram 机器人交互,内置安全认证与访问控制。
ZSeven-W/dsh-android★ 169
在对话里直接操作 Android 设备——模拟器或 USB 手机,完全通过 adb 驱动:20 个 Agent 工具用于流式投屏、Gradle 构建运行、UI 树或 OCR 交互、logcat、进程与内存检查,并附带三键导航面板。
社区评论
评论公开保存在 GitHub Discussions。加载评论会连接 GitHub 和 Giscus;发表内容需要 GitHub 账号。