agent-device 0.21.11 → 0.21.13

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 (201) hide show
  1. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.11.apk → agent-device-android-ime-helper-0.21.13.apk} +0 -0
  2. package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.13.apk.sha256 +1 -0
  3. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.11.manifest.json → agent-device-android-ime-helper-0.21.13.manifest.json} +4 -4
  4. package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.21.11.apk → agent-device-android-snapshot-helper-0.21.13.apk} +0 -0
  5. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.13.apk.sha256 +1 -0
  6. package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.21.11.manifest.json → agent-device-android-snapshot-helper-0.21.13.manifest.json} +6 -6
  7. package/apple/fold-helper/Fold.m +97 -0
  8. package/apple/macos-helper/Package.swift +3 -6
  9. package/apple/macos-helper/Sources/AgentDeviceMacOSHelper/main.swift +3 -8
  10. package/apple/macos-helper/Tests/AgentDeviceMacOSHelperTests/ScreenshotResponseTests.swift +15 -0
  11. package/apple/snapshot-bridge/SnapshotBridgeRuntime.m +47 -1
  12. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunner/AgentDeviceRunnerApp.m +99 -42
  13. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunner/Info.plist +23 -0
  14. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunner.xcodeproj/project.pbxproj +17 -0
  15. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAppScreenCapture.swift +21 -13
  16. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerScrollViewportPolicy.swift +1 -162
  17. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedGesture.h +0 -9
  18. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedGesture.m +0 -56
  19. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSystemSurfaceHostPolicy.swift +0 -48
  20. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTapPointPolicy.swift +0 -50
  21. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+AXSnapshotFallback.swift +22 -568
  22. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Alert.swift +21 -9
  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 +18 -2236
  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 +165 -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 +147 -95
  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 +287 -0
  38. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScrollGesture.swift +1 -200
  39. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SequenceExecution.swift +0 -185
  40. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +75 -285
  41. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotAcquisition.swift +23 -10
  42. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotBackendCapabilities.swift +0 -78
  43. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCapturePlan.swift +83 -578
  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 +27 -97
  49. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedInteraction.swift +1 -11
  50. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedTextEntry.swift +11 -87
  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 +142 -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/src/absence-observation-errors.js +1 -1
  62. package/dist/src/adapter.js +1 -1
  63. package/dist/src/agent-device-client.js +1 -1
  64. package/dist/src/alert-runtime.js +1 -1
  65. package/dist/src/android-adb.d.ts +1 -1
  66. package/dist/src/app-launch.js +2 -2
  67. package/dist/src/app-log-runtime2.js +3 -3
  68. package/dist/src/app-resolution.js +2 -2
  69. package/dist/src/back-mode.js +1 -1
  70. package/dist/src/capture-disclosure.js +1 -1
  71. package/dist/src/capture.js +1 -1
  72. package/dist/src/cli-config.js +1 -1
  73. package/dist/src/cli-help.js +10 -7
  74. package/dist/src/cli-runner.js +1 -1
  75. package/dist/src/cli.js +1 -1
  76. package/dist/src/client-types.d.ts +5 -8
  77. package/dist/src/code-signature.js +1 -1
  78. package/dist/src/command-schema.js +3 -3
  79. package/dist/src/command-tools.js +3 -3
  80. package/dist/src/connection.js +1 -1
  81. package/dist/src/daemon-client-lifecycle.js +1 -1
  82. package/dist/src/daemon-resolution.js +1 -1
  83. package/dist/src/device-claim-rule.js +2 -2
  84. package/dist/src/device-input-state.d.ts +1 -1
  85. package/dist/src/device-rotation.js +1 -1
  86. package/dist/src/device-session.js +1 -1
  87. package/dist/src/devicectl.js +1 -1
  88. package/dist/src/display-inventory.js +1 -1
  89. package/dist/src/doctor-facade.js +1 -1
  90. package/dist/src/find.js +1 -1
  91. package/dist/src/gesture-plan-types.d.ts +38 -0
  92. package/dist/src/harmonyos.js +1 -1
  93. package/dist/src/helper.js +2 -2
  94. package/dist/src/host.js +1 -1
  95. package/dist/src/install-source-network-transport.js +1 -1
  96. package/dist/src/install-source2.js +1 -1
  97. package/dist/src/interaction-ref-policy.js +1 -1
  98. package/dist/src/interaction2.js +1 -1
  99. package/dist/src/interactor-operation-catalog.js +1 -1
  100. package/dist/src/interactor.js +4 -4
  101. package/dist/src/interactor2.js +1 -1
  102. package/dist/src/internal/bin.js +1 -1
  103. package/dist/src/internal/daemon.js +2 -2
  104. package/dist/src/inventory2.js +1 -1
  105. package/dist/src/ios-snapshot-acquisition.js +1 -1
  106. package/dist/src/ios-snapshot-runtime.js +1 -1
  107. package/dist/src/limrun-runtime-dependencies.js +1 -1
  108. package/dist/src/limrun.d.ts +435 -4
  109. package/dist/src/linux.js +1 -1
  110. package/dist/src/local-interactor-operation-set.js +1 -1
  111. package/dist/src/macos-facade.js +1 -1
  112. package/dist/src/managed-device-scope.js +1 -1
  113. package/dist/src/mechanics.js +4 -4
  114. package/dist/src/mobile-snapshot-semantics.js +1 -1
  115. package/dist/src/perf-facade.js +1 -2
  116. package/dist/src/perf-runtime-plan.js +1 -1
  117. package/dist/src/perf-target.js +2 -0
  118. package/dist/src/physical-device-apps.js +1 -0
  119. package/dist/src/physical-device-control.js +1 -1
  120. package/dist/src/platform-request-scope.js +1 -1
  121. package/dist/src/platform-runtime-operation-host.js +1 -1
  122. package/dist/src/platform-runtime-screen-recording-finalizer-host.js +1 -1
  123. package/dist/src/platform-runtime-unavailable.js +1 -1
  124. package/dist/src/platform-runtime.js +1 -1
  125. package/dist/src/platform-runtime2.js +1 -1
  126. package/dist/src/provider-webdriver.js +1 -1
  127. package/dist/src/proxy.js +1 -1
  128. package/dist/src/quality-warnings.js +1 -1
  129. package/dist/src/react-native.js +1 -1
  130. package/dist/src/record-runtime.js +1 -1
  131. package/dist/src/registry.js +35 -35
  132. package/dist/src/request-admission.js +1 -1
  133. package/dist/src/request-runtime-binding.js +1 -1
  134. package/dist/src/runner-client.js +1 -1
  135. package/dist/src/runner-dev-tools-security.js +1 -1
  136. package/dist/src/runner-device-readiness.js +1 -1
  137. package/dist/src/runner-disposal.js +1 -1
  138. package/dist/src/runner-error-classification.js +3 -0
  139. package/dist/src/runner-operations-facade.js +1 -1
  140. package/dist/src/runner-presentation.js +1 -1
  141. package/dist/src/runner.js +1 -1
  142. package/dist/src/runtime.js +3 -3
  143. package/dist/src/runtime10.js +1 -1
  144. package/dist/src/runtime2.js +2 -2
  145. package/dist/src/runtime4.js +5 -5
  146. package/dist/src/runtime5.js +1 -1
  147. package/dist/src/runtime6.js +1 -1
  148. package/dist/src/runtime7.js +1 -1
  149. package/dist/src/runtime8.js +1 -1
  150. package/dist/src/runtime9.js +1 -1
  151. package/dist/src/screen-recording-admission-ledger.js +1 -1
  152. package/dist/src/screen-recording-resource-recovery.js +1 -1
  153. package/dist/src/screen-recording-transport.js +1 -1
  154. package/dist/src/screenshot-runtime.js +1 -1
  155. package/dist/src/screenshot3.js +1 -1
  156. package/dist/src/script.js +1 -1
  157. package/dist/src/scroll-command.d.ts +377 -0
  158. package/dist/src/scroll-command.js +1 -1
  159. package/dist/src/sdk-batch.js +2 -2
  160. package/dist/src/sdk-contracts.d.ts +9 -0
  161. package/dist/src/sdk-device.js +1 -1
  162. package/dist/src/sdk-selectors.d.ts +23 -715
  163. package/dist/src/selection.js +0 -0
  164. package/dist/src/selector-runtime.js +1 -1
  165. package/dist/src/semantic-index.js +1 -1
  166. package/dist/src/server.js +1 -1
  167. package/dist/src/session-observation.js +1 -1
  168. package/dist/src/session-snapshot.js +1 -1
  169. package/dist/src/session2.js +2 -2
  170. package/dist/src/simctl-facade.js +1 -1
  171. package/dist/src/simctl.js +1 -1
  172. package/dist/src/simulator-facade.js +1 -1
  173. package/dist/src/simulator-state.js +1 -1
  174. package/dist/src/simulator.js +1 -1
  175. package/dist/src/snapshot-runtime-binding.js +1 -1
  176. package/dist/src/snapshot-runtime.js +1 -1
  177. package/dist/src/snapshot-state.js +1 -1
  178. package/dist/src/snapshot4.js +1 -1
  179. package/dist/src/src7.js +1 -1
  180. package/dist/src/text-entry-focus.js +1 -1
  181. package/dist/src/tool-provider.js +1 -1
  182. package/dist/src/touch-runtime.js +1 -1
  183. package/dist/src/tree.js +1 -1
  184. package/dist/src/update-check.js +1 -1
  185. package/dist/src/version.js +1 -1
  186. package/dist/src/web2.js +1 -1
  187. package/package.json +4 -2
  188. package/server.json +2 -2
  189. package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.11.apk.sha256 +0 -1
  190. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.11.apk.sha256 +0 -1
  191. package/apple/macos-helper/Sources/AgentDeviceMacOSDeviceHub/DeviceHubPose.swift +0 -47
  192. package/apple/macos-helper/Sources/AgentDeviceMacOSDeviceHub/DeviceHubWindowInventory.swift +0 -65
  193. package/apple/macos-helper/Sources/AgentDeviceMacOSHelper/DeviceHubPose.swift +0 -225
  194. package/apple/macos-helper/Sources/AgentDeviceMacOSHelper/DeviceHubSidebar.swift +0 -57
  195. package/apple/macos-helper/Sources/AgentDeviceMacOSHelper/DeviceHubWindowDiscovery.swift +0 -108
  196. package/apple/macos-helper/Tests/AgentDeviceMacOSDeviceHubTests/DeviceHubPoseTests.swift +0 -30
  197. package/apple/macos-helper/Tests/AgentDeviceMacOSDeviceHubTests/DeviceHubWindowInventoryTests.swift +0 -65
  198. package/dist/src/app-inventory.d.ts +0 -4
  199. package/dist/src/apps-simctl.js +0 -1
  200. package/dist/src/cloud-artifacts.d.ts +0 -61
  201. package/dist/src/runner-contract.js +0 -3
