@metamask/device-mcp 0.1.0 → 0.3.0

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 (156) hide show
  1. package/CHANGELOG.md +29 -14
  2. package/LICENSE +6 -0
  3. package/LICENSE.APACHE2 +201 -0
  4. package/LICENSE.MIT +21 -0
  5. package/README.md +114 -33
  6. package/dist/backends/adb-backend.cjs +21 -5
  7. package/dist/backends/adb-backend.cjs.map +1 -1
  8. package/dist/backends/adb-backend.d.cts +9 -2
  9. package/dist/backends/adb-backend.d.cts.map +1 -1
  10. package/dist/backends/adb-backend.d.mts +9 -2
  11. package/dist/backends/adb-backend.d.mts.map +1 -1
  12. package/dist/backends/adb-backend.mjs +21 -5
  13. package/dist/backends/adb-backend.mjs.map +1 -1
  14. package/dist/backends/appium-backend.cjs +25 -7
  15. package/dist/backends/appium-backend.cjs.map +1 -1
  16. package/dist/backends/appium-backend.d.cts +9 -2
  17. package/dist/backends/appium-backend.d.cts.map +1 -1
  18. package/dist/backends/appium-backend.d.mts +9 -2
  19. package/dist/backends/appium-backend.d.mts.map +1 -1
  20. package/dist/backends/appium-backend.mjs +25 -7
  21. package/dist/backends/appium-backend.mjs.map +1 -1
  22. package/dist/backends/idb-backend.cjs +96 -38
  23. package/dist/backends/idb-backend.cjs.map +1 -1
  24. package/dist/backends/idb-backend.d.cts +9 -2
  25. package/dist/backends/idb-backend.d.cts.map +1 -1
  26. package/dist/backends/idb-backend.d.mts +9 -2
  27. package/dist/backends/idb-backend.d.mts.map +1 -1
  28. package/dist/backends/idb-backend.mjs +97 -39
  29. package/dist/backends/idb-backend.mjs.map +1 -1
  30. package/dist/backends/index.cjs +37 -15
  31. package/dist/backends/index.cjs.map +1 -1
  32. package/dist/backends/index.d.cts +8 -11
  33. package/dist/backends/index.d.cts.map +1 -1
  34. package/dist/backends/index.d.mts +8 -11
  35. package/dist/backends/index.d.mts.map +1 -1
  36. package/dist/backends/index.mjs +38 -16
  37. package/dist/backends/index.mjs.map +1 -1
  38. package/dist/backends/types.cjs.map +1 -1
  39. package/dist/backends/types.d.cts +20 -1
  40. package/dist/backends/types.d.cts.map +1 -1
  41. package/dist/backends/types.d.mts +20 -1
  42. package/dist/backends/types.d.mts.map +1 -1
  43. package/dist/backends/types.mjs.map +1 -1
  44. package/dist/cli/device-mcp.cjs +11 -2
  45. package/dist/cli/device-mcp.cjs.map +1 -1
  46. package/dist/cli/device-mcp.mjs +11 -2
  47. package/dist/cli/device-mcp.mjs.map +1 -1
  48. package/dist/hermes/hermes-cdp.cjs +674 -0
  49. package/dist/hermes/hermes-cdp.cjs.map +1 -0
  50. package/dist/hermes/hermes-cdp.d.cts +248 -0
  51. package/dist/hermes/hermes-cdp.d.cts.map +1 -0
  52. package/dist/hermes/hermes-cdp.d.mts +248 -0
  53. package/dist/hermes/hermes-cdp.d.mts.map +1 -0
  54. package/dist/hermes/hermes-cdp.mjs +665 -0
  55. package/dist/hermes/hermes-cdp.mjs.map +1 -0
  56. package/dist/hermes/session.cjs +196 -0
  57. package/dist/hermes/session.cjs.map +1 -0
  58. package/dist/hermes/session.d.cts +163 -0
  59. package/dist/hermes/session.d.cts.map +1 -0
  60. package/dist/hermes/session.d.mts +163 -0
  61. package/dist/hermes/session.d.mts.map +1 -0
  62. package/dist/hermes/session.mjs +189 -0
  63. package/dist/hermes/session.mjs.map +1 -0
  64. package/dist/index.cjs +19 -1
  65. package/dist/index.cjs.map +1 -1
  66. package/dist/index.d.cts +8 -1
  67. package/dist/index.d.cts.map +1 -1
  68. package/dist/index.d.mts +8 -1
  69. package/dist/index.d.mts.map +1 -1
  70. package/dist/index.mjs +3 -0
  71. package/dist/index.mjs.map +1 -1
  72. package/dist/server.cjs +8 -0
  73. package/dist/server.cjs.map +1 -1
  74. package/dist/server.d.cts +2 -2
  75. package/dist/server.d.cts.map +1 -1
  76. package/dist/server.d.mts +2 -2
  77. package/dist/server.d.mts.map +1 -1
  78. package/dist/server.mjs +9 -1
  79. package/dist/server.mjs.map +1 -1
  80. package/dist/tools/get-element-text.cjs +46 -0
  81. package/dist/tools/get-element-text.cjs.map +1 -0
  82. package/dist/tools/get-element-text.d.cts +4 -0
  83. package/dist/tools/get-element-text.d.cts.map +1 -0
  84. package/dist/tools/get-element-text.d.mts +4 -0
  85. package/dist/tools/get-element-text.d.mts.map +1 -0
  86. package/dist/tools/get-element-text.mjs +43 -0
  87. package/dist/tools/get-element-text.mjs.map +1 -0
  88. package/dist/tools/hermes-cdp.cjs +102 -0
  89. package/dist/tools/hermes-cdp.cjs.map +1 -0
  90. package/dist/tools/hermes-cdp.d.cts +18 -0
  91. package/dist/tools/hermes-cdp.d.cts.map +1 -0
  92. package/dist/tools/hermes-cdp.d.mts +18 -0
  93. package/dist/tools/hermes-cdp.d.mts.map +1 -0
  94. package/dist/tools/hermes-cdp.mjs +99 -0
  95. package/dist/tools/hermes-cdp.mjs.map +1 -0
  96. package/dist/tools/hermes-targets.cjs +127 -0
  97. package/dist/tools/hermes-targets.cjs.map +1 -0
  98. package/dist/tools/hermes-targets.d.cts +20 -0
  99. package/dist/tools/hermes-targets.d.cts.map +1 -0
  100. package/dist/tools/hermes-targets.d.mts +20 -0
  101. package/dist/tools/hermes-targets.d.mts.map +1 -0
  102. package/dist/tools/hermes-targets.mjs +124 -0
  103. package/dist/tools/hermes-targets.mjs.map +1 -0
  104. package/dist/tools/index.cjs +11 -1
  105. package/dist/tools/index.cjs.map +1 -1
  106. package/dist/tools/index.d.cts +5 -0
  107. package/dist/tools/index.d.cts.map +1 -1
  108. package/dist/tools/index.d.mts +5 -0
  109. package/dist/tools/index.d.mts.map +1 -1
  110. package/dist/tools/index.mjs +5 -0
  111. package/dist/tools/index.mjs.map +1 -1
  112. package/dist/tools/list-devices.cjs +36 -0
  113. package/dist/tools/list-devices.cjs.map +1 -0
  114. package/dist/tools/list-devices.d.cts +4 -0
  115. package/dist/tools/list-devices.d.cts.map +1 -0
  116. package/dist/tools/list-devices.d.mts +4 -0
  117. package/dist/tools/list-devices.d.mts.map +1 -0
  118. package/dist/tools/list-devices.mjs +33 -0
  119. package/dist/tools/list-devices.mjs.map +1 -0
  120. package/dist/tools/screenshot.cjs +8 -3
  121. package/dist/tools/screenshot.cjs.map +1 -1
  122. package/dist/tools/screenshot.d.cts.map +1 -1
  123. package/dist/tools/screenshot.d.mts.map +1 -1
  124. package/dist/tools/screenshot.mjs +8 -3
  125. package/dist/tools/screenshot.mjs.map +1 -1
  126. package/dist/tools/select-device.cjs +38 -0
  127. package/dist/tools/select-device.cjs.map +1 -0
  128. package/dist/tools/select-device.d.cts +4 -0
  129. package/dist/tools/select-device.d.cts.map +1 -0
  130. package/dist/tools/select-device.d.mts +4 -0
  131. package/dist/tools/select-device.d.mts.map +1 -0
  132. package/dist/tools/select-device.mjs +35 -0
  133. package/dist/tools/select-device.mjs.map +1 -0
  134. package/dist/utils/exec.cjs +11 -9
  135. package/dist/utils/exec.cjs.map +1 -1
  136. package/dist/utils/exec.d.cts.map +1 -1
  137. package/dist/utils/exec.d.mts.map +1 -1
  138. package/dist/utils/exec.mjs +11 -9
  139. package/dist/utils/exec.mjs.map +1 -1
  140. package/dist/utils/output-path.cjs +128 -0
  141. package/dist/utils/output-path.cjs.map +1 -0
  142. package/dist/utils/output-path.d.cts +41 -0
  143. package/dist/utils/output-path.d.cts.map +1 -0
  144. package/dist/utils/output-path.d.mts +41 -0
  145. package/dist/utils/output-path.d.mts.map +1 -0
  146. package/dist/utils/output-path.mjs +123 -0
  147. package/dist/utils/output-path.mjs.map +1 -0
  148. package/dist/utils/platform.cjs +121 -36
  149. package/dist/utils/platform.cjs.map +1 -1
  150. package/dist/utils/platform.d.cts +14 -3
  151. package/dist/utils/platform.d.cts.map +1 -1
  152. package/dist/utils/platform.d.mts +14 -3
  153. package/dist/utils/platform.d.mts.map +1 -1
  154. package/dist/utils/platform.mjs +117 -36
  155. package/dist/utils/platform.mjs.map +1 -1
  156. package/package.json +2 -2
@@ -9,16 +9,21 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
9
9
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10
10
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
11
  };
12
- var _IdbBackend_connected, _IdbBackend_udid, _IdbBackend_recordingProcess, _IdbBackend_recordingPath;
12
+ var _IdbBackend_instances, _IdbBackend_connected, _IdbBackend_udid, _IdbBackend_idbPath, _IdbBackend_recordingProcess, _IdbBackend_recordingPath, _IdbBackend_getAppStateViaSimctl;
13
13
  import { execFile as execFileCb, spawn } from "node:child_process";
14
+ import { readFile } from "node:fs/promises";
14
15
  import { ACCEPT_LABELS, DENY_LABELS } from "../utils/alert-labels.mjs";
15
16
  import { findElement, describeElement, computeSwipeEnd } from "../utils/element.mjs";
