agent-device 0.20.5 → 0.20.7

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 (196) hide show
  1. package/README.md +5 -3
  2. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.20.5.apk → agent-device-android-ime-helper-0.20.7.apk} +0 -0
  3. package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.7.apk.sha256 +1 -0
  4. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.20.5.manifest.json → agent-device-android-ime-helper-0.20.7.manifest.json} +4 -4
  5. package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.20.5.apk → agent-device-android-snapshot-helper-0.20.7.apk} +0 -0
  6. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.7.apk.sha256 +1 -0
  7. package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.20.5.manifest.json → agent-device-android-snapshot-helper-0.20.7.manifest.json} +6 -6
  8. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunner/AgentDeviceRunnerApp.m +48 -0
  9. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/AgentDeviceRunnerUITests-Bridging-Header.h +1 -0
  10. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.h +108 -1
  11. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.m +630 -89
  12. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSelectorMatchPolicy.swift +78 -0
  13. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedGesture.m +126 -187
  14. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedTextEntry.h +32 -0
  15. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedTextEntry.m +212 -0
  16. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+AXSnapshotFallback.swift +149 -10
  17. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +161 -32
  18. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CoordinateTextEntryTests.swift +4 -0
  19. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +36 -28
  20. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Keyboard.swift +23 -5
  21. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Lifecycle.swift +10 -0
  22. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+LifecycleCacheTests.swift +0 -67
  23. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +18 -1
  24. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScreenRecorder.swift +2 -22
  25. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SelectorMatchPolicyTests.swift +4 -0
  26. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +2 -1
  27. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCapturePlan.swift +145 -20
  28. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotTraversalIdentityTests.swift +0 -20
  29. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedGesturePolicy.swift +4 -0
  30. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedTextEntry.swift +234 -0
  31. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntry.swift +106 -448
  32. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntryPolicyTests.swift +4 -0
  33. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextTyping.swift +602 -0
  34. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests.swift +18 -0
  35. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerXCTestEventBridge.h +72 -0
  36. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerXCTestEventBridge.m +89 -0
  37. package/dist/src/agent-browser-tool.js +1 -1
  38. package/dist/src/agent-device-client.js +2 -2
  39. package/dist/src/android-adb.js +1 -1
  40. package/dist/src/android.js +1 -1
  41. package/dist/src/app-helpers.js +1 -1
  42. package/dist/src/app-lifecycle.js +7 -7
  43. package/dist/src/app-lifecycle2.js +2 -0
  44. package/dist/src/app-log-files.js +1 -0
  45. package/dist/src/app-log-reconnect.js +1 -0
  46. package/dist/src/app-log-runtime.js +4 -0
  47. package/dist/src/app-resolution.js +2 -1
  48. package/dist/src/apps.js +5 -5
  49. package/dist/src/audio-probe.js +1 -1
  50. package/dist/src/auth-session.js +1 -0
  51. package/dist/src/auth.js +2 -0
  52. package/dist/src/boot-diagnostics.js +2 -2
  53. package/dist/src/cli-config.js +1 -1
  54. package/dist/src/cli-grammar.js +1 -0
  55. package/dist/src/cli-help.js +204 -254
  56. package/dist/src/cli-output.js +1 -0
  57. package/dist/src/cli-runner.js +1 -2
  58. package/dist/src/cli.js +6 -16
  59. package/dist/src/client-metro.js +1 -1
  60. package/dist/src/cloud-artifacts.d.ts +2 -137
  61. package/dist/src/command-metadata.js +1 -1
  62. package/dist/src/command-schema.js +3 -3
  63. package/dist/src/connection-runtime.js +1 -0
  64. package/dist/src/connection.js +5 -0
  65. package/dist/src/context.js +1 -1
  66. package/dist/src/daemon-shutdown-report.js +1 -0
  67. package/dist/src/daemon.js +2 -0
  68. package/dist/src/debug-symbols.js +3 -3
  69. package/dist/src/device-claim-inspection.js +1 -0
  70. package/dist/src/device-input-state.js +2 -2
  71. package/dist/src/device.js +1 -1
  72. package/dist/src/device2.js +2 -0
  73. package/dist/src/find.js +1 -1
  74. package/dist/src/finders.js +1 -1
  75. package/dist/src/generic-settle.js +1 -0
  76. package/dist/src/generic.js +1 -1
  77. package/dist/src/harmonyos.js +1 -0
  78. package/dist/src/helper.js +1 -1
  79. package/dist/src/host-process.js +2 -2
  80. package/dist/src/ime-lifecycle.js +7 -7
  81. package/dist/src/index.d.ts +69 -18
  82. package/dist/src/input-actions.js +4 -4
  83. package/dist/src/input-actions2.js +1 -1
  84. package/dist/src/input-actions3.js +1 -0
  85. package/dist/src/install-artifact.js +1 -5
  86. package/dist/src/install-artifact2.js +1 -1
  87. package/dist/src/install-source2.js +1 -1
  88. package/dist/src/interaction-runtime.js +1 -0
  89. package/dist/src/interaction-snapshot.js +1 -1
  90. package/dist/src/interaction-touch-reference-frame.js +1 -0
  91. package/dist/src/interaction.js +1 -1
  92. package/dist/src/interactor.js +2 -2
  93. package/dist/src/interactor2.js +1 -1
  94. package/dist/src/internal/bin.js +2 -2
  95. package/dist/src/internal/daemon.js +9 -16
  96. package/dist/src/inventory.js +5 -0
  97. package/dist/src/inventory2.js +1 -0
  98. package/dist/src/inventory3.js +2 -0
  99. package/dist/src/inventory4.js +1 -0
  100. package/dist/src/inventory5.js +1 -0
  101. package/dist/src/inventory6.js +1 -0
  102. package/dist/src/lease-context.js +1 -1
  103. package/dist/src/lease.js +1 -1
  104. package/dist/src/limrun-runtime-dependencies.js +1 -0
  105. package/dist/src/limrun.d.ts +10 -104
  106. package/dist/src/limrun.js +1 -1
  107. package/dist/src/linux.js +1 -1
  108. package/dist/src/logcat.js +1 -1
  109. package/dist/src/manifest.js +1 -1
  110. package/dist/src/owner-identity.js +1 -0
  111. package/dist/src/physical-device-control.js +1 -1
  112. package/dist/src/platform-runtime-app-log-android-transport.js +1 -0
  113. package/dist/src/platform-runtime-app-log-process.js +1 -0
  114. package/dist/src/platform-runtime-host.js +1 -0
  115. package/dist/src/platform-runtime-network-web-transport.js +1 -0
  116. package/dist/src/platform-runtime-operation-host.js +5 -0
  117. package/dist/src/platform-runtime-toolchain-host.js +1 -0
  118. package/dist/src/platform-runtime.js +1 -0
  119. package/dist/src/prepare-kind.js +15 -0
  120. package/dist/src/process-entry.js +1 -0
  121. package/dist/src/process-exit.js +1 -0
  122. package/dist/src/process-lock.js +1 -1
  123. package/dist/src/provider-webdriver.js +1 -0
  124. package/dist/src/provider.js +1 -0
  125. package/dist/src/proxy.js +2 -0
  126. package/dist/src/react-native.js +1 -1
  127. package/dist/src/record-trace.js +1 -1
  128. package/dist/src/registry.js +25 -24
  129. package/dist/src/remote-config.js +1 -1
  130. package/dist/src/remote-config2.js +1 -1
  131. package/dist/src/replay.js +3 -0
  132. package/dist/src/reporting.js +4 -4
  133. package/dist/src/runner-client.js +1 -1
  134. package/dist/src/runner-disposal.js +1 -1
  135. package/dist/src/runner-lease.js +1 -1
  136. package/dist/src/runtime.js +3 -3
  137. package/dist/src/runtime2.js +4 -0
  138. package/dist/src/runtime3.js +3 -0
  139. package/dist/src/runtime4.js +1 -0
  140. package/dist/src/runtime5.js +1 -0
  141. package/dist/src/runtime6.js +1 -0
  142. package/dist/src/runtime7.js +1 -0
  143. package/dist/src/screenshot-result.js +4 -4
  144. package/dist/src/screenshot.js +1 -0
  145. package/dist/src/sdk-android-adb.d.ts +20 -2
  146. package/dist/src/sdk-android-adb.js +2 -2
  147. package/dist/src/sdk-batch-runner.js +3 -3
  148. package/dist/src/sdk-contracts.d.ts +47 -6
  149. package/dist/src/sdk-contracts.js +1 -1
  150. package/dist/src/sdk-device.js +1 -1
  151. package/dist/src/sdk-finders.d.ts +4 -20
  152. package/dist/src/sdk-finders.js +1 -1
  153. package/dist/src/sdk-remote-config.js +1 -1
  154. package/dist/src/sdk-selectors.d.ts +601 -0
  155. package/dist/src/sdk-selectors.js +1 -1
  156. package/dist/src/selector-runtime.js +1 -1
  157. package/dist/src/selector-vocabulary.js +1 -1
  158. package/dist/src/selectors.d.ts +1 -46
  159. package/dist/src/selectors.js +1 -1
  160. package/dist/src/server.js +3 -3
  161. package/dist/src/session-target-evidence.js +1 -1
  162. package/dist/src/session.js +10 -9
  163. package/dist/src/shared.js +2 -0
  164. package/dist/src/shell-quote.js +1 -0
  165. package/dist/src/simulator.js +1 -1
  166. package/dist/src/snapshot-runtime.js +1 -0
  167. package/dist/src/snapshot-session.js +1 -0
  168. package/dist/src/snapshot.js +1 -1
  169. package/dist/src/snapshot2.js +1 -1
  170. package/dist/src/src.js +1 -1
  171. package/dist/src/src2.js +2 -0
  172. package/dist/src/src3.js +1 -0
  173. package/dist/src/text-surface.js +1 -0
  174. package/dist/src/timing-safe-equal.js +1 -0
  175. package/dist/src/tool-provider.js +3 -3
  176. package/dist/src/tool-provider2.js +1 -1
  177. package/dist/src/tool-provider3.js +1 -1
  178. package/dist/src/update-check.js +1 -1
  179. package/dist/src/version.js +1 -1
  180. package/dist/src/web.js +1 -1
  181. package/package.json +72 -50
  182. package/server.json +3 -3
  183. package/skills/agent-device/SKILL.md +6 -31
  184. package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.5.apk.sha256 +0 -1
  185. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.5.apk.sha256 +0 -1
  186. package/dist/apple/runner/AgentDeviceRunner/RecordingScripts/recording-resize.swift +0 -225
  187. package/dist/src/app-log-request-scope.js +0 -1
  188. package/dist/src/devices.js +0 -1
  189. package/dist/src/devices2.js +0 -1
  190. package/dist/src/devices3.js +0 -1
  191. package/dist/src/devices4.js +0 -1
  192. package/dist/src/interaction.d.ts +0 -230
  193. package/dist/src/provider-limrun-runtime.js +0 -1
  194. package/dist/src/register-builtins.js +0 -1
  195. package/dist/src/screenshot-geometry.js +0 -1
  196. package/dist/src/viewport-dimension.js +0 -14
