agent-device 0.16.8 → 0.16.10

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 (27) hide show
  1. package/README.md +1 -0
  2. package/android-multitouch-helper/dist/{agent-device-android-multitouch-helper-0.16.8.apk → agent-device-android-multitouch-helper-0.16.10.apk} +0 -0
  3. package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.16.10.apk.sha256 +1 -0
  4. package/android-multitouch-helper/dist/{agent-device-android-multitouch-helper-0.16.8.manifest.json → agent-device-android-multitouch-helper-0.16.10.manifest.json} +4 -4
  5. package/android-snapshot-helper/dist/{agent-device-android-snapshot-helper-0.16.8.apk → agent-device-android-snapshot-helper-0.16.10.apk} +0 -0
  6. package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.16.10.apk.sha256 +1 -0
  7. package/android-snapshot-helper/dist/{agent-device-android-snapshot-helper-0.16.8.manifest.json → agent-device-android-snapshot-helper-0.16.10.manifest.json} +6 -6
  8. package/dist/src/2415.js +19 -19
  9. package/dist/src/8114.js +3 -3
  10. package/dist/src/apps.js +2 -2
  11. package/dist/src/generic.js +4 -3
  12. package/dist/src/input-actions.js +1 -1
  13. package/dist/src/session.js +2 -2
  14. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +197 -232
  15. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandJournal.swift +282 -0
  16. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Exceptions.swift +29 -0
  17. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +8 -771
  18. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +30 -0
  19. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +2 -20
  20. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SystemModal.swift +10 -50
  21. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntry.swift +723 -0
  22. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Transport.swift +64 -22
  23. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests.swift +7 -4
  24. package/package.json +1 -1
  25. package/server.json +2 -2
  26. package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.16.8.apk.sha256 +0 -1
  27. package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.16.8.apk.sha256 +0 -1
