agent-device 0.21.6 → 0.21.8

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.6.apk → agent-device-android-ime-helper-0.21.8.apk} +0 -0
  2. package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.8.apk.sha256 +1 -0
  3. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.6.manifest.json → agent-device-android-ime-helper-0.21.8.manifest.json} +4 -4
  4. package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.21.6.apk → agent-device-android-snapshot-helper-0.21.8.apk} +0 -0
  5. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.8.apk.sha256 +1 -0
  6. package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.21.6.manifest.json → agent-device-android-snapshot-helper-0.21.8.manifest.json} +6 -6
  7. package/apple/macos-helper/Package.swift +16 -1
  8. package/apple/macos-helper/Sources/AgentDeviceMacOSDeviceHub/DeviceHubPose.swift +47 -0
  9. package/apple/macos-helper/Sources/AgentDeviceMacOSHelper/DeviceHubPose.swift +320 -0
  10. package/apple/macos-helper/Sources/AgentDeviceMacOSHelper/main.swift +66 -13
  11. package/apple/macos-helper/Sources/AgentDeviceMacOSInput/MouseClickDelivery.swift +116 -0
  12. package/apple/macos-helper/Sources/AgentDeviceMacOSInput/MouseClickSchedule.swift +61 -0
  13. package/apple/macos-helper/Tests/AgentDeviceMacOSDeviceHubTests/DeviceHubPoseTests.swift +30 -0
  14. package/apple/macos-helper/Tests/AgentDeviceMacOSInputTests/MouseClickScheduleTests.swift +58 -0
  15. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.h +4 -0
  16. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.m +20 -0
  17. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerScrollViewportPolicy.swift +1 -2
  18. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+AXSnapshotFallback.swift +25 -12
  19. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +56 -1
  20. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandJournal.swift +1 -1
  21. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +36 -108
  22. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Keyboard.swift +241 -0
  23. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Lifecycle.swift +29 -0
  24. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +46 -0
  25. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+PrivateAXPresentation.swift +85 -26
  26. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +134 -117
  27. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotBackendCapabilities.swift +1 -3
  28. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCapturePlan.swift +25 -4
  29. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SystemModal.swift +1 -1
  30. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests.swift +3 -0
  31. package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotCoordinateSpace.swift +197 -0
  32. package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotModels.swift +30 -4
  33. package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotPresentation.swift +0 -81
  34. package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotPresentationInvariant.swift +1 -9
  35. package/dist/src/absence-observation-errors.js +1 -1
  36. package/dist/src/adapter.js +1 -1
  37. package/dist/src/adb-executor.js +2 -2
  38. package/dist/src/adb-failure.js +1 -1
  39. package/dist/src/adb-transport.js +1 -1
  40. package/dist/src/adb.js +1 -1
  41. package/dist/src/agent-browser-lifecycle.js +1 -1
  42. package/dist/src/agent-browser-process-record.js +1 -1
  43. package/dist/src/agent-browser-provider.js +1 -1
  44. package/dist/src/agent-browser-tool.js +1 -1
  45. package/dist/src/agent-device-client.js +2 -2
  46. package/dist/src/ai-sdk.js +1 -1
  47. package/dist/src/alert-runtime.js +1 -1
  48. package/dist/src/android-adb.d.ts +29 -2
  49. package/dist/src/android-adb.js +1 -1
  50. package/dist/src/android-input-ownership.js +1 -1
  51. package/dist/src/android.js +1 -1
  52. package/dist/src/app-catalog.js +1 -1
  53. package/dist/src/app-deployment-resolution.js +1 -1
  54. package/dist/src/app-helpers.js +1 -1
  55. package/dist/src/app-inventory.js +1 -1
  56. package/dist/src/app-launch.js +2 -2
  57. package/dist/src/app-lifecycle.js +2 -2
  58. package/dist/src/app-lifecycle2.js +2 -2
  59. package/dist/src/app-log-files.js +1 -1
  60. package/dist/src/app-log-runtime2.js +3 -3
  61. package/dist/src/app-resolution.js +2 -2
  62. package/dist/src/app-state.js +1 -1
  63. package/dist/src/apple-runner-platform.js +1 -1
  64. package/dist/src/application-lifecycle-interaction.js +1 -1
  65. package/dist/src/archive.js +1 -1
  66. package/dist/src/artifact-download.js +1 -1
  67. package/dist/src/auth-session.js +1 -1
  68. package/dist/src/auth.js +1 -1
  69. package/dist/src/back-mode.js +1 -1
  70. package/dist/src/backend-snapshot-options.js +1 -1
  71. package/dist/src/boot-diagnostics.js +1 -1
  72. package/dist/src/capture-disclosure.js +1 -0
  73. package/dist/src/capture.js +1 -1
  74. package/dist/src/cli-config.js +1 -1
  75. package/dist/src/cli-help.js +18 -2
  76. package/dist/src/cli-output.js +1 -1
  77. package/dist/src/cli.js +4 -4
  78. package/dist/src/click-button.js +1 -1
  79. package/dist/src/client-metro.js +1 -1
  80. package/dist/src/client-types.d.ts +65 -3
  81. package/dist/src/clipboard-shell-response.js +1 -0
  82. package/dist/src/command-schema.js +1 -1
  83. package/dist/src/command-tools.js +4 -2
  84. package/dist/src/command.js +1 -1
  85. package/dist/src/config.js +1 -1
  86. package/dist/src/connection-runtime.js +1 -1
  87. package/dist/src/connection.js +1 -1
  88. package/dist/src/contracts.d.ts +1 -1
  89. package/dist/src/contracts.js +1 -1
  90. package/dist/src/daemon-client-lifecycle.js +1 -1
  91. package/dist/src/daemon.js +1 -1
  92. package/dist/src/debug-symbols-facade.js +1 -1
  93. package/dist/src/device-boot.js +1 -1
  94. package/dist/src/device-claim-inspection.js +1 -1
  95. package/dist/src/device-claim-rule.js +2 -1
  96. package/dist/src/device-input-state.d.ts +5 -5
  97. package/dist/src/device-inventory-context.js +1 -1
  98. package/dist/src/device-rotation.js +1 -1
  99. package/dist/src/device-selection-resolver.js +1 -1
  100. package/dist/src/device-session.js +1 -1
  101. package/dist/src/device-shell.js +1 -0
  102. package/dist/src/device.js +1 -1
  103. package/dist/src/device2.js +1 -1
  104. package/dist/src/devicectl.js +1 -0
  105. package/dist/src/diagnostics.js +1 -1
  106. package/dist/src/dispatch-resolve.js +1 -1
  107. package/dist/src/display-inventory.js +1 -0
  108. package/dist/src/doctor-facade.js +1 -1
  109. package/dist/src/doctor2.js +1 -1
  110. package/dist/src/durable-resource.js +1 -1
  111. package/dist/src/engine-eval-script.js +1 -1
  112. package/dist/src/error.js +1 -1
  113. package/dist/src/exec.js +1 -1
  114. package/dist/src/file.js +1 -1
  115. package/dist/src/find.js +1 -1
  116. package/dist/src/finders.js +1 -1
  117. package/dist/src/format.js +2 -1
  118. package/dist/src/generic.js +1 -1
  119. package/dist/src/gesture-admission.js +1 -1
  120. package/dist/src/gesture-plan.js +1 -1
  121. package/dist/src/gesture-runtime.js +1 -1
  122. package/dist/src/harmonyos.js +1 -1
  123. package/dist/src/hdc.js +1 -1
  124. package/dist/src/helper.js +2 -2
  125. package/dist/src/host.js +1 -0
  126. package/dist/src/human-control-contract.js +1 -1
  127. package/dist/src/human-control.js +1 -1
  128. package/dist/src/index.d.ts +1 -1
  129. package/dist/src/index.js +1 -1
  130. package/dist/src/input-actions.js +1 -1
  131. package/dist/src/input-actions2.js +1 -1
  132. package/dist/src/install-artifact-facade.js +1 -1
  133. package/dist/src/install-source-network-transport.js +1 -1
  134. package/dist/src/install-source2.js +1 -1
  135. package/dist/src/interaction-positionals.js +1 -1
  136. package/dist/src/interaction-ref-policy.js +1 -1
  137. package/dist/src/interaction.js +1 -1
  138. package/dist/src/interaction2.js +1 -1
  139. package/dist/src/interactor-operation-binding.js +1 -0
  140. package/dist/src/interactor-operation-catalog.js +1 -1
  141. package/dist/src/interactor.js +4 -5
  142. package/dist/src/interactor2.js +1 -1
  143. package/dist/src/interactors.js +1 -1
  144. package/dist/src/internal/bin.js +1 -1
  145. package/dist/src/internal/daemon.js +2 -2
  146. package/dist/src/internal/png-worker.d.ts +9 -1
  147. package/dist/src/internal/png-worker.js +1 -1
  148. package/dist/src/internal/run-script-http-child.js +1 -1
  149. package/dist/src/inventory.js +4 -4
  150. package/dist/src/inventory2.js +1 -1
  151. package/dist/src/inventory3.js +2 -2
  152. package/dist/src/inventory5.js +1 -1
  153. package/dist/src/ios-snapshot-acquisition.js +1 -1
  154. package/dist/src/ios-snapshot-runtime.js +1 -1
  155. package/dist/src/ios-target-activation.js +1 -0
  156. package/dist/src/lease-context.js +1 -1
  157. package/dist/src/lease-scope.js +1 -1
  158. package/dist/src/lease.js +1 -1
  159. package/dist/src/limrun-download-file.js +1 -0
  160. package/dist/src/limrun-runtime-dependencies.js +1 -1
  161. package/dist/src/limrun.d.ts +10 -4
  162. package/dist/src/linux.js +1 -1
  163. package/dist/src/local-interactor-operation-set.js +1 -1
  164. package/dist/src/location-coordinates.js +1 -1
  165. package/dist/src/macos-facade.js +1 -1
  166. package/dist/src/managed-device-scope.js +1 -1
  167. package/dist/src/mechanics.js +17 -16
  168. package/dist/src/mobile-snapshot-semantics.js +1 -1
  169. package/dist/src/multitouch-support.js +1 -1
  170. package/dist/src/observation.js +2 -2
  171. package/dist/src/output-common.js +5 -2
  172. package/dist/src/parameterized-recorded-fill.js +1 -1
  173. package/dist/src/perf-facade.js +2 -2
  174. package/dist/src/perf-runtime-operation-builder.js +1 -1
  175. package/dist/src/perf-runtime-plan.js +1 -1
  176. package/dist/src/perf.js +1 -1
  177. package/dist/src/physical-device-control.js +1 -1
  178. package/dist/src/platform-request-scope.js +1 -1
  179. package/dist/src/platform-runtime-android-adb-host.js +1 -1
  180. package/dist/src/platform-runtime-host.js +1 -1
  181. package/dist/src/platform-runtime-managed-owner.js +1 -1
  182. package/dist/src/platform-runtime-open-target.js +1 -1
  183. package/dist/src/platform-runtime-operation-host.js +4 -4
  184. package/dist/src/platform-runtime-runtime-hints.js +2 -2
  185. package/dist/src/platform-runtime-screen-recording-android-host.js +1 -1
  186. package/dist/src/platform-runtime-screen-recording-apple-runner-transport.js +1 -1
  187. package/dist/src/platform-runtime-screen-recording-apple-simulator-host.js +1 -1
  188. package/dist/src/platform-runtime-screen-recording-apple-transport.js +1 -1
  189. package/dist/src/platform-runtime-screen-recording-finalizer-host.js +1 -1
  190. package/dist/src/platform-runtime-screen-recording-harmony-host.js +1 -1
  191. package/dist/src/platform-runtime-screen-recording-process-host.js +1 -1
  192. package/dist/src/platform-runtime-unavailable.js +1 -1
  193. package/dist/src/platform-runtime.js +1 -1
  194. package/dist/src/platform-runtime2.js +1 -1
  195. package/dist/src/png-crop-bytes.js +1 -1
  196. package/dist/src/png-worker-client.js +1 -0
  197. package/dist/src/png.js +1 -1
  198. package/dist/src/prepare-kind.js +1 -1
  199. package/dist/src/provider-session-ownership.js +1 -1
  200. package/dist/src/provider-webdriver.js +1 -1
  201. package/dist/src/proxy.js +1 -1
  202. package/dist/src/quality-warnings.js +1 -1
  203. package/dist/src/react-native.js +1 -1
  204. package/dist/src/record-runtime.js +1 -1
  205. package/dist/src/record-trace.js +1 -1
  206. package/dist/src/rect-center.js +1 -1
  207. package/dist/src/register-builtins.js +1 -1
  208. package/dist/src/registry.js +35 -35
  209. package/dist/src/remote-config2.js +1 -1
  210. package/dist/src/replay-divergence.js +1 -1
  211. package/dist/src/replay.js +1 -1
  212. package/dist/src/reporting.js +1 -1
  213. package/dist/src/request-admission.js +1 -1
  214. package/dist/src/request-cancel.js +1 -1
  215. package/dist/src/request-runtime-binding.js +1 -1
  216. package/dist/src/result-serialization.js +1 -1
  217. package/dist/src/retry.js +1 -1
  218. package/dist/src/runner-cache-metadata.js +2 -2
  219. package/dist/src/runner-client.js +1 -1
  220. package/dist/src/runner-contract.js +3 -0
  221. package/dist/src/runner-dev-tools-security.js +1 -0
  222. package/dist/src/runner-device-readiness.js +1 -0
  223. package/dist/src/runner-disposal.js +1 -1
  224. package/dist/src/runner-operations-facade.js +1 -1
  225. package/dist/src/runner-presentation.js +1 -1
  226. package/dist/src/runner.js +1 -1
  227. package/dist/src/runtime-transport-hints.js +1 -1
  228. package/dist/src/runtime.js +3 -3
  229. package/dist/src/runtime10.js +1 -1
  230. package/dist/src/runtime2.js +4 -4
  231. package/dist/src/runtime3.js +1 -1
  232. package/dist/src/runtime4.js +5 -5
  233. package/dist/src/runtime5.js +1 -1
  234. package/dist/src/runtime6.js +1 -1
  235. package/dist/src/runtime7.js +1 -1
  236. package/dist/src/runtime8.js +1 -1
  237. package/dist/src/runtime9.js +1 -1
  238. package/dist/src/screen-recording-admission-ledger.js +1 -0
  239. package/dist/src/screen-recording-completion.js +1 -1
  240. package/dist/src/screen-recording-options.js +1 -1
  241. package/dist/src/screen-recording-resource-recovery.js +1 -1
  242. package/dist/src/screen-recording-transport.js +1 -0
  243. package/dist/src/screenshot-density.js +1 -1
  244. package/dist/src/screenshot-image.js +1 -0
  245. package/dist/src/screenshot-runtime.js +1 -1
  246. package/dist/src/screenshot.js +1 -1
  247. package/dist/src/screenshot3.js +1 -1
  248. package/dist/src/script.js +1 -1
  249. package/dist/src/scroll-command.js +1 -1
  250. package/dist/src/scroll-gesture.js +1 -1
  251. package/dist/src/sdk-batch-runner.js +2 -2
  252. package/dist/src/sdk-batch.js +2 -2
  253. package/dist/src/sdk-contracts.d.ts +76 -1
  254. package/dist/src/sdk-contracts.js +2 -2
  255. package/dist/src/sdk-device.js +1 -1
  256. package/dist/src/sdk-finders.d.ts +1 -1
  257. package/dist/src/sdk-finders.js +1 -1
  258. package/dist/src/sdk-io.js +1 -1
  259. package/dist/src/sdk-remote-config.js +1 -1
  260. package/dist/src/sdk-selectors.d.ts +29 -3
  261. package/dist/src/sdk-selectors.js +1 -1
  262. package/dist/src/selection.js +0 -0
  263. package/dist/src/selector-runtime.js +1 -1
  264. package/dist/src/selectors.js +1 -1
  265. package/dist/src/semantic-index.js +1 -1
  266. package/dist/src/server.js +1 -1
  267. package/dist/src/session-allocation.js +1 -1
  268. package/dist/src/session-observation.js +1 -1
  269. package/dist/src/session-routing.js +1 -1
  270. package/dist/src/session-runtime-admission.js +1 -1
  271. package/dist/src/session-snapshot.js +1 -1
  272. package/dist/src/session-store.js +3 -3
  273. package/dist/src/session2.js +4 -5
  274. package/dist/src/settings.js +1 -1
  275. package/dist/src/simctl-facade.js +1 -1
  276. package/dist/src/simctl.js +1 -1
  277. package/dist/src/simulator-boot.js +1 -1
  278. package/dist/src/simulator-facade.js +1 -1
  279. package/dist/src/simulator.js +1 -1
  280. package/dist/src/snapshot-capture-annotations.js +1 -1
  281. package/dist/src/snapshot-diagnostics.js +1 -1
  282. package/dist/src/snapshot-quality-backend-capabilities.js +1 -1
  283. package/dist/src/snapshot-runtime-binding.js +1 -1
  284. package/dist/src/snapshot-runtime.js +1 -1
  285. package/dist/src/snapshot-state.js +1 -1
  286. package/dist/src/snapshot.js +1 -1
  287. package/dist/src/snapshot2.js +1 -1
  288. package/dist/src/snapshot3.js +1 -1
  289. package/dist/src/snapshot4.js +1 -1
  290. package/dist/src/src.js +1 -1
  291. package/dist/src/src4.js +1 -1
  292. package/dist/src/src7.js +1 -1
  293. package/dist/src/src8.js +2 -2
  294. package/dist/src/stop-sequence.js +1 -1
  295. package/dist/src/string-enum.js +1 -1
  296. package/dist/src/takeover.js +1 -1
  297. package/dist/src/text-entry-focus.js +1 -1
  298. package/dist/src/tool-provider.js +1 -1
  299. package/dist/src/tool-provider2.js +1 -1
  300. package/dist/src/touch-runtime.js +1 -1
  301. package/dist/src/transport.js +1 -1
  302. package/dist/src/tree.js +1 -1
  303. package/dist/src/tv-remote.js +1 -1
  304. package/dist/src/type-text-runtime.js +1 -1
  305. package/dist/src/verified-file.js +1 -1
  306. package/dist/src/video.js +1 -1
  307. package/dist/src/viewport.js +1 -1
  308. package/dist/src/web.js +1 -1
  309. package/dist/src/web2.js +1 -1
  310. package/dist/src/webdriver-source.js +1 -1
  311. package/dist/src/window-state.js +1 -1
  312. package/package.json +4 -1
  313. package/server.json +2 -2
  314. package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.6.apk.sha256 +0 -1
  315. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.6.apk.sha256 +0 -1
  316. package/dist/src/session-target-evidence.js +0 -1
  317. package/dist/src/vars.js +0 -2