package/README.md CHANGED
@@ -15,7 +15,7 @@
15
15
 
16
16
  Let your coding agent verify its changes in the running app.
17
17
 
18
- `agent-device` lets coding agents inspect, control, and verify apps on iOS, Android, tvOS, Android TV, Amazon Vega OS TV through the Vega Virtual Device (VVD), web, macOS, and Linux. Agents can read token-efficient accessibility snapshots where supported, find elements by ref or selector, run device actions, and save evidence for review. Initial Vega OS support is VVD-only and covers discovery, app lifecycle, and complete TV-remote control; physical Fire TV, capture, and selector backends remain unsupported.
18
+ `agent-device` lets coding agents inspect, control, and verify apps on iOS, Android, HarmonyOS, tvOS, Android TV, Amazon Vega OS TV through the Vega Virtual Device (VVD), web, macOS, and Linux. Agents can read token-efficient accessibility snapshots where supported, find elements by ref or selector, run device actions, and save evidence for review. HarmonyOS support uses HDC and ArkUI `uitest` on connected devices and DevEco emulators; use `capabilities --platform harmonyos` to inspect its evidence-backed command subset. Initial Vega OS support is VVD-only and covers discovery, app lifecycle, and complete TV-remote control; physical Fire TV, capture, and selector backends remain unsupported.
19
19
 