@@ -19,7 +19,11 @@ extension RunnerTests {
19
19
  if buffer.count + data.count > self.maxRequestBytes {
20
20
  let response = self.jsonResponse(
21
21
  status: 413,
22
- response: Response(ok: false, error: ErrorPayload(message: "request too large"))
22
+ response: self.errorResponse(
23
+ code: "INVALID_ARGS",
24
+ message: "runner request body exceeds \(self.maxRequestBytes) bytes",
25
+ hint: "Send one runner command per request and keep the payload below the runner request limit."
26
+ )
23
27
  )
24
28
  self.sendResponse(response, over: connection) { [weak self] in
25
29
  self?.finish()
@@ -28,10 +32,11 @@ extension RunnerTests {
28
32
  }
29
33
  let combined = buffer + data
30
34
  if let body = self.parseRequest(data: combined) {
31
- let result = self.handleRequestBody(body)
32
- self.sendResponse(result.data, over: connection) { [weak self] in
33
- if result.shouldFinish {
34
- self?.finish()
35
+ self.handleRequestBody(body) { [weak self] result in
36
+ self?.sendResponse(result.data, over: connection) { [weak self] in
37
+ if result.shouldFinish {
38
+ self?.finish()
39
+ }
35
40
  }
36
41
  }
37
42
  } else {
@@ -82,29 +87,62 @@ extension RunnerTests {
82
87
  return nil
83
88
  }
84
89
 
85
- private func handleRequestBody(_ body: Data) -> (data: Data, shouldFinish: Bool) {
86
- guard let json = String(data: body, encoding: .utf8) else {
87
- return (
88
- jsonResponse(status: 400, response: Response(ok: false, error: ErrorPayload(message: "invalid json"))),
89
- false
90
- )
91
- }
92
- guard let data = json.data(using: .utf8) else {
93
- return (
94
- jsonResponse(status: 400, response: Response(ok: false, error: ErrorPayload(message: "invalid json"))),
90
+ private func handleRequestBody(
91
+ _ body: Data,
92
+ completion: @escaping ((data: Data, shouldFinish: Bool)) -> Void
93
+ ) {
94
+ guard String(data: body, encoding: .utf8) != nil else {
95
+ completion((
96
+ jsonResponse(
97
+ status: 400,
98
+ response: errorResponse(
99
+ code: "INVALID_ARGS",
100
+ message: "runner request body must be UTF-8 JSON",
101
+ hint: "Send a JSON object matching the runner command protocol."
102
+ )
103
+ ),
95
104
  false
96
- )
105
+ ))
106
+ return
97
107
  }
98
108
 
99
109
  do {
100
- let command = try JSONDecoder().decode(Command.self, from: data)
101
- let response = try execute(command: command)
102
- return (jsonResponse(status: 200, response: response), command.command == .shutdown)
110
+ let command = try JSONDecoder().decode(Command.self, from: body)
111
+ if command.command == .status {
112
+ completion((jsonResponse(status: 200, response: executeStatus(command: command)), false))
113
+ return
114
+ }
115
+ commandJournal.accept(command: command)
116
+ commandExecutionQueue.async {
117
+ do {
118
+ let response = try self.executeAccepted(command: command)
119
+ completion((self.jsonResponse(status: 200, response: response), command.command == .shutdown))
120
+ } catch {
121
+ completion((
122
+ self.jsonResponse(
123
+ status: 500,
124
+ response: self.errorResponse(
125
+ code: "COMMAND_FAILED",
126
+ message: error.localizedDescription,
127
+ hint: "Check the runner log for XCTest details, then retry after the app is foregrounded if this was a timeout or activation failure."
128
+ )
129
+ ),
130
+ false
131
+ ))
132
+ }
133
+ }
103
134
  } catch {
104
- return (
105
- jsonResponse(status: 500, response: Response(ok: false, error: ErrorPayload(message: "\(error)"))),
135
+ completion((
136
+ jsonResponse(
137
+ status: 400,
138
+ response: errorResponse(
139
+ code: "INVALID_ARGS",
140
+ message: "runner command payload is invalid: \(String(describing: error))",
141
+ hint: "Check the command name and fields against the runner protocol."
142
+ )
143
+ ),
106
144
  false
107
- )
145
+ ))
108
146
  }
109
147
  }
110
148
 
@@ -116,6 +154,10 @@ extension RunnerTests {
116
154
  return httpResponse(status: status, body: body)
117
155
  }
118
156
 
157
+ private func errorResponse(code: String, message: String, hint: String? = nil) -> Response {
158
+ Response(ok: false, error: ErrorPayload(code: code, message: message, hint: hint))
159
+ }
160
+
119
161
  private func httpResponse(status: Int, body: String) -> Data {
120
162
  let headers = [
121
163
  "HTTP/1.1 \(status) OK",
@@ -32,6 +32,8 @@ final class RunnerTests: XCTestCase {
32
32
  static let defaultRecordingFps: Int32 = 15
33
33
  var listener: NWListener?
34
34
  var doneExpectation: XCTestExpectation?
35
+ let transportQueue = DispatchQueue(label: "agent-device.runner.transport")
36
+ let commandExecutionQueue = DispatchQueue(label: "agent-device.runner.commands")
35
37
  let app = XCUIApplication()
36
38
  lazy var springboard = XCUIApplication(bundleIdentifier: Self.springboardBundleId)
37
39
  var currentApp: XCUIApplication?
@@ -53,6 +55,7 @@ final class RunnerTests: XCTestCase {
53
55
  var needsPostSnapshotInteractionDelay = false
54
56
  var needsFirstInteractionDelay = false
55
57
  var activeRecording: ScreenRecorder?
58
+ let commandJournal = RunnerCommandJournal()
56
59
  let interactiveTypes: Set<XCUIElement.ElementType> = [
57
60
  .button,
58
61
  .cell,
@@ -91,7 +94,6 @@ final class RunnerTests: XCTestCase {
91
94
  func testCommand() throws {
92
95
  doneExpectation = expectation(description: "agent-device command handled")
93
96
  NSLog("AGENT_DEVICE_RUNNER_HEADLESS_STARTUP=1")
94
- let queue = DispatchQueue(label: "agent-device.runner")
95
97
  let desiredPort = RunnerEnv.resolvePort()
96
98
  NSLog("AGENT_DEVICE_RUNNER_DESIRED_PORT=%d", desiredPort)
97
99
  listener = try makeRunnerListener(desiredPort: desiredPort)
@@ -112,10 +114,11 @@ final class RunnerTests: XCTestCase {
112
114
  }
113
115
  }
114
116
  listener?.newConnectionHandler = { [weak self] conn in
115
- conn.start(queue: queue)
116
- self?.handle(connection: conn)
117
+ guard let self else { return }
118
+ conn.start(queue: self.transportQueue)
119
+ self.handle(connection: conn)
117
120
  }
118
- listener?.start(queue: queue)
121
+ listener?.start(queue: transportQueue)
119
122
 
120
123
  guard let expectation = doneExpectation else {
121
124
  XCTFail("runner expectation was not initialized")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-device",
3
- "version": "0.16.8",
3
+ "version": "0.16.10",
4
4
  "description": "Agent-native CLI for AI mobile testing and app automation across iOS, Android, tvOS, Android TV, macOS, and Linux.",
5
5
  "mcpName": "io.github.callstackincubator/agent-device",
6
6
  "license": "MIT",
package/server.json CHANGED
@@ -7,12 +7,12 @@
7
7
  "url": "https://github.com/callstackincubator/agent-device",
8
8
  "source": "github"
9
9
  },
10
- "version": "0.16.8",
10
+ "version": "0.16.10",
11
11
  "packages": [
12
12
  {
13
13
  "registryType": "npm",
14
14
  "identifier": "agent-device",
15
- "version": "0.16.8",
15
+ "version": "0.16.10",
16
16
  "transport": {
17
17
  "type": "stdio"
18
18
  }
@@ -1 +0,0 @@
1
- 4e826fb21a7459738e33e4f51a331b9c53feed8b8612f0f46eb24319653cee6f agent-device-android-multitouch-helper-0.16.8.apk
@@ -1 +0,0 @@
1
- f7205d81add1147ea269b7e67d9a7fe7f56454775b3ba1503142349928b248ea agent-device-android-snapshot-helper-0.16.8.apk