prompttest-mobile 1.5.1

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 (64) hide show
  1. package/CONTRIBUTING.md +80 -0
  2. package/LICENSE +42 -0
  3. package/LICENSES.md +81 -0
  4. package/README.md +526 -0
  5. package/SECURITY.md +56 -0
  6. package/TERMS.md +138 -0
  7. package/dist/bin/prompttest.d.ts +2 -0
  8. package/dist/bin/prompttest.js +1418 -0
  9. package/dist/bin/server.d.ts +1 -0
  10. package/dist/constants/commands.d.ts +125 -0
  11. package/dist/engine.bundle.js +1039 -0
  12. package/dist/index.d.ts +143 -0
  13. package/dist/index.js +1039 -0
  14. package/dist/lib/adaptive-timing.d.ts +55 -0
  15. package/dist/lib/adb-provisioner.d.ts +55 -0
  16. package/dist/lib/adb.d.ts +448 -0
  17. package/dist/lib/ai/heuristic-resolver.d.ts +19 -0
  18. package/dist/lib/ai/index.d.ts +16 -0
  19. package/dist/lib/ai/llm-provider.d.ts +40 -0
  20. package/dist/lib/ai/types.d.ts +64 -0
  21. package/dist/lib/baseline.d.ts +159 -0
  22. package/dist/lib/benchmark.d.ts +100 -0
  23. package/dist/lib/checkpoint.d.ts +61 -0
  24. package/dist/lib/ci.d.ts +49 -0
  25. package/dist/lib/config-loader.d.ts +87 -0
  26. package/dist/lib/config.d.ts +136 -0
  27. package/dist/lib/crawler.d.ts +335 -0
  28. package/dist/lib/data-loader.d.ts +53 -0
  29. package/dist/lib/dfs-engine.d.ts +149 -0
  30. package/dist/lib/dictionary.d.ts +41 -0
  31. package/dist/lib/doctor.d.ts +45 -0
  32. package/dist/lib/driver-interface.d.ts +50 -0
  33. package/dist/lib/enterprise.d.ts +71 -0
  34. package/dist/lib/errors.d.ts +68 -0
  35. package/dist/lib/explorer.d.ts +165 -0
  36. package/dist/lib/feedback.d.ts +35 -0
  37. package/dist/lib/form-filler.d.ts +101 -0
  38. package/dist/lib/ios-driver.d.ts +38 -0
  39. package/dist/lib/jail-guard.d.ts +59 -0
  40. package/dist/lib/license.d.ts +51 -0
  41. package/dist/lib/live-server.d.ts +52 -0
  42. package/dist/lib/lock.d.ts +30 -0
  43. package/dist/lib/logger.d.ts +68 -0
  44. package/dist/lib/memory.d.ts +259 -0
  45. package/dist/lib/patterns.d.ts +202 -0
  46. package/dist/lib/profiler.d.ts +75 -0
  47. package/dist/lib/prompt-runner.d.ts +101 -0
  48. package/dist/lib/quiescence.d.ts +44 -0
  49. package/dist/lib/recorder.d.ts +155 -0
  50. package/dist/lib/repl.d.ts +29 -0
  51. package/dist/lib/reporter.d.ts +269 -0
  52. package/dist/lib/runner-utils.d.ts +316 -0
  53. package/dist/lib/scaffold.d.ts +53 -0
  54. package/dist/lib/step-handlers.d.ts +390 -0
  55. package/dist/lib/triage.d.ts +50 -0
  56. package/dist/lib/wizard.d.ts +42 -0
  57. package/dist/lib/zip-util.d.ts +36 -0
  58. package/docs/ARCHITECTURE.md +154 -0
  59. package/docs/CLI_CONTRACT.md +131 -0
  60. package/docs/CLI_STUDIO_CONTRACT.md +123 -0
  61. package/docs/PERFORMANCE_BASELINE.md +71 -0
  62. package/docs/PRODUCT_STATUS.md +56 -0
  63. package/docs/USER_MANUAL.md +764 -0
  64. package/package.json +66 -0
