agent-device 0.21.12 → 0.21.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (317) hide show
  1. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.12.apk → agent-device-android-ime-helper-0.21.14.apk} +0 -0
  2. package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.14.apk.sha256 +1 -0
  3. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.12.manifest.json → agent-device-android-ime-helper-0.21.14.manifest.json} +4 -4
  4. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.14.apk +0 -0
  5. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.14.apk.sha256 +1 -0
  6. package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.21.12.manifest.json → agent-device-android-snapshot-helper-0.21.14.manifest.json} +6 -6
  7. package/apple/macos-helper/Package.swift +4 -0
  8. package/apple/macos-helper/Sources/AgentDeviceMacOSHelper/main.swift +3 -6
  9. package/apple/macos-helper/Tests/AgentDeviceMacOSHelperTests/ScreenshotResponseTests.swift +15 -0
  10. package/apple/snapshot-bridge/SnapshotBridgeRuntime.m +47 -1
  11. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunner/AgentDeviceRunnerApp.m +122 -42
  12. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunner/Info.plist +23 -0
  13. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunner.xcodeproj/project.pbxproj +17 -0
  14. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAppScreenCapture.swift +21 -13
  15. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerScrollViewportPolicy.swift +1 -162
  16. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedGesture.h +0 -9
  17. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedGesture.m +0 -56
  18. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSystemSurfaceHostPolicy.swift +0 -48
  19. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTapPointPolicy.swift +0 -50
  20. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+AXSnapshotFallback.swift +33 -586
  21. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Alert.swift +40 -24
  22. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+AlertObservation.swift +2 -3
  23. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+BlockingSystemModalResolution.swift +0 -36
  24. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandDispatch.swift +630 -0
  25. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +34 -2256
  26. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandJournal.swift +1 -338
  27. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Environment.swift +0 -12
  28. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+GestureExecution.swift +160 -0
  29. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +0 -24
  30. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Keyboard.swift +0 -142
  31. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Lifecycle.swift +90 -39
  32. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+MainThreadWork.swift +78 -106
  33. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +23 -2
  34. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Navigation.swift +162 -113
  35. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+PrivateAXPresentation.swift +0 -209
  36. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScreenRecorder.swift +86 -10
  37. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScrollDragExecution.swift +271 -0
  38. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScrollGesture.swift +1 -200
  39. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SequenceExecution.swift +20 -227
  40. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +78 -295
  41. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotAcquisition.swift +40 -27
  42. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotBackendCapabilities.swift +0 -78
  43. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCapturePlan.swift +85 -581
  44. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCaptureTarget.swift +106 -0
  45. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotExecution.swift +142 -0
  46. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotTiming.swift +49 -78
  47. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedCommitDeadline.swift +0 -44
  48. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedGesturePolicy.swift +73 -114
  49. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedInteraction.swift +1 -12
  50. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedTextEntry.swift +11 -94
  51. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SystemModal.swift +2 -10
  52. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntry.swift +1 -1
  53. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntryFocus.swift +0 -35
  54. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextInputCandidatePolicy.swift +0 -31
  55. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextTyping.swift +2 -18
  56. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Transport.swift +34 -52
  57. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TvRemote.swift +0 -22
  58. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TypeExecution.swift +135 -0
  59. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests.swift +22 -6
  60. package/dist/apple/runner/AgentDeviceRunner/RecordingScripts/recording-overlay.swift +140 -20
  61. package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotCoordinateSpace.swift +16 -19
  62. package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotGeometry.swift +21 -9
  63. package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotModels.swift +59 -10
  64. package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotPresentationInvariant.swift +12 -10
  65. package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotVisibilityFold.swift +13 -8
  66. package/dist/src/absence-observation-errors.js +1 -1
  67. package/dist/src/adapter.js +1 -1
  68. package/dist/src/adb-executor.js +1 -1
  69. package/dist/src/adb-failure.js +1 -1
  70. package/dist/src/adb-transport.js +1 -1
  71. package/dist/src/agent-browser-provider.js +1 -1
  72. package/dist/src/agent-browser-tool.js +1 -1
  73. package/dist/src/agent-device-client.js +2 -2
  74. package/dist/src/ai-sdk.js +1 -1
  75. package/dist/src/alert-runtime.js +1 -1
  76. package/dist/src/android-adb.d.ts +1 -1
  77. package/dist/src/app-catalog.js +1 -1
  78. package/dist/src/app-deployment-resolution.js +1 -1
  79. package/dist/src/app-inventory.js +1 -1
  80. package/dist/src/app-launch.js +2 -2
  81. package/dist/src/app-lifecycle.js +1 -1
  82. package/dist/src/app-lifecycle2.js +1 -1
  83. package/dist/src/app-log-files.js +1 -1
  84. package/dist/src/app-log-runtime2.js +3 -3
  85. package/dist/src/app-resolution.js +2 -2
  86. package/dist/src/apple-runner-platform.js +1 -1
  87. package/dist/src/application-lifecycle-interaction.js +1 -1
  88. package/dist/src/archive.js +1 -1
  89. package/dist/src/artifact-download.js +1 -1
  90. package/dist/src/auth-session.js +1 -1
  91. package/dist/src/auth.js +1 -1
  92. package/dist/src/back-mode.js +1 -1
  93. package/dist/src/backend-snapshot-options.js +1 -1
  94. package/dist/src/boot-diagnostics.js +1 -1
  95. package/dist/src/capture-disclosure.js +1 -1
  96. package/dist/src/capture.js +1 -1
  97. package/dist/src/cli-config.js +1 -1
  98. package/dist/src/cli-help.js +8 -7
  99. package/dist/src/cli-runner.js +1 -1
  100. package/dist/src/cli.js +4 -4
  101. package/dist/src/click-button.js +1 -1
  102. package/dist/src/client-metro.js +1 -1
  103. package/dist/src/client-types.d.ts +4 -5
  104. package/dist/src/clipboard-shell-response.js +1 -1
  105. package/dist/src/code-signature.js +1 -1
  106. package/dist/src/command-schema.js +3 -3
  107. package/dist/src/command-tools.js +3 -3
  108. package/dist/src/connection-runtime.js +1 -1
  109. package/dist/src/connection.js +1 -1
  110. package/dist/src/contracts.js +1 -1
  111. package/dist/src/daemon-client-lifecycle.js +1 -1
  112. package/dist/src/daemon-resolution.js +1 -1
  113. package/dist/src/daemon.js +1 -1
  114. package/dist/src/debug-symbols-facade.js +1 -1
  115. package/dist/src/device-claim-rule.js +2 -2
  116. package/dist/src/device-input-state.d.ts +1 -1
  117. package/dist/src/device-inventory-context.js +1 -1
  118. package/dist/src/device-rotation.js +1 -1
  119. package/dist/src/device-selection-resolver.js +1 -1
  120. package/dist/src/device-session.js +1 -1
  121. package/dist/src/device-shell.js +1 -1
  122. package/dist/src/device2.js +1 -1
  123. package/dist/src/devicectl.js +1 -1
  124. package/dist/src/diagnostics.js +1 -1
  125. package/dist/src/dispatch-resolve.js +1 -1
  126. package/dist/src/display-inventory.js +1 -1
  127. package/dist/src/doctor-facade.js +1 -1
  128. package/dist/src/doctor2.js +1 -1
  129. package/dist/src/engine-eval-script.js +1 -1
  130. package/dist/src/error.js +1 -1
  131. package/dist/src/exec.js +1 -1
  132. package/dist/src/file.js +1 -1
  133. package/dist/src/find.js +1 -1
  134. package/dist/src/format.js +1 -1
  135. package/dist/src/gesture-plan-types.d.ts +38 -0
  136. package/dist/src/gesture-plan.js +1 -1
  137. package/dist/src/gesture-runtime.js +1 -1
  138. package/dist/src/harmonyos.js +1 -1
  139. package/dist/src/helper.js +2 -2
  140. package/dist/src/host.js +1 -1
  141. package/dist/src/human-control-contract.js +1 -1
  142. package/dist/src/human-control.js +1 -1
  143. package/dist/src/index.js +1 -1
  144. package/dist/src/input-actions.js +1 -1
  145. package/dist/src/input-actions2.js +1 -1
  146. package/dist/src/install-artifact-facade.js +1 -1
  147. package/dist/src/install-source-network-transport.js +1 -1
  148. package/dist/src/install-source2.js +1 -1
  149. package/dist/src/interaction-positionals.js +1 -1
  150. package/dist/src/interaction-ref-policy.js +1 -1
  151. package/dist/src/interaction2.js +1 -1
  152. package/dist/src/interactor-operation-binding.js +1 -1
  153. package/dist/src/interactor-operation-catalog.js +1 -1
  154. package/dist/src/interactor.js +4 -4
  155. package/dist/src/interactor2.js +1 -1
  156. package/dist/src/interactors.js +1 -1
  157. package/dist/src/internal/bin.js +1 -1
  158. package/dist/src/internal/daemon.js +2 -2
  159. package/dist/src/internal/png-worker.js +1 -1
  160. package/dist/src/internal/run-script-http-child.js +1 -1
  161. package/dist/src/inventory.js +1 -1
  162. package/dist/src/inventory2.js +1 -1
  163. package/dist/src/inventory3.js +1 -1
  164. package/dist/src/inventory5.js +1 -1
  165. package/dist/src/ios-snapshot-acquisition.js +1 -1
  166. package/dist/src/ios-snapshot-runtime.js +1 -1
  167. package/dist/src/lease.js +1 -1
  168. package/dist/src/limrun-download-file.js +1 -1
  169. package/dist/src/limrun-runtime-dependencies.js +1 -1
  170. package/dist/src/limrun.d.ts +435 -4
  171. package/dist/src/linux.js +1 -1
  172. package/dist/src/local-interactor-operation-set.js +1 -1
  173. package/dist/src/location-coordinates.js +1 -1
  174. package/dist/src/managed-device-scope.js +1 -1
  175. package/dist/src/mechanics.js +5 -5
  176. package/dist/src/mobile-snapshot-semantics.js +1 -1
  177. package/dist/src/multitouch-support.js +1 -1
  178. package/dist/src/native-build-cache.js +1 -0
  179. package/dist/src/observation.js +1 -1
  180. package/dist/src/parameterized-recorded-fill.js +1 -1
  181. package/dist/src/perf-facade.js +1 -2
  182. package/dist/src/perf-runtime-operation-builder.js +1 -1
  183. package/dist/src/perf-runtime-plan.js +1 -1
  184. package/dist/src/perf-target.js +2 -0
  185. package/dist/src/perf.js +1 -1
  186. package/dist/src/physical-device-apps.js +1 -0
  187. package/dist/src/physical-device-control.js +1 -1
  188. package/dist/src/platform-request-scope.js +1 -1
  189. package/dist/src/platform-runtime-host.js +1 -1
  190. package/dist/src/platform-runtime-managed-owner.js +1 -1
  191. package/dist/src/platform-runtime-open-target.js +1 -1
  192. package/dist/src/platform-runtime-operation-host.js +2 -2
  193. package/dist/src/platform-runtime-runtime-hints.js +1 -1
  194. package/dist/src/platform-runtime-screen-recording-apple-simulator-host.js +1 -1
  195. package/dist/src/platform-runtime-screen-recording-finalizer-host.js +1 -1
  196. package/dist/src/platform-runtime-screen-recording-process-host.js +1 -1
  197. package/dist/src/platform-runtime-unavailable.js +1 -1
  198. package/dist/src/platform-runtime.js +1 -1
  199. package/dist/src/platform-runtime2.js +1 -1
  200. package/dist/src/png-crop-bytes.js +1 -1
  201. package/dist/src/png-size.js +1 -1
  202. package/dist/src/png-worker-client.js +1 -1
  203. package/dist/src/png.js +1 -1
  204. package/dist/src/prepare-kind.js +1 -1
  205. package/dist/src/provider-session-ownership.js +1 -1
  206. package/dist/src/provider-webdriver.js +1 -1
  207. package/dist/src/proxy.js +1 -1
  208. package/dist/src/quality-warnings.js +1 -1
  209. package/dist/src/react-native.js +1 -1
  210. package/dist/src/record-runtime.js +1 -1
  211. package/dist/src/recording.js +1 -1
  212. package/dist/src/register-builtins.js +1 -1
  213. package/dist/src/registry.js +35 -35
  214. package/dist/src/remote-config2.js +1 -1
  215. package/dist/src/replay-divergence.js +1 -1
  216. package/dist/src/replay.js +1 -1
  217. package/dist/src/reporting.js +1 -1
  218. package/dist/src/request-admission.js +1 -1
  219. package/dist/src/request-cancel.js +1 -1
  220. package/dist/src/request-runtime-binding.js +1 -1
  221. package/dist/src/retry.js +1 -1
  222. package/dist/src/runner-cache-metadata.js +1 -1
  223. package/dist/src/runner-client.js +1 -1
  224. package/dist/src/runner-dev-tools-security.js +1 -1
  225. package/dist/src/runner-device-readiness.js +1 -1
  226. package/dist/src/runner-disposal.js +1 -1
  227. package/dist/src/runner-error-classification.js +3 -0
  228. package/dist/src/runner-operations-facade.js +1 -1
  229. package/dist/src/runner-presentation.js +1 -1
  230. package/dist/src/runner.js +1 -1
  231. package/dist/src/runtime-transport-hints.js +1 -1
  232. package/dist/src/runtime.js +3 -3
  233. package/dist/src/runtime10.js +2 -2
  234. package/dist/src/runtime2.js +2 -2
  235. package/dist/src/runtime3.js +1 -1
  236. package/dist/src/runtime4.js +4 -4
  237. package/dist/src/runtime5.js +1 -1
  238. package/dist/src/runtime6.js +1 -1
  239. package/dist/src/runtime7.js +1 -1
  240. package/dist/src/runtime8.js +1 -1
  241. package/dist/src/runtime9.js +1 -1
  242. package/dist/src/screen-recording-admission-ledger.js +1 -1
  243. package/dist/src/screen-recording-completion.js +1 -1
  244. package/dist/src/screen-recording-options.js +1 -1
  245. package/dist/src/screen-recording-resource-recovery.js +1 -1
  246. package/dist/src/screen-recording-transport.js +1 -1
  247. package/dist/src/screenshot-density.js +1 -1
  248. package/dist/src/screenshot-image.js +1 -1
  249. package/dist/src/screenshot-runtime.js +1 -1
  250. package/dist/src/screenshot.js +1 -1
  251. package/dist/src/screenshot3.js +1 -1
  252. package/dist/src/script.js +1 -1
  253. package/dist/src/scroll-command.d.ts +377 -0
  254. package/dist/src/scroll-command.js +1 -1
  255. package/dist/src/scroll-gesture.js +1 -1
  256. package/dist/src/sdk-batch-runner.js +2 -2
  257. package/dist/src/sdk-batch.js +2 -2
  258. package/dist/src/sdk-contracts.d.ts +28 -0
  259. package/dist/src/sdk-contracts.js +1 -1
  260. package/dist/src/sdk-device.js +1 -1
  261. package/dist/src/sdk-io.js +1 -1
  262. package/dist/src/sdk-remote-config.js +1 -1
  263. package/dist/src/sdk-selectors.d.ts +23 -726
  264. package/dist/src/selection.js +0 -0
  265. package/dist/src/selector-runtime.js +1 -1
  266. package/dist/src/semantic-index.js +1 -1
  267. package/dist/src/server.js +1 -1
  268. package/dist/src/session-allocation.js +1 -1
  269. package/dist/src/session-observation.js +1 -1
  270. package/dist/src/session-routing.js +1 -1
  271. package/dist/src/session-runtime-admission.js +1 -1
  272. package/dist/src/session-snapshot.js +1 -1
  273. package/dist/src/session-store.js +2 -2
  274. package/dist/src/session2.js +3 -3
  275. package/dist/src/settings.js +1 -1
  276. package/dist/src/simctl-facade.js +1 -1
  277. package/dist/src/simctl.js +1 -1
  278. package/dist/src/simulator-state.js +1 -1
  279. package/dist/src/simulator.js +1 -1
  280. package/dist/src/snapshot-runtime-binding.js +1 -1
  281. package/dist/src/snapshot-runtime.js +1 -1
  282. package/dist/src/snapshot-state.js +1 -1
  283. package/dist/src/snapshot2.js +1 -1
  284. package/dist/src/snapshot3.js +1 -1
  285. package/dist/src/snapshot4.js +1 -1
  286. package/dist/src/src.js +1 -1
  287. package/dist/src/src7.js +1 -1
  288. package/dist/src/src8.js +2 -2
  289. package/dist/src/string-enum.js +1 -1
  290. package/dist/src/takeover.js +1 -1
  291. package/dist/src/text-entry-focus.js +1 -1
  292. package/dist/src/tool-provider-facade.js +1 -1
  293. package/dist/src/tool-provider.js +2 -2
  294. package/dist/src/tool-provider2.js +1 -1
  295. package/dist/src/touch-runtime.js +1 -1
  296. package/dist/src/transport.js +1 -1
  297. package/dist/src/tree.js +1 -1
  298. package/dist/src/tv-remote.js +1 -1
  299. package/dist/src/type-text-runtime.js +1 -1
  300. package/dist/src/update-check.js +1 -1
  301. package/dist/src/verified-file.js +1 -1
  302. package/dist/src/version.js +1 -1
  303. package/dist/src/video.js +1 -1
  304. package/dist/src/viewport.js +1 -1
  305. package/dist/src/web.js +1 -1
  306. package/dist/src/web2.js +1 -1
  307. package/dist/src/webdriver-source.js +1 -1
  308. package/package.json +3 -2
  309. package/server.json +2 -2
  310. package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.12.apk.sha256 +0 -1
  311. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.12.apk +0 -0
  312. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.12.apk.sha256 +0 -1
  313. package/dist/src/app-inventory.d.ts +0 -4
  314. package/dist/src/apps-simctl.js +0 -1
  315. package/dist/src/cloud-artifacts.d.ts +0 -61
  316. package/dist/src/runner-contract.js +0 -3
  317. package/dist/src/snapshot-process.js +0 -1