@@ -12,10 +12,24 @@ extension RunnerTests {
12
12
  private static let rawSnapshotMaxNodes = 5_000
13
13
  private static let rawSnapshotTooLargeHint =
14
14
  "Raw iOS snapshot exceeded the runner payload guard. Use regular snapshot for visible UI, or scope/depth-limit raw snapshot when inspecting a large accessibility tree."
15
+
16
+
17
+ private static let regularSnapshotMaxNodes = 50_000
18
+ private static let regularSnapshotTooLargeCode = "IOS_SNAPSHOT_TOO_LARGE"
19
+ private static let regularSnapshotTooLargeHint =
20
+ "iOS snapshot walked an unexpectedly large accessibility tree. Scope the snapshot to a subtree or use screenshot."
15
21
  struct SnapshotTraversalContext {
16
22
  let queryRoot: XCUIElement
17
23
  let rootSnapshot: XCUIElementSnapshot
18
24
  let viewport: CGRect
25
+
26
+ let interfaceOrientation: Int
27
+
28
+
29
+
30
+
31
+
32
+ let keyboardBand: RunnerKeyboardBandFact?
19
33
  }
20
34
 
21
35
  private struct SnapshotEvaluation {
@@ -30,8 +44,16 @@ extension RunnerTests {
30
44
  let snapshot: XCUIElementSnapshot
31
45
  let depth: Int
32
46
  let parentIndex: Int?
33
- let parentPresentedDepth: Int
34
- let parentTraversal: SnapshotVisibilityFold.TraversalState
47
+ }
48
+
49
+
50
+
51
+
52
+
53
+
54
+ static func canDescendAtRawDepth(_ depth: Int, hint: CaptureHint) -> Bool {
55
+ guard let rawLimit = hint.rawTraversalDepth else { return true }
56
+ return depth < rawLimit
35
57
  }
36
58
 
37
59
  struct SnapshotCaptureFailure: Error {
@@ -116,6 +138,13 @@ extension RunnerTests {
116
138
 
117
139
 
118
140
 
141
+ static let keyboardBandProbeBudget: TimeInterval = 0.3
142
+
143
+
144
+
145
+
146
+
147
+
119
148
  func snapshotFast(app: XCUIApplication, options: PresentationOptions) throws -> DataPayload {
120
149
  let deadline = Date().addingTimeInterval(Self.snapshotPlanBudget)
121
150
  if let blocking = boundedBlockingSystemAlertSnapshot(deadline: deadline) {
@@ -133,7 +162,7 @@ extension RunnerTests {
133
162
  func recursiveTreeSnapshotAcquisition(
134
163
  context: SnapshotTraversalContext,
135
164
  hint: CaptureHint
136
- ) -> SnapshotAcquisition {
165
+ ) throws -> SnapshotAcquisition {
137
166
  var cachedDescendantElements: [XCUIElement]?
138
167
  func collapsedTabDescendants() -> [XCUIElement] {
139
168
  if let cachedDescendantElements {
@@ -149,54 +178,37 @@ extension RunnerTests {
149
178
 
150
179
 
151
180
 
152
-
153
-
154
181
  var nodes: [RawAXNode] = []
155
- let rootEvaluation = evaluateSnapshot(context.rootSnapshot)
156
182
  nodes.append(
157
183
  makeSnapshotNode(
158
184
  snapshot: context.rootSnapshot,
159
- evaluation: rootEvaluation,
185
+ evaluation: evaluateSnapshot(context.rootSnapshot),
160
186
  depth: 0,
161
187
  index: 0,
162
- parentIndex: nil,
163
- viewport: context.viewport
188
+ parentIndex: nil
164
189
  )
165
190
  )
166
- let shouldVisitRootChildren = SnapshotPresentation.shouldAcquireChildren(
167
- for: hint,
168
- rawDepth: 0,
169
- regularPresentedDepth: 0
170
- )
171
- if shouldVisitRootChildren {
191
+ if Self.canDescendAtRawDepth(0, hint: hint) {
172
192
  appendCollapsedTabFallbackNodes(
173
193
  to: &nodes,
174
194
  containerSnapshot: context.rootSnapshot,
175
195
  resolveElements: collapsedTabDescendants,
176
196
  depth: 1,
177
- parentIndex: 0,
178
- viewport: context.viewport
197
+ parentIndex: 0
179
198
  )
180
199
  }
181
200
 
182
201
  var seen = Set<String>()
183
202
  var stack: [SnapshotTraversalEntry] = []
184
- if shouldVisitRootChildren {
203
+ if Self.canDescendAtRawDepth(0, hint: hint) {
185
204
  stack = context.rootSnapshot.children.map {
186
- SnapshotTraversalEntry(
187
- snapshot: $0,
188
- depth: 1,
189
- parentIndex: 0,
190
- parentPresentedDepth: 0,
191
- parentTraversal: .root
192
- )
205
+ SnapshotTraversalEntry(snapshot: $0, depth: 1, parentIndex: 0)
193
206
  }
194
207
  }
195
208
 
196
209
  while let entry = stack.popLast() {
197
210
  let snapshot = entry.snapshot
198
211
  let depth = entry.depth
199
- let parentIndex = entry.parentIndex
200
212
  if let limit = hint.rawTraversalDepth, depth > limit { continue }
201
213
 
202
214
  let evaluation = evaluateSnapshot(snapshot)
@@ -205,8 +217,7 @@ extension RunnerTests {
205
217
  evaluation: evaluation,
206
218
  depth: depth,
207
219
  index: nodes.count,
208
- parentIndex: parentIndex,
209
- viewport: context.viewport
220
+ parentIndex: entry.parentIndex
210
221
  )
211
222
  let key = Self.snapshotTraversalIdentity(
212
223
  elementType: snapshot.elementType,
@@ -219,43 +230,28 @@ extension RunnerTests {
219
230
  seen.insert(key)
220
231
  }
221
232
 
222
- let currentIndex = !isDuplicate ? nodes.count : parentIndex
223
- let transition = SnapshotPresentation.regularTraversalTransition(
224
- for: node,
225
- parentPresentedDepth: entry.parentPresentedDepth,
226
- parentTraversal: entry.parentTraversal,
227
- hint: hint,
228
- rawDepth: depth,
229
- viewport: context.viewport,
230
- hasChildren: !snapshot.children.isEmpty,
231
- isDuplicate: isDuplicate,
232
- policy: .platformDefault
233
- )
234
- if transition.shouldVisitChildren {
235
- for child in snapshot.children.reversed() {
236
- stack.append(
237
- SnapshotTraversalEntry(
238
- snapshot: child,
239
- depth: depth + 1,
240
- parentIndex: currentIndex,
241
- parentPresentedDepth: transition.presentedDepth,
242
- parentTraversal: transition.traversal
243
- )
244
- )
245
- }
233
+
234
+
235
+ let currentIndex = isDuplicate ? entry.parentIndex : nodes.count
236
+ for child in snapshot.children.reversed() {
237
+ stack.append(
238
+ SnapshotTraversalEntry(snapshot: child, depth: depth + 1, parentIndex: currentIndex)
239
+ )
246
240
  }
247
241
 
248
242
  if isDuplicate { continue }
249
243
 
250
244
  nodes.append(node)
251
- if transition.shouldVisitChildren {
245
+ if nodes.count > Self.regularSnapshotMaxNodes {
246
+ throw regularSnapshotTooLargeFailure(nodeCount: nodes.count)
247
+ }
248
+ if Self.canDescendAtRawDepth(depth, hint: hint) {
252
249
  appendCollapsedTabFallbackNodes(
253
250
  to: &nodes,
254
251
  containerSnapshot: snapshot,
255
252
  resolveElements: collapsedTabDescendants,
256
253
  depth: depth + 1,
257
- parentIndex: node.index,
258
- viewport: context.viewport
254
+ parentIndex: node.index
259
255
  )
260
256
  }
261
257
  }
@@ -265,7 +261,8 @@ extension RunnerTests {
265
261
  nodes: nodes,
266
262
  truncated: false,
267
263
  effectiveDepth: nil,
268
- viewport: context.viewport
264
+ viewport: context.viewport,
265
+ interfaceOrientation: context.interfaceOrientation
269
266
  )
270
267
  }
271
268
 
@@ -366,7 +363,11 @@ extension RunnerTests {
366
363
  ) throws -> SnapshotAcquisition {
367
364
  var nodes: [RawAXNode] = []
368
365
 
369
- func walk(_ snapshot: XCUIElementSnapshot, depth: Int, parentIndex: Int?) throws {
366
+ func walk(
367
+ _ snapshot: XCUIElementSnapshot,
368
+ depth: Int,
369
+ parentIndex: Int?
370
+ ) throws {
370
371
  if let limit = hint.rawTraversalDepth, depth > limit { return }
371
372
 
372
373
  let evaluation = evaluateSnapshot(snapshot)
@@ -380,24 +381,32 @@ extension RunnerTests {
380
381
  evaluation: evaluation,
381
382
  depth: depth,
382
383
  index: currentIndex,
383
- parentIndex: parentIndex,
384
- viewport: context.viewport
384
+ parentIndex: parentIndex
385
385
  )
386
386
  )
387
387
 
388
388
  let children = snapshot.children
389
389
  for child in children {
390
- try walk(child, depth: depth + 1, parentIndex: currentIndex)
390
+ try walk(
391
+ child,
392
+ depth: depth + 1,
393
+ parentIndex: currentIndex
394
+ )
391
395
  }
392
396
  }
393
397
 
394
- try walk(context.rootSnapshot, depth: 0, parentIndex: nil)
398
+ try walk(
399
+ context.rootSnapshot,
400
+ depth: 0,
401
+ parentIndex: nil
402
+ )
395
403
  return SnapshotAcquisition(
396
404
  hint: hint,
397
405
  nodes: nodes,
398
406
  truncated: false,
399
407
  effectiveDepth: nil,
400
- viewport: context.viewport
408
+ viewport: context.viewport,
409
+ interfaceOrientation: context.interfaceOrientation
401
410
  )
402
411
  }
403
412
 
@@ -415,7 +424,8 @@ extension RunnerTests {
415
424
  nodes: nodes,
416
425
  truncated: false,
417
426
  effectiveDepth: nil,
418
- viewport: .infinite
427
+ viewport: .infinite,
428
+ interfaceOrientation: RunnerInterfaceOrientation.unknown
419
429
  )
420
430
  }
421
431
 
@@ -436,12 +446,7 @@ extension RunnerTests {
436
446
  truncated = true
437
447
  break
438
448
  }
439
- guard let node = flatSnapshotNode(
440
- element: element,
441
- index: 0,
442
- parentIndex: 0,
443
- viewport: viewport
444
- ) else {
449
+ guard let node = flatSnapshotNode(element: element, index: 0, parentIndex: 0) else {
445
450
  continue
446
451
  }
447
452
  let key = "\(node.type)-\(node.label ?? "")-\(node.identifier ?? "")-\(node.value ?? "")-\(node.rect.x)-\(node.rect.y)-\(node.rect.width)-\(node.rect.height)"
@@ -491,7 +496,8 @@ extension RunnerTests {
491
496
  nodes: nodes,
492
497
  truncated: truncated,
493
498
  effectiveDepth: nil,
494
- viewport: viewport
499
+ viewport: viewport,
500
+ interfaceOrientation: RunnerInterfaceOrientation.unknown
495
501
  )
496
502
  }
497
503
 
@@ -529,6 +535,14 @@ extension RunnerTests {
529
535
  )
530
536
  }
531
537
 
538
+ private func regularSnapshotTooLargeFailure(nodeCount: Int) -> SnapshotCaptureFailure {
539
+ SnapshotCaptureFailure(
540
+ code: Self.regularSnapshotTooLargeCode,
541
+ message: "iOS snapshot exceeded \(Self.regularSnapshotMaxNodes) nodes while walking node \(nodeCount).",
542
+ hint: Self.regularSnapshotTooLargeHint
543
+ )
544
+ }
545
+
532
546
  func sparseTruncatedSnapshotPayload(
533
547
  message: String? = nil,
534
548
  snapshotQuality: SnapshotQuality? = nil,
@@ -793,7 +807,7 @@ extension RunnerTests {
793
807
  label: nil,
794
808
  identifier: nil,
795
809
  value: nil,
796
- rect: snapshotRect(from: rect),
810
+ rect: SnapshotRect(rect),
797
811
  enabled: true,
798
812
  focused: nil,
799
813
  selected: nil,
@@ -814,15 +828,6 @@ extension RunnerTests {
814
828
  return CGRect(x: 0, y: 0, width: max(1, maxX), height: max(1, maxY))
815
829
  }
816
830
 
817
- func snapshotRect(from frame: CGRect) -> SnapshotRect {
818
- return SnapshotRect(
819
- x: Double(frame.origin.x),
820
- y: Double(frame.origin.y),
821
- width: Double(frame.size.width),
822
- height: Double(frame.size.height)
823
- )
824
- }
825
-
826
831
 
827
832
 
828
833
  func makeSnapshotTraversalContext(
@@ -831,24 +836,40 @@ extension RunnerTests {
831
836
  captureDeadline: Date = .distantFuture,
832
837
  treeCaptureSliceBudgetOverride: TimeInterval? = nil
833
838
  ) throws -> SnapshotTraversalContext? {
834
- let viewport = try runMainThreadWork(
839
+
840
+
841
+
842
+ let geometry = try runMainThreadWork(
835
843
  "snapshot_viewport",
836
844
  timeout: min(1.0, max(0.1, captureDeadline.timeIntervalSinceNow)),
837
845
  timeoutError: snapshotMainThreadTimeoutError("preparing tree snapshot")
838
846
  ) {
839
- self.safeSnapshotViewport(app: app)
847
+ (
848
+ viewport: self.safeSnapshotViewport(app: app),
849
+ interfaceOrientation: self.capturedInterfaceOrientation(app: app)
850
+ )
840
851
  }
841
-
852
+ let viewport = geometry.viewport
853
+ let interfaceOrientation = geometry.interfaceOrientation
842
854
  let treeSliceBudget = treeCaptureSliceBudgetOverride ?? treeCaptureSliceBudget
843
855
  let slice = min(treeSliceBudget, max(0.5, captureDeadline.timeIntervalSinceNow))
844
856
  guard let rootSnapshot = try captureSnapshotRootBounded(app, sliceSeconds: slice) else {
845
857
  return nil
846
858
  }
847
859
 
860
+
861
+
862
+
863
+
864
+
865
+ let keyboardBand = captureKeyboardBandFact(app: app, deadline: captureDeadline)
866
+
848
867
  return SnapshotTraversalContext(
849
868
  queryRoot: app,
850
869
  rootSnapshot: rootSnapshot,
851
- viewport: viewport
870
+ viewport: viewport,
871
+ interfaceOrientation: interfaceOrientation,
872
+ keyboardBand: keyboardBand
852
873
  )
853
874
  }
854
875
 
@@ -972,24 +993,21 @@ extension RunnerTests {
972
993
  evaluation: SnapshotEvaluation,
973
994
  depth: Int,
974
995
  index: Int,
975
- parentIndex: Int?,
976
- viewport: CGRect
996
+ parentIndex: Int?
977
997
  ) -> RawAXNode {
998
+
999
+
978
1000
  return RawAXNode(
979
1001
  index: index,
980
1002
  type: elementTypeName(snapshot.elementType),
981
1003
  label: evaluation.label.isEmpty ? nil : evaluation.label,
982
1004
  identifier: evaluation.identifier.isEmpty ? nil : evaluation.identifier,
983
1005
  value: evaluation.valueText,
984
- rect: snapshotRect(from: snapshot.frame),
1006
+ rect: SnapshotRect(snapshot.frame),
985
1007
  enabled: snapshot.isEnabled,
986
1008
  focused: evaluation.focused ? true : nil,
987
1009
  selected: evaluation.selected ? true : nil,
988
- hittable: parentIndex != nil && SnapshotGeometry.isGeometricallyActionable(
989
- enabled: snapshot.isEnabled,
990
- frame: snapshot.frame,
991
- viewport: viewport
992
- ),
1010
+ hittable: false,
993
1011
  depth: depth,
994
1012
  parentIndex: parentIndex,
995
1013
  hiddenContentAbove: nil,
@@ -997,6 +1015,14 @@ extension RunnerTests {
997
1015
  )
998
1016
  }
999
1017
 
1018
+
1019
+
1020
+ func capturedInterfaceOrientation(app: XCUIApplication) -> Int {
1021
+ safely("SNAPSHOT_INTERFACE_ORIENTATION", RunnerInterfaceOrientation.unknown) {
1022
+ Int(RunnerSynthesizedGesture.interfaceOrientation(forApplication: app))
1023
+ }
1024
+ }
1025
+
1000
1026
  private func snapshotValueText(_ snapshot: XCUIElementSnapshot) -> String? {
1001
1027
  guard let value = snapshot.value else { return nil }
1002
1028
  let text = String(describing: value).trimmingCharacters(in: .whitespacesAndNewlines)
@@ -1042,16 +1068,14 @@ extension RunnerTests {
1042
1068
  containerSnapshot: XCUIElementSnapshot,
1043
1069
  resolveElements: () -> [XCUIElement],
1044
1070
  depth: Int,
1045
- parentIndex: Int,
1046
- viewport: CGRect
1071
+ parentIndex: Int
1047
1072
  ) {
1048
1073
  let fallbackNodes = collapsedTabFallbackNodes(
1049
1074
  for: containerSnapshot,
1050
1075
  resolveElements: resolveElements,
1051
1076
  startingIndex: nodes.count,
1052
1077
  depth: depth,
1053
- parentIndex: parentIndex,
1054
- viewport: viewport
1078
+ parentIndex: parentIndex
1055
1079
  )
1056
1080
  nodes.append(contentsOf: fallbackNodes)
1057
1081
  }
@@ -1061,10 +1085,13 @@ extension RunnerTests {
1061
1085
  resolveElements: () -> [XCUIElement],
1062
1086
  startingIndex: Int,
1063
1087
  depth: Int,
1064
- parentIndex: Int,
1065
- viewport: CGRect
1088
+ parentIndex: Int
1066
1089
  ) -> [RawAXNode] {
1067
1090
  if !containerSnapshot.children.isEmpty { return [] }
1091
+
1092
+
1093
+
1094
+
1068
1095
  guard shouldExpandCollapsedTabContainer(containerSnapshot) else { return [] }
1069
1096
  let containerFrame = containerSnapshot.frame
1070
1097
  if containerFrame.isNull || containerFrame.isEmpty { return [] }
@@ -1076,8 +1103,7 @@ extension RunnerTests {
1076
1103
  collapsedTabCandidateNode(
1077
1104
  element: element,
1078
1105
  containerSnapshot: containerSnapshot,
1079
- containerFrame: containerFrame,
1080
- viewport: viewport
1106
+ containerFrame: containerFrame
1081
1107
  )
1082
1108
  }
1083
1109
  .sorted { left, right in
@@ -1125,8 +1151,7 @@ extension RunnerTests {
1125
1151
  private func collapsedTabCandidateNode(
1126
1152
  element: XCUIElement,
1127
1153
  containerSnapshot: XCUIElementSnapshot,
1128
- containerFrame: CGRect,
1129
- viewport: CGRect
1154
+ containerFrame: CGRect
1130
1155
  ) -> RawAXNode? {
1131
1156
  var node: RawAXNode?
1132
1157
  let exceptionMessage = RunnerObjCExceptionCatcher.catchException({
@@ -1156,21 +1181,19 @@ extension RunnerTests {
1156
1181
  return
1157
1182
  }
1158
1183
 
1184
+
1185
+
1159
1186
  node = RawAXNode(
1160
1187
  index: 0,
1161
1188
  type: elementTypeName(elementType),
1162
1189
  label: label.isEmpty ? nil : label,
1163
1190
  identifier: identifier.isEmpty ? nil : identifier,
1164
1191
  value: valueText,
1165
- rect: snapshotRect(from: frame),
1192
+ rect: SnapshotRect(frame),
1166
1193
  enabled: element.isEnabled,
1167
1194
  focused: elementHasFocus(element) ? true : nil,
1168
1195
  selected: element.isSelected ? true : nil,
1169
- hittable: SnapshotGeometry.isGeometricallyActionable(
1170
- enabled: element.isEnabled,
1171
- frame: frame,
1172
- viewport: viewport
1173
- ),
1196
+ hittable: false,
1174
1197
  depth: 0,
1175
1198
  parentIndex: nil,
1176
1199
  hiddenContentAbove: nil,
@@ -1295,8 +1318,7 @@ extension RunnerTests {
1295
1318
  private func flatSnapshotNode(
1296
1319
  element: XCUIElement,
1297
1320
  index: Int,
1298
- parentIndex: Int?,
1299
- viewport: CGRect
1321
+ parentIndex: Int?
1300
1322
  ) -> RawAXNode? {
1301
1323
  var node: RawAXNode?
1302
1324
  let exceptionMessage = RunnerObjCExceptionCatcher.catchException({
@@ -1310,11 +1332,6 @@ extension RunnerTests {
1310
1332
  let valueText = snapshotValueText(element)
1311
1333
  let elementType = element.elementType
1312
1334
  let enabled = element.isEnabled
1313
- let hittable = SnapshotGeometry.isGeometricallyActionable(
1314
- enabled: enabled,
1315
- frame: frame,
1316
- viewport: viewport
1317
- )
1318
1335
 
1319
1336
  node = RawAXNode(
1320
1337
  index: index,
@@ -1322,11 +1339,11 @@ extension RunnerTests {
1322
1339
  label: label.isEmpty ? nil : label,
1323
1340
  identifier: identifier.isEmpty ? nil : identifier,
1324
1341
  value: valueText,
1325
- rect: snapshotRect(from: frame),
1342
+ rect: SnapshotRect(frame),
1326
1343
  enabled: enabled,
1327
1344
  focused: elementHasFocus(element) ? true : nil,
1328
1345
  selected: element.isSelected ? true : nil,
1329
- hittable: hittable,
1346
+ hittable: false,
1330
1347
  depth: 1,
1331
1348
  parentIndex: parentIndex,
1332
1349
  hiddenContentAbove: nil,
@@ -11,8 +11,6 @@ enum SnapshotBackendEnvironment {
11
11
 
12
12
  enum SnapshotRegularDepthCapability: String {
13
13
 
14
- case presentedFrontier = "presented-frontier"
15
-
16
14
 
17
15
  case flat
18
16
 
@@ -63,7 +61,7 @@ enum SnapshotBackendKind: String, CaseIterable {
63
61
  var regularDepthCapability: SnapshotRegularDepthCapability {
64
62
  switch self {
65
63
  case .recursiveTree:
66
- return .presentedFrontier
64
+ return .presentationCut
67
65
  case .querySweep:
68
66
  return .flat
69
67
  case .privateAX:
@@ -62,6 +62,10 @@ struct SnapshotBackendCapture {
62
62
  var customActions: SnapshotCustomActionCoverage? = nil
63
63
  var qualityPayload: DataPayload? = nil
64
64
  var timing: SnapshotCaptureTiming? = nil
65
+
66
+
67
+
68
+ var keyboardBand: KeyboardBandFactPayload? = nil
65
69
  }
66
70
 
67
71
  extension RunnerTests {
@@ -416,6 +420,9 @@ extension RunnerTests {
416
420
  let hint = SnapshotPresentation.captureHint(for: options)
417
421
  var timer = SnapshotPhaseTimer()
418
422
  let acquisition: SnapshotAcquisition?
423
+
424
+
425
+ var keyboardBand: RunnerKeyboardBandFact?
419
426
  do {
420
427
  acquisition = try timer.measure(.acquisition) {
421
428
  switch kind {
@@ -430,6 +437,7 @@ extension RunnerTests {
430
437
  else {
431
438
  return nil
432
439
  }
440
+ keyboardBand = context.keyboardBand
433
441
  return try self.runMainThreadWork(
434
442
  "tree_processing",
435
443
  timeout: min(self.treeCaptureSliceBudget, max(0.5, deadline.timeIntervalSinceNow)),
@@ -437,7 +445,7 @@ extension RunnerTests {
437
445
  ) {
438
446
  hint.isRaw
439
447
  ? try self.rawTreeSnapshotAcquisition(context: context, hint: hint)
440
- : self.recursiveTreeSnapshotAcquisition(context: context, hint: hint)
448
+ : try self.recursiveTreeSnapshotAcquisition(context: context, hint: hint)
441
449
  }
442
450
  case .querySweep:
443
451
  return try self.runMainThreadWork(
@@ -472,19 +480,30 @@ extension RunnerTests {
472
480
  )
473
481
  }
474
482
 
483
+
484
+
485
+
486
+ let normalizedAcquisition = acquisition.replacingNodes(
487
+ SnapshotGeometrySpace.normalized(
488
+ nodes: acquisition.nodes,
489
+ viewport: acquisition.viewport,
490
+ interfaceOrientation: acquisition.interfaceOrientation
491
+ )
492
+ )
493
+
475
494
  let presented: SnapshotBackendCapture
476
495
  do {
477
496
  presented = try timer.measure(.presentation) {
478
- guard let result = try SnapshotPresentation.present(acquisition, options: options) else {
497
+ guard let result = try SnapshotPresentation.present(normalizedAcquisition, options: options) else {
479
498
  NSLog(
480
499
  "AGENT_DEVICE_RUNNER_SNAPSHOT_PROJECTION_MISMATCH requested=%@ acquired=%@",
481
500
  hint.projection.rawValue,
482
- acquisition.hint.projection.rawValue
501
+ normalizedAcquisition.hint.projection.rawValue
483
502
  )
484
503
  throw Self.snapshotProjectionMismatchFailure(
485
504
  kind,
486
505
  requested: hint.projection,
487
- acquired: acquisition.hint.projection
506
+ acquired: normalizedAcquisition.hint.projection
488
507
  )
489
508
  }
490
509
  return Self.makeSnapshotBackendCapture(from: result)
@@ -503,6 +522,7 @@ extension RunnerTests {
503
522
 
504
523
  var capture = presented
505
524
  capture.timing = timer.timing
525
+ capture.keyboardBand = keyboardBand?.payload
506
526
  return SnapshotBackendAttempt(
507
527
  outcome: .captured(capture),
508
528
  timing: timer.timing
@@ -641,6 +661,7 @@ extension RunnerTests {
641
661
  return SnapshotQualityPayload(nodes: nodes, truncated: quality.truncated == true)
642
662
  },
643
663
  snapshotQuality: quality,
664
+ keyboard: capture.keyboardBand,
644
665
  runnerFatal: payload.runnerFatal,
645
666
  runnerFatalReason: payload.runnerFatalReason
646
667
  )
@@ -232,7 +232,7 @@ extension RunnerTests {
232
232
  label: label.isEmpty ? nil : label,
233
233
  identifier: identifier.isEmpty ? nil : identifier,
234
234
  value: nil,
235
- rect: snapshotRect(from: element.frame),
235
+ rect: SnapshotRect(element.frame),
236
236
  enabled: element.isEnabled,
237
237
  focused: nil,
238
238
  selected: nil,
@@ -57,6 +57,9 @@ final class RunnerTests: XCTestCase {
57
57
  var currentAppProcessIdentifier: Int?
58
58
 
59
59
 
60
+ var pendingTargetActivation: TargetActivationFactPayload?
61
+
62
+
60
63
 
61
64
 
62
65
  var textEntryTapWitness: TextEntryTapWitness?