20
20
  Your coding agent or QA tool reads each result and chooses the next command. `agent-device` runs the command and saves evidence when asked.
21
21
 
@@ -61,6 +61,8 @@ agent-device close
61
61
 
62
62
  Use refs only from the latest output. Do not assume an earlier `@eN` still identifies the same element. After a command with `--settle`, use the refs in its diff. Take another snapshot only if the diff omits what you need.
63
63
 
64
+ `--settle` works the same way on `scroll` and `back`, so scroll-then-observe and back-then-observe are one call too.
65
+
64
66
  Snapshots use the app's accessibility tree. Clear labels, roles, and test IDs make agent runs more reliable. Use screenshots and videos as evidence or when accessibility data is poor. Use refs and selectors for actions and assertions when you can.
65
67
 
66
68
  ![agent-device demo showing Codex using agent-device to create a new contact in the iOS Contacts app from a simple prompt](./website/docs/public/agent-device-contacts.gif)
@@ -107,7 +109,7 @@ See [Commands](https://oss.callstack.com/agent-device/docs/commands) for the com
107
109
 
108
110
  ## How it works
109
111
 
110
- `agent-device` keeps device state in sessions. It sends commands to XCTest on iOS and tvOS, ADB and the snapshot helper on Android, Vega CLI/VDA on the Vega Virtual Device, a local helper on macOS, and AT-SPI on Linux.
112
+ `agent-device` keeps device state in sessions. It sends commands to XCTest on iOS and tvOS, ADB and the snapshot helper on Android, HDC and ArkUI `uitest` on HarmonyOS, Vega CLI/VDA on the Vega Virtual Device, a local helper on macOS, and AT-SPI on Linux.
111
113
 
112
114
  Node.js apps can use the typed client or public subpaths. `agent-device/android-adb` provides the Android ADB provider interface, helpers for logcat, the clipboard, the keyboard, and apps, and port reverse management.
113
115
 
@@ -115,7 +117,7 @@ Node.js apps can use the typed client or public subpaths. `agent-device/android-
115
117
 
116
118
  ### What is agent-device?
117
119
 
118
- `agent-device` is a command-line tool that lets coding agents inspect, control, and verify apps and save evidence for review. It supports iOS, Android, TV, web, macOS, and Linux.
120
+ `agent-device` is a command-line tool that lets coding agents inspect, control, and verify apps and save evidence for review. It supports iOS, Android, HarmonyOS, TV, web, macOS, and Linux.
119
121
 
120
122
  ### Does it work with React Native, Expo, Flutter, and native apps?
121
123
 
@@ -0,0 +1 @@
1
+ 7311d6a527bdf8be33b752e59e73f4a527585654f8d530d3680ab15ccf271cb0 agent-device-android-ime-helper-0.20.7.apk
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "android-ime-helper",
3
- "version": "0.20.5",
4
- "assetName": "agent-device-android-ime-helper-0.20.5.apk",
5
- "sha256": "1f5a95fcf0c6d668a11453644b2e897147932b528c1aa6c74883eaf9d73a5e7f",
3
+ "version": "0.20.7",
4
+ "assetName": "agent-device-android-ime-helper-0.20.7.apk",
5
+ "sha256": "7311d6a527bdf8be33b752e59e73f4a527585654f8d530d3680ab15ccf271cb0",
6
6
  "packageName": "com.callstack.agentdevice.imehelper",
7
- "versionCode": 20005,
7
+ "versionCode": 20007,
8
8
  "serviceComponent": "com.callstack.agentdevice.imehelper/.TestInputMethodService",
9
9
  "broadcastProtocol": "android-ime-helper-v1"
10
10
  }
@@ -0,0 +1 @@
1
+ c45f72eea93c19b4a17fedb4b25f880d5e225c9ab41be4017db8613fdd276e09 agent-device-android-snapshot-helper-0.20.7.apk
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "android-snapshot-helper",
3
- "version": "0.20.5",
4
- "releaseTag": "v0.20.5",
5
- "assetName": "agent-device-android-snapshot-helper-0.20.5.apk",
3
+ "version": "0.20.7",
4
+ "releaseTag": "v0.20.7",
5
+ "assetName": "agent-device-android-snapshot-helper-0.20.7.apk",
6
6
  "apkUrl": null,
7
- "sha256": "ce370af9f1c97e7c812cb93772f864596731c10f3d0b7cadc1c88b772a062970",
8
- "checksumName": "agent-device-android-snapshot-helper-0.20.5.apk.sha256",
7
+ "sha256": "c45f72eea93c19b4a17fedb4b25f880d5e225c9ab41be4017db8613fdd276e09",
8
+ "checksumName": "agent-device-android-snapshot-helper-0.20.7.apk.sha256",
9
9
  "packageName": "com.callstack.agentdevice.snapshothelper",
10
- "versionCode": 20005,
10
+ "versionCode": 20007,
11
11
  "instrumentationRunner": "com.callstack.agentdevice.snapshothelper/.SnapshotInstrumentation",
12
12
  "minSdk": 23,
13
13
  "targetSdk": 36,
@@ -62,6 +62,13 @@ int main(int argc, const char *argv[]) {
62
62
 
63
63
  @implementation AgentDeviceRunnerViewController
64
64
 
65
+ - (void)agentDeviceTextEntryDidChange:(UITextField *)textField {
66
+ if ([NSProcessInfo.processInfo.arguments containsObject:@"--agent-device-text-entry-disappear-after-input"] &&
67
+ textField.text.length > 0) {
68
+ [textField removeFromSuperview];
69
+ }
70
+ }
71
+
65
72
  - (void)viewDidLoad {
66
73
  [super viewDidLoad];
67
74
 
@@ -78,6 +85,47 @@ int main(int argc, const char *argv[]) {
78
85
  [label.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor],
79
86
  [label.centerYAnchor constraintEqualToAnchor:self.view.centerYAnchor],
80
87
  ]];
88
+
89
+ // Keep the fixture behind a launch argument so normal runner snapshots remain unchanged.
90
+ #if TARGET_OS_IOS
91
+ if ([NSProcessInfo.processInfo.arguments containsObject:@"--agent-device-text-entry-regression"]) {
92
+ UITextField *textField = [[UITextField alloc] init];
93
+ textField.accessibilityIdentifier = @"agent-device-hardware-keyboard-input";
94
+ textField.borderStyle = UITextBorderStyleRoundedRect;
95
+ textField.inputView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1, 1)];
96
+ [textField addTarget:self
97
+ action:@selector(agentDeviceTextEntryDidChange:)
98
+ forControlEvents:UIControlEventEditingChanged];
99
+ textField.translatesAutoresizingMaskIntoConstraints = NO;
100
+ [self.view addSubview:textField];
101
+ [NSLayoutConstraint activateConstraints:@[
102
+ [textField.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor],
103
+ [textField.topAnchor constraintEqualToAnchor:label.bottomAnchor constant:24],
104
+ [textField.widthAnchor constraintEqualToConstant:240],
105
+ [textField.heightAnchor constraintEqualToConstant:44],
106
+ ]];
107
+ }
108
+
109
+ if ([NSProcessInfo.processInfo.arguments containsObject:@"--agent-device-selector-read-regression"]) {
110
+ NSString *const duplicateIdentifier = @"agent-device-selector-read-duplicate";
111
+
112
+ UIButton *visibleButton = [UIButton buttonWithType:UIButtonTypeSystem];
113
+ visibleButton.accessibilityIdentifier = duplicateIdentifier;
114
+ [visibleButton setTitle:@"Readable target" forState:UIControlStateNormal];
115
+ visibleButton.translatesAutoresizingMaskIntoConstraints = NO;
116
+ [self.view addSubview:visibleButton];
117
+
118
+ UILabel *offscreenLabel = [[UILabel alloc] initWithFrame:CGRectMake(-200, -200, 100, 40)];
119
+ offscreenLabel.accessibilityIdentifier = duplicateIdentifier;
120
+ offscreenLabel.text = @"Decorative duplicate";
121
+ [self.view addSubview:offscreenLabel];
122
+
123
+ [NSLayoutConstraint activateConstraints:@[
124
+ [visibleButton.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor],
125
+ [visibleButton.topAnchor constraintEqualToAnchor:label.bottomAnchor constant:24],
126
+ ]];
127
+ }
128
+ #endif
81
129
  }
82
130
 
83
131
  @end
@@ -1,3 +1,4 @@
1
1
  #import "RunnerObjCExceptionCatcher.h"
2
2
  #import "RunnerAXSnapshotBridge.h"
3
3
  #import "RunnerSynthesizedGesture.h"
4
+ #import "RunnerSynthesizedTextEntry.h"
@@ -1,16 +1,123 @@
1
1
  #import <Foundation/Foundation.h>
2
+ #import <CoreGraphics/CoreGraphics.h>
2
3
  #import <XCTest/XCTest.h>
3
4
 
4
5
  NS_ASSUME_NONNULL_BEGIN
5
6
 
7
+ /// Keys of the `deepExtension` dictionary in the snapshot response, shared
8
+ /// with the Swift consumer so the response shape has one spelling.
9
+ FOUNDATION_EXPORT NSString *const RunnerAXSnapshotDeepExtensionKey;
10
+ FOUNDATION_EXPORT NSString *const RunnerAXSnapshotDeepExtensionCallsKey;
11
+ FOUNDATION_EXPORT NSString *const RunnerAXSnapshotDeepExtensionNodesAddedKey;
12
+ FOUNDATION_EXPORT NSString *const RunnerAXSnapshotDeepExtensionPendingKey;
13
+ FOUNDATION_EXPORT NSString *const RunnerAXSnapshotDeepExtensionMissedKey;
14
+
15
+ /// Keys of the `customActions` dictionary in the snapshot response: how many
16
+ /// merged elements were eligible for an action read, and how many the bounded
17
+ /// pass actually reached. Present only when the capture asked for actions.
18
+ FOUNDATION_EXPORT NSString *const RunnerAXSnapshotCustomActionsKey;
19
+ FOUNDATION_EXPORT NSString *const RunnerAXSnapshotCustomActionsReadKey;
20
+ FOUNDATION_EXPORT NSString *const RunnerAXSnapshotCustomActionsCandidatesKey;
21
+ FOUNDATION_EXPORT NSString *const RunnerAXSnapshotCustomActionsTruncatedKey;
22
+ FOUNDATION_EXPORT NSString *const RunnerAXSnapshotCustomActionsBlockedKey;
23
+
24
+ /// A depth-capped childless node awaiting an element-rooted follow-up request.
25
+ /// Public so the runner unit bundle can drive the extension's miss paths with
26
+ /// fabricated snapshots — the executed contract that missed frontiers are
27
+ /// counted, never silently dropped.
28
+ @interface RunnerAXSnapshotFrontier : NSObject
29
+ @property(nonatomic, strong, nullable) id snapshot;
30
+ @property(nonatomic, strong, nullable) NSMutableDictionary *node;
31
+ @property(nonatomic, assign) NSInteger depth;
32
+ @end
33
+
6
34
  @interface RunnerAXSnapshotBridge : NSObject
7
35
 
36
+ /// Captures the app's accessibility tree, then chains element-rooted follow-up
37
+ /// requests from depth-capped frontier nodes (the AX depth limit is
38
+ /// per-request, so re-rooting reaches content the app-rooted request could
39
+ /// not). The response gains a `deepExtension` {calls, nodesAdded,
40
+ /// pendingFrontiers, missedFrontiers} dictionary when any frontier existed and
41
+ /// the call limit allowed extension. Pass 0 to disable extension entirely.
42
+ ///
43
+ /// `customActionLimit` bounds the per-element custom-action reads described on
44
+ /// `customActionNamesForElement:axClient:`; pass 0 to skip them entirely.
8
45
  + (NSDictionary<NSString *, id> *)snapshotTreeForApplication:(XCUIApplication *)application
9
46
  maxDepth:(NSInteger)maxDepth
10
- maxNodes:(NSInteger)maxNodes;
47
+ maxNodes:(NSInteger)maxNodes
48
+ deepExtensionCallLimit:(NSInteger)deepExtensionCallLimit
49
+ customActionLimit:(NSInteger)customActionLimit
50
+ deadline:(nullable NSDate *)deadline;
51
+
52
+ /// Names of the element's UIAccessibilityCustomActions, or nil when it has
53
+ /// none.
54
+ ///
55
+ /// One element per call on purpose. The bulk snapshot request cannot carry this
56
+ /// attribute: adding it makes testmanagerd's reply decoder reject the nested
57
+ /// arrays a custom action serializes into ("value for key 'NS.objects' was of
58
+ /// unexpected class 'NSArray'"), drop the reply, and time the request out after
59
+ /// ~65s instead of the usual ~110ms. Per-element reads use a different XPC
60
+ /// message and answer normally.
61
+ ///
62
+ /// Reading is all we can do: the actions are not invocable from the runner.
63
+ /// XCUIElement exposes no custom-action API; XCAXClient_iOS's
64
+ /// performAction:onElement:value: answers kAXErrorCannotComplete for every AX
65
+ /// action number; setAttribute: on the custom-actions attribute reports success
66
+ /// and does nothing; parameterizedAttribute: answers kAXErrorNoValue; and the
67
+ /// raw AXUIElement C API cannot be aimed at app elements because
68
+ /// XCAccessibilityElement is token-based and answers nil for AXUIElement.
69
+ + (nullable NSArray<NSString *> *)customActionNamesForElement:(id)element
70
+ axClient:(id)axClient
71
+ completed:(BOOL *)completed;
72
+
73
+ /// Bounds one element's contribution to the response (max actions, max name
74
+ /// length). Reports whether anything was clipped so truncation is disclosed
75
+ /// rather than silently presented as a complete list.
76
+ + (NSArray<NSString *> *)cappedActionNames:(NSArray<NSString *> *)names
77
+ truncated:(BOOL *)truncated;
78
+
79
+ /// The bounded read pass over merged leaves, exposed for the runner unit
80
+ /// bundle: the containment contract (a hung read blocks the pass and is
81
+ /// disclosed, and adds no further dispatches) is only executable from here.
82
+ /// Returns {read, candidates, truncated, blocked}.
83
+ + (NSDictionary<NSString *, NSNumber *> *)
84
+ annotateCustomActionsOnMergedLeaves:(nullable NSArray<RunnerAXSnapshotFrontier *> *)leaves
85
+ axClient:(id)axClient
86
+ limit:(NSInteger)limit
87
+ rootFrame:(CGRect)rootFrame
88
+ deadline:(nullable NSDate *)deadline;
89
+
90
+ /// Reads dispatched but not yet returned. The AX call cannot be cancelled, so a
91
+ /// read that blew its deadline stays counted here until it finally returns —
92
+ /// which is precisely the state in which further reads must be refused rather
93
+ /// than queued behind it. Consumed by the read pass to disclose the skip.
94
+ + (NSInteger)customActionReadsInFlight;
95
+
96
+ /// Total reads ever dispatched. The containment invariant is "a blocked capture
97
+ /// adds no work", which is only observable as this counter standing still.
98
+ + (NSInteger)customActionReadDispatchCount;
99
+
100
+ /// The shared AX client (`XCUIDevice.accessibilityInterface`), or nil when the
101
+ /// private interface is unavailable.
102
+ + (nullable id)accessibilityClient;
11
103
 
12
104
  + (NSInteger)processIdentifierForApplication:(XCUIApplication *)application;
13
105
 
106
+ /// The frontier-extension loop, exposed for the runner unit bundle: a frontier
107
+ /// whose element vanished or whose re-rooted request fails must count as
108
+ /// missed (see the deepExtension keys above) — an all-miss extension reporting
109
+ /// itself drained would present a capped capture as complete.
110
+ + (nullable NSDictionary *)extendSnapshotFrontiers:(NSMutableArray<RunnerAXSnapshotFrontier *> *)frontiers
111
+ axClient:(id)axClient
112
+ attributes:(NSArray *)attributes
113
+ maxDepth:(NSInteger)maxDepth
114
+ maxNodes:(NSInteger)maxNodes
115
+ nodeCount:(NSInteger *)nodeCount
116
+ truncated:(BOOL *)truncated
117
+ callsAllowed:(NSInteger)callsAllowed
118
+ mergedLeaves:(nullable NSMutableArray<RunnerAXSnapshotFrontier *> *)mergedLeaves
119
+ deadline:(nullable NSDate *)deadline;
120
+
14
121
  @end
15
122
 
16
123
  NS_ASSUME_NONNULL_END