@@ -49,24 +49,52 @@ extension RunnerTests {
49
49
 
50
50
 
51
51
 
52
+
53
+
52
54
  func captureRunnerFrame(app: XCUIApplication) -> RunnerImage? {
53
- #if os(iOS)
54
- guard case .success(let captured) = captureObservedScreen(app: app) else {
55
+ switch captureRunnerFrameResult(app: app) {
56
+ case .success(let captured):
57
+ return captured.image
58
+ case .failure:
55
59
  return nil
56
60
  }
57
- return captured.image
61
+ }
62
+
63
+
64
+
65
+
66
+
67
+ func captureRunnerFrameResult(
68
+ app: XCUIApplication
69
+ ) -> Result<CapturedAppScreen, RunnerAppScreenCaptureFailure> {
70
+ #if os(iOS)
71
+ return captureObservedScreen(app: app)
58
72
  #else
59
- var image: RunnerImage?
73
+ var outcome: Result<CapturedAppScreen, RunnerAppScreenCaptureFailure> = .failure(
74
+ .unrenderableImage
75
+ )
60
76
  let capture = {
61
- let screenshot = XCUIScreen.main.screenshot()
62
- image = screenshot.image
77
+ let image = XCUIScreen.main.screenshot().image
78
+ if let cgImage = runnerCGImage(from: image) {
79
+
80
+
81
+ outcome = .success(
82
+ CapturedAppScreen(
83
+ image: image,
84
+ displayID: 0,
85
+ pixelWidth: cgImage.width,
86
+ pixelHeight: cgImage.height,
87
+ pixelsPerPoint: 1
88
+ )
89
+ )
90
+ }
63
91
  }
64
92
  if Thread.isMainThread {
65
93
  capture()
66
94
  } else {
67
95
  DispatchQueue.main.sync(execute: capture)
68
96
  }
69
- return image
97
+ return outcome
70
98
  #endif
71
99
  }
72
100
 
@@ -166,8 +194,17 @@ extension RunnerTests {
166
194
  currentApp = app
167
195
  currentBundleId = nil
168
196
  currentAppProcessIdentifier = nil
197
+ resetTargetBoundState()
198
+ }
199
+
200
+
201
+
202
+
203
+ func resetTargetBoundState() {
169
204
  clearRememberedTextEntryTap()
170
- snapshotXCTestPenaltyWarmupExemptionPending = false
205
+ snapshotXCTestPenaltyWarmupExemption.isPending = false
206
+ lastLoggedFastAppGuardLine = nil
207
+ lastLoggedGesturePolicyLines.removeAll()
171
208
  }
172
209
 
173
210
  func invalidateCachedTarget(reason: String) {
@@ -177,8 +214,7 @@ extension RunnerTests {
177
214
  currentApp = nil
178
215
  currentBundleId = nil
179
216
  currentAppProcessIdentifier = nil
180
- clearRememberedTextEntryTap()
181
- snapshotXCTestPenaltyWarmupExemptionPending = false
217
+ resetTargetBoundState()
182
218
  }
183
219
 
184
220
  func resetTargetAfterExternalRelaunch() -> Response {
@@ -208,10 +244,10 @@ extension RunnerTests {
208
244
  )
209
245
  currentApp = candidate
210
246
  currentAppProcessIdentifier = observedProcessIdentifier
211
- clearRememberedTextEntryTap()
247
+ resetTargetBoundState()
212
248
  clearSnapshotXCTestChannelPenalty(reason: "target_process_changed")
213
249
  clearPrivateAXAcceptedDepth(reason: "target_process_changed")
214
- snapshotXCTestPenaltyWarmupExemptionPending = true
250
+ snapshotXCTestPenaltyWarmupExemption.isPending = true
215
251
  beginFirstInteractionStabilization()
216
252
  }
217
253
 
@@ -246,22 +282,26 @@ extension RunnerTests {
246
282
 
247
283
  func canUseFastForegroundAppGuard(
248
284
  activeApp: XCUIApplication,
249
- requestedBundleId: String?,
250
- command: CommandType
285
+ requestedBundleId: String?
251
286
  ) -> Bool {
252
287
  guard let requestedBundleId, currentBundleId == requestedBundleId, currentApp != nil else {
253
288
  return false
254
289
  }
255
290
  guard activeApp.state == .runningForeground else { return false }
256
- NSLog(
257
- "AGENT_DEVICE_RUNNER_FAST_APP_GUARD command=%@ bundle=%@ state=%d",
258
- String(describing: command),
259
- requestedBundleId,
260
- activeApp.state.rawValue
261
- )
291
+ writeFastAppGuardMarker(bundleId: requestedBundleId, state: activeApp.state)
262
292
  return true
263
293
  }
264
294
 
295
+ func writeFastAppGuardMarker(bundleId: String, state: XCUIApplication.State) {
296
+
297
+
298
+ let line = "AGENT_DEVICE_RUNNER_FAST_APP_GUARD bundle=\(bundleId) state=\(state.rawValue)"
299
+ if lastLoggedFastAppGuardLine != line {
300
+ lastLoggedFastAppGuardLine = line
301
+ runnerMarkerWriter(line)
302
+ }
303
+ }
304
+
265
305
 
266
306
 
267
307
 
@@ -276,6 +316,31 @@ extension RunnerTests {
276
316
  return foreign.count == 1 ? foreign.first : nil
277
317
  }
278
318
 
319
+
320
+
321
+ func notRunningReadResponse(command: Command, bundleId: String) -> Response? {
322
+ #if os(iOS)
323
+ guard isReadOnlyCommand(command),
324
+ XCUIApplication(bundleIdentifier: bundleId).state == .notRunning
325
+ else { return nil }
326
+ NSLog(
327
+ "AGENT_DEVICE_RUNNER_READ_TARGET_NOT_RUNNING bundle=%@ command=%@",
328
+ bundleId,
329
+ command.command.rawValue
330
+ )
331
+ return Response(
332
+ ok: false,
333
+ error: ErrorPayload(
334
+ code: RunnerWireErrorCode.appNotRunning,
335
+ message: "app '\(bundleId)' is not running",
336
+ hint: "Reads do not launch the app. Relaunch it with open; if a system prompt such as a deep-link confirmation holds its launch, answer it with alert accept."
337
+ )
338
+ )
339
+ #else
340
+ return nil
341
+ #endif
342
+ }
343
+
279
344
  func activateTarget(bundleId: String, reason: String) -> XCUIApplication {
280
345
  let target = XCUIApplication(bundleIdentifier: bundleId)
281
346
  let initialState = target.state
@@ -312,8 +377,7 @@ extension RunnerTests {
312
377
  currentApp = target
313
378
  currentBundleId = bundleId
314
379
  currentAppProcessIdentifier = Self.processIdentifier(of: target)
315
- clearRememberedTextEntryTap()
316
- snapshotXCTestPenaltyWarmupExemptionPending = false
380
+ resetTargetBoundState()
317
381
  beginFirstInteractionStabilization()
318
382
  return target
319
383
  }
@@ -387,25 +451,13 @@ extension RunnerTests {
387
451
  }
388
452
 
389
453
  func shouldRetryCommand(_ command: Command) -> Bool {
390
- if RunnerEnv.isTruthy("AGENT_DEVICE_RUNNER_DISABLE_READONLY_RETRY") {
391
- return false
392
- }
393
- return isReadOnlyCommand(command)
454
+ isReadOnlyCommand(command)
394
455
  }
395
456
 
396
457
  func shouldRetryException(_ command: Command, message: String) -> Bool {
397
458
  guard shouldRetryCommand(command) else { return false }
398
- let normalized = message.lowercased()
399
- if normalized.contains("kaxerrorservernotfound") {
400
- return true
401
- }
402
- if normalized.contains("main thread execution timed out") {
403
- return true
404
- }
405
- if normalized.contains("timed out") && command.command == .snapshot {
406
- return true
407
- }
408
- return false
459
+
460
+ return message.lowercased().contains("kaxerrorservernotfound")
409
461
  }
410
462
 
411
463
 
@@ -424,8 +476,7 @@ extension RunnerTests {
424
476
 
425
477
  func shouldRetryResponse(_ response: Response) -> Bool {
426
478
  guard response.ok == false else { return false }
427
- guard let message = response.error?.message.lowercased() else { return false }
428
- return message.contains("is not available")
479
+ return response.error?.retryableFailure != nil
429
480
  }
430
481
 
431
482
  func isInteractionCommand(_ command: CommandType) -> Bool {
@@ -12,7 +12,9 @@ import XCTest
12
12
  extension RunnerTests {
13
13
 
14
14
 
15
- private final class MainThreadWorkState {
15
+ private final class MainThreadWorkState<T> {
16
+ let completed = DispatchSemaphore(value: 0)
17
+ var result: Result<T, Error>?
16
18
  var finished = false
17
19
  var abandoned = false
18
20
  }
@@ -62,24 +64,71 @@ extension RunnerTests {
62
64
  if Thread.isMainThread {
63
65
  return try work()
64
66
  }
65
- var result: Result<T, Error>?
66
- let semaphore = DispatchSemaphore(value: 0)
67
- let workState = MainThreadWorkState()
67
+ mainThreadWorkLock.lock()
68
+ let state = enqueueMainThreadWorkLocked(operation, work)
69
+ mainThreadWorkLock.unlock()
70
+ return try awaitMainThreadWork(
71
+ state,
72
+ operation: operation,
73
+ timeout: timeout,
74
+ timeoutError: timeoutError,
75
+ onAbandoned: onAbandoned
76
+ )
77
+ }
78
+
79
+
80
+
81
+
82
+
83
+
84
+
85
+ func runMainThreadWorkIfIdle<T>(
86
+ _ operation: String,
87
+ timeout: TimeInterval,
88
+ timeoutError: @escaping () -> Error,
89
+ _ work: @escaping () throws -> T
90
+ ) throws -> T? {
91
+ if Thread.isMainThread {
92
+ return nil
93
+ }
94
+ mainThreadWorkLock.lock()
95
+ guard mainThreadWorkInFlightCount == 0 else {
96
+ mainThreadWorkLock.unlock()
97
+ return nil
98
+ }
99
+ let state = enqueueMainThreadWorkLocked(operation, work)
100
+ mainThreadWorkLock.unlock()
101
+ return try awaitMainThreadWork(
102
+ state,
103
+ operation: operation,
104
+ timeout: timeout,
105
+ timeoutError: timeoutError,
106
+ onAbandoned: nil
107
+ )
108
+ }
109
+
110
+ private func enqueueMainThreadWorkLocked<T>(
111
+ _ operation: String,
112
+ _ work: @escaping () throws -> T
113
+ ) -> MainThreadWorkState<T> {
114
+ let state = MainThreadWorkState<T>()
115
+ mainThreadWorkInFlightCount += 1
68
116
  DispatchQueue.main.async {
69
117
  do {
70
- result = .success(try work())
118
+ state.result = .success(try work())
71
119
  } catch {
72
- result = .failure(error)
120
+ state.result = .failure(error)
73
121
  }
74
122
  self.mainThreadWorkLock.lock()
75
- let abandoned = workState.abandoned
123
+ self.mainThreadWorkInFlightCount -= 1
124
+ let abandoned = state.abandoned
76
125
  if abandoned {
77
126
  self.abandonedMainThreadWorkCount -= 1
78
127
  if self.abandonedMainThreadWorkCount == 0 {
79
128
  self.abandonedMainThreadWorkSince = nil
80
129
  }
81
130
  } else {
82
- workState.finished = true
131
+ state.finished = true
83
132
  }
84
133
  let allDrained = abandoned && self.abandonedMainThreadWorkCount == 0
85
134
  self.mainThreadWorkLock.unlock()
@@ -89,14 +138,29 @@ extension RunnerTests {
89
138
  NSLog("AGENT_DEVICE_RUNNER_ABANDONED_WORK_DRAINED")
90
139
  }
91
140
  }
92
- semaphore.signal()
141
+ state.completed.signal()
93
142
  }
94
- let waitResult = semaphore.wait(timeout: .now() + timeout)
143
+ return state
144
+ }
145
+
146
+ private func awaitMainThreadWork<T>(
147
+ _ state: MainThreadWorkState<T>,
148
+ operation: String,
149
+ timeout: TimeInterval,
150
+ timeoutError: @escaping () -> Error,
151
+ onAbandoned: (() -> Void)?
152
+ ) throws -> T {
153
+ let waitResult = state.completed.wait(timeout: .now() + timeout)
95
154
  if waitResult == .timedOut {
155
+
156
+
157
+
158
+
159
+
96
160
  mainThreadWorkLock.lock()
97
- let abandoned = !workState.finished
161
+ let abandoned = !state.finished
98
162
  if abandoned {
99
- workState.abandoned = true
163
+ state.abandoned = true
100
164
  abandonedMainThreadWorkCount += 1
101
165
  if abandonedMainThreadWorkSince == nil {
102
166
  abandonedMainThreadWorkSince = Date()
@@ -110,10 +174,10 @@ extension RunnerTests {
110
174
  timeout
111
175
  )
112
176
  onAbandoned?()
177
+ throw timeoutError()
113
178
  }
114
- throw timeoutError()
115
179
  }
116
- switch result {
180
+ switch state.result {
117
181
  case .success(let value):
118
182
  return value
119
183
  case .failure(let error):
@@ -135,95 +199,3 @@ extension RunnerTests {
135
199
  )
136
200
  }
137
201
  }
138
-
139
-
140
-
141
-
142
-
143
-
144
-
145
-
146
-
147
-
148
-
149
-
150
-
151
-
152
-
153
-
154
-
155
-
156
-
157
-
158
-
159
-
160
-
161
-
162
-
163
-
164
-
165
-
166
-
167
-
168
-
169
-
170
-
171
-
172
-
173
-
174
-
175
-
176
-
177
-
178
-
179
-
180
-
181
-
182
-
183
-
184
-
185
-
186
-
187
-
188
-
189
-
190
-
191
-
192
-
193
-
194
-
195
-
196
-
197
-
198
-
199
-
200
-
201
-
202
-
203
-
204
-
205
-
206
-
207
-
208
-
209
-
210
-
211
-
212
-
213
-
214
-
215
-
216
-
217
-
218
-
219
-
220
-
221
-
222
-
223
-
224
-
225
-
226
-
227
-
228
-
229
-
@@ -17,7 +17,6 @@ enum CommandType: String, Codable {
17
17
  case readText
18
18
  case snapshot
19
19
  case screenshot
20
- case back
21
20
  case backInApp
22
21
  case backSystem
23
22
  case home
@@ -78,7 +77,7 @@ extension CommandType {
78
77
 
79
78
 
80
79
  case .tap, .longPress, .drag, .remotePress, .type, .swipe, .scroll, .desktopScroll,
81
- .back, .backInApp, .backSystem, .rotate, .appSwitcher,
80
+ .backInApp, .backSystem, .rotate, .appSwitcher,
82
81
  .keyboardDismiss, .keyboardReturn, .sequence, .gesture:
83
82
  return CommandTraits(isInteraction: true, readOnly: .never, isLifecycle: false)
84
83
 
@@ -386,8 +385,30 @@ struct SnapshotQualityPayload: Codable {
386
385
  }
387
386
  }
388
387
 
388
+
389
+ enum RetryableResponseFailure: Equatable {
390
+ case targetAppUnavailable
391
+ }
392
+
389
393
  struct ErrorPayload: Codable {
390
394
  var code: String?
391
395
  let message: String
392
396
  var hint: String?
397
+
398
+
399
+ var retryableFailure: RetryableResponseFailure? = nil
400
+
401
+ private enum CodingKeys: String, CodingKey {
402
+ case code
403
+ case message
404
+ case hint
405
+ }
406
+
407
+ static func targetAppUnavailable(bundleId: String?) -> ErrorPayload {
408
+ let subject = bundleId.map { "app '\($0)'" } ?? "runner app"
409
+ return ErrorPayload(
410
+ message: "\(subject) is not available",
411
+ retryableFailure: .targetAppUnavailable
412
+ )
413
+ }
393
414
  }