16
- import { execStrict, exec, isCommandAvailable } from "../utils/exec.mjs";
17
+ import { execStrict, exec } from "../utils/exec.mjs";
18
+ import { hardenArtifactFile, resolveArtifactPath } from "../utils/output-path.mjs";
19
+ import { resolveIdbPath } from "../utils/platform.mjs";
17
20
  export class IdbBackend {
18
21
  constructor(udid) {
22
+ _IdbBackend_instances.add(this);
19
23
  this.platform = 'ios';
20
24
  _IdbBackend_connected.set(this, false);
21
25
  _IdbBackend_udid.set(this, void 0);
26
+ _IdbBackend_idbPath.set(this, 'idb');
22
27
  _IdbBackend_recordingProcess.set(this, null);
23
28
  _IdbBackend_recordingPath.set(this, null);
24
29
  __classPrivateFieldSet(this, _IdbBackend_udid, udid, "f");
@@ -27,16 +32,13 @@ export class IdbBackend {
27
32
  if (__classPrivateFieldGet(this, _IdbBackend_connected, "f")) {
28
33
  return;
29
34
  }
30
- if (!(await isCommandAvailable('idb'))) {
31
- throw new Error('idb is not installed.\n' +
32
- 'Install: brew tap facebook/fb && brew install idb-companion && pip3 install fb-idb');
33
- }
34
- await exec('idb', ['connect', __classPrivateFieldGet(this, _IdbBackend_udid, "f")]);
35
+ __classPrivateFieldSet(this, _IdbBackend_idbPath, await resolveIdbPath(), "f");
36
+ await exec(__classPrivateFieldGet(this, _IdbBackend_idbPath, "f"), ['connect', __classPrivateFieldGet(this, _IdbBackend_udid, "f")]);
35
37
  __classPrivateFieldSet(this, _IdbBackend_connected, true, "f");
36
38
  }
37
39
  async getDeviceInfo() {
38
40
  await this.ensureConnected();
39
- const raw = await execStrict('idb', [
41
+ const raw = await execStrict(__classPrivateFieldGet(this, _IdbBackend_idbPath, "f"), [
40
42
  'describe',
41
43
  '--udid',
42
44
  __classPrivateFieldGet(this, _IdbBackend_udid, "f"),
@@ -59,7 +61,7 @@ export class IdbBackend {
59
61
  }
60
62
  async snapshot() {
61
63
  await this.ensureConnected();
62
- const raw = await execStrict('idb', [
64
+ const raw = await execStrict(__classPrivateFieldGet(this, _IdbBackend_idbPath, "f"), [
63
65
  'ui',
64
66
  'describe-all',
65
67
  '--udid',
@@ -91,9 +93,19 @@ export class IdbBackend {
91
93
  targetDescription: describeElement(element),
92
94
  };
93
95
  }
96
+ async getElementText(query) {
97
+ await this.ensureConnected();
98
+ const snapshot = await this.snapshot();
99
+ const element = findElement(snapshot.hierarchy, query);
100
+ if (!element) {
101
+ throw new Error(`Element not found: ${JSON.stringify(query)}\n` +
102
+ 'Use device_snapshot to inspect the current UI hierarchy.');
103
+ }
104
+ return element.label ?? element.value ?? '';
105
+ }
94
106
  async tapCoordinates(x, y) {
95
107
  await this.ensureConnected();
96
- await execStrict('idb', [
108
+ await execStrict(__classPrivateFieldGet(this, _IdbBackend_idbPath, "f"), [
97
109
  'ui',
98
110
  'tap',
99
111
  String(x),
@@ -104,7 +116,7 @@ export class IdbBackend {
104
116
  }
105
117
  async typeText(text) {
106
118
  await this.ensureConnected();
107
- await exec('idb', [
119
+ await exec(__classPrivateFieldGet(this, _IdbBackend_idbPath, "f"), [
108
120
  'ui',
109
121
  'key-sequence',
110
122
  '--',
@@ -112,8 +124,8 @@ export class IdbBackend {
112
124
  '--udid',
113
125
  __classPrivateFieldGet(this, _IdbBackend_udid, "f"),
114
126
  ]);
115
- await exec('idb', ['ui', 'key', 'DELETE', '--udid', __classPrivateFieldGet(this, _IdbBackend_udid, "f")]);
116
- await execStrict('idb', ['ui', 'text', text, '--udid', __classPrivateFieldGet(this, _IdbBackend_udid, "f")]);
127
+ await exec(__classPrivateFieldGet(this, _IdbBackend_idbPath, "f"), ['ui', 'key', 'DELETE', '--udid', __classPrivateFieldGet(this, _IdbBackend_udid, "f")]);
128
+ await execStrict(__classPrivateFieldGet(this, _IdbBackend_idbPath, "f"), ['ui', 'text', text, '--udid', __classPrivateFieldGet(this, _IdbBackend_udid, "f")]);
117
129
  }
118
130
  async swipe(direction, startX, startY, distance) {
119
131
  await this.ensureConnected();
@@ -121,7 +133,7 @@ export class IdbBackend {
121
133
  const sx = startX ?? 200;
122
134
  const sy = startY ?? 400;
123
135
  const [endX, endY] = computeSwipeEnd(sx, sy, direction, d);
124
- await execStrict('idb', [
136
+ await execStrict(__classPrivateFieldGet(this, _IdbBackend_idbPath, "f"), [
125
137
  'ui',
126
138
  'swipe',
127
139
  String(sx),
@@ -146,33 +158,66 @@ export class IdbBackend {
146
158
  }
147
159
  async getAppState(bundleId) {
148
160
  await this.ensureConnected();
149
- const raw = await execStrict('idb', ['list-apps', '--udid', __classPrivateFieldGet(this, _IdbBackend_udid, "f")]);
150
- for (const line of raw.trim().split('\n')) {
151
- if (line.includes(bundleId)) {
152
- const parts = line.split('|').map((s) => s.trim());
153
- return {
154
- bundleId,
155
- state: parts[2] ?? 'Unknown',
156
- pid: parts[3] ? parseInt(parts[3], 10) : undefined,
157
- };
161
+ try {
162
+ const raw = await execStrict(__classPrivateFieldGet(this, _IdbBackend_idbPath, "f"), [
163
+ 'list-apps',
164
+ '--udid',
165
+ __classPrivateFieldGet(this, _IdbBackend_udid, "f"),
166
+ ]);
167
+ for (const line of raw.trim().split('\n')) {
168
+ if (line.includes(bundleId)) {
169
+ const parts = line.split('|').map((s) => s.trim());
170
+ return {
171
+ bundleId,
172
+ state: parts[2] ?? 'Unknown',
173
+ pid: parts[3] ? parseInt(parts[3], 10) : undefined,
174
+ };
175
+ }
158
176
  }
177
+ return { bundleId, state: 'Not Installed' };
178
+ }
179
+ catch {
180
+ return __classPrivateFieldGet(this, _IdbBackend_instances, "m", _IdbBackend_getAppStateViaSimctl).call(this, bundleId);
159
181
  }
160
- return { bundleId, state: 'Not Installed' };
161
182
  }
162
- async screenshot(outputPath) {
183
+ async screenshot(outputPath, options) {
163
184
  await this.ensureConnected();
164
- const path = outputPath ?? `/tmp/device-mcp-screenshot-${Date.now()}.png`;
165
- await execStrict('idb', ['screenshot', path, '--udid', __classPrivateFieldGet(this, _IdbBackend_udid, "f")]);
166
- const data = await execStrict('base64', [path]);
167
- return { data: data.trim(), format: 'png', path };
185
+ const path = resolveArtifactPath(outputPath, 'screenshot');
186
+ await execStrict(__classPrivateFieldGet(this, _IdbBackend_idbPath, "f"), ['screenshot', path, '--udid', __classPrivateFieldGet(this, _IdbBackend_udid, "f")]);
187
+ hardenArtifactFile(path);
188
+ if (options?.encode === false) {
189
+ return { data: undefined, format: 'png', path };
190
+ }
191
+ const data = await readFile(path, 'base64');
192
+ return { data, format: 'png', path };
168
193
  }
169
194
  async openApp(bundleId) {
170
195
  await this.ensureConnected();
171
- await execStrict('idb', ['launch', bundleId, '--udid', __classPrivateFieldGet(this, _IdbBackend_udid, "f")]);
196
+ try {
197
+ await execStrict(__classPrivateFieldGet(this, _IdbBackend_idbPath, "f"), [
198
+ 'launch',
199
+ bundleId,
200
+ '--udid',
201
+ __classPrivateFieldGet(this, _IdbBackend_udid, "f"),
202
+ ]);
203
+ }
204
+ catch {
205
+ await execStrict('xcrun', ['simctl', 'launch', __classPrivateFieldGet(this, _IdbBackend_udid, "f"), bundleId]);
206
+ }
172
207
  }
173
208
  async closeApp(bundleId) {
174
209
  await this.ensureConnected();
175
- await execStrict('idb', ['terminate', bundleId, '--udid', __classPrivateFieldGet(this, _IdbBackend_udid, "f")]);
210
+ try {
211
+ await execStrict(__classPrivateFieldGet(this, _IdbBackend_idbPath, "f"), [
212
+ 'terminate',
213
+ bundleId,
214
+ '--udid',
215
+ __classPrivateFieldGet(this, _IdbBackend_udid, "f"),
216
+ ]);
217
+ }
218
+ catch {
219
+ await execStrict('xcrun', ['simctl', 'terminate', __classPrivateFieldGet(this, _IdbBackend_udid, "f"), bundleId]);
220
+ }
176
221
  }
177
222
  async pressButton(button) {
178
223
  await this.ensureConnected();
@@ -182,7 +227,7 @@ export class IdbBackend {
182
227
  back: 'HOME',
183
228
  enter: 'RETURN',
184
229
  };
185
- await execStrict('idb', [
230
+ await execStrict(__classPrivateFieldGet(this, _IdbBackend_idbPath, "f"), [
186
231
  'ui',
187
232
  'key',
188
233
  keyMap[button],
@@ -192,7 +237,13 @@ export class IdbBackend {
192
237
  }
193
238
  async dismissKeyboard() {
194
239
  await this.ensureConnected();
195
- await execStrict('idb', ['ui', 'key', 'RETURN', '--udid', __classPrivateFieldGet(this, _IdbBackend_udid, "f")]);
240
+ await execStrict(__classPrivateFieldGet(this, _IdbBackend_idbPath, "f"), [
241
+ 'ui',
242
+ 'key',
243
+ 'RETURN',
244
+ '--udid',
245
+ __classPrivateFieldGet(this, _IdbBackend_udid, "f"),
246
+ ]);
196
247
  }
197
248
  async dismissAlert(accept) {
198
249
  await this.ensureConnected();
@@ -222,7 +273,7 @@ export class IdbBackend {
222
273
  if (filter) {
223
274
  args.push('--predicate', `eventMessage CONTAINS "${filter}"`);
224
275
  }
225
- const raw = await execStrict('idb', args);
276
+ const raw = await execStrict(__classPrivateFieldGet(this, _IdbBackend_idbPath, "f"), args);
226
277
  const entries = raw
227
278
  .trim()
228
279
  .split('\n')
@@ -244,7 +295,7 @@ export class IdbBackend {
244
295
  }
245
296
  const cx = Math.round(element.frame.x + element.frame.width / 2);
246
297
  const cy = Math.round(element.frame.y + element.frame.height / 2);
247
- await execStrict('idb', [
298
+ await execStrict(__classPrivateFieldGet(this, _IdbBackend_idbPath, "f"), [
248
299
  'ui',
249
300
  'tap',
250
301
  String(cx),
@@ -291,7 +342,7 @@ export class IdbBackend {
291
342
  }
292
343
  async getWindowSize() {
293
344
  await this.ensureConnected();
294
- const raw = await execStrict('idb', [
345
+ const raw = await execStrict(__classPrivateFieldGet(this, _IdbBackend_idbPath, "f"), [
295
346
  'describe',
296
347
  '--udid',
297
348
  __classPrivateFieldGet(this, _IdbBackend_udid, "f"),
@@ -341,9 +392,9 @@ export class IdbBackend {
341
392
  if (__classPrivateFieldGet(this, _IdbBackend_recordingProcess, "f")) {
342
393
  throw new Error('Screen recording is already in progress');
343
394
  }
344
- const path = outputPath ?? `/tmp/device-mcp-recording-${Date.now()}.mp4`;
395
+ const path = resolveArtifactPath(outputPath, 'recording');
345
396
  __classPrivateFieldSet(this, _IdbBackend_recordingPath, path, "f");
346
- __classPrivateFieldSet(this, _IdbBackend_recordingProcess, spawn('idb', [
397
+ __classPrivateFieldSet(this, _IdbBackend_recordingProcess, spawn(__classPrivateFieldGet(this, _IdbBackend_idbPath, "f"), [
347
398
  'record-video',
348
399
  path,
349
400
  '--udid',
@@ -363,10 +414,17 @@ export class IdbBackend {
363
414
  await new Promise((resolve) => setTimeout(resolve, 1000));
364
415
  __classPrivateFieldSet(this, _IdbBackend_recordingProcess, null, "f");
365
416
  __classPrivateFieldSet(this, _IdbBackend_recordingPath, null, "f");
417
+ hardenArtifactFile(path);
366
418
  return path;
367
419
  }
368
420
  }
369
- _IdbBackend_connected = new WeakMap(), _IdbBackend_udid = new WeakMap(), _IdbBackend_recordingProcess = new WeakMap(), _IdbBackend_recordingPath = new WeakMap();
421
+ _IdbBackend_connected = new WeakMap(), _IdbBackend_udid = new WeakMap(), _IdbBackend_idbPath = new WeakMap(), _IdbBackend_recordingProcess = new WeakMap(), _IdbBackend_recordingPath = new WeakMap(), _IdbBackend_instances = new WeakSet(), _IdbBackend_getAppStateViaSimctl = async function _IdbBackend_getAppStateViaSimctl(bundleId) {
422
+ const result = await exec('xcrun', ['simctl', 'listapps', __classPrivateFieldGet(this, _IdbBackend_udid, "f")]);
423
+ if (result.exitCode === 0 && result.stdout.includes(bundleId)) {
424
+ return { bundleId, state: 'Running' };
425
+ }
426
+ return { bundleId, state: 'Not Installed' };
427
+ };
370
428
  function collectAlertTexts(elements) {
371
429
  const texts = [];
372
430
  for (const el of elements) {
@@ -1 +1 @@
1
- {"version":3,"file":"idb-backend.mjs","sourceRoot":"","sources":["../../src/backends/idb-backend.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,OAAO,EAAE,QAAQ,IAAI,UAAU,EAAE,KAAK,EAAE,2BAA2B;AAgBnE,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,kCAAiC;AACtE,OAAO,EACL,WAAW,EACX,eAAe,EACf,eAAe,EAChB,6BAA4B;AAC7B,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,kBAAkB,EAAE,0BAAyB;AAExE,MAAM,OAAO,UAAU;IAWrB,YAAY,IAAY;QAVf,aAAQ,GAAG,KAAc,CAAC;QAEnC,gCAAa,KAAK,EAAC;QAEV,mCAAc;QAEvB,uCAAyC,IAAI,EAAC;QAE9C,oCAAgC,IAAI,EAAC;QAGnC,uBAAA,IAAI,oBAAS,IAAI,MAAA,CAAC;IACpB,CAAC;IAED,KAAK,CAAC,eAAe;QACnB,IAAI,uBAAA,IAAI,6BAAW,EAAE,CAAC;YACpB,OAAO;QACT,CAAC;QAED,IAAI,CAAC,CAAC,MAAM,kBAAkB,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;YACvC,MAAM,IAAI,KAAK,CACb,yBAAyB;gBACvB,oFAAoF,CACvF,CAAC;QACJ,CAAC;QAED,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC,SAAS,EAAE,uBAAA,IAAI,wBAAM,CAAC,CAAC,CAAC;QAC3C,uBAAA,IAAI,yBAAc,IAAI,MAAA,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,aAAa;QACjB,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC;QAC7B,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,KAAK,EAAE;YAClC,UAAU;YACV,QAAQ;YACR,uBAAA,IAAI,wBAAM;YACV,QAAQ;SACT,CAAC,CAAC;QACH,IAAI,IAA6B,CAAC;QAClC,IAAI,CAAC;YACH,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAA4B,CAAC;QACpD,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,KAAK,CACb,iDAAiD,uBAAA,IAAI,wBAAM,KAAK,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CACpF,CAAC;QACJ,CAAC;QACD,OAAO;YACL,QAAQ,EAAE,KAAK;YACf,QAAQ,EAAE,uBAAA,IAAI,wBAAM;YACpB,IAAI,EAAG,IAAI,CAAC,IAAe,IAAI,SAAS;YACxC,SAAS,EAAG,IAAI,CAAC,UAAqB,IAAI,SAAS;YACnD,KAAK,EAAG,IAAI,CAAC,KAAgB,IAAI,SAAS;SAC3C,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,QAAQ;QACZ,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC;QAC7B,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,KAAK,EAAE;YAClC,IAAI;YACJ,cAAc;YACd,QAAQ;YACR,uBAAA,IAAI,wBAAM;SACX,CAAC,CAAC;QACH,MAAM,SAAS,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC;QACzC,OAAO;YACL,QAAQ,EAAE,KAAK;YACf,SAAS;YACT,GAAG;YACH,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;SACtB,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,KAAmB;QAClC,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC;QAC7B,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;QACvC,MAAM,OAAO,GAAG,WAAW,CAAC,QAAQ,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QACvD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CACb,sBAAsB,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI;gBAC7C,0DAA0D,CAC7D,CAAC;QACJ,CAAC;QAED,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;QAChE,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACjE,MAAM,IAAI,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAEhC,OAAO;YACL,OAAO,EAAE,IAAI;YACb,CAAC;YACD,CAAC;YACD,iBAAiB,EAAE,eAAe,CAAC,OAAO,CAAC;SAC5C,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,CAAS,EAAE,CAAS;QACvC,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC;QAC7B,MAAM,UAAU,CAAC,KAAK,EAAE;YACtB,IAAI;YACJ,KAAK;YACL,MAAM,CAAC,CAAC,CAAC;YACT,MAAM,CAAC,CAAC,CAAC;YACT,QAAQ;YACR,uBAAA,IAAI,wBAAM;SACX,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,IAAY;QACzB,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC;QAC7B,MAAM,IAAI,CAAC,KAAK,EAAE;YAChB,IAAI;YACJ,cAAc;YACd,IAAI;YACJ,OAAO;YACP,QAAQ;YACR,uBAAA,IAAI,wBAAM;SACX,CAAC,CAAC;QACH,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,uBAAA,IAAI,wBAAM,CAAC,CAAC,CAAC;QACjE,MAAM,UAAU,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,uBAAA,IAAI,wBAAM,CAAC,CAAC,CAAC;IACtE,CAAC;IAED,KAAK,CAAC,KAAK,CACT,SAA2C,EAC3C,MAAe,EACf,MAAe,EACf,QAAiB;QAEjB,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC;QAC7B,MAAM,CAAC,GAAG,QAAQ,IAAI,GAAG,CAAC;QAC1B,MAAM,EAAE,GAAG,MAAM,IAAI,GAAG,CAAC;QACzB,MAAM,EAAE,GAAG,MAAM,IAAI,GAAG,CAAC;QACzB,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,eAAe,CAAC,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC;QAE3D,MAAM,UAAU,CAAC,KAAK,EAAE;YACtB,IAAI;YACJ,OAAO;YACP,MAAM,CAAC,EAAE,CAAC;YACV,MAAM,CAAC,EAAE,CAAC;YACV,MAAM,CAAC,IAAI,CAAC;YACZ,MAAM,CAAC,IAAI,CAAC;YACZ,QAAQ;YACR,uBAAA,IAAI,wBAAM;SACX,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,cAAc,CAClB,KAAmB,EACnB,SAAS,GAAG,KAAM,EAClB,UAAU,GAAG,GAAG;QAEhB,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,SAAS,EAAE,CAAC;YACtC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;YACvC,MAAM,OAAO,GAAG,WAAW,CAAC,QAAQ,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;YACvD,IAAI,OAAO,EAAE,CAAC;gBACZ,OAAO,OAAO,CAAC;YACjB,CAAC;YACD,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC;QAClE,CAAC;QACD,MAAM,IAAI,KAAK,CACb,kCAAkC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,SAAS,KAAK,CAC3E,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,QAAgB;QAChC,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC;QAC7B,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,KAAK,EAAE,CAAC,WAAW,EAAE,QAAQ,EAAE,uBAAA,IAAI,wBAAM,CAAC,CAAC,CAAC;QAEzE,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1C,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC5B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;gBACnD,OAAO;oBACL,QAAQ;oBACR,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,SAAS;oBAC5B,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS;iBACnD,CAAC;YACJ,CAAC;QACH,CAAC;QAED,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,eAAe,EAAE,CAAC;IAC9C,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,UAAmB;QAClC,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC;QAC7B,MAAM,IAAI,GAAG,UAAU,IAAI,8BAA8B,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC;QAC1E,MAAM,UAAU,CAAC,KAAK,EAAE,CAAC,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,uBAAA,IAAI,wBAAM,CAAC,CAAC,CAAC;QACpE,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;QAChD,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IACpD,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,QAAgB;QAC5B,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC;QAC7B,MAAM,UAAU,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,uBAAA,IAAI,wBAAM,CAAC,CAAC,CAAC;IACtE,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,QAAgB;QAC7B,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC;QAC7B,MAAM,UAAU,CAAC,KAAK,EAAE,CAAC,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,uBAAA,IAAI,wBAAM,CAAC,CAAC,CAAC;IACzE,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,MAAoB;QACpC,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC;QAC7B,MAAM,MAAM,GAAiC;YAC3C,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,MAAM;YACZ,KAAK,EAAE,QAAQ;SAChB,CAAC;QACF,MAAM,UAAU,CAAC,KAAK,EAAE;YACtB,IAAI;YACJ,KAAK;YACL,MAAM,CAAC,MAAM,CAAC;YACd,QAAQ;YACR,uBAAA,IAAI,wBAAM;SACX,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,eAAe;QACnB,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC;QAC7B,MAAM,UAAU,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,uBAAA,IAAI,wBAAM,CAAC,CAAC,CAAC;IACzE,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,MAAe;QAChC,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC;QAC7B,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;QACnC,MAAM,UAAU,GAAG,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,WAAW,CAAC;QAExD,KAAK,MAAM,KAAK,IAAI,UAAU,EAAE,CAAC;YAC/B,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;YACvD,IAAI,OAAO,EAAE,CAAC;gBACZ,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;gBACjE,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;gBAClE,MAAM,IAAI,CAAC,cAAc,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;gBAClC,OAAO;YACT,CAAC;QACH,CAAC;QAED,MAAM,IAAI,KAAK,CAAC,iCAAiC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC5E,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,eAAe,GAAG,EAAE,EAAE,MAAe;QACjD,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC;QAC7B,MAAM,IAAI,GAAG;YACX,KAAK;YACL,QAAQ;YACR,uBAAA,IAAI,wBAAM;YACV,IAAI;YACJ,QAAQ;YACR,GAAG,eAAe,GAAG;SACtB,CAAC;QACF,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,0BAA0B,MAAM,GAAG,CAAC,CAAC;QAChE,CAAC;QACD,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QAC1C,MAAM,OAAO,GAAG,GAAG;aAChB,IAAI,EAAE;aACN,KAAK,CAAC,IAAI,CAAC;aACX,MAAM,CAAC,OAAO,CAAC;aACf,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YACd,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE;YACvC,KAAK,EAAE,MAAM;YACb,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE;SACnC,CAAC,CAAC,CAAC;QACN,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IACxC,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,KAAmB,EAAE,UAAU,GAAG,IAAI;QACpD,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC;QAC7B,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;QACnC,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QACnD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CACb,sBAAsB,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI;gBAC7C,0DAA0D,CAC7D,CAAC;QACJ,CAAC;QAED,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;QACjE,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAClE,MAAM,UAAU,CAAC,KAAK,EAAE;YACtB,IAAI;YACJ,KAAK;YACL,MAAM,CAAC,EAAE,CAAC;YACV,MAAM,CAAC,EAAE,CAAC;YACV,YAAY;YACZ,MAAM,CAAC,UAAU,GAAG,IAAI,CAAC;YACzB,QAAQ;YACR,uBAAA,IAAI,wBAAM;SACX,CAAC,CAAC;QAEH,OAAO;YACL,OAAO,EAAE,IAAI;YACb,CAAC,EAAE,EAAE;YACL,CAAC,EAAE,EAAE;YACL,iBAAiB,EAAE,eAAe,CAAC,OAAO,CAAC;SAC5C,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,eAAe,CACnB,KAAmB,EACnB,YAA2B,MAAM,EACjC,WAAW,GAAG,EAAE;QAEhB,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC;QAC7B,IAAI,WAAW,GAAG,EAAE,CAAC;QAErB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,EAAE,CAAC,EAAE,EAAE,CAAC;YACrC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnC,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;YACnD,IAAI,OAAO,EAAE,CAAC;gBACZ,OAAO,OAAO,CAAC;YACjB,CAAC;YACD,IAAI,IAAI,CAAC,GAAG,KAAK,WAAW,EAAE,CAAC;gBAC7B,MAAM;YACR,CAAC;YACD,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC;YACvB,MAAM,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QAC9B,CAAC;QACD,MAAM,IAAI,KAAK,CACb,sCAAsC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI;YAC7D,0DAA0D,CAC7D,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,YAAY;QAChB,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC;QAC7B,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;QACnC,MAAM,KAAK,GAAG,iBAAiB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAChD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CACb,oCAAoC;gBAClC,0DAA0D,CAC7D,CAAC;QACJ,CAAC;QACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED,KAAK,CAAC,aAAa;QACjB,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC;QAC7B,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,KAAK,EAAE;YAClC,UAAU;YACV,QAAQ;YACR,uBAAA,IAAI,wBAAM;YACV,QAAQ;SACT,CAAC,CAAC;QACH,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAA4B,CAAC;YACxD,MAAM,IAAI,GAAG,IAAI,CAAC,iBAEL,CAAC;YACd,IAAI,IAAI,EAAE,KAAK,IAAI,IAAI,EAAE,MAAM,EAAE,CAAC;gBAChC,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC;YACpD,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,0CAA0C;QAC5C,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;QACnC,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9B,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;YAC/B,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAClD,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YAChE,CAAC;QACH,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;IACjE,CAAC;IAED,KAAK,CAAC,WAAW;QACf,OAAO,CAAC,YAAY,CAAC,CAAC;IACxB,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,OAAe;QAC9B,IAAI,OAAO,KAAK,YAAY,EAAE,CAAC;YAC7B,OAAO;QACT,CAAC;QACD,MAAM,IAAI,KAAK,CACb,0EAA0E,CAC3E,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,YAAY;QAChB,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC;QAC7B,OAAO,UAAU,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,uBAAA,IAAI,wBAAM,CAAC,CAAC,CAAC;IAChE,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,IAAY;QAC7B,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC;QAC7B,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC1C,MAAM,IAAI,GAAG,UAAU,CACrB,OAAO,EACP,CAAC,QAAQ,EAAE,QAAQ,EAAE,uBAAA,IAAI,wBAAM,CAAC,EAChC,EAAE,OAAO,EAAE,KAAM,EAAE,EACnB,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAClE,CAAC;YACF,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;QACxB,CAAC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,oBAAoB,CAAC,UAAmB;QAC5C,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC;QAC7B,IAAI,uBAAA,IAAI,oCAAkB,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;QAC7D,CAAC;QACD,MAAM,IAAI,GAAG,UAAU,IAAI,6BAA6B,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC;QACzE,uBAAA,IAAI,6BAAkB,IAAI,MAAA,CAAC;QAC3B,uBAAA,IAAI,gCAAqB,KAAK,CAAC,KAAK,EAAE;YACpC,cAAc;YACd,IAAI;YACJ,QAAQ;YACR,uBAAA,IAAI,wBAAM;SACX,CAAC,MAAA,CAAC;QACH,uBAAA,IAAI,oCAAkB,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YACtC,uBAAA,IAAI,gCAAqB,IAAI,MAAA,CAAC;YAC9B,uBAAA,IAAI,6BAAkB,IAAI,MAAA,CAAC;QAC7B,CAAC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,mBAAmB;QACvB,IAAI,CAAC,uBAAA,IAAI,oCAAkB,IAAI,CAAC,uBAAA,IAAI,iCAAe,EAAE,CAAC;YACpD,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;QACrD,CAAC;QACD,MAAM,IAAI,GAAG,uBAAA,IAAI,iCAAe,CAAC;QACjC,uBAAA,IAAI,oCAAkB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACtC,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;QAC1D,uBAAA,IAAI,gCAAqB,IAAI,MAAA,CAAC;QAC9B,uBAAA,IAAI,6BAAkB,IAAI,MAAA,CAAC;QAC3B,OAAO,IAAI,CAAC;IACd,CAAC;CACF;;AAED,SAAS,iBAAiB,CAAC,QAAqB;IAC9C,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,EAAE,IAAI,QAAQ,EAAE,CAAC;QAC1B,MAAM,gBAAgB,GACpB,EAAE,CAAC,IAAI,KAAK,OAAO,IAAI,EAAE,CAAC,IAAI,KAAK,OAAO,IAAI,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAC1E,IAAI,gBAAgB,EAAE,CAAC;YACrB,wBAAwB,CAAC,EAAE,CAAC,QAAQ,IAAI,EAAE,EAAE,KAAK,CAAC,CAAC;YACnD,OAAO,KAAK,CAAC;QACf,CAAC;QACD,IAAI,EAAE,CAAC,QAAQ,EAAE,CAAC;YAChB,MAAM,KAAK,GAAG,iBAAiB,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC;YAC7C,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACrB,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,wBAAwB,CAC/B,QAAqB,EACrB,KAAe;IAEf,KAAK,MAAM,EAAE,IAAI,QAAQ,EAAE,CAAC;QAC1B,IAAI,EAAE,CAAC,IAAI,KAAK,YAAY,IAAI,EAAE,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YACvD,MAAM,IAAI,GAAG,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,KAAK,CAAC;YAClC,IAAI,IAAI,EAAE,CAAC;gBACT,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACnB,CAAC;QACH,CAAC;QACD,IAAI,EAAE,CAAC,QAAQ,EAAE,CAAC;YAChB,wBAAwB,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,GAAW;IAC3C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC/B,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAC1B,OAAO,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QACnC,CAAC;QACD,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YACpB,OAAO,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QAC5C,CAAC;QACD,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;YACL;gBACE,IAAI,EAAE,KAAK;gBACX,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;gBACxB,KAAK,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE;gBAC1C,OAAO,EAAE,IAAI;aACd;SACF,CAAC;IACJ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,IAA6B;IACzD,MAAM,KAAK,GAAG,IAAI,CAAC,KAEN,CAAC;IAEd,OAAO;QACL,IAAI,EAAG,IAAI,CAAC,IAAe,IAAK,IAAI,CAAC,MAAiB,IAAI,SAAS;QACnE,KAAK,EAAG,IAAI,CAAC,OAAkB,IAAK,IAAI,CAAC,KAAgB,IAAI,SAAS;QACtE,KAAK,EAAG,IAAI,CAAC,OAAkB,IAAK,IAAI,CAAC,KAAgB,IAAI,SAAS;QACtE,UAAU,EACP,IAAI,CAAC,UAAqB,IAAK,IAAI,CAAC,UAAqB,IAAI,SAAS;QACzE,KAAK,EAAE,KAAK,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE;QACnD,OAAO,EAAG,IAAI,CAAC,OAAmB,IAAI,IAAI;QAC1C,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC;YACpC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,aAAa,CAAC;YAClC,CAAC,CAAC,SAAS;KACd,CAAC;AACJ,CAAC","sourcesContent":["import { execFile as execFileCb, spawn } from 'node:child_process';\nimport type { ChildProcess } from 'node:child_process';\n\nimport type {\n DeviceBackend,\n DeviceButton,\n DeviceInfo,\n SnapshotResult,\n ScreenshotResult,\n LogsResult,\n TapResult,\n AppStateResult,\n ElementQuery,\n UIElement,\n WindowSize,\n} from './types.js';\nimport { ACCEPT_LABELS, DENY_LABELS } from '../utils/alert-labels.js';\nimport {\n findElement,\n describeElement,\n computeSwipeEnd,\n} from '../utils/element.js';\nimport { execStrict, exec, isCommandAvailable } from '../utils/exec.js';\n\nexport class IdbBackend implements DeviceBackend {\n readonly platform = 'ios' as const;\n\n #connected = false;\n\n readonly #udid: string;\n\n #recordingProcess: ChildProcess | null = null;\n\n #recordingPath: string | null = null;\n\n constructor(udid: string) {\n this.#udid = udid;\n }\n\n async ensureConnected(): Promise<void> {\n if (this.#connected) {\n return;\n }\n\n if (!(await isCommandAvailable('idb'))) {\n throw new Error(\n 'idb is not installed.\\n' +\n 'Install: brew tap facebook/fb && brew install idb-companion && pip3 install fb-idb',\n );\n }\n\n await exec('idb', ['connect', this.#udid]);\n this.#connected = true;\n }\n\n async getDeviceInfo(): Promise<DeviceInfo> {\n await this.ensureConnected();\n const raw = await execStrict('idb', [\n 'describe',\n '--udid',\n this.#udid,\n '--json',\n ]);\n let info: Record<string, unknown>;\n try {\n info = JSON.parse(raw) as Record<string, unknown>;\n } catch {\n throw new Error(\n `idb describe returned invalid JSON for device ${this.#udid}: ${raw.slice(0, 200)}`,\n );\n }\n return {\n platform: 'ios',\n deviceId: this.#udid,\n name: (info.name as string) ?? 'Unknown',\n osVersion: (info.os_version as string) ?? 'Unknown',\n state: (info.state as string) ?? 'Unknown',\n };\n }\n\n async snapshot(): Promise<SnapshotResult> {\n await this.ensureConnected();\n const raw = await execStrict('idb', [\n 'ui',\n 'describe-all',\n '--udid',\n this.#udid,\n ]);\n const hierarchy = parseIdbHierarchy(raw);\n return {\n platform: 'ios',\n hierarchy,\n raw,\n timestamp: Date.now(),\n };\n }\n\n async tapElement(query: ElementQuery): Promise<TapResult> {\n await this.ensureConnected();\n const snapshot = await this.snapshot();\n const element = findElement(snapshot.hierarchy, query);\n if (!element) {\n throw new Error(\n `Element not found: ${JSON.stringify(query)}\\n` +\n 'Use device_snapshot to inspect the current UI hierarchy.',\n );\n }\n\n const x = Math.round(element.frame.x + element.frame.width / 2);\n const y = Math.round(element.frame.y + element.frame.height / 2);\n await this.tapCoordinates(x, y);\n\n return {\n success: true,\n x,\n y,\n targetDescription: describeElement(element),\n };\n }\n\n async tapCoordinates(x: number, y: number): Promise<void> {\n await this.ensureConnected();\n await execStrict('idb', [\n 'ui',\n 'tap',\n String(x),\n String(y),\n '--udid',\n this.#udid,\n ]);\n }\n\n async typeText(text: string): Promise<void> {\n await this.ensureConnected();\n await exec('idb', [\n 'ui',\n 'key-sequence',\n '--',\n 'cmd+a',\n '--udid',\n this.#udid,\n ]);\n await exec('idb', ['ui', 'key', 'DELETE', '--udid', this.#udid]);\n await execStrict('idb', ['ui', 'text', text, '--udid', this.#udid]);\n }\n\n async swipe(\n direction: 'up' | 'down' | 'left' | 'right',\n startX?: number,\n startY?: number,\n distance?: number,\n ): Promise<void> {\n await this.ensureConnected();\n const d = distance ?? 500;\n const sx = startX ?? 200;\n const sy = startY ?? 400;\n const [endX, endY] = computeSwipeEnd(sx, sy, direction, d);\n\n await execStrict('idb', [\n 'ui',\n 'swipe',\n String(sx),\n String(sy),\n String(endX),\n String(endY),\n '--udid',\n this.#udid,\n ]);\n }\n\n async waitForElement(\n query: ElementQuery,\n timeoutMs = 10_000,\n intervalMs = 500,\n ): Promise<UIElement> {\n const start = Date.now();\n while (Date.now() - start < timeoutMs) {\n const snapshot = await this.snapshot();\n const element = findElement(snapshot.hierarchy, query);\n if (element) {\n return element;\n }\n await new Promise((resolve) => setTimeout(resolve, intervalMs));\n }\n throw new Error(\n `Timed out waiting for element: ${JSON.stringify(query)} (${timeoutMs}ms)`,\n );\n }\n\n async getAppState(bundleId: string): Promise<AppStateResult> {\n await this.ensureConnected();\n const raw = await execStrict('idb', ['list-apps', '--udid', this.#udid]);\n\n for (const line of raw.trim().split('\\n')) {\n if (line.includes(bundleId)) {\n const parts = line.split('|').map((s) => s.trim());\n return {\n bundleId,\n state: parts[2] ?? 'Unknown',\n pid: parts[3] ? parseInt(parts[3], 10) : undefined,\n };\n }\n }\n\n return { bundleId, state: 'Not Installed' };\n }\n\n async screenshot(outputPath?: string): Promise<ScreenshotResult> {\n await this.ensureConnected();\n const path = outputPath ?? `/tmp/device-mcp-screenshot-${Date.now()}.png`;\n await execStrict('idb', ['screenshot', path, '--udid', this.#udid]);\n const data = await execStrict('base64', [path]);\n return { data: data.trim(), format: 'png', path };\n }\n\n async openApp(bundleId: string): Promise<void> {\n await this.ensureConnected();\n await execStrict('idb', ['launch', bundleId, '--udid', this.#udid]);\n }\n\n async closeApp(bundleId: string): Promise<void> {\n await this.ensureConnected();\n await execStrict('idb', ['terminate', bundleId, '--udid', this.#udid]);\n }\n\n async pressButton(button: DeviceButton): Promise<void> {\n await this.ensureConnected();\n const keyMap: Record<DeviceButton, string> = {\n home: 'HOME',\n lock: 'LOCK',\n back: 'HOME',\n enter: 'RETURN',\n };\n await execStrict('idb', [\n 'ui',\n 'key',\n keyMap[button],\n '--udid',\n this.#udid,\n ]);\n }\n\n async dismissKeyboard(): Promise<void> {\n await this.ensureConnected();\n await execStrict('idb', ['ui', 'key', 'RETURN', '--udid', this.#udid]);\n }\n\n async dismissAlert(accept: boolean): Promise<void> {\n await this.ensureConnected();\n const snap = await this.snapshot();\n const candidates = accept ? ACCEPT_LABELS : DENY_LABELS;\n\n for (const label of candidates) {\n const element = findElement(snap.hierarchy, { label });\n if (element) {\n const cx = Math.round(element.frame.x + element.frame.width / 2);\n const cy = Math.round(element.frame.y + element.frame.height / 2);\n await this.tapCoordinates(cx, cy);\n return;\n }\n }\n\n throw new Error(`No alert button found. Tried: ${candidates.join(', ')}`);\n }\n\n async getLogs(durationSeconds = 30, filter?: string): Promise<LogsResult> {\n await this.ensureConnected();\n const args = [\n 'log',\n '--udid',\n this.#udid,\n '--',\n '--last',\n `${durationSeconds}s`,\n ];\n if (filter) {\n args.push('--predicate', `eventMessage CONTAINS \"${filter}\"`);\n }\n const raw = await execStrict('idb', args);\n const entries = raw\n .trim()\n .split('\\n')\n .filter(Boolean)\n .map((line) => ({\n timestamp: line.substring(0, 31).trim(),\n level: 'info',\n message: line.substring(31).trim(),\n }));\n return { entries, source: 'idb log' };\n }\n\n async longPress(query: ElementQuery, durationMs = 1000): Promise<TapResult> {\n await this.ensureConnected();\n const snap = await this.snapshot();\n const element = findElement(snap.hierarchy, query);\n if (!element) {\n throw new Error(\n `Element not found: ${JSON.stringify(query)}\\n` +\n 'Use device_snapshot to inspect the current UI hierarchy.',\n );\n }\n\n const cx = Math.round(element.frame.x + element.frame.width / 2);\n const cy = Math.round(element.frame.y + element.frame.height / 2);\n await execStrict('idb', [\n 'ui',\n 'tap',\n String(cx),\n String(cy),\n '--duration',\n String(durationMs / 1000),\n '--udid',\n this.#udid,\n ]);\n\n return {\n success: true,\n x: cx,\n y: cy,\n targetDescription: describeElement(element),\n };\n }\n\n async scrollToElement(\n query: ElementQuery,\n direction: 'up' | 'down' = 'down',\n maxAttempts = 10,\n ): Promise<UIElement> {\n await this.ensureConnected();\n let previousRaw = '';\n\n for (let i = 0; i < maxAttempts; i++) {\n const snap = await this.snapshot();\n const element = findElement(snap.hierarchy, query);\n if (element) {\n return element;\n }\n if (snap.raw === previousRaw) {\n break;\n }\n previousRaw = snap.raw;\n await this.swipe(direction);\n }\n throw new Error(\n `Element not found after scrolling: ${JSON.stringify(query)}\\n` +\n 'Use device_snapshot to inspect the current UI hierarchy.',\n );\n }\n\n async getAlertText(): Promise<string> {\n await this.ensureConnected();\n const snap = await this.snapshot();\n const texts = collectAlertTexts(snap.hierarchy);\n if (texts.length === 0) {\n throw new Error(\n 'No alert is currently displayed.\\n' +\n 'Use device_snapshot to inspect the current UI hierarchy.',\n );\n }\n return texts.join('\\n');\n }\n\n async getWindowSize(): Promise<WindowSize> {\n await this.ensureConnected();\n const raw = await execStrict('idb', [\n 'describe',\n '--udid',\n this.#udid,\n '--json',\n ]);\n try {\n const info = JSON.parse(raw) as Record<string, unknown>;\n const dims = info.screen_dimensions as\n | { width: number; height: number }\n | undefined;\n if (dims?.width && dims?.height) {\n return { width: dims.width, height: dims.height };\n }\n } catch {\n // fall through to snapshot-based approach\n }\n const snap = await this.snapshot();\n if (snap.hierarchy.length > 0) {\n const root = snap.hierarchy[0];\n if (root.frame.width > 0 && root.frame.height > 0) {\n return { width: root.frame.width, height: root.frame.height };\n }\n }\n throw new Error('Unable to determine window size from device');\n }\n\n async getContexts(): Promise<string[]> {\n return ['NATIVE_APP'];\n }\n\n async setContext(context: string): Promise<void> {\n if (context === 'NATIVE_APP') {\n return;\n }\n throw new Error(\n 'Context switching requires Appium backend. IDB only supports NATIVE_APP.',\n );\n }\n\n async getClipboard(): Promise<string> {\n await this.ensureConnected();\n return execStrict('xcrun', ['simctl', 'pbpaste', this.#udid]);\n }\n\n async setClipboard(text: string): Promise<void> {\n await this.ensureConnected();\n await new Promise<void>((resolve, reject) => {\n const proc = execFileCb(\n 'xcrun',\n ['simctl', 'pbcopy', this.#udid],\n { timeout: 30_000 },\n (error) => (error ? reject(new Error(error.message)) : resolve()),\n );\n proc.stdin?.end(text);\n });\n }\n\n async startScreenRecording(outputPath?: string): Promise<void> {\n await this.ensureConnected();\n if (this.#recordingProcess) {\n throw new Error('Screen recording is already in progress');\n }\n const path = outputPath ?? `/tmp/device-mcp-recording-${Date.now()}.mp4`;\n this.#recordingPath = path;\n this.#recordingProcess = spawn('idb', [\n 'record-video',\n path,\n '--udid',\n this.#udid,\n ]);\n this.#recordingProcess.on('error', () => {\n this.#recordingProcess = null;\n this.#recordingPath = null;\n });\n }\n\n async stopScreenRecording(): Promise<string> {\n if (!this.#recordingProcess || !this.#recordingPath) {\n throw new Error('No screen recording in progress');\n }\n const path = this.#recordingPath;\n this.#recordingProcess.kill('SIGINT');\n await new Promise((resolve) => setTimeout(resolve, 1000));\n this.#recordingProcess = null;\n this.#recordingPath = null;\n return path;\n }\n}\n\nfunction collectAlertTexts(elements: UIElement[]): string[] {\n const texts: string[] = [];\n for (const el of elements) {\n const isAlertContainer =\n el.type === 'Alert' || el.type === 'Sheet' || el.type.includes('Alert');\n if (isAlertContainer) {\n collectTextsFromChildren(el.children ?? [], texts);\n return texts;\n }\n if (el.children) {\n const found = collectAlertTexts(el.children);\n if (found.length > 0) {\n return found;\n }\n }\n }\n return texts;\n}\n\nfunction collectTextsFromChildren(\n elements: UIElement[],\n texts: string[],\n): void {\n for (const el of elements) {\n if (el.type === 'StaticText' || el.type === 'TextView') {\n const text = el.value ?? el.label;\n if (text) {\n texts.push(text);\n }\n }\n if (el.children) {\n collectTextsFromChildren(el.children, texts);\n }\n }\n}\n\nexport function parseIdbHierarchy(raw: string): UIElement[] {\n try {\n const parsed = JSON.parse(raw);\n if (Array.isArray(parsed)) {\n return parsed.map(mapIdbElement);\n }\n if (parsed.children) {\n return parsed.children.map(mapIdbElement);\n }\n return [mapIdbElement(parsed)];\n } catch {\n return [\n {\n type: 'raw',\n label: raw.slice(0, 200),\n frame: { x: 0, y: 0, width: 0, height: 0 },\n enabled: true,\n },\n ];\n }\n}\n\nexport function mapIdbElement(node: Record<string, unknown>): UIElement {\n const frame = node.frame as\n | { x: number; y: number; width: number; height: number }\n | undefined;\n\n return {\n type: (node.type as string) ?? (node.AXType as string) ?? 'Unknown',\n label: (node.AXLabel as string) ?? (node.label as string) ?? undefined,\n value: (node.AXValue as string) ?? (node.value as string) ?? undefined,\n identifier:\n (node.AXUniqueId as string) ?? (node.identifier as string) ?? undefined,\n frame: frame ?? { x: 0, y: 0, width: 0, height: 0 },\n enabled: (node.enabled as boolean) ?? true,\n children: Array.isArray(node.children)\n ? node.children.map(mapIdbElement)\n : undefined,\n };\n}\n"]}
1
+ {"version":3,"file":"idb-backend.mjs","sourceRoot":"","sources":["../../src/backends/idb-backend.ts"],"names":[],"mappings":"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","sourcesContent":["import { execFile as execFileCb, spawn } from 'node:child_process';\nimport type { ChildProcess } from 'node:child_process';\nimport { readFile } from 'node:fs/promises';\n\nimport type {\n DeviceBackend,\n DeviceButton,\n DeviceInfo,\n SnapshotResult,\n ScreenshotResult,\n ScreenshotFileResult,\n ScreenshotOptions,\n LogsResult,\n TapResult,\n AppStateResult,\n ElementQuery,\n UIElement,\n WindowSize,\n} from './types.js';\nimport { ACCEPT_LABELS, DENY_LABELS } from '../utils/alert-labels.js';\nimport {\n findElement,\n describeElement,\n computeSwipeEnd,\n} from '../utils/element.js';\nimport { execStrict, exec } from '../utils/exec.js';\nimport {\n hardenArtifactFile,\n resolveArtifactPath,\n} from '../utils/output-path.js';\nimport { resolveIdbPath } from '../utils/platform.js';\n\nexport class IdbBackend implements DeviceBackend {\n readonly platform = 'ios' as const;\n\n #connected = false;\n\n readonly #udid: string;\n\n #idbPath = 'idb';\n\n #recordingProcess: ChildProcess | null = null;\n\n #recordingPath: string | null = null;\n\n constructor(udid: string) {\n this.#udid = udid;\n }\n\n async ensureConnected(): Promise<void> {\n if (this.#connected) {\n return;\n }\n\n this.#idbPath = await resolveIdbPath();\n await exec(this.#idbPath, ['connect', this.#udid]);\n this.#connected = true;\n }\n\n async getDeviceInfo(): Promise<DeviceInfo> {\n await this.ensureConnected();\n const raw = await execStrict(this.#idbPath, [\n 'describe',\n '--udid',\n this.#udid,\n '--json',\n ]);\n let info: Record<string, unknown>;\n try {\n info = JSON.parse(raw) as Record<string, unknown>;\n } catch {\n throw new Error(\n `idb describe returned invalid JSON for device ${this.#udid}: ${raw.slice(0, 200)}`,\n );\n }\n return {\n platform: 'ios',\n deviceId: this.#udid,\n name: (info.name as string) ?? 'Unknown',\n osVersion: (info.os_version as string) ?? 'Unknown',\n state: (info.state as string) ?? 'Unknown',\n };\n }\n\n async snapshot(): Promise<SnapshotResult> {\n await this.ensureConnected();\n const raw = await execStrict(this.#idbPath, [\n 'ui',\n 'describe-all',\n '--udid',\n this.#udid,\n ]);\n const hierarchy = parseIdbHierarchy(raw);\n return {\n platform: 'ios',\n hierarchy,\n raw,\n timestamp: Date.now(),\n };\n }\n\n async tapElement(query: ElementQuery): Promise<TapResult> {\n await this.ensureConnected();\n const snapshot = await this.snapshot();\n const element = findElement(snapshot.hierarchy, query);\n if (!element) {\n throw new Error(\n `Element not found: ${JSON.stringify(query)}\\n` +\n 'Use device_snapshot to inspect the current UI hierarchy.',\n );\n }\n\n const x = Math.round(element.frame.x + element.frame.width / 2);\n const y = Math.round(element.frame.y + element.frame.height / 2);\n await this.tapCoordinates(x, y);\n\n return {\n success: true,\n x,\n y,\n targetDescription: describeElement(element),\n };\n }\n\n async getElementText(query: ElementQuery): Promise<string> {\n await this.ensureConnected();\n const snapshot = await this.snapshot();\n const element = findElement(snapshot.hierarchy, query);\n if (!element) {\n throw new Error(\n `Element not found: ${JSON.stringify(query)}\\n` +\n 'Use device_snapshot to inspect the current UI hierarchy.',\n );\n }\n return element.label ?? element.value ?? '';\n }\n\n async tapCoordinates(x: number, y: number): Promise<void> {\n await this.ensureConnected();\n await execStrict(this.#idbPath, [\n 'ui',\n 'tap',\n String(x),\n String(y),\n '--udid',\n this.#udid,\n ]);\n }\n\n async typeText(text: string): Promise<void> {\n await this.ensureConnected();\n await exec(this.#idbPath, [\n 'ui',\n 'key-sequence',\n '--',\n 'cmd+a',\n '--udid',\n this.#udid,\n ]);\n await exec(this.#idbPath, ['ui', 'key', 'DELETE', '--udid', this.#udid]);\n await execStrict(this.#idbPath, ['ui', 'text', text, '--udid', this.#udid]);\n }\n\n async swipe(\n direction: 'up' | 'down' | 'left' | 'right',\n startX?: number,\n startY?: number,\n distance?: number,\n ): Promise<void> {\n await this.ensureConnected();\n const d = distance ?? 500;\n const sx = startX ?? 200;\n const sy = startY ?? 400;\n const [endX, endY] = computeSwipeEnd(sx, sy, direction, d);\n\n await execStrict(this.#idbPath, [\n 'ui',\n 'swipe',\n String(sx),\n String(sy),\n String(endX),\n String(endY),\n '--udid',\n this.#udid,\n ]);\n }\n\n async waitForElement(\n query: ElementQuery,\n timeoutMs = 10_000,\n intervalMs = 500,\n ): Promise<UIElement> {\n const start = Date.now();\n while (Date.now() - start < timeoutMs) {\n const snapshot = await this.snapshot();\n const element = findElement(snapshot.hierarchy, query);\n if (element) {\n return element;\n }\n await new Promise((resolve) => setTimeout(resolve, intervalMs));\n }\n throw new Error(\n `Timed out waiting for element: ${JSON.stringify(query)} (${timeoutMs}ms)`,\n );\n }\n\n async getAppState(bundleId: string): Promise<AppStateResult> {\n await this.ensureConnected();\n try {\n const raw = await execStrict(this.#idbPath, [\n 'list-apps',\n '--udid',\n this.#udid,\n ]);\n\n for (const line of raw.trim().split('\\n')) {\n if (line.includes(bundleId)) {\n const parts = line.split('|').map((s) => s.trim());\n return {\n bundleId,\n state: parts[2] ?? 'Unknown',\n pid: parts[3] ? parseInt(parts[3], 10) : undefined,\n };\n }\n }\n\n return { bundleId, state: 'Not Installed' };\n } catch {\n return this.#getAppStateViaSimctl(bundleId);\n }\n }\n\n async #getAppStateViaSimctl(bundleId: string): Promise<AppStateResult> {\n const result = await exec('xcrun', ['simctl', 'listapps', this.#udid]);\n if (result.exitCode === 0 && result.stdout.includes(bundleId)) {\n return { bundleId, state: 'Running' };\n }\n return { bundleId, state: 'Not Installed' };\n }\n\n screenshot(\n outputPath?: string,\n options?: { encode?: true },\n ): Promise<ScreenshotResult>;\n\n screenshot(\n outputPath: string | undefined,\n options: { encode: false },\n ): Promise<ScreenshotFileResult>;\n\n screenshot(\n outputPath?: string,\n options?: ScreenshotOptions,\n ): Promise<ScreenshotResult | ScreenshotFileResult>;\n\n async screenshot(\n outputPath?: string,\n options?: ScreenshotOptions,\n ): Promise<ScreenshotResult | ScreenshotFileResult> {\n await this.ensureConnected();\n const path = resolveArtifactPath(outputPath, 'screenshot');\n await execStrict(this.#idbPath, ['screenshot', path, '--udid', this.#udid]);\n hardenArtifactFile(path);\n if (options?.encode === false) {\n return { data: undefined, format: 'png', path };\n }\n const data = await readFile(path, 'base64');\n return { data, format: 'png', path };\n }\n\n async openApp(bundleId: string): Promise<void> {\n await this.ensureConnected();\n try {\n await execStrict(this.#idbPath, [\n 'launch',\n bundleId,\n '--udid',\n this.#udid,\n ]);\n } catch {\n await execStrict('xcrun', ['simctl', 'launch', this.#udid, bundleId]);\n }\n }\n\n async closeApp(bundleId: string): Promise<void> {\n await this.ensureConnected();\n try {\n await execStrict(this.#idbPath, [\n 'terminate',\n bundleId,\n '--udid',\n this.#udid,\n ]);\n } catch {\n await execStrict('xcrun', ['simctl', 'terminate', this.#udid, bundleId]);\n }\n }\n\n async pressButton(button: DeviceButton): Promise<void> {\n await this.ensureConnected();\n const keyMap: Record<DeviceButton, string> = {\n home: 'HOME',\n lock: 'LOCK',\n back: 'HOME',\n enter: 'RETURN',\n };\n await execStrict(this.#idbPath, [\n 'ui',\n 'key',\n keyMap[button],\n '--udid',\n this.#udid,\n ]);\n }\n\n async dismissKeyboard(): Promise<void> {\n await this.ensureConnected();\n await execStrict(this.#idbPath, [\n 'ui',\n 'key',\n 'RETURN',\n '--udid',\n this.#udid,\n ]);\n }\n\n async dismissAlert(accept: boolean): Promise<void> {\n await this.ensureConnected();\n const snap = await this.snapshot();\n const candidates = accept ? ACCEPT_LABELS : DENY_LABELS;\n\n for (const label of candidates) {\n const element = findElement(snap.hierarchy, { label });\n if (element) {\n const cx = Math.round(element.frame.x + element.frame.width / 2);\n const cy = Math.round(element.frame.y + element.frame.height / 2);\n await this.tapCoordinates(cx, cy);\n return;\n }\n }\n\n throw new Error(`No alert button found. Tried: ${candidates.join(', ')}`);\n }\n\n async getLogs(durationSeconds = 30, filter?: string): Promise<LogsResult> {\n await this.ensureConnected();\n const args = [\n 'log',\n '--udid',\n this.#udid,\n '--',\n '--last',\n `${durationSeconds}s`,\n ];\n if (filter) {\n args.push('--predicate', `eventMessage CONTAINS \"${filter}\"`);\n }\n const raw = await execStrict(this.#idbPath, args);\n const entries = raw\n .trim()\n .split('\\n')\n .filter(Boolean)\n .map((line) => ({\n timestamp: line.substring(0, 31).trim(),\n level: 'info',\n message: line.substring(31).trim(),\n }));\n return { entries, source: 'idb log' };\n }\n\n async longPress(query: ElementQuery, durationMs = 1000): Promise<TapResult> {\n await this.ensureConnected();\n const snap = await this.snapshot();\n const element = findElement(snap.hierarchy, query);\n if (!element) {\n throw new Error(\n `Element not found: ${JSON.stringify(query)}\\n` +\n 'Use device_snapshot to inspect the current UI hierarchy.',\n );\n }\n\n const cx = Math.round(element.frame.x + element.frame.width / 2);\n const cy = Math.round(element.frame.y + element.frame.height / 2);\n await execStrict(this.#idbPath, [\n 'ui',\n 'tap',\n String(cx),\n String(cy),\n '--duration',\n String(durationMs / 1000),\n '--udid',\n this.#udid,\n ]);\n\n return {\n success: true,\n x: cx,\n y: cy,\n targetDescription: describeElement(element),\n };\n }\n\n async scrollToElement(\n query: ElementQuery,\n direction: 'up' | 'down' = 'down',\n maxAttempts = 10,\n ): Promise<UIElement> {\n await this.ensureConnected();\n let previousRaw = '';\n\n for (let i = 0; i < maxAttempts; i++) {\n const snap = await this.snapshot();\n const element = findElement(snap.hierarchy, query);\n if (element) {\n return element;\n }\n if (snap.raw === previousRaw) {\n break;\n }\n previousRaw = snap.raw;\n await this.swipe(direction);\n }\n throw new Error(\n `Element not found after scrolling: ${JSON.stringify(query)}\\n` +\n 'Use device_snapshot to inspect the current UI hierarchy.',\n );\n }\n\n async getAlertText(): Promise<string> {\n await this.ensureConnected();\n const snap = await this.snapshot();\n const texts = collectAlertTexts(snap.hierarchy);\n if (texts.length === 0) {\n throw new Error(\n 'No alert is currently displayed.\\n' +\n 'Use device_snapshot to inspect the current UI hierarchy.',\n );\n }\n return texts.join('\\n');\n }\n\n async getWindowSize(): Promise<WindowSize> {\n await this.ensureConnected();\n const raw = await execStrict(this.#idbPath, [\n 'describe',\n '--udid',\n this.#udid,\n '--json',\n ]);\n try {\n const info = JSON.parse(raw) as Record<string, unknown>;\n const dims = info.screen_dimensions as\n | { width: number; height: number }\n | undefined;\n if (dims?.width && dims?.height) {\n return { width: dims.width, height: dims.height };\n }\n } catch {\n // fall through to snapshot-based approach\n }\n const snap = await this.snapshot();\n if (snap.hierarchy.length > 0) {\n const root = snap.hierarchy[0];\n if (root.frame.width > 0 && root.frame.height > 0) {\n return { width: root.frame.width, height: root.frame.height };\n }\n }\n throw new Error('Unable to determine window size from device');\n }\n\n async getContexts(): Promise<string[]> {\n return ['NATIVE_APP'];\n }\n\n async setContext(context: string): Promise<void> {\n if (context === 'NATIVE_APP') {\n return;\n }\n throw new Error(\n 'Context switching requires Appium backend. IDB only supports NATIVE_APP.',\n );\n }\n\n async getClipboard(): Promise<string> {\n await this.ensureConnected();\n return execStrict('xcrun', ['simctl', 'pbpaste', this.#udid]);\n }\n\n async setClipboard(text: string): Promise<void> {\n await this.ensureConnected();\n await new Promise<void>((resolve, reject) => {\n const proc = execFileCb(\n 'xcrun',\n ['simctl', 'pbcopy', this.#udid],\n { timeout: 30_000 },\n (error) => (error ? reject(new Error(error.message)) : resolve()),\n );\n proc.stdin?.end(text);\n });\n }\n\n async startScreenRecording(outputPath?: string): Promise<void> {\n await this.ensureConnected();\n if (this.#recordingProcess) {\n throw new Error('Screen recording is already in progress');\n }\n const path = resolveArtifactPath(outputPath, 'recording');\n this.#recordingPath = path;\n this.#recordingProcess = spawn(this.#idbPath, [\n 'record-video',\n path,\n '--udid',\n this.#udid,\n ]);\n this.#recordingProcess.on('error', () => {\n this.#recordingProcess = null;\n this.#recordingPath = null;\n });\n }\n\n async stopScreenRecording(): Promise<string> {\n if (!this.#recordingProcess || !this.#recordingPath) {\n throw new Error('No screen recording in progress');\n }\n const path = this.#recordingPath;\n this.#recordingProcess.kill('SIGINT');\n await new Promise((resolve) => setTimeout(resolve, 1000));\n this.#recordingProcess = null;\n this.#recordingPath = null;\n hardenArtifactFile(path);\n return path;\n }\n}\n\nfunction collectAlertTexts(elements: UIElement[]): string[] {\n const texts: string[] = [];\n for (const el of elements) {\n const isAlertContainer =\n el.type === 'Alert' || el.type === 'Sheet' || el.type.includes('Alert');\n if (isAlertContainer) {\n collectTextsFromChildren(el.children ?? [], texts);\n return texts;\n }\n if (el.children) {\n const found = collectAlertTexts(el.children);\n if (found.length > 0) {\n return found;\n }\n }\n }\n return texts;\n}\n\nfunction collectTextsFromChildren(\n elements: UIElement[],\n texts: string[],\n): void {\n for (const el of elements) {\n if (el.type === 'StaticText' || el.type === 'TextView') {\n const text = el.value ?? el.label;\n if (text) {\n texts.push(text);\n }\n }\n if (el.children) {\n collectTextsFromChildren(el.children, texts);\n }\n }\n}\n\nexport function parseIdbHierarchy(raw: string): UIElement[] {\n try {\n const parsed = JSON.parse(raw);\n if (Array.isArray(parsed)) {\n return parsed.map(mapIdbElement);\n }\n if (parsed.children) {\n return parsed.children.map(mapIdbElement);\n }\n return [mapIdbElement(parsed)];\n } catch {\n return [\n {\n type: 'raw',\n label: raw.slice(0, 200),\n frame: { x: 0, y: 0, width: 0, height: 0 },\n enabled: true,\n },\n ];\n }\n}\n\nexport function mapIdbElement(node: Record<string, unknown>): UIElement {\n const frame = node.frame as\n | { x: number; y: number; width: number; height: number }\n | undefined;\n\n return {\n type: (node.type as string) ?? (node.AXType as string) ?? 'Unknown',\n label: (node.AXLabel as string) ?? (node.label as string) ?? undefined,\n value: (node.AXValue as string) ?? (node.value as string) ?? undefined,\n identifier:\n (node.AXUniqueId as string) ?? (node.identifier as string) ?? undefined,\n frame: frame ?? { x: 0, y: 0, width: 0, height: 0 },\n enabled: (node.enabled as boolean) ?? true,\n children: Array.isArray(node.children)\n ? node.children.map(mapIdbElement)\n : undefined,\n };\n}\n"]}
@@ -14,7 +14,7 @@ var appium_backend_js_2 = require("./appium-backend.cjs");
14
14
  Object.defineProperty(exports, "AppiumBackend", { enumerable: true, get: function () { return appium_backend_js_2.AppiumBackend; } });
15
15
  var idb_backend_js_2 = require("./idb-backend.cjs");
16
16
  Object.defineProperty(exports, "IdbBackend", { enumerable: true, get: function () { return idb_backend_js_2.IdbBackend; } });
17
- async function createBackend(explicitDeviceId) {
17
+ async function createBackend(explicitDeviceId, explicitPlatform) {
18
18
  const sessionConfig = await (0, session_file_js_1.readSessionFile)();
19
19
  if (sessionConfig) {
20
20
  console.error(`Found .device-session (${sessionConfig.mode}, ${sessionConfig.platform})`);
@@ -22,38 +22,59 @@ async function createBackend(explicitDeviceId) {
22
22
  await backend.ensureConnected();
23
23
  return backend;
24
24
  }
25
- const { platform, deviceId } = await (0, platform_js_1.detectPlatform)(explicitDeviceId);
25
+ const { platform, deviceId } = await (0, platform_js_1.detectPlatform)(explicitDeviceId, explicitPlatform);
26
26
  const backend = platform === 'ios' ? new idb_backend_js_1.IdbBackend(deviceId) : new adb_backend_js_1.AdbBackend(deviceId);
27
27
  await backend.ensureConnected();
28
28
  return backend;
29
29
  }
30
- /**
31
- * Lazy backend that defers device detection to first tool call.
32
- * Allows the MCP server to start and complete the handshake
33
- * even when no device is connected yet.
34
- *
35
- * @param explicitDeviceId - Optional device ID override.
36
- * @returns A DeviceBackend that resolves on first use.
37
- */
38
- function createLazyBackend(explicitDeviceId) {
30
+ function createLazyBackend(explicitDeviceId, explicitPlatform) {
39
31
  let inner = null;
40
32
  let connecting = null;
33
+ let pendingDevices = null;
34
+ let selectedOverride = null;
41
35
  async function resolve() {
42
36
  if (inner) {
43
37
  return inner;
44
38
  }
39
+ if (pendingDevices && !selectedOverride) {
40
+ throw new platform_js_1.MultipleDevicesError(pendingDevices);
41
+ }
45
42
  if (!connecting) {
46
- connecting = createBackend(explicitDeviceId).then((backend) => {
43
+ const deviceId = selectedOverride ?? explicitDeviceId;
44
+ connecting = createBackend(deviceId, explicitPlatform)
45
+ .then((backend) => {
47
46
  inner = backend;
47
+ pendingDevices = null;
48
48
  return backend;
49
+ })
50
+ .catch((error) => {
51
+ connecting = null;
52
+ if (error instanceof platform_js_1.MultipleDevicesError) {
53
+ pendingDevices = error.devices;
54
+ }
55
+ throw error;
49
56
  });
50
57
  }
51
58
  return connecting;
52
59
  }
60
+ async function screenshot(outputPath, options) {
61
+ return (await resolve()).screenshot(outputPath, options);
62
+ }
53
63
  return {
54
64
  get platform() {
55
65
  return inner?.platform ?? 'ios';
56
66
  },
67
+ selectDevice(deviceId) {
68
+ selectedOverride = deviceId;
69
+ inner = null;
70
+ connecting = null;
71
+ },
72
+ async listDevices() {
73
+ if (pendingDevices) {
74
+ return pendingDevices;
75
+ }
76
+ return (0, platform_js_1.detectAllDevices)(explicitPlatform);
77
+ },
57
78
  async getDeviceInfo() {
58
79
  return (await resolve()).getDeviceInfo();
59
80
  },
@@ -78,9 +99,7 @@ function createLazyBackend(explicitDeviceId) {
78
99
  async getAppState(bundleId) {
79
100
  return (await resolve()).getAppState(bundleId);
80
101
  },
81
- async screenshot(outputPath) {
82
- return (await resolve()).screenshot(outputPath);
83
- },
102
+ screenshot,
84
103
  async openApp(bundleId) {
85
104
  return (await resolve()).openApp(bundleId);
86
105
  },
@@ -129,6 +148,9 @@ function createLazyBackend(explicitDeviceId) {
129
148
  async stopScreenRecording() {
130
149
  return (await resolve()).stopScreenRecording();
131
150
  },
151
+ async getElementText(query) {
152
+ return (await resolve()).getElementText(query);
153
+ },
132
154
  };
133
155
  }
134
156
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sourceRoot":"","sources":["../../src/backends/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { AdbBackend } from './adb-backend.js';\nimport { AppiumBackend } from './appium-backend.js';\nimport { IdbBackend } from './idb-backend.js';\nimport { readSessionFile } from './session-file.js';\nimport type {\n DeviceBackend,\n DeviceButton,\n DeviceInfo,\n LogsResult,\n ScreenshotResult,\n SnapshotResult,\n TapResult,\n AppStateResult,\n ElementQuery,\n UIElement,\n Platform,\n WindowSize,\n} from './types.js';\nimport { detectPlatform } from '../utils/platform.js';\n\nexport type { DeviceBackend } from './types.js';\nexport { AdbBackend } from './adb-backend.js';\nexport { AppiumBackend } from './appium-backend.js';\nexport { IdbBackend } from './idb-backend.js';\n\nexport async function createBackend(\n explicitDeviceId?: string,\n): Promise<DeviceBackend> {\n const sessionConfig = await readSessionFile();\n\n if (sessionConfig) {\n console.error(\n `Found .device-session (${sessionConfig.mode}, ${sessionConfig.platform})`,\n );\n const backend = new AppiumBackend(sessionConfig);\n await backend.ensureConnected();\n return backend;\n }\n\n const { platform, deviceId } = await detectPlatform(explicitDeviceId);\n\n const backend =\n platform === 'ios' ? new IdbBackend(deviceId) : new AdbBackend(deviceId);\n\n await backend.ensureConnected();\n return backend;\n}\n\n/**\n * Lazy backend that defers device detection to first tool call.\n * Allows the MCP server to start and complete the handshake\n * even when no device is connected yet.\n *\n * @param explicitDeviceId - Optional device ID override.\n * @returns A DeviceBackend that resolves on first use.\n */\nexport function createLazyBackend(explicitDeviceId?: string): DeviceBackend {\n let inner: DeviceBackend | null = null;\n let connecting: Promise<DeviceBackend> | null = null;\n\n async function resolve(): Promise<DeviceBackend> {\n if (inner) {\n return inner;\n }\n if (!connecting) {\n connecting = createBackend(explicitDeviceId).then((backend) => {\n inner = backend;\n return backend;\n });\n }\n return connecting;\n }\n\n return {\n get platform(): Platform {\n return inner?.platform ?? 'ios';\n },\n\n async getDeviceInfo(): Promise<DeviceInfo> {\n return (await resolve()).getDeviceInfo();\n },\n\n async snapshot(): Promise<SnapshotResult> {\n return (await resolve()).snapshot();\n },\n\n async tapElement(query: ElementQuery): Promise<TapResult> {\n return (await resolve()).tapElement(query);\n },\n\n async tapCoordinates(x: number, y: number): Promise<void> {\n return (await resolve()).tapCoordinates(x, y);\n },\n\n async typeText(text: string): Promise<void> {\n return (await resolve()).typeText(text);\n },\n\n async swipe(\n direction: 'up' | 'down' | 'left' | 'right',\n startX?: number,\n startY?: number,\n distance?: number,\n ): Promise<void> {\n return (await resolve()).swipe(direction, startX, startY, distance);\n },\n\n async waitForElement(\n query: ElementQuery,\n timeoutMs?: number,\n intervalMs?: number,\n ): Promise<UIElement> {\n return (await resolve()).waitForElement(query, timeoutMs, intervalMs);\n },\n\n async getAppState(bundleId: string): Promise<AppStateResult> {\n return (await resolve()).getAppState(bundleId);\n },\n\n async screenshot(outputPath?: string): Promise<ScreenshotResult> {\n return (await resolve()).screenshot(outputPath);\n },\n\n async openApp(bundleId: string): Promise<void> {\n return (await resolve()).openApp(bundleId);\n },\n\n async closeApp(bundleId: string): Promise<void> {\n return (await resolve()).closeApp(bundleId);\n },\n\n async pressButton(button: DeviceButton): Promise<void> {\n return (await resolve()).pressButton(button);\n },\n\n async dismissKeyboard(): Promise<void> {\n return (await resolve()).dismissKeyboard();\n },\n\n async dismissAlert(accept: boolean): Promise<void> {\n return (await resolve()).dismissAlert(accept);\n },\n\n async getLogs(\n durationSeconds?: number,\n filter?: string,\n ): Promise<LogsResult> {\n return (await resolve()).getLogs(durationSeconds, filter);\n },\n\n async longPress(\n query: ElementQuery,\n durationMs?: number,\n ): Promise<TapResult> {\n return (await resolve()).longPress(query, durationMs);\n },\n\n async scrollToElement(\n query: ElementQuery,\n direction?: 'up' | 'down',\n maxAttempts?: number,\n ): Promise<UIElement> {\n return (await resolve()).scrollToElement(query, direction, maxAttempts);\n },\n\n async getAlertText(): Promise<string> {\n return (await resolve()).getAlertText();\n },\n\n async getWindowSize(): Promise<WindowSize> {\n return (await resolve()).getWindowSize();\n },\n\n async getContexts(): Promise<string[]> {\n return (await resolve()).getContexts();\n },\n\n async setContext(context: string): Promise<void> {\n return (await resolve()).setContext(context);\n },\n\n async getClipboard(): Promise<string> {\n return (await resolve()).getClipboard();\n },\n\n async setClipboard(text: string): Promise<void> {\n return (await resolve()).setClipboard(text);\n },\n\n async startScreenRecording(outputPath?: string): Promise<void> {\n return (await resolve()).startScreenRecording(outputPath);\n },\n\n async stopScreenRecording(): Promise<string> {\n return (await resolve()).stopScreenRecording();\n },\n };\n}\n"]}
1
+ {"version":3,"file":"index.cjs","sourceRoot":"","sources":["../../src/backends/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { AdbBackend } from './adb-backend.js';\nimport { AppiumBackend } from './appium-backend.js';\nimport { IdbBackend } from './idb-backend.js';\nimport { readSessionFile } from './session-file.js';\nimport type {\n DeviceBackend,\n DeviceButton,\n DeviceInfo,\n LogsResult,\n ScreenshotResult,\n ScreenshotFileResult,\n ScreenshotOptions,\n SnapshotResult,\n TapResult,\n AppStateResult,\n ElementQuery,\n UIElement,\n Platform,\n WindowSize,\n} from './types.js';\nimport {\n detectPlatform,\n detectAllDevices,\n MultipleDevicesError,\n} from '../utils/platform.js';\nimport type { DetectedDevice } from '../utils/platform.js';\n\nexport type { DeviceBackend } from './types.js';\nexport { AdbBackend } from './adb-backend.js';\nexport { AppiumBackend } from './appium-backend.js';\nexport { IdbBackend } from './idb-backend.js';\n\nexport type LazyDeviceBackend = DeviceBackend & {\n selectDevice(deviceId: string): void;\n listDevices(): Promise<DetectedDevice[]>;\n};\n\nexport async function createBackend(\n explicitDeviceId?: string,\n explicitPlatform?: Platform,\n): Promise<DeviceBackend> {\n const sessionConfig = await readSessionFile();\n\n if (sessionConfig) {\n console.error(\n `Found .device-session (${sessionConfig.mode}, ${sessionConfig.platform})`,\n );\n const backend = new AppiumBackend(sessionConfig);\n await backend.ensureConnected();\n return backend;\n }\n\n const { platform, deviceId } = await detectPlatform(\n explicitDeviceId,\n explicitPlatform,\n );\n\n const backend =\n platform === 'ios' ? new IdbBackend(deviceId) : new AdbBackend(deviceId);\n\n await backend.ensureConnected();\n return backend;\n}\n\nexport function createLazyBackend(\n explicitDeviceId?: string,\n explicitPlatform?: Platform,\n): LazyDeviceBackend {\n let inner: DeviceBackend | null = null;\n let connecting: Promise<DeviceBackend> | null = null;\n let pendingDevices: DetectedDevice[] | null = null;\n let selectedOverride: string | null = null;\n\n async function resolve(): Promise<DeviceBackend> {\n if (inner) {\n return inner;\n }\n\n if (pendingDevices && !selectedOverride) {\n throw new MultipleDevicesError(pendingDevices);\n }\n\n if (!connecting) {\n const deviceId = selectedOverride ?? explicitDeviceId;\n connecting = createBackend(deviceId, explicitPlatform)\n .then((backend) => {\n inner = backend;\n pendingDevices = null;\n return backend;\n })\n .catch((error: unknown) => {\n connecting = null;\n if (error instanceof MultipleDevicesError) {\n pendingDevices = error.devices;\n }\n throw error;\n });\n }\n return connecting;\n }\n\n function screenshot(\n outputPath?: string,\n options?: { encode?: true },\n ): Promise<ScreenshotResult>;\n function screenshot(\n outputPath: string | undefined,\n options: { encode: false },\n ): Promise<ScreenshotFileResult>;\n function screenshot(\n outputPath?: string,\n options?: ScreenshotOptions,\n ): Promise<ScreenshotResult | ScreenshotFileResult>;\n async function screenshot(\n outputPath?: string,\n options?: ScreenshotOptions,\n ): Promise<ScreenshotResult | ScreenshotFileResult> {\n return (await resolve()).screenshot(outputPath, options);\n }\n\n return {\n get platform(): Platform {\n return inner?.platform ?? 'ios';\n },\n\n selectDevice(deviceId: string): void {\n selectedOverride = deviceId;\n inner = null;\n connecting = null;\n },\n\n async listDevices(): Promise<DetectedDevice[]> {\n if (pendingDevices) {\n return pendingDevices;\n }\n return detectAllDevices(explicitPlatform);\n },\n\n async getDeviceInfo(): Promise<DeviceInfo> {\n return (await resolve()).getDeviceInfo();\n },\n\n async snapshot(): Promise<SnapshotResult> {\n return (await resolve()).snapshot();\n },\n\n async tapElement(query: ElementQuery): Promise<TapResult> {\n return (await resolve()).tapElement(query);\n },\n\n async tapCoordinates(x: number, y: number): Promise<void> {\n return (await resolve()).tapCoordinates(x, y);\n },\n\n async typeText(text: string): Promise<void> {\n return (await resolve()).typeText(text);\n },\n\n async swipe(\n direction: 'up' | 'down' | 'left' | 'right',\n startX?: number,\n startY?: number,\n distance?: number,\n ): Promise<void> {\n return (await resolve()).swipe(direction, startX, startY, distance);\n },\n\n async waitForElement(\n query: ElementQuery,\n timeoutMs?: number,\n intervalMs?: number,\n ): Promise<UIElement> {\n return (await resolve()).waitForElement(query, timeoutMs, intervalMs);\n },\n\n async getAppState(bundleId: string): Promise<AppStateResult> {\n return (await resolve()).getAppState(bundleId);\n },\n\n screenshot,\n\n async openApp(bundleId: string): Promise<void> {\n return (await resolve()).openApp(bundleId);\n },\n\n async closeApp(bundleId: string): Promise<void> {\n return (await resolve()).closeApp(bundleId);\n },\n\n async pressButton(button: DeviceButton): Promise<void> {\n return (await resolve()).pressButton(button);\n },\n\n async dismissKeyboard(): Promise<void> {\n return (await resolve()).dismissKeyboard();\n },\n\n async dismissAlert(accept: boolean): Promise<void> {\n return (await resolve()).dismissAlert(accept);\n },\n\n async getLogs(\n durationSeconds?: number,\n filter?: string,\n ): Promise<LogsResult> {\n return (await resolve()).getLogs(durationSeconds, filter);\n },\n\n async longPress(\n query: ElementQuery,\n durationMs?: number,\n ): Promise<TapResult> {\n return (await resolve()).longPress(query, durationMs);\n },\n\n async scrollToElement(\n query: ElementQuery,\n direction?: 'up' | 'down',\n maxAttempts?: number,\n ): Promise<UIElement> {\n return (await resolve()).scrollToElement(query, direction, maxAttempts);\n },\n\n async getAlertText(): Promise<string> {\n return (await resolve()).getAlertText();\n },\n\n async getWindowSize(): Promise<WindowSize> {\n return (await resolve()).getWindowSize();\n },\n\n async getContexts(): Promise<string[]> {\n return (await resolve()).getContexts();\n },\n\n async setContext(context: string): Promise<void> {\n return (await resolve()).setContext(context);\n },\n\n async getClipboard(): Promise<string> {\n return (await resolve()).getClipboard();\n },\n\n async setClipboard(text: string): Promise<void> {\n return (await resolve()).setClipboard(text);\n },\n\n async startScreenRecording(outputPath?: string): Promise<void> {\n return (await resolve()).startScreenRecording(outputPath);\n },\n\n async stopScreenRecording(): Promise<string> {\n return (await resolve()).stopScreenRecording();\n },\n\n async getElementText(query: ElementQuery): Promise<string> {\n return (await resolve()).getElementText(query);\n },\n };\n}\n"]}
@@ -1,16 +1,13 @@
1
- import type { DeviceBackend } from "./types.cjs";
1
+ import type { DeviceBackend, Platform } from "./types.cjs";
2
+ import type { DetectedDevice } from "../utils/platform.cjs";
2
3
  export type { DeviceBackend } from "./types.cjs";
3
4
  export { AdbBackend } from "./adb-backend.cjs";
4
5
  export { AppiumBackend } from "./appium-backend.cjs";
5
6
  export { IdbBackend } from "./idb-backend.cjs";
6
- export declare function createBackend(explicitDeviceId?: string): Promise<DeviceBackend>;
7
- /**
8
- * Lazy backend that defers device detection to first tool call.
9
- * Allows the MCP server to start and complete the handshake
10
- * even when no device is connected yet.
11
- *
12
- * @param explicitDeviceId - Optional device ID override.
13
- * @returns A DeviceBackend that resolves on first use.
14
- */
15
- export declare function createLazyBackend(explicitDeviceId?: string): DeviceBackend;
7
+ export type LazyDeviceBackend = DeviceBackend & {
8
+ selectDevice(deviceId: string): void;
9
+ listDevices(): Promise<DetectedDevice[]>;
10
+ };
11
+ export declare function createBackend(explicitDeviceId?: string, explicitPlatform?: Platform): Promise<DeviceBackend>;
12
+ export declare function createLazyBackend(explicitDeviceId?: string, explicitPlatform?: Platform): LazyDeviceBackend;
16
13
  //# sourceMappingURL=index.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../../src/backends/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,aAAa,EAYd,oBAAmB;AAGpB,YAAY,EAAE,aAAa,EAAE,oBAAmB;AAChD,OAAO,EAAE,UAAU,EAAE,0BAAyB;AAC9C,OAAO,EAAE,aAAa,EAAE,6BAA4B;AACpD,OAAO,EAAE,UAAU,EAAE,0BAAyB;AAE9C,wBAAsB,aAAa,CACjC,gBAAgB,CAAC,EAAE,MAAM,GACxB,OAAO,CAAC,aAAa,CAAC,CAmBxB;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,gBAAgB,CAAC,EAAE,MAAM,GAAG,aAAa,CA6I1E"}
1
+ {"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../../src/backends/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,aAAa,EAYb,QAAQ,EAET,oBAAmB;AAMpB,OAAO,KAAK,EAAE,cAAc,EAAE,8BAA6B;AAE3D,YAAY,EAAE,aAAa,EAAE,oBAAmB;AAChD,OAAO,EAAE,UAAU,EAAE,0BAAyB;AAC9C,OAAO,EAAE,aAAa,EAAE,6BAA4B;AACpD,OAAO,EAAE,UAAU,EAAE,0BAAyB;AAE9C,MAAM,MAAM,iBAAiB,GAAG,aAAa,GAAG;IAC9C,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,WAAW,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;CAC1C,CAAC;AAEF,wBAAsB,aAAa,CACjC,gBAAgB,CAAC,EAAE,MAAM,EACzB,gBAAgB,CAAC,EAAE,QAAQ,GAC1B,OAAO,CAAC,aAAa,CAAC,CAsBxB;AAED,wBAAgB,iBAAiB,CAC/B,gBAAgB,CAAC,EAAE,MAAM,EACzB,gBAAgB,CAAC,EAAE,QAAQ,GAC1B,iBAAiB,CAgMnB"}