@@ -0,0 +1,55 @@
1
+ /**
2
+ * @module adaptive-timing
3
+ * @description Device-Aware Adaptive Dynamic Waiting & Auto-Profiling.
4
+ *
5
+ * Automatically balances test timing between ultra-fast physical devices (USB 3.0)
6
+ * and resource-constrained CI emulators (software-rendered VMs in GitHub Actions).
7
+ *
8
+ * Implements exponential backoff condition-driven polling with instant short-circuiting:
9
+ * fast devices finish immediately upon event completion, while slow emulators receive
10
+ * adaptive headroom without CPU exhaustion.
11
+ */
12
+ import type { AndroidDriver } from './adb.js';
13
+ export interface DeviceProfile {
14
+ /** Whether the target device is an emulator / virtual device */
15
+ isEmulator: boolean;
16
+ /** Whether the process is executing inside a CI / CD environment (e.g. GitHub Actions) */
17
+ isCI: boolean;
18
+ /** Calculated dynamic velocity multiplier (1.0 = real device, 1.5 = local emulator, 2.5 = CI) */
19
+ velocityMultiplier: number;
20
+ /** Default timeout ceiling for UI element detection */
21
+ defaultTimeoutMs: number;
22
+ /** Extended timeout ceiling for multi-step transitions and cold loads */
23
+ extendedTimeoutMs: number;
24
+ /** Minimum stability duration for dual-sample quiescence verification */
25
+ quiescenceSettleMs: number;
26
+ /** Initial polling interval in milliseconds */
27
+ initialPollMs: number;
28
+ /** Maximum backoff polling interval in milliseconds */
29
+ maxPollIntervalMs: number;
30
+ }
31
+ /**
32
+ * Probes the connected device and host runtime to construct an adaptive timing profile.
33
+ * Cached per session so that subsequent steps reuse the profiled characteristics.
34
+ *
35
+ * @param driver - Android driver instance
36
+ * @param serial - Optional target device serial
37
+ */
38
+ export declare function profileDeviceEnvironment(driver: AndroidDriver, serial?: string): Promise<DeviceProfile>;
39
+ /**
40
+ * Resets the cached device profile (primarily used in testing).
41
+ */
42
+ export declare function resetDeviceProfile(): void;
43
+ /**
44
+ * Polls an asynchronous condition using adaptive backoff with immediate short-circuiting.
45
+ *
46
+ * Fast devices short-circuit the instant the condition returns a truthy value.
47
+ * Slow emulators receive backoff polling that preserves CPU cycles for rendering.
48
+ *
49
+ * @param checkFn - Async callback returning a truthy value when the condition is met.
50
+ * @param timeoutMs - Maximum duration to wait before giving up.
51
+ * @param initialIntervalMs - Starting interval between checks.
52
+ * @param maxIntervalMs - Cap for the backoff interval.
53
+ * @returns The resolved value of the condition, or throws a timeout Error.
54
+ */
55
+ export declare function pollWithAdaptiveBackoff<T>(checkFn: () => Promise<T | null | undefined | false>, timeoutMs: number, initialIntervalMs?: number, maxIntervalMs?: number): Promise<T>;
@@ -0,0 +1,55 @@
1
+ /**
2
+ * @module adb-provisioner
3
+ * @description
4
+ * Zero-dependency hardware discovery and ADB provisioning engine.
5
+ * Automatically discovers, validates, and provisions Android Debug Bridge (ADB)
6
+ * binaries across Windows, macOS, and Linux without requiring full Android Studio installation.
7
+ */
8
+ export interface AdbDiagnosticInfo {
9
+ binaryPath: string;
10
+ isAvailable: boolean;
11
+ version?: string;
12
+ source: 'PROMPTTEST_OVERRIDE' | 'BUNDLED_LOCAL' | 'SYSTEM_PATH' | 'ANDROID_HOME' | 'STANDALONE_CACHE' | 'STANDARD_SDK' | 'FALLBACK';
13
+ }
14
+ /**
15
+ * Discovers the absolute or executable path to the ADB binary on the host system.
16
+ * Evaluates candidate locations in strict order of reliability:
17
+ * 1. Environment override (`PROMPTTEST_ADB_PATH`)
18
+ * 2. Bundled / Adjacent platform-tools (next to executable, app bundle, or current cwd)
19
+ * 3. System PATH lookup
20
+ * 4. Android SDK environment variables (`ANDROID_HOME`, `ANDROID_SDK_ROOT`)
21
+ * 5. Standard platform installation paths
22
+ * 6. Standalone user cache (`~/.prompttest/platform-tools/adb`)
23
+ */
24
+ export declare function getAdbBinary(): string;
25
+ /**
26
+ * Checks whether the resolved ADB binary is executable and operational.
27
+ *
28
+ * @param customPath Optional custom binary path to verify.
29
+ */
30
+ export declare function isAdbAvailable(customPath?: string): boolean;
31
+ /**
32
+ * Returns full diagnostics about ADB availability and resolution origin.
33
+ */
34
+ export declare function getAdbDiagnostics(): AdbDiagnosticInfo;
35
+ /**
36
+ * Resets cached ADB path (useful for testing and runtime environment shifts).
37
+ */
38
+ export declare function resetAdbCache(): void;
39
+ /**
40
+ * Automatically downloads and provisions official platform-tools if ADB is missing.
41
+ */
42
+ export declare function downloadPlatformToolsFallback(customDestDir?: string): Promise<string>;
43
+ /**
44
+ * Prompts the user for explicit permission to download official platform-tools if ADB is missing.
45
+ * Automatically approved if --download-adb, -y, or --yes flag is present in process.argv.
46
+ */
47
+ export declare function promptUserForAdbDownload(): Promise<boolean>;
48
+ /**
49
+ * Asserts that ADB is available, prompting for user permission before automated provisioning if missing.
50
+ *
51
+ * @param options.skipPrompt If true, bypasses the user prompt (e.g. when --download-adb flag is passed).
52
+ */
53
+ export declare function ensureAdbProvisioned(options?: {
54
+ skipPrompt?: boolean;
55
+ }): Promise<string>;
@@ -0,0 +1,448 @@
1
+ /**
2
+ * @module adb
3
+ * @description
4
+ * Low-level ADB native driver for the PromptTest framework.
5
+ * This module manages device communication, screen capture, touch input, app lifecycle,
6
+ * and logcat streaming using Android Debug Bridge (ADB).
7
+ * It acts as the bridge between the framework and the physical/emulated Android devices.
8
+ */
9
+ /**
10
+ * Represents a connected Android device and its attributes.
11
+ */
12
+ export interface AndroidDevice {
13
+ /** The unique serial number or IP:Port of the device */
14
+ serial: string;
15
+ /** The connection state of the device */
16
+ state: 'device' | 'offline' | 'unauthorized' | 'unknown';
17
+ /** The hardware model of the device (optional) */
18
+ model?: string;
19
+ /** The product name of the device (optional) */
20
+ product?: string;
21
+ /** Transport connection type: 'usb' | 'wifi' | 'emulator' */
22
+ connectionType?: 'usb' | 'wifi' | 'emulator';
23
+ }
24
+ export interface DeviceMetrics {
25
+ battery?: {
26
+ level?: number;
27
+ temperatureC?: number;
28
+ status?: string;
29
+ };
30
+ display?: {
31
+ width?: number;
32
+ height?: number;
33
+ density?: number;
34
+ };
35
+ memory?: {
36
+ pssKb?: number;
37
+ privateDirtyKb?: number;
38
+ nativeHeapKb?: number;
39
+ };
40
+ graphics?: {
41
+ framesRendered?: number;
42
+ jankyFrames?: number;
43
+ percentile90Ms?: number;
44
+ };
45
+ }
46
+ export declare function parseDeviceMetrics(batteryOutput: string, displayOutput: string, memoryOutput: string, graphicsOutput: string): DeviceMetrics;
47
+ /**
48
+ * Classifies a device connection type from its serial or model properties.
49
+ */
50
+ export declare function classifyDeviceConnection(serial: string): 'usb' | 'wifi' | 'emulator';
51
+ /**
52
+ * Deduplicates multiple transport connections for the same physical Android hardware.
53
+ * Priority: USB > Wi-Fi (IP:port) > Wi-Fi (mDNS) > Emulator.
54
+ * Prevents simultaneous execution collisions on the same physical phone.
55
+ */
56
+ export declare function deduplicateDevices(devices: AndroidDevice[]): AndroidDevice[];
57
+ /**
58
+ * AndroidDriver is responsible for executing ADB commands and handling device interactions.
59
+ * It manages the default targeted device, executes shell commands, extracts device state,
60
+ * handles input events, and streams logcat output.
61
+ */
62
+ export declare class AndroidDriver {
63
+ private defaultSerial;
64
+ private cachedDimensions;
65
+ private inFlightHierarchies;
66
+ /**
67
+ * Initializes a new AndroidDriver instance.
68
+ * @param serial Optional serial number to set as the default device.
69
+ */
70
+ constructor(serial?: string);
71
+ /**
72
+ * Sets the default device serial to be used for subsequent commands.
73
+ * @param serial The device serial number or IP:port.
74
+ */
75
+ setDefaultDevice(serial: string): void;
76
+ /**
77
+ * Gets the currently set default device serial.
78
+ * @returns The default serial number, or null if none is set.
79
+ */
80
+ getDefaultDevice(): string | null;
81
+ /**
82
+ * Gets the physical screen dimensions of the device.
83
+ * Caches the result to prevent repeated ADB calls.
84
+ * @param serial Optional target device serial.
85
+ * @returns An object containing the width and height of the screen.
86
+ */
87
+ getScreenDimensions(serial?: string): Promise<{
88
+ width: number;
89
+ height: number;
90
+ }>;
91
+ /**
92
+ * Invalidates cached screen dimensions for a device or all devices (e.g. after screen rotation).
93
+ * @param serial Optional target device serial.
94
+ */
95
+ clearScreenDimensionsCache(serial?: string): void;
96
+ /**
97
+ * Retrieves the height of the device's navigation bar.
98
+ * @param serial Optional target device serial.
99
+ * @returns The navigation bar height in pixels, or 0 if not found.
100
+ */
101
+ getNavigationBarHeight(serial?: string): Promise<number>;
102
+ private isGlobalAdbCommand;
103
+ private execAdbInternal;
104
+ /**
105
+ * Executes an ADB command and returns its standard output and error.
106
+ * Features an exponential backoff retry loop for transient failures (e.g., device offline).
107
+ * @param args The ADB command arguments.
108
+ * @param serial Optional target device serial.
109
+ * @param timeoutMs Command execution timeout in milliseconds (default: 20000).
110
+ * @param maxRetries Maximum number of retries upon failure (default: 2).
111
+ * @returns An object containing stdout and stderr as strings.
112
+ * @throws An Error if the command fails consistently or times out.
113
+ */
114
+ execAdb(args: readonly string[] | string[], serial?: string, timeoutMs?: number, maxRetries?: number): Promise<{
115
+ stdout: string;
116
+ stderr: string;
117
+ }>;
118
+ /**
119
+ * Executes an ADB command that returns binary data, such as screen captures.
120
+ * @param args The ADB command arguments.
121
+ * @param serial Optional target device serial.
122
+ * @param timeoutMs Command execution timeout in milliseconds (default: 45000).
123
+ * @returns A Buffer containing the command's binary output.
124
+ * @throws An Error if the command fails or times out.
125
+ */
126
+ execAdbBinary(args: readonly string[] | string[], serial?: string, timeoutMs?: number): Promise<Buffer>;
127
+ /**
128
+ /**
129
+ * Retrieves all raw connected Android devices from ADB without deduplication.
130
+ */
131
+ getRawConnectedDevices(): Promise<AndroidDevice[]>;
132
+ /**
133
+ * Retrieves a list of currently connected Android devices.
134
+ * By default, deduplicates multiple transport channels for the same physical phone (prioritizing USB > Wi-Fi).
135
+ * @param options.deduplicate Set to false to return raw unfiltered endpoints.
136
+ * @returns A promise resolving to an array of AndroidDevice objects.
137
+ */
138
+ getConnectedDevices(options?: {
139
+ deduplicate?: boolean;
140
+ }): Promise<AndroidDevice[]>;
141
+ /**
142
+ * Helper utility to deduplicate a list of AndroidDevice items.
143
+ */
144
+ deduplicateDevices(devices: AndroidDevice[]): AndroidDevice[];
145
+ /**
146
+ * Wakes up the device screen and attempts to dismiss the keyguard.
147
+ * @param serial Optional target device serial.
148
+ */
149
+ wakeDevice(serial?: string): Promise<void>;
150
+ /**
151
+ * Ensures a default device is selected, waking it up in the process.
152
+ * If no default is set, it selects the first authorized connected device.
153
+ * @param serial Optional explicit serial to set and wake.
154
+ * @returns The determined default serial number, or undefined if no devices are available.
155
+ */
156
+ ensureDefaultDevice(serial?: string): Promise<string | undefined>;
157
+ /**
158
+ * Retrieves the hardware model name of the specified device.
159
+ * @param serial Optional target device serial.
160
+ * @returns The model string of the device, or a fallback generic string.
161
+ */
162
+ getDeviceModel(serial?: string): Promise<string>;
163
+ /**
164
+ * Captures a screenshot from the device.
165
+ * @param serial Optional target device serial.
166
+ * @returns A Buffer containing the raw PNG screenshot data.
167
+ */
168
+ captureScreenshot(serial?: string): Promise<Buffer>;
169
+ /**
170
+ * Dumps the current UI hierarchy XML from the device screen.
171
+ * Coalesces concurrent in-flight calls for the same device to prevent redundant ADB invocations (SP-01).
172
+ * @param serial Optional target device serial.
173
+ * @returns A string containing the UI hierarchy XML.
174
+ */
175
+ getUiHierarchy(serial?: string): Promise<string>;
176
+ /**
177
+ * Clears any active in-flight hierarchy promises (e.g. after error or teardown).
178
+ * @param serial Optional target device serial.
179
+ */
180
+ clearInFlightHierarchies(serial?: string): void;
181
+ /**
182
+ * Identifies the package name of the app currently running in the foreground.
183
+ * Uses dumpsys to inspect activities and window focus.
184
+ * @param serial Optional target device serial.
185
+ * @returns The package name of the foreground app, or null if it cannot be determined.
186
+ */
187
+ getForegroundPackage(serial?: string): Promise<string | null>;
188
+ /**
189
+ * Taps on the screen at the specified coordinates.
190
+ * @param x The X coordinate.
191
+ * @param y The Y coordinate.
192
+ * @param serial Optional target device serial.
193
+ */
194
+ tap(x: number, y: number, serial?: string): Promise<void>;
195
+ /**
196
+ * Inputs text into the currently focused text field on the device.
197
+ * Falls back to character-by-character injection if shell escaping fails.
198
+ * @param text The string to input.
199
+ * @param serial Optional target device serial.
200
+ */
201
+ inputText(text: string, serial?: string): Promise<void>;
202
+ /**
203
+ * Simulates pressing a hardware key on the device.
204
+ * @param keyCode The Android keycode (number or string).
205
+ * @param serial Optional target device serial.
206
+ */
207
+ pressKey(keyCode: number | string, serial?: string): Promise<void>;
208
+ /**
209
+ * Simulates pressing the Enter key.
210
+ * @param serial Optional target device serial.
211
+ */
212
+ pressEnter(serial?: string): Promise<void>;
213
+ /**
214
+ * Simulates pressing the Tab key.
215
+ * @param serial Optional target device serial.
216
+ */
217
+ pressTab(serial?: string): Promise<void>;
218
+ /**
219
+ * Simulates pressing the Home key.
220
+ * @param serial Optional target device serial.
221
+ */
222
+ pressHome(serial?: string): Promise<void>;
223
+ /**
224
+ * Simulates pressing the Back key (KEYCODE_BACK: 4).
225
+ * @param serial Optional target device serial.
226
+ */
227
+ pressBack(serial?: string): Promise<void>;
228
+ /**
229
+ * Enables or disables Wi-Fi connectivity on the device.
230
+ * @param enabled True to enable Wi-Fi, false to disable.
231
+ * @param serial Optional target device serial.
232
+ */
233
+ setWifiEnabled(enabled: boolean, serial?: string): Promise<void>;
234
+ /**
235
+ * Enables or disables Airplane mode on the device.
236
+ * @param enabled True to enable airplane mode, false to disable.
237
+ * @param serial Optional target device serial.
238
+ */
239
+ setAirplaneMode(enabled: boolean, serial?: string): Promise<void>;
240
+ /**
241
+ * Locks the screen orientation to portrait (0) or landscape (1).
242
+ * @param orientation Desired orientation ('portrait' | 'landscape').
243
+ * @param serial Optional target device serial.
244
+ */
245
+ setOrientation(orientation: 'portrait' | 'landscape', serial?: string): Promise<void>;
246
+ /**
247
+ * Expands the system notification shade.
248
+ * @param serial Optional target device serial.
249
+ */
250
+ openNotificationShade(serial?: string): Promise<void>;
251
+ /**
252
+ * Collapses the system notification shade.
253
+ * @param serial Optional target device serial.
254
+ */
255
+ collapseNotificationShade(serial?: string): Promise<void>;
256
+ /**
257
+ * Clears the current input field by sending multiple backspace key events.
258
+ * @param count The number of backspaces to send (default: 45).
259
+ * @param serial Optional target device serial.
260
+ */
261
+ clearInput(count?: number, serial?: string): Promise<void>;
262
+ /**
263
+ * Aggressively clears a text field by moving the cursor to both ends and deleting.
264
+ * @param serial Optional target device serial.
265
+ * @param fieldLength Estimated length of the field to clear (default: 80).
266
+ */
267
+ clearField(serial?: string, fieldLength?: number): Promise<void>;
268
+ /**
269
+ * Performs a swipe gesture on the device screen.
270
+ * @param x1 The starting X coordinate.
271
+ * @param y1 The starting Y coordinate.
272
+ * @param x2 The ending X coordinate.
273
+ * @param y2 The ending Y coordinate.
274
+ * @param durationMs The duration of the swipe in milliseconds (default: 300).
275
+ * @param serial Optional target device serial.
276
+ */
277
+ swipe(x1: number, y1: number, x2: number, y2: number, durationMs?: number, serial?: string): Promise<void>;
278
+ /**
279
+ * Launches an application by its package name.
280
+ * @param packageName The package name of the app to launch.
281
+ * @param serial Optional target device serial.
282
+ */
283
+ launchApp(packageName: string, serial?: string): Promise<void>;
284
+ /**
285
+ * Force stops an application.
286
+ * @param packageName The package name of the app to stop.
287
+ * @param serial Optional target device serial.
288
+ */
289
+ forceStop(packageName: string, serial?: string): Promise<void>;
290
+ /**
291
+ * Clears the user data and cache of an application.
292
+ * @param packageName The package name of the app to clear.
293
+ * @param serial Optional target device serial.
294
+ */
295
+ clearAppData(packageName: string, serial?: string): Promise<void>;
296
+ /**
297
+ * Restarts an application by force stopping and then launching it again.
298
+ * @param packageName The package name of the app to restart.
299
+ * @param serial Optional target device serial.
300
+ */
301
+ restartApp(packageName: string, serial?: string): Promise<void>;
302
+ /**
303
+ * Grants a specific runtime permission to an application.
304
+ * @param packageName The package name of the app.
305
+ * @param permission The Android permission string (e.g., android.permission.CAMERA).
306
+ * @param serial Optional target device serial.
307
+ */
308
+ grantPermission(packageName: string, permission: string, serial?: string): Promise<void>;
309
+ /**
310
+ * Checks if an application is installed on the device.
311
+ * @param packageName The package name to check.
312
+ * @param serial Optional target device serial.
313
+ * @returns True if the app is installed, false otherwise.
314
+ */
315
+ isAppInstalled(packageName: string, serial?: string): Promise<boolean>;
316
+ /**
317
+ * Installs an APK onto the device.
318
+ * @param apkPath The local file path to the APK.
319
+ * @param serial Optional target device serial.
320
+ */
321
+ installApk(apkPath: string, serial?: string): Promise<void>;
322
+ /**
323
+ * Uninstalls an application from the device.
324
+ * @param packageName The package name of the app to uninstall.
325
+ * @param serial Optional target device serial.
326
+ */
327
+ uninstallApp(packageName: string, serial?: string): Promise<void>;
328
+ /**
329
+ * Opens a deep link URI on the device.
330
+ * @param uri The deep link URI string.
331
+ * @param serial Optional target device serial.
332
+ */
333
+ openDeepLink(uri: string, serial?: string): Promise<void>;
334
+ /**
335
+ * Checks the logcat buffer for fatal crashes related to a specific package.
336
+ * @param packageName The package name to check for crashes.
337
+ * @param serial Optional target device serial.
338
+ * @returns The crash log string if found, otherwise null.
339
+ */
340
+ checkCrashes(packageName: string, serial?: string): Promise<string | null>;
341
+ /**
342
+ * Clears historical crash logs from the logcat buffer.
343
+ * @param serial Optional target device serial.
344
+ */
345
+ clearCrashLogs(serial?: string): Promise<void>;
346
+ /**
347
+ * Auto-detects the device's local Wi-Fi IPv4 address on the active wlan0 interface.
348
+ * @param serial Optional target device serial.
349
+ * @returns The detected IPv4 address, or null if not found.
350
+ */
351
+ getDeviceIp(serial?: string): Promise<string | null>;
352
+ /**
353
+ * Switches device to TCP/IP mode and establishes a wireless ADB connection.
354
+ * @param customTarget Optional IP or IP:Port to connect to.
355
+ * @param port The port to use for the TCP connection (default: 5555).
356
+ * @param serial Optional target device serial.
357
+ * @returns An object detailing the connection success, target, and message.
358
+ * @throws An Error if the device IP cannot be detected.
359
+ */
360
+ connectWifi(customTarget?: string, port?: number, serial?: string): Promise<{
361
+ success: boolean;
362
+ target: string;
363
+ message: string;
364
+ }>;
365
+ /**
366
+ * Disconnects wireless Wi-Fi ADB connection.
367
+ * @param customTarget Optional IP or IP:Port to connect to.
368
+ * @param port The port to use for the TCP connection (default: 5555).
369
+ * @param serial Optional target device serial.
370
+ * @returns An object detailing the connection success, target, and message.
371
+ * @throws An Error if the device IP cannot be detected.
372
+ */
373
+ disconnectWifi(target?: string): Promise<string>;
374
+ pairWifi(target: string, pairingCode: string): Promise<{
375
+ success: boolean;
376
+ message: string;
377
+ }>;
378
+ getDeviceMetrics(serial?: string): Promise<DeviceMetrics>;
379
+ /**
380
+ * Streams the Android events logcat buffer in real-time.
381
+ * Used for detecting screen transitions via wm_on_resume_called events.
382
+ * Non-blocking: fires onLine callback for each log line received.
383
+ * @param serial The target device serial.
384
+ * @param onLine Callback function invoked for each log line.
385
+ * @returns The spawned child process running the logcat command.
386
+ */
387
+ streamLogcatEvents(serial: string, onLine: (line: string) => void): import('child_process').ChildProcess;
388
+ /**
389
+ * Streams the main logcat buffer filtered for crash and ANR signals.
390
+ * Non-blocking: fires onLine callback whenever AndroidRuntime or ANR logs appear.
391
+ * @param serial The target device serial.
392
+ * @param onLine Callback function invoked for each crash log line.
393
+ * @returns The spawned child process running the logcat command.
394
+ */
395
+ streamLogcatCrashes(serial: string, onLine: (line: string) => void): import('child_process').ChildProcess;
396
+ /**
397
+ * Streams logcat filtered for Toast and Snackbar signals.
398
+ * Non-blocking: fires onLine callback for UI feedback messages.
399
+ * @param serial The target device serial.
400
+ * @param onLine Callback function invoked for each toast/snackbar log line.
401
+ * @returns The spawned child process running the logcat command.
402
+ */
403
+ streamLogcatToasts(serial: string, onLine: (line: string) => void): import('child_process').ChildProcess;
404
+ /**
405
+ * Retrieves the last N lines of device logcat for triage and diagnostic reporting.
406
+ * @param lines Number of logcat lines to capture (default: 150).
407
+ * @param serial Optional target device serial.
408
+ * @returns The captured logcat output as a string.
409
+ */
410
+ getLogcatTail(lines?: number, serial?: string): Promise<string>;
411
+ /**
412
+ * Starts a non-blocking background screen recording via ADB shell screenrecord.
413
+ * @param remotePath Device path to store the temporary MP4 recording (default: '/sdcard/prompttest_temp.mp4').
414
+ * @param serial Optional target device serial.
415
+ * @returns An object containing the remote file path and the spawned ChildProcess.
416
+ */
417
+ startScreenRecording(remotePath?: string, serial?: string): Promise<{
418
+ remotePath: string;
419
+ process: import('child_process').ChildProcess;
420
+ }>;
421
+ /**
422
+ * Stops an active screen recording, pulls the MP4 file to host, and cleans up device storage.
423
+ * @param recording The recording object returned by startScreenRecording.
424
+ * @param localDestPath Local path where the MP4 video will be saved.
425
+ * @param serial Optional target device serial.
426
+ * @returns The local path to the saved MP4 recording.
427
+ */
428
+ stopScreenRecording(recording: {
429
+ remotePath: string;
430
+ process: import('child_process').ChildProcess;
431
+ }, localDestPath: string, serial?: string): Promise<string>;
432
+ /**
433
+ * Checks if the virtual software keyboard (IME) is currently active and visible on screen.
434
+ * Uses fast shell grep filtering across Android IME & Window properties with resilient fallbacks.
435
+ * @param serial Optional target device serial.
436
+ * @returns Promise resolving to true if virtual keyboard is displayed.
437
+ */
438
+ isKeyboardVisible(serial?: string): Promise<boolean>;
439
+ /**
440
+ * Enables Android accessibility settings to assist WebView node extraction.
441
+ * @param serial Optional target device serial.
442
+ */
443
+ ensureAccessibilityServices(serial?: string): Promise<void>;
444
+ }
445
+ /**
446
+ * Singleton instance of AndroidDriver exported for application-wide use.
447
+ */
448
+ export declare const androidDriver: AndroidDriver;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * @module ai/heuristic-resolver
3
+ * @description Fully offline heuristic resolver utilizing Levenshtein distance,
4
+ * synonym dictionaries, and spatial/structural rules. Requires zero network calls or API keys.
5
+ */
6
+ import { UiNode } from '../crawler.js';
7
+ import { PromptStep } from '../prompt-runner.js';
8
+ import { SemanticResolver, Suggestion, SemanticContext } from './types.js';
9
+ export declare class HeuristicResolver implements SemanticResolver {
10
+ readonly providerName = "heuristic";
11
+ /**
12
+ * Expands recognized standard macro intents offline.
13
+ */
14
+ resolveIntent(intent: string, _ctx?: SemanticContext): Promise<PromptStep[] | null>;
15
+ /**
16
+ * Discovers matching replacement elements when a target locator is broken or missing.
17
+ */
18
+ findSuggestions(missingTarget: string, flat: UiNode[], _ctx?: SemanticContext): Promise<Suggestion[]>;
19
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * @module ai
3
+ * @description Semantic resolution, AI provider integration, and self-healing engine.
4
+ */
5
+ import { SemanticResolver } from './types.js';
6
+ import { PromptTestConfig } from '../config-loader.js';
7
+ export * from './types.js';
8
+ export * from './heuristic-resolver.js';
9
+ export * from './llm-provider.js';
10
+ /**
11
+ * Creates and returns the appropriate SemanticResolver based on configuration.
12
+ *
13
+ * @param config - Optional configuration overrides.
14
+ * @returns An initialized SemanticResolver instance.
15
+ */
16
+ export declare function createSemanticResolver(config?: Partial<PromptTestConfig['ai']>): SemanticResolver;
@@ -0,0 +1,40 @@
1
+ /**
2
+ * @module ai/llm-provider
3
+ * @description Cloud and local LLM semantic resolver implementations supporting
4
+ * OpenAI, Anthropic, Ollama, and Mock providers for automated intent expansion and self-healing.
5
+ */
6
+ import { UiNode } from '../crawler.js';
7
+ import { PromptStep } from '../prompt-runner.js';
8
+ import { SemanticResolver, Suggestion, SemanticContext } from './types.js';
9
+ export interface LLMConfig {
10
+ provider: 'openai' | 'anthropic' | 'ollama' | 'mock';
11
+ model?: string;
12
+ apiKey?: string;
13
+ endpoint?: string;
14
+ timeoutMs?: number;
15
+ }
16
+ /**
17
+ * Mock resolver for deterministic unit tests and headless CI environments.
18
+ */
19
+ export declare class MockAIProvider implements SemanticResolver {
20
+ readonly providerName = "mock";
21
+ private mockIntents;
22
+ private mockSuggestions;
23
+ constructor();
24
+ setMockIntent(intent: string, steps: PromptStep[]): void;
25
+ setMockSuggestion(target: string, suggestions: Suggestion[]): void;
26
+ resolveIntent(intent: string, _ctx?: SemanticContext): Promise<PromptStep[] | null>;
27
+ findSuggestions(missingTarget: string, flat: UiNode[], _ctx?: SemanticContext): Promise<Suggestion[]>;
28
+ }
29
+ /**
30
+ * Production LLM resolver communicating with OpenAI, Anthropic, or Ollama.
31
+ */
32
+ export declare class LLMResolver implements SemanticResolver {
33
+ readonly providerName: string;
34
+ private config;
35
+ private heuristicFallback;
36
+ constructor(config: LLMConfig);
37
+ resolveIntent(intent: string, ctx?: SemanticContext): Promise<PromptStep[] | null>;
38
+ findSuggestions(missingTarget: string, flat: UiNode[], ctx?: SemanticContext): Promise<Suggestion[]>;
39
+ private callLlm;
40
+ }