@@ -1,225 +0,0 @@
1
- import AgentDeviceMacOSDeviceHub
2
- import AppKit
3
- import ApplicationServices
4
- import Darwin
5
- import Foundation
6
-
7
- /// How long sidebar selection and pose-control discovery may each wait before refusing a press.
8
- private let deviceHubSettleDeadline: TimeInterval = 8
9
- private let deviceHubPoll: TimeInterval = 0.25
10
-
11
- struct DeviceHubPoseResponse: Encodable {
12
- let pose: String
13
- let control: String
14
- let windowTitle: String
15
- /** Whether Device Hub had to be asked to reopen a window before the device could be selected. */
16
- let reopened: Bool
17
- /** Whether the window was switched to the device through its sidebar row. */
18
- let selected: Bool
19
- }
20
-
21
- func handleDeviceHub(arguments: [String]) throws -> any Encodable {
22
- guard arguments.first == "pose" else {
23
- throw HelperError.invalidArgs("device-hub requires pose")
24
- }
25
- let rest = Array(arguments.dropFirst())
26
- guard let udid = helperOptionValue(arguments: rest, name: "--udid")?
27
- .trimmingCharacters(in: .whitespacesAndNewlines),
28
- !udid.isEmpty
29
- else {
30
- throw HelperError.invalidArgs("device-hub pose requires --udid <udid>")
31
- }
32
- guard let deviceName = helperOptionValue(arguments: rest, name: "--device-name")?
33
- .trimmingCharacters(in: .whitespacesAndNewlines),
34
- !deviceName.isEmpty
35
- else {
36
- throw HelperError.invalidArgs("device-hub pose requires --device-name <name>")
37
- }
38
- guard let pose = helperOptionValue(arguments: rest, name: "--pose").flatMap(DeviceHubPose.init(argument:))
39
- else {
40
- throw HelperError.invalidArgs("device-hub pose requires --pose <closed|book|open>")
41
- }
42
- let control = pose.controlDescription
43
- guard AXIsProcessTrusted() else {
44
- throw HelperError.commandFailed(
45
- "fold needs Accessibility permission to press the Device Hub pose control",
46
- details: ["reason": "accessibility-permission", "permission": "accessibility"]
47
- )
48
- }
49
- let discovery = try discoverDeviceHubWindow(udid: udid, deviceName: deviceName)
50
- let window = discovery.window
51
- defer {
52
- if discovery.revealedSidebar {
53
- _ = setDeviceHubSidebar(visible: false, window: window,
54
- deadline: ProcessInfo.processInfo.systemUptime + 0.5)
55
- }
56
- }
57
- let selected = try selectDevice(row: discovery.row, deviceName: deviceName, in: window)
58
- let windowTitle = stringAttribute(window, attribute: kAXTitleAttribute as String) ?? ""
59
- guard let button = awaitPoseButton(in: window, description: control) else {
60
- throw HelperError.commandFailed(
61
- "Device Hub shows no \(control) pose control for \(deviceName)",
62
- details: [
63
- "reason": "device-hub-pose-control-missing",
64
- "windowTitle": windowTitle,
65
- "control": control,
66
- ]
67
- )
68
- }
69
- let status = AXUIElementPerformAction(button, kAXPressAction as CFString)
70
- guard status == .success else {
71
- throw HelperError.commandFailed(
72
- "Device Hub refused the \(control) pose press",
73
- details: ["reason": "device-hub-press-failed", "status": "\(status.rawValue)"]
74
- )
75
- }
76
- return SuccessEnvelope(
77
- data: DeviceHubPoseResponse(
78
- pose: pose.rawValue,
79
- control: control,
80
- windowTitle: windowTitle,
81
- reopened: discovery.reopened,
82
- selected: selected
83
- )
84
- )
85
- }
86
-
87
- private func windowShows(deviceName: String, _ window: AXUIElement) -> Bool {
88
- return deviceHubWindowShows(
89
- deviceName: deviceName,
90
- title: stringAttribute(window, attribute: kAXTitleAttribute as String)
91
- )
92
- }
93
-
94
- /// `kAEReopenApplication` is what the Dock sends when an app with no open windows is clicked, and
95
- /// it is the one event Device Hub answers by restoring the device window. Sent to the process
96
- /// directly, because LaunchServices cannot address a trampolined app by bundle identifier.
97
- func sendDeviceHubReopenEvent(to pid: pid_t, timeout: TimeInterval) throws {
98
- let target = NSAppleEventDescriptor(processIdentifier: pid)
99
- let event = NSAppleEventDescriptor(
100
- eventClass: AEEventClass(kCoreEventClass),
101
- eventID: AEEventID(kAEReopenApplication),
102
- targetDescriptor: target,
103
- returnID: AEReturnID(kAutoGenerateReturnID),
104
- transactionID: AETransactionID(kAnyTransactionID)
105
- )
106
- do {
107
- _ = try event.sendEvent(options: [.noReply], timeout: min(5, max(0.001, timeout)))
108
- } catch {
109
- let code = (error as NSError).code
110
- throw HelperError.commandFailed(
111
- "fold could not ask Device Hub to reopen its device window",
112
- details: [
113
- "reason": code == -1743 ? "automation-permission" : "device-hub-reopen-failed",
114
- "error": String(describing: error),
115
- ]
116
- )
117
- }
118
- }
119
-
120
- /// Switches the window to the device through its sidebar row, whose accessibility identifier is
121
- /// `TableRow.Device.<udid>` — the one place Device Hub exposes a device identity that two
122
- /// simulators sharing a name cannot confuse. A window already titled with the device still gets
123
- /// the selection, because the title alone cannot tell such twins apart.
124
- private func selectDevice(
125
- row: AXUIElement,
126
- deviceName: String,
127
- in window: AXUIElement
128
- ) throws -> Bool {
129
- let deadline = ProcessInfo.processInfo.systemUptime + deviceHubSettleDeadline
130
- AXUIElementSetMessagingTimeout(row, 0.25)
131
- AXUIElementSetMessagingTimeout(window, 0.25)
132
- let status = AXUIElementSetAttributeValue(row, kAXSelectedAttribute as CFString, kCFBooleanTrue)
133
- guard status == .success || status == .cannotComplete else {
134
- throw HelperError.commandFailed(
135
- "Device Hub refused to select \(deviceName) in its sidebar",
136
- details: ["reason": "device-hub-select-failed", "status": "\(status.rawValue)"]
137
- )
138
- }
139
- while ProcessInfo.processInfo.systemUptime < deadline {
140
- var selected: CFTypeRef?
141
- if AXUIElementCopyAttributeValue(row, kAXSelectedAttribute as CFString, &selected) == .success,
142
- (selected as? Bool) == true, windowShows(deviceName: deviceName, window) { return true }
143
- Thread.sleep(forTimeInterval: deviceHubPoll)
144
- }
145
- throw HelperError.commandFailed(
146
- "Device Hub did not confirm selection of \(deviceName)",
147
- details: ["reason": "device-hub-select-unconfirmed", "status": "\(status.rawValue)"]
148
- )
149
- }
150
-
151
- func deviceHubDeviceRow(udid: String, in window: AXUIElement, deadline: TimeInterval) -> AXUIElement? {
152
- guard let label = findDeviceHubElement(root: window, depth: 0, deadline: deadline, where: {
153
- stringAttribute($0, attribute: "AXIdentifier") == deviceHubDeviceRowIdentifier(udid: udid)
154
- }) else {
155
- return nil
156
- }
157
- var current: AXUIElement? = label
158
- while let element = current, ProcessInfo.processInfo.systemUptime < deadline {
159
- AXUIElementSetMessagingTimeout(element, Float(max(0.001, min(0.25, deadline - ProcessInfo.processInfo.systemUptime))))
160
- if stringAttribute(element, attribute: kAXRoleAttribute as String) == "AXRow" {
161
- return element
162
- }
163
- current = elementAttribute(element, attribute: kAXParentAttribute as String)
164
- }
165
- return nil
166
- }
167
-
168
- /// The action bar is rebuilt for the device the window shows, so right after a sidebar selection
169
- /// the window already carries the new title while the pose controls are still being laid out.
170
- /// The controls are therefore awaited, not looked up once.
171
- private func awaitPoseButton(in window: AXUIElement, description: String) -> AXUIElement? {
172
- let deadline = ProcessInfo.processInfo.systemUptime + deviceHubSettleDeadline
173
- while true {
174
- if let button = poseButton(in: window, description: description, deadline: deadline) {
175
- return button
176
- }
177
- guard ProcessInfo.processInfo.systemUptime < deadline else { return nil }
178
- Thread.sleep(forTimeInterval: deviceHubPoll)
179
- }
180
- }
181
-
182
- /// The pose controls sit in the window's action bar as `AXButton`s described by their preset
183
- /// name; the simulated screen inside the same window is an iOS content group whose own buttons
184
- /// carry app labels, never these three.
185
- private func poseButton(in window: AXUIElement, description: String, deadline: TimeInterval) -> AXUIElement? {
186
- return findDeviceHubElement(root: window, depth: 0, deadline: deadline) {
187
- stringAttribute($0, attribute: kAXRoleAttribute as String) == "AXButton"
188
- && stringAttribute($0, attribute: kAXDescriptionAttribute as String) == description
189
- }
190
- }
191
-
192
- func findDeviceHubElement(
193
- root: AXUIElement,
194
- depth: Int,
195
- deadline: TimeInterval,
196
- where matches: (AXUIElement) -> Bool
197
- ) -> AXUIElement? {
198
- let remaining = deadline - ProcessInfo.processInfo.systemUptime
199
- if depth > 14 || remaining <= 0 {
200
- return nil
201
- }
202
- AXUIElementSetMessagingTimeout(root, Float(min(0.25, remaining)))
203
- for child in children(of: root) {
204
- let remaining = deadline - ProcessInfo.processInfo.systemUptime
205
- guard remaining > 0 else { return nil }
206
- AXUIElementSetMessagingTimeout(child, Float(min(0.25, remaining)))
207
- if matches(child) {
208
- return child
209
- }
210
- if stringAttribute(child, attribute: kAXSubroleAttribute as String) == "iOSContentGroup" {
211
- continue
212
- }
213
- if let nested = findDeviceHubElement(root: child, depth: depth + 1, deadline: deadline, where: matches) {
214
- return nested
215
- }
216
- }
217
- return nil
218
- }
219
-
220
- func helperOptionValue(arguments: [String], name: String) -> String? {
221
- guard let index = arguments.firstIndex(of: name), arguments.indices.contains(index + 1) else {
222
- return nil
223
- }
224
- return arguments[index + 1]
225
- }
@@ -1,57 +0,0 @@
1
- import AgentDeviceMacOSDeviceHub
2
- import ApplicationServices
3
- import Foundation
4
-
5
- func identifyDeviceHubRow(
6
- udid: String,
7
- candidate: DeviceHubWindowCandidate,
8
- deadline: TimeInterval
9
- ) -> DeviceHubRowLookup {
10
- let now = ProcessInfo.processInfo.systemUptime
11
- let visibleRowDeadline = now + max(0, deadline - now) / 3
12
- if let row = deviceHubDeviceRow(udid: udid, in: candidate.window, deadline: visibleRowDeadline) {
13
- return .identified(row, restoreSidebar: false)
14
- }
15
- let searchDeadline = deadline - 0.25
16
- guard let button = deviceHubSidebarButton(visible: true, window: candidate.window, deadline: searchDeadline) else {
17
- return ProcessInfo.processInfo.systemUptime >= searchDeadline ? .timedOut : .sidebarUnavailable
18
- }
19
- var transferCleanup = false
20
- defer {
21
- if !transferCleanup {
22
- _ = setDeviceHubSidebar(visible: false, window: candidate.window, deadline: deadline)
23
- }
24
- }
25
- let status = pressDeviceHubSidebarButton(button, deadline: searchDeadline)
26
- guard status == .success || status == .cannotComplete else { return .unconfirmed }
27
- repeat {
28
- if let row = deviceHubDeviceRow(udid: udid, in: candidate.window, deadline: searchDeadline) {
29
- transferCleanup = true
30
- return .identified(row, restoreSidebar: true)
31
- }
32
- let remaining = searchDeadline - ProcessInfo.processInfo.systemUptime
33
- if remaining <= 0 { return .timedOut }
34
- Thread.sleep(forTimeInterval: min(0.05, remaining))
35
- } while ProcessInfo.processInfo.systemUptime < searchDeadline
36
- return .timedOut
37
- }
38
-
39
- func setDeviceHubSidebar(visible: Bool, window: AXUIElement, deadline: TimeInterval) -> Bool {
40
- guard let button = deviceHubSidebarButton(visible: visible, window: window, deadline: deadline) else { return false }
41
- return pressDeviceHubSidebarButton(button, deadline: deadline) == .success
42
- }
43
-
44
- private func deviceHubSidebarButton(visible: Bool, window: AXUIElement, deadline: TimeInterval) -> AXUIElement? {
45
- let description = visible ? "Show Sidebar" : "Hide Sidebar"
46
- return findDeviceHubElement(root: window, depth: 0, deadline: deadline) {
47
- stringAttribute($0, attribute: kAXRoleAttribute as String) == "AXButton"
48
- && stringAttribute($0, attribute: kAXDescriptionAttribute as String) == description
49
- }
50
- }
51
-
52
- private func pressDeviceHubSidebarButton(_ button: AXUIElement, deadline: TimeInterval) -> AXError {
53
- let remaining = deadline - ProcessInfo.processInfo.systemUptime
54
- guard remaining > 0 else { return .cannotComplete }
55
- AXUIElementSetMessagingTimeout(button, Float(min(0.1, remaining)))
56
- return AXUIElementPerformAction(button, kAXPressAction as CFString)
57
- }
@@ -1,108 +0,0 @@
1
- import AgentDeviceMacOSDeviceHub
2
- import AppKit
3
- import ApplicationServices
4
- import Darwin
5
-
6
- struct DiscoveredDeviceHubWindow {
7
- let window: AXUIElement
8
- let reopened: Bool
9
- let row: AXUIElement
10
- let revealedSidebar: Bool
11
- }
12
-
13
- func discoverDeviceHubWindow(udid: String, deviceName: String) throws -> DiscoveredDeviceHubWindow {
14
- let deadline = ProcessInfo.processInfo.systemUptime + 8
15
- var reopened = Set<pid_t>()
16
- var reopenFailures: [pid_t: String] = [:]
17
- var inventory = DeviceHubWindowInventory()
18
- var processIDs: [pid_t] = []
19
- repeat {
20
- processIDs = deviceHubProcessIdentifiers()
21
- if processIDs.isEmpty {
22
- throw HelperError.commandFailed(
23
- "Xcode Device Hub is not running",
24
- details: ["reason": "device-hub-not-running", "bundleId": "com.apple.dt.Devices"]
25
- )
26
- }
27
- inventory = DeviceHubWindowInventory()
28
- for pid in processIDs {
29
- let remaining = deadline - ProcessInfo.processInfo.systemUptime
30
- guard remaining > 0 else { inventory.expireBudget(); break }
31
- let app = AXUIElementCreateApplication(pid)
32
- AXUIElementSetMessagingTimeout(app, Float(min(0.5, remaining)))
33
- var value: CFTypeRef?
34
- let status = AXUIElementCopyAttributeValue(app, kAXWindowsAttribute as CFString, &value)
35
- if status == .success, let windows = value as? [AXUIElement] {
36
- for window in windows { AXUIElementSetMessagingTimeout(window, 0.5) }
37
- inventory.record(processID: pid, read: .available(windows))
38
- } else {
39
- inventory.record(processID: pid, read: .failed(
40
- status == .success ? AXError.illegalArgument.rawValue : status.rawValue
41
- ))
42
- }
43
- }
44
- for (index, candidate) in inventory.candidates.enumerated() {
45
- let now = ProcessInfo.processInfo.systemUptime
46
- guard now < deadline else { inventory.expireBudget(); break }
47
- let candidateDeadline = now + (deadline - now) / Double(inventory.candidates.count - index) / 2
48
- let outcome = identifyDeviceHubRow(udid: udid, candidate: candidate, deadline: candidateDeadline)
49
- inventory.record(candidate: index, outcome: outcome)
50
- if case .identified(let row, let restoreSidebar) = outcome {
51
- return DiscoveredDeviceHubWindow(window: candidate.window,
52
- reopened: reopened.contains(candidate.processID), row: row, revealedSidebar: restoreSidebar)
53
- }
54
- }
55
- let attempted = reopened.union(reopenFailures.keys)
56
- for pid in inventory.processesToReopen(attempted: attempted) {
57
- guard ProcessInfo.processInfo.systemUptime < deadline else { inventory.expireBudget(); break }
58
- do {
59
- try sendDeviceHubReopenEvent(to: pid, timeout: deadline - ProcessInfo.processInfo.systemUptime)
60
- reopened.insert(pid)
61
- } catch let error as HelperError {
62
- guard case .commandFailed(_, let details) = error else { throw error }
63
- reopenFailures[pid] = details["reason"] ?? "device-hub-reopen-failed"
64
- }
65
- }
66
- let remaining = deadline - ProcessInfo.processInfo.systemUptime
67
- if remaining <= 0 { inventory.expireBudget(); break }
68
- Thread.sleep(forTimeInterval: min(0.25, remaining))
69
- } while ProcessInfo.processInfo.systemUptime < deadline
70
-
71
- let statuses = inventory.failures.sorted { $0.key < $1.key }
72
- .map { "\($0.key):\($0.value)" }.joined(separator: ",")
73
- throw HelperError.commandFailed(
74
- "Could not confirm a Device Hub window for the requested device",
75
- details: [
76
- "reason": inventory.failureReason(reopenFailures: reopenFailures),
77
- "reopenFailures": reopenFailures.sorted { $0.key < $1.key }.map { "\($0.key):\($0.value)" }.joined(separator: ","),
78
- "candidateOutcomes": inventory.candidateOutcomes.joined(separator: ","),
79
- "udid": udid,
80
- "deviceName": deviceName,
81
- "processIDs": processIDs.map(String.init).joined(separator: ","),
82
- "axWindowReadStatuses": statuses,
83
- "hostDisplayIDs": deviceHubHostDisplays().map { String($0) }.joined(separator: ","),
84
- ]
85
- )
86
- }
87
-
88
- private func deviceHubProcessIdentifiers() -> [pid_t] {
89
- let byteCount = proc_listpids(UInt32(PROC_ALL_PIDS), 0, nil, 0)
90
- guard byteCount > 0 else { return [] }
91
- var pids = [pid_t](repeating: 0, count: Int(byteCount) / MemoryLayout<pid_t>.size + 64)
92
- let filled = proc_listpids(UInt32(PROC_ALL_PIDS), 0, &pids, Int32(pids.count * MemoryLayout<pid_t>.size))
93
- guard filled > 0 else { return [] }
94
- return pids.prefix(Int(filled) / MemoryLayout<pid_t>.size).filter { pid in
95
- guard pid > 0 else { return false }
96
- var path = [CChar](repeating: 0, count: 4096)
97
- guard proc_pidpath(pid, &path, UInt32(path.count)) > 0 else { return false }
98
- return String(cString: path).hasSuffix(deviceHubExecutableSuffix)
99
- }.sorted()
100
- }
101
-
102
- private func deviceHubHostDisplays() -> [CGDirectDisplayID] {
103
- var count: UInt32 = 0
104
- guard CGGetActiveDisplayList(0, nil, &count) == .success else { return [] }
105
- var displays = [CGDirectDisplayID](repeating: 0, count: Int(count))
106
- guard CGGetActiveDisplayList(count, &displays, &count) == .success else { return [] }
107
- return Array(displays.prefix(Int(count)))
108
- }
@@ -1,30 +0,0 @@
1
- import XCTest
2
-
3
- @testable import AgentDeviceMacOSDeviceHub
4
-
5
- final class DeviceHubPoseTests: XCTestCase {
6
- func testEveryPoseNamesTheActionBarControlDeviceHubDescribes() {
7
- XCTAssertEqual(DeviceHubPose(argument: "closed")?.controlDescription, "Closed")
8
- XCTAssertEqual(DeviceHubPose(argument: "book")?.controlDescription, "Book")
9
- XCTAssertEqual(DeviceHubPose(argument: "OPEN")?.controlDescription, "Open")
10
- XCTAssertNil(DeviceHubPose(argument: "half-open"), "the helper takes Device Hub's names, not the CLI's")
11
- XCTAssertEqual(Set(DeviceHubPose.allCases.map(\.controlDescription)), ["Closed", "Book", "Open"])
12
- }
13
-
14
- // Device Hub titles the window `<name> – iOS 27.1`; a simulator whose name merely starts
15
- // with another's must not claim that window.
16
- func testWindowTitleMatchesTheDeviceNameAsAPrefixWord() {
17
- XCTAssertTrue(deviceHubWindowShows(deviceName: "iPhone Duo", title: "iPhone Duo – iOS 27.1"))
18
- XCTAssertTrue(deviceHubWindowShows(deviceName: "iPhone Duo", title: "iPhone Duo"))
19
- XCTAssertFalse(deviceHubWindowShows(deviceName: "iPhone Duo", title: "iPhone Duo Lab – iOS 27.1"))
20
- XCTAssertFalse(deviceHubWindowShows(deviceName: "iPhone Duo", title: "bench-golden-v1 – iOS 27.0"))
21
- XCTAssertFalse(deviceHubWindowShows(deviceName: "iPhone Duo", title: nil))
22
- }
23
-
24
- func testSidebarRowIsKeyedByUdid() {
25
- XCTAssertEqual(
26
- deviceHubDeviceRowIdentifier(udid: "4F879835-4AB3-4046-B033-5AB769209DD4"),
27
- "TableRow.Device.4F879835-4AB3-4046-B033-5AB769209DD4"
28
- )
29
- }
30
- }
@@ -1,65 +0,0 @@
1
- import ApplicationServices
2
- import XCTest
3
- @testable import AgentDeviceMacOSDeviceHub
4
-
5
- final class DeviceHubWindowInventoryTests: XCTestCase {
6
- func testLaterWindowKeepsItsProcessAndDoesNotPreventEmptyProcessReopen() {
7
- var inventory = DeviceHubWindowInventory()
8
- let window = AXUIElementCreateApplication(20)
9
- inventory.record(processID: 10, read: .available([]))
10
- inventory.record(processID: 20, read: .available([window]))
11
- XCTAssertEqual(inventory.candidates.map(\.processID), [20])
12
- XCTAssertTrue(CFEqual(inventory.candidates[0].window, window))
13
- inventory.record(candidate: 0, outcome: .sidebarUnavailable)
14
- XCTAssertEqual(inventory.processesToReopen(attempted: []), [10])
15
- XCTAssertEqual(inventory.failureReason(), "device-hub-identity-unconfirmed")
16
- XCTAssertEqual(inventory.candidateOutcomes, ["20:0:sidebar-unavailable"])
17
- }
18
-
19
- func testFailedReadsAreNotReopenedOrMisreportedAsMissingWindows() {
20
- var inventory = DeviceHubWindowInventory()
21
- inventory.record(processID: 10, read: .failed(-25204))
22
- inventory.record(processID: 20, read: .available([]))
23
- XCTAssertEqual(inventory.processesToReopen(attempted: []), [20])
24
- XCTAssertEqual(inventory.failures, [10: -25204])
25
- XCTAssertEqual(inventory.failureReason(), "device-hub-window-read-failed")
26
- }
27
-
28
- func testSuccessfulEmptyReadIsMissingAndReopenIsAttemptedOnlyOnce() {
29
- var inventory = DeviceHubWindowInventory()
30
- inventory.record(processID: 10, read: .available([]))
31
- XCTAssertEqual(inventory.failureReason(), "device-hub-window-missing")
32
- XCTAssertEqual(inventory.processesToReopen(attempted: []), [10])
33
- XCTAssertEqual(inventory.processesToReopen(attempted: [10]), [])
34
- }
35
-
36
- func testSharedBudgetExhaustionStopsReopenWithoutClaimingMissingDevice() {
37
- var inventory = DeviceHubWindowInventory()
38
- inventory.record(processID: 10, read: .available([]))
39
- inventory.expireBudget()
40
- XCTAssertEqual(inventory.processesToReopen(attempted: []), [])
41
- XCTAssertEqual(inventory.failureReason(), "device-hub-discovery-timeout")
42
- }
43
-
44
- func testCandidateOutcomesRetainUncertaintyAndOwningProcess() {
45
- var inventory = DeviceHubWindowInventory()
46
- inventory.record(processID: 10, read: .available([AXUIElementCreateApplication(10)]))
47
- inventory.record(processID: 20, read: .available([AXUIElementCreateApplication(20)]))
48
- inventory.record(candidate: 0, outcome: .timedOut)
49
- inventory.record(candidate: 1, outcome: .unconfirmed)
50
- XCTAssertEqual(inventory.candidateOutcomes, ["10:0:timed-out", "20:1:row-unconfirmed"])
51
- XCTAssertEqual(inventory.failureReason(), "device-hub-identity-unconfirmed")
52
- }
53
- func testUnrelatedReopenFailureDoesNotMaskCandidateUncertainty() {
54
- var inventory = DeviceHubWindowInventory()
55
- inventory.record(processID: 10, read: .available([]))
56
- let failures: [Int32: String] = [10: "automation-permission"]
57
- XCTAssertEqual(inventory.failureReason(reopenFailures: failures), "automation-permission")
58
- inventory.record(processID: 20, read: .available([AXUIElementCreateApplication(20)]))
59
- inventory.record(candidate: 0, outcome: .timedOut)
60
- XCTAssertEqual(inventory.failureReason(reopenFailures: failures), "device-hub-identity-unconfirmed")
61
- inventory.expireBudget()
62
- XCTAssertEqual(inventory.failureReason(reopenFailures: failures), "device-hub-discovery-timeout")
63
- }
64
-
65
- }
@@ -1,4 +0,0 @@
1
- //#region packages/contracts/src/app-inventory.d.ts
2
- type AppsFilter = 'user-installed' | 'all';
3
- //#endregion
4
- export { AppsFilter as t };
@@ -1 +0,0 @@
1
- import{o as e}from"./tool-provider.js";import{t}from"./simctl.js";function n(e,n){return t(e,n)}function r(t,r,i){return e(n(t,r),i)}function i(e){return e.includes(`not installed`)||e.includes(`not found`)||e.includes(`no such file`)}export{r as n,n as r,i as t};
@@ -1,61 +0,0 @@
1
- import { n as DaemonArtifactType } from "./sdk-contracts.js";
2
- //#region packages/contracts/src/cloud-artifacts.d.ts
3
- declare const CLOUD_ARTIFACT_KINDS: readonly ['video', 'appium-log', 'device-log', 'automation-log', 'provider-session', 'raw'];
4
- type CloudArtifactKind = (typeof CLOUD_ARTIFACT_KINDS)[number];
5
- type CloudArtifactAvailability = 'ready' | 'pending' | 'unavailable' | 'expired';
6
- type CloudArtifact = {
7
- provider: string;
8
- kind: CloudArtifactKind;
9
- name: string;
10
- url?: string;
11
- providerSessionId?: string;
12
- providerArtifactId?: string;
13
- contentType?: string;
14
- extension?: string;
15
- availability?: CloudArtifactAvailability;
16
- metadata?: Record<string, unknown>;
17
- };
18
- type CloudArtifactsStatus = 'ready' | 'pending' | 'unavailable';
19
- type CloudArtifactsResult = {
20
- provider: string;
21
- status: CloudArtifactsStatus;
22
- cloudArtifacts: CloudArtifact[];
23
- providerSessionId?: string;
24
- message?: string;
25
- };
26
- type DaemonArtifactInventoryEntry = {
27
- id: string;
28
- artifactType?: DaemonArtifactType;
29
- filename: string;
30
- mimeType: string;
31
- sizeBytes: number;
32
- createdAt: string;
33
- expiresAt: string;
34
- };
35
- type DaemonArtifactsResult = {
36
- source: 'daemon';
37
- status: 'ready';
38
- artifacts: DaemonArtifactInventoryEntry[];
39
- message?: string;
40
- };
41
- type AgentArtifactsResult = CloudArtifactsResult | DaemonArtifactsResult;
42
- type CloudArtifactsQuery = {
43
- provider?: string;
44
- leaseId?: string;
45
- providerSessionId?: string;
46
- };
47
- type CloudProviderSessionResult = {
48
- provider?: string;
49
- providerSessionId?: string;
50
- cloudArtifacts?: CloudArtifactsResult;
51
- } & Record<string, unknown>;
52
- /**
53
- * Return undefined only when this provider implementation does not handle the query.
54
- * Return a CloudArtifactsResult with status "unavailable" when the provider handled the
55
- * query but artifact retrieval failed, and "pending" when artifacts are not finalized yet.
56
- */
57
- type CloudArtifactProvider = {
58
- listCloudArtifacts?: (query: CloudArtifactsQuery) => Promise<CloudArtifactsResult | undefined>;
59
- };
60
- //#endregion
61
- export { CloudArtifactProvider as n, CloudProviderSessionResult as r, AgentArtifactsResult as t };
@@ -1,3 +0,0 @@
1
- import{D as e,P as t,U as n,k as r}from"./sdk-contracts.js";import{i}from"./alert-contract.js";import{f as a,i as o,m as s,o as c,y as l}from"./host.js";import u from"node:crypto";const d=`RUNNER_BUSY`,f=`MAIN_THREAD_TIMEOUT`,p="If runner build products look stale or corrupted, run `pnpm clean:xcuitest` in a local checkout, or remove ~/.agent-device/apple-runner/derived, then retry.";function m(e){let t=a(e.requestId);return e.signal?!t||t===e.signal?e.signal:AbortSignal.any([t,e.signal]):t}const h=e=>e.retriable===!0,g=e=>typeof e.devToolsSecurityStatus==`string`,_=e=>e.usbmuxDeviceAttached===!1,v=e=>e.runnerReadinessPreflightFailed===!0&&!t(e),y=`build_failed_unclassified`,b={reason:`signing_provisioning_profile_missing`,hint:`Install/select a valid iOS provisioning profile, or set AGENT_DEVICE_IOS_PROVISIONING_PROFILE.`},x=[{reason:`usbmux_device_unattached`,match:{code:`DEVICE_NOT_FOUND`,details:_},verdicts:{connectRetry:!1}},{reason:`flagged_retriable`,match:{code:`COMMAND_FAILED`,details:h},verdicts:{retryable:!0,connectRetry:!0}},{reason:`xcodebuild_exited_early`,match:{code:`COMMAND_FAILED`,messageIncludesAll:[`xcodebuild exited early`]},verdicts:{retryable:!1,connectRetry:!1,artifactSuspect:!1}},{reason:`device_busy_connecting`,match:{code:`COMMAND_FAILED`,messageIncludesAll:[`device is busy`,`connecting`]},verdicts:{retryable:!1,connectRetry:!1}},{reason:`runner_readiness_preflight_failed`,match:{code:`COMMAND_FAILED`,details:v},verdicts:{restartAfterReadinessPreflight:!0}},{reason:`runner_connect_refused`,match:{code:`COMMAND_FAILED`,messageIncludesAll:[`runner did not accept connection`]},verdicts:{retryable:!0,connectRetry:!0,restartBeforeSend:!0,artifactSuspect:!0}},{reason:`runner_endpoint_probe_exhausted`,match:{code:`COMMAND_FAILED`,messageIncludesAll:[`runner endpoint probe failed`]},verdicts:{artifactSuspect:!0}},{reason:`fetch_failed`,match:{code:`COMMAND_FAILED`,messageIncludesAll:[`fetch failed`]},verdicts:{retryable:!0,connectRetry:!0}},{reason:`econnrefused`,match:{code:`COMMAND_FAILED`,messageIncludesAll:[`econnrefused`]},verdicts:{retryable:!0,connectRetry:!0}},{reason:`socket_hang_up`,match:{code:`COMMAND_FAILED`,messageIncludesAll:[`socket hang up`]},verdicts:{retryable:!0,connectRetry:!0}},{reason:`ax_snapshot_failure`,match:{code:`IOS_AX_SNAPSHOT_FAILED`},verdicts:{sessionFatalReason:`ax_snapshot_failure`}},{reason:`xctest_recorded_failure`,match:{code:`XCTEST_RECORDED_FAILURE`},verdicts:{sessionFatalReason:`xctest_recorded_failure`}},{reason:`runner_main_thread_wedged`,match:{code:`RUNNER_WEDGED`},verdicts:{sessionFatalReason:`runner_main_thread_wedged`}},{reason:`bundle_identifier_registration_failed`,match:{toolTextIncludesAll:[`failed registering bundle identifier`]},verdicts:{},buildFailure:{reason:`bundle_identifier_already_registered`,hint:`Set AGENT_DEVICE_IOS_BUNDLE_ID to a unique reverse-DNS value (for example, com.yourname.agentdevice.runner), then retry.`}},{reason:`bundle_identifier_unavailable`,match:{toolTextLineIncludesAll:[`app identifier`,`not available`]},verdicts:{},buildFailure:{reason:`bundle_identifier_already_registered`,hint:`Set AGENT_DEVICE_IOS_BUNDLE_ID to a unique reverse-DNS value (for example, com.yourname.agentdevice.runner), then retry.`}},{reason:`signing_requires_development_team`,match:{toolTextIncludesAll:[`requires a development team`]},verdicts:{},buildFailure:{reason:`signing_no_development_team`,hint:`Configure signing in Xcode or set AGENT_DEVICE_IOS_TEAM_ID for physical-device runs.`}},{reason:`conflicting_provisioning_settings_unproven`,match:{toolTextIncludesAll:[`conflicting provisioning settings`]},verdicts:{},buildFailure:{reason:y,hint:p}},{reason:`signing_no_profiles_for_bundle_id`,match:{toolTextIncludesAll:[`no profiles for`]},verdicts:{},buildFailure:b},{reason:`signing_provisioning_profile_xcode_error`,match:{toolTextLineIncludesAll:[`provisioning profile`,`ideprovisioningerrordomain`]},verdicts:{},buildFailure:b},{reason:`signing_provisioning_profile_does_not_cover`,match:{toolTextLineIncludesAll:[`provisioning profile`,`doesn't include`]},verdicts:{},buildFailure:b},{reason:`signing_provisioning_profile_expired`,match:{toolTextLineIncludesAll:[`provisioning profile`,`has expired`]},verdicts:{},buildFailure:b},{reason:`signing_unspecified`,match:{toolTextIncludesAll:[`code signing`]},verdicts:{},buildFailure:{reason:`signing_unspecified`,hint:`Enable Automatic Signing in Xcode or provide AGENT_DEVICE_IOS_TEAM_ID and optional AGENT_DEVICE_IOS_SIGNING_IDENTITY.`}},{reason:`devtools_security_refused`,match:{code:`COMMAND_FAILED`,details:g},verdicts:{},buildFailure:{reason:`devtools_security_developer_mode_disabled`,hint:"Run `sudo DevToolsSecurity -enable`, then retry the iOS runner. UI test runners start suspended until Xcode/testmanagerd can attach."}}];function S(e,t){return t.code!==void 0&&e.code!==t.code||!C(e,t.details)||!E(e,t.toolTextIncludesAll)||!D(e,t.toolTextLineIncludesAll)?!1:w(e,t.messageIncludesAll)}function C(e,t){return t===void 0||t(e.details??{})}function w(e,t){if(!t)return!0;let n=`${e.message??``}`.toLowerCase();return t.every(e=>n.includes(e))}function T(e){let t=e.details??{};return[e.message,t.stdout,t.stderr].filter(e=>typeof e==`string`).join(`
2
- `).toLowerCase()}function E(e,t){if(!t)return!0;let n=T(e);return t.every(e=>n.includes(e))}function D(e,t){return!t||T(e).split(`
3
- `).some(e=>t.every(t=>e.includes(t)))}function O(t,n){if(t instanceof e){for(let e of x)if(e.verdicts[n]!==void 0&&S(t,e.match))return e.verdicts[n]}}function k(t){return!(t instanceof e)||t.code!==`COMMAND_FAILED`?!1:O(t,`retryable`)??!1}function A(t){if(!(t instanceof e))return!1;let n=t.details?.runnerErrorCode;return n===d||n===f}function j(t){return!(t instanceof e)||t.code!==`DEVICE_NOT_FOUND`?!1:_(t.details??{})}function M(e){return O(e,`connectRetry`)??!0}function N(e){return O(e,`restartAfterReadinessPreflight`)??!1}function P(e){return O(e,`artifactSuspect`)??!1}function F(e){return O(e,`sessionFatalReason`)}function I(e){return(O(e,`restartBeforeSend`)??!1)&&M(e)}const L=`SCROLL_KEYBOARD_OCCLUDES_SURFACE`,R=new Set([d,f,i,L,...new Set([`APP_SCREEN_WINDOW_UNRESOLVED`,`APP_SCREEN_UNRESOLVED`,`APP_SCREEN_CAPTURE_UNRENDERABLE`])]);function z(e){let t=e!==void 0&&R.has(e);return Object.freeze({code:t?`COMMAND_FAILED`:n(e),details:Object.freeze({runnerErrorCode:e,...e===d?{retriable:!0}:{}})})}function B(t){let n;try{n=JSON.parse(t)}catch{throw new e(`COMMAND_FAILED`,`Invalid runner response`,{text:t})}return n&&typeof n==`object`?n:{}}function V(e){return e.ok===!0}function H(e){return!e.data||typeof e.data!=`object`||Array.isArray(e.data)?{}:e.data}function U(t,n){let r=W(t.error?.code),i=typeof t.error?.message==`string`?t.error.message:void 0,a=typeof t.error?.hint==`string`?t.error.hint:void 0,o=z(r);return new e(o.code,i??`Runner error`,{runner:t,...o.details,xcodebuild:{exitCode:1,stdout:``,stderr:``},hint:a,logPath:n})}function W(e){return typeof e==`string`&&e.trim().length>0?e.trim():void 0}function G(e,t,n,r){let i=`${e}\n${t}\n${n}`.toLowerCase();if(i.includes(`device is busy`)&&i.includes(`connecting`))return`Target iOS device is still connecting. Keep it unlocked, wait for device trust/connection to settle, then retry.`;let a=r??`IOS_RUNNER_CONNECT_TIMEOUT`;return a===`IOS_RUNNER_DEVICE_NOT_PROVISIONED`?o(a):`${o(a)} ${p}`}function K(t){let{port:n,endpoints:r,logPath:i,lastError:a,deviceStates:s}=t,l=`Runner did not accept connection`;return Y(new e(`COMMAND_FAILED`,l,{port:n,endpoints:r,logPath:i,lastError:a?String(a):void 0,reason:c({error:a,message:l,context:{platform:`ios`,phase:`connect`}}),hint:o(`IOS_RUNNER_CONNECT_TIMEOUT`)}),s)}async function q(t){let{session:n,port:r,logPath:i}=t,a=await n.testPromise,o=`Runner did not accept connection (xcodebuild exited early)`,s=n.readLogTail?.(65536)??``,l=c({message:o,stdout:s,stderr:s,context:{platform:`ios`,phase:`connect`}});return Y(new e(`COMMAND_FAILED`,o,{port:r,logPath:n.runnerLogPath??i,xcodebuild:{exitCode:a.exitCode,stderr:s},reason:l,hint:G(o,s,s,l)}),n.startupDeviceStates)}function J(t){if(t instanceof e)for(let e of x){let n=e.buildFailure;if(n&&S(t,e.match))return{reason:n.reason,hint:n.hint,matched:!0}}return{reason:y,hint:p,matched:!1}}function Y(t,n){if(!n||!(t instanceof e))return t;let r=X(t)===void 0&&n.developerDiskImage===`unavailable`&&!Q(t)&&!Z(t);return new e(t.code,t.message,{...t.details??{},...r?{reason:`device_developer_disk_image_unavailable`,hint:n.developerDiskImageHint}:{},developerDiskImage:n.developerDiskImage},t.cause)}function X(e){let t=e.details?.reason;if(typeof t==`string`&&t!==`build_failed_unclassified`)return t}function Z(e){let t=e.details?.startupHostDeadlineHit;return typeof t==`boolean`?t:s(e)}function Q(e){let t=e.details?.startupRuleMatched;return typeof t==`boolean`?t:J(e).matched}function $(e){return e.command===`status`||e.commandId?.trim()?e:{...e,commandId:ee()}}function ee(){return`runner-${u.randomUUID()}`}function te(e){if(l(e))throw r()}export{P as _,U as a,M as b,B as c,A as d,V as f,m as g,F as h,q as i,Y as l,H as m,te as n,z as o,j as p,K as r,J as s,L as t,k as u,N as v,$ as x,I as y};