agent-device 0.19.0 → 0.19.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.
- package/README.md +5 -1
- package/android-multitouch-helper/dist/{agent-device-android-multitouch-helper-0.19.0.apk → agent-device-android-multitouch-helper-0.19.1.apk} +0 -0
- package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.19.1.apk.sha256 +1 -0
- package/android-multitouch-helper/dist/{agent-device-android-multitouch-helper-0.19.0.manifest.json → agent-device-android-multitouch-helper-0.19.1.manifest.json} +4 -4
- package/android-snapshot-helper/dist/{agent-device-android-snapshot-helper-0.19.0.apk → agent-device-android-snapshot-helper-0.19.1.apk} +0 -0
- package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.19.1.apk.sha256 +1 -0
- package/android-snapshot-helper/dist/{agent-device-android-snapshot-helper-0.19.0.manifest.json → agent-device-android-snapshot-helper-0.19.1.manifest.json} +6 -6
- package/dist/apple-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+AXSnapshotFallback.swift +24 -7
- package/dist/apple-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +506 -119
- package/dist/apple-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +153 -48
- package/dist/apple-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Navigation.swift +172 -0
- package/dist/apple-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SequenceExecution.swift +76 -5
- package/dist/apple-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +60 -52
- package/dist/apple-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCapturePlan.swift +159 -56
- package/dist/apple-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedGesturePolicy.swift +142 -0
- package/dist/apple-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests.swift +16 -14
- package/dist/src/android-adb.d.ts +1 -2
- package/dist/src/android-adb.js +1 -1
- package/dist/src/android-input-ownership.js +6 -0
- package/dist/src/android.js +1 -1
- package/dist/src/app-lifecycle.js +3 -3
- package/dist/src/apple-runner-options.js +1 -1
- package/dist/src/apps.js +5 -5
- package/dist/src/cli-help.js +131 -34
- package/dist/src/cli-runner.js +1 -1
- package/dist/src/cli.js +11 -11
- package/dist/src/client.js +2 -2
- package/dist/src/command-metadata.js +1 -1
- package/dist/src/command-schema.js +3 -3
- package/dist/src/device-input-state.js +2 -2
- package/dist/src/devices2.js +1 -1
- package/dist/src/find.js +1 -1
- package/dist/src/generic.js +1 -1
- package/dist/src/index.d.ts +199 -20
- package/dist/src/input-actions.js +3 -3
- package/dist/src/interaction-snapshot.js +1 -1
- package/dist/src/interaction.js +1 -1
- package/dist/src/interactor.js +2 -2
- package/dist/src/internal/bin.js +1 -1
- package/dist/src/internal/daemon.js +17 -15
- package/dist/src/lease.js +1 -1
- package/dist/src/linux.js +1 -1
- package/dist/src/metro.d.ts +0 -1
- package/dist/src/notifications.js +1 -1
- package/dist/src/points.js +1 -1
- package/dist/src/project-runtime.js +1 -1
- package/dist/src/providers.js +1 -1
- package/dist/src/react-native.js +1 -1
- package/dist/src/record-trace-recording.js +2 -2
- package/dist/src/record-trace.js +1 -1
- package/dist/src/registry.js +24 -23
- package/dist/src/reporting.js +3 -3
- package/dist/src/runner-client.js +1 -1
- package/dist/src/runtime.js +2 -2
- package/dist/src/sdk-android-adb.d.ts +2 -2
- package/dist/src/sdk-batch-runner.d.ts +0 -1
- package/dist/src/sdk-batch.js +2 -2
- package/dist/src/sdk-finders.d.ts +1 -2
- package/dist/src/sdk-finders.js +1 -1
- package/dist/src/sdk-io.d.ts +0 -1
- package/dist/src/sdk-remote-config.d.ts +1 -2
- package/dist/src/sdk-remote-config.js +1 -1
- package/dist/src/sdk-selectors.js +1 -1
- package/dist/src/selector-runtime.js +1 -1
- package/dist/src/selectors.d.ts +0 -1
- package/dist/src/selectors.js +1 -1
- package/dist/src/selectors2.js +1 -1
- package/dist/src/server.js +3 -3
- package/dist/src/session.js +10 -10
- package/dist/src/simctl.js +1 -1
- package/dist/src/simulator.js +1 -1
- package/dist/src/snapshot-diagnostics.js +2 -2
- package/dist/src/snapshot-helper.js +4 -4
- package/dist/src/snapshot-quality.js +1 -1
- package/dist/src/snapshot2.js +2 -2
- package/dist/src/tv-remote.js +14 -0
- package/dist/src/web.js +1 -1
- package/package.json +5 -4
- package/server.json +2 -2
- package/skills/agent-device/SKILL.md +8 -7
- package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.19.0.apk.sha256 +0 -1
- package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.19.0.apk.sha256 +0 -1
- package/dist/src/device-rotation.js +0 -14
- package/dist/src/logcat.js +0 -6
package/dist/src/index.d.ts
CHANGED
|
@@ -4,7 +4,6 @@ import { t as BatchRunResult } from "./sdk-batch-runner.js";
|
|
|
4
4
|
import { r as FindLocator } from "./sdk-finders.js";
|
|
5
5
|
import { p as createLocalArtifactAdapter } from "./sdk-io.js";
|
|
6
6
|
import { a as PrepareMetroRuntimeResult, c as MetroBridgeScope, i as MetroPrepareKind, o as ReloadMetroResult, r as RemoteConnectionProfileFields, t as CloudProviderProfileFields } from "./sdk-remote-config.js";
|
|
7
|
-
|
|
8
7
|
//#region src/platforms/android/snapshot-helper-types.d.ts
|
|
9
8
|
type AndroidSnapshotHelperTransport = 'instrumentation' | 'persistent-session';
|
|
10
9
|
type AndroidSnapshotCaptureMode = 'interactive-windows' | 'active-window';
|
|
@@ -81,10 +80,60 @@ type ClickButton = (typeof CLICK_BUTTONS)[number];
|
|
|
81
80
|
declare const RECORDING_EXPORT_QUALITIES: readonly ['medium', 'high'];
|
|
82
81
|
type RecordingExportQuality = (typeof RECORDING_EXPORT_QUALITIES)[number];
|
|
83
82
|
//#endregion
|
|
83
|
+
//#region src/core/recording-scope.d.ts
|
|
84
|
+
declare const RECORDING_SCOPE_VALUES: readonly ['app', 'device', 'system'];
|
|
85
|
+
type RecordingScope = (typeof RECORDING_SCOPE_VALUES)[number];
|
|
86
|
+
//#endregion
|
|
84
87
|
//#region src/core/device-rotation.d.ts
|
|
85
88
|
declare const DEVICE_ROTATIONS: readonly ['portrait', 'portrait-upside-down', 'landscape-left', 'landscape-right'];
|
|
86
89
|
type DeviceRotation = (typeof DEVICE_ROTATIONS)[number];
|
|
87
90
|
//#endregion
|
|
91
|
+
//#region src/core/tv-remote.d.ts
|
|
92
|
+
declare const TV_REMOTE_BUTTON_DEFINITIONS: {
|
|
93
|
+
readonly up: {
|
|
94
|
+
readonly aliases: readonly [];
|
|
95
|
+
readonly androidKeyevent: 'KEYCODE_DPAD_UP';
|
|
96
|
+
readonly appleRemoteButton: 'up';
|
|
97
|
+
};
|
|
98
|
+
readonly down: {
|
|
99
|
+
readonly aliases: readonly [];
|
|
100
|
+
readonly androidKeyevent: 'KEYCODE_DPAD_DOWN';
|
|
101
|
+
readonly appleRemoteButton: 'down';
|
|
102
|
+
};
|
|
103
|
+
readonly left: {
|
|
104
|
+
readonly aliases: readonly [];
|
|
105
|
+
readonly androidKeyevent: 'KEYCODE_DPAD_LEFT';
|
|
106
|
+
readonly appleRemoteButton: 'left';
|
|
107
|
+
};
|
|
108
|
+
readonly right: {
|
|
109
|
+
readonly aliases: readonly [];
|
|
110
|
+
readonly androidKeyevent: 'KEYCODE_DPAD_RIGHT';
|
|
111
|
+
readonly appleRemoteButton: 'right';
|
|
112
|
+
};
|
|
113
|
+
readonly select: {
|
|
114
|
+
readonly aliases: readonly ["ok", "center", "enter"];
|
|
115
|
+
readonly androidKeyevent: 'KEYCODE_DPAD_CENTER';
|
|
116
|
+
readonly appleRemoteButton: 'select';
|
|
117
|
+
};
|
|
118
|
+
readonly menu: {
|
|
119
|
+
readonly aliases: readonly [];
|
|
120
|
+
readonly androidKeyevent: 'KEYCODE_MENU';
|
|
121
|
+
readonly appleRemoteButton: 'menu';
|
|
122
|
+
};
|
|
123
|
+
readonly home: {
|
|
124
|
+
readonly aliases: readonly [];
|
|
125
|
+
readonly androidKeyevent: 'KEYCODE_HOME';
|
|
126
|
+
readonly appleRemoteButton: 'home';
|
|
127
|
+
};
|
|
128
|
+
readonly back: {
|
|
129
|
+
readonly aliases: readonly [];
|
|
130
|
+
readonly androidKeyevent: 'KEYCODE_BACK';
|
|
131
|
+
readonly appleRemoteButton: 'menu';
|
|
132
|
+
};
|
|
133
|
+
};
|
|
134
|
+
declare const TV_REMOTE_BUTTONS: (keyof typeof TV_REMOTE_BUTTON_DEFINITIONS)[];
|
|
135
|
+
type TvRemoteButton = (typeof TV_REMOTE_BUTTONS)[number];
|
|
136
|
+
//#endregion
|
|
88
137
|
//#region src/core/scroll-gesture.d.ts
|
|
89
138
|
declare const SCROLL_DIRECTIONS: readonly ['up', 'down', 'left', 'right'];
|
|
90
139
|
type ScrollDirection = (typeof SCROLL_DIRECTIONS)[number];
|
|
@@ -106,6 +155,13 @@ type TransformGestureParams = {
|
|
|
106
155
|
declare const ALERT_ACTIONS: readonly ['get', 'accept', 'dismiss', 'wait'];
|
|
107
156
|
type AlertAction = (typeof ALERT_ACTIONS)[number];
|
|
108
157
|
//#endregion
|
|
158
|
+
//#region src/contracts/json.d.ts
|
|
159
|
+
type JsonPrimitive = string | number | boolean | null;
|
|
160
|
+
type JsonValue = JsonPrimitive | JsonObject | JsonValue[];
|
|
161
|
+
type JsonObject = {
|
|
162
|
+
[key: string]: JsonValue;
|
|
163
|
+
};
|
|
164
|
+
//#endregion
|
|
109
165
|
//#region src/core/session-surface.d.ts
|
|
110
166
|
declare const SESSION_SURFACES: readonly ['app', 'frontmost-app', 'desktop', 'menubar'];
|
|
111
167
|
type SessionSurface = (typeof SESSION_SURFACES)[number];
|
|
@@ -113,6 +169,11 @@ type SessionSurface = (typeof SESSION_SURFACES)[number];
|
|
|
113
169
|
//#region src/utils/screenshot-result.d.ts
|
|
114
170
|
type ScreenshotResultData = {
|
|
115
171
|
path?: string;
|
|
172
|
+
width?: number;
|
|
173
|
+
height?: number;
|
|
174
|
+
logicalWidth?: number;
|
|
175
|
+
logicalHeight?: number;
|
|
176
|
+
pixelDensity?: number;
|
|
116
177
|
overlayRefs?: ScreenshotOverlayRef[];
|
|
117
178
|
};
|
|
118
179
|
//#endregion
|
|
@@ -202,13 +263,15 @@ type SettleObservation = {
|
|
|
202
263
|
refs?: Array<{
|
|
203
264
|
ref: string;
|
|
204
265
|
}>;
|
|
266
|
+
/** Present only for `settled: true` observations that stored the settled tree. */
|
|
205
267
|
diff?: {
|
|
206
268
|
summary: {
|
|
207
269
|
additions: number;
|
|
208
270
|
removals: number;
|
|
209
271
|
unchanged: number;
|
|
210
272
|
};
|
|
211
|
-
lines: SettleDiffLine[];
|
|
273
|
+
lines: SettleDiffLine[];
|
|
274
|
+
/** Present (true) when lines were capped to the response bound. */
|
|
212
275
|
truncated?: boolean;
|
|
213
276
|
};
|
|
214
277
|
hint?: string;
|
|
@@ -272,10 +335,13 @@ type PerfKind = (typeof PERF_KIND_VALUES)[number];
|
|
|
272
335
|
*/
|
|
273
336
|
type BootCommandResult = {
|
|
274
337
|
platform: PublicPlatform;
|
|
275
|
-
target: DeviceTarget;
|
|
276
|
-
|
|
338
|
+
target: DeviceTarget;
|
|
339
|
+
/** Human-readable device name (`device.name`). */
|
|
340
|
+
device: string;
|
|
341
|
+
/** Stable device id (`device.id`). */
|
|
277
342
|
id: string;
|
|
278
|
-
kind: DeviceKind;
|
|
343
|
+
kind: DeviceKind;
|
|
344
|
+
/** Always `true` on the success path. */
|
|
279
345
|
booted: true;
|
|
280
346
|
/**
|
|
281
347
|
* Additive Apple-OS discriminant (`device.appleOs`): iPhone/iPad/tvOS/visionOS/macOS.
|
|
@@ -293,8 +359,10 @@ type BootCommandResult = {
|
|
|
293
359
|
*/
|
|
294
360
|
type ShutdownCommandResult = {
|
|
295
361
|
platform: PublicPlatform;
|
|
296
|
-
target: DeviceTarget;
|
|
297
|
-
|
|
362
|
+
target: DeviceTarget;
|
|
363
|
+
/** Human-readable device name (`device.name`). */
|
|
364
|
+
device: string;
|
|
365
|
+
/** Stable device id (`device.id`). */
|
|
298
366
|
id: string;
|
|
299
367
|
kind: DeviceKind;
|
|
300
368
|
shutdown: TargetShutdownResult;
|
|
@@ -352,6 +420,13 @@ type AppSwitcherCommandResult = {
|
|
|
352
420
|
action: 'app-switcher';
|
|
353
421
|
message: string;
|
|
354
422
|
};
|
|
423
|
+
/** `tv-remote` — `{ action: 'tv-remote', button, durationMs?, message }`. */
|
|
424
|
+
type TvRemoteCommandResult = {
|
|
425
|
+
action: 'tv-remote';
|
|
426
|
+
button: TvRemoteButton;
|
|
427
|
+
durationMs?: number;
|
|
428
|
+
message: string;
|
|
429
|
+
};
|
|
355
430
|
//#endregion
|
|
356
431
|
//#region src/contracts/clipboard.d.ts
|
|
357
432
|
/**
|
|
@@ -387,8 +462,10 @@ type AppStateCommandResult = {
|
|
|
387
462
|
appName: string;
|
|
388
463
|
appBundleId?: string;
|
|
389
464
|
source: 'session';
|
|
390
|
-
surface: SessionSurface;
|
|
391
|
-
|
|
465
|
+
surface: SessionSurface;
|
|
466
|
+
/** iOS only — the session device's UDID. */
|
|
467
|
+
device_udid?: string;
|
|
468
|
+
/** iOS only — the simulator set path, or `null` when unknown. */
|
|
392
469
|
ios_simulator_device_set?: string | null;
|
|
393
470
|
} | {
|
|
394
471
|
platform: 'android';
|
|
@@ -427,6 +504,86 @@ type KeyboardCommandResult = {
|
|
|
427
504
|
message?: string;
|
|
428
505
|
};
|
|
429
506
|
//#endregion
|
|
507
|
+
//#region src/contracts/wait.d.ts
|
|
508
|
+
/**
|
|
509
|
+
* Public daemon result for `wait`. The runtime-local result carries a `kind`
|
|
510
|
+
* discriminant, but `toDaemonWaitData` intentionally projects the normal daemon
|
|
511
|
+
* payload to this compact shape. The direct iOS selector fast path may still
|
|
512
|
+
* include `kind: 'selector'` additively.
|
|
513
|
+
*/
|
|
514
|
+
type WaitCommandResult = {
|
|
515
|
+
waitedMs: number;
|
|
516
|
+
kind?: 'selector';
|
|
517
|
+
text?: string;
|
|
518
|
+
selector?: string;
|
|
519
|
+
captures?: number;
|
|
520
|
+
nodeCount?: number;
|
|
521
|
+
hint?: string;
|
|
522
|
+
warning?: string;
|
|
523
|
+
};
|
|
524
|
+
//#endregion
|
|
525
|
+
//#region src/contracts/prepare.d.ts
|
|
526
|
+
type PrepareIosRunnerCacheKind = 'exact' | 'restore-key' | 'miss' | 'external';
|
|
527
|
+
type PrepareIosRunnerArtifactState = 'valid' | 'rebuilt';
|
|
528
|
+
type PrepareIosRunnerTiming = {
|
|
529
|
+
totalMs: number;
|
|
530
|
+
additiveParts: {
|
|
531
|
+
buildMs?: number;
|
|
532
|
+
connectAfterBuildMs: number;
|
|
533
|
+
healthCheckMs: number;
|
|
534
|
+
};
|
|
535
|
+
containment: {
|
|
536
|
+
connectMs?: ['buildMs'];
|
|
537
|
+
healthCheckMs: [];
|
|
538
|
+
};
|
|
539
|
+
note: string;
|
|
540
|
+
};
|
|
541
|
+
/**
|
|
542
|
+
* Public daemon result for `prepare ios-runner`. The runner-local prepare result
|
|
543
|
+
* is projected by `prepareIosRunnerResponseData` with device identity and timing
|
|
544
|
+
* guidance before it reaches the client.
|
|
545
|
+
*/
|
|
546
|
+
type PrepareCommandResult = {
|
|
547
|
+
action: 'ios-runner';
|
|
548
|
+
platform: PublicPlatform;
|
|
549
|
+
deviceId: string;
|
|
550
|
+
deviceName: string;
|
|
551
|
+
kind: DeviceKind;
|
|
552
|
+
durationMs: number;
|
|
553
|
+
runner: JsonObject;
|
|
554
|
+
cache?: PrepareIosRunnerCacheKind;
|
|
555
|
+
artifact?: PrepareIosRunnerArtifactState;
|
|
556
|
+
buildMs?: number;
|
|
557
|
+
connectMs: number;
|
|
558
|
+
healthCheckMs: number;
|
|
559
|
+
xctestrunPath?: string;
|
|
560
|
+
recoveryReason?: string;
|
|
561
|
+
failureReason?: string;
|
|
562
|
+
timing: PrepareIosRunnerTiming;
|
|
563
|
+
message: string;
|
|
564
|
+
};
|
|
565
|
+
//#endregion
|
|
566
|
+
//#region src/contracts/push.d.ts
|
|
567
|
+
type PushCommandResult = {
|
|
568
|
+
platform: 'ios';
|
|
569
|
+
bundleId: string;
|
|
570
|
+
message: string;
|
|
571
|
+
} | {
|
|
572
|
+
platform: 'android';
|
|
573
|
+
package: string;
|
|
574
|
+
action: string;
|
|
575
|
+
extrasCount: number;
|
|
576
|
+
message: string;
|
|
577
|
+
};
|
|
578
|
+
//#endregion
|
|
579
|
+
//#region src/contracts/app-events.d.ts
|
|
580
|
+
type TriggerAppEventCommandResult = {
|
|
581
|
+
event: string;
|
|
582
|
+
eventUrl: string;
|
|
583
|
+
transport: 'deep-link';
|
|
584
|
+
message: string;
|
|
585
|
+
};
|
|
586
|
+
//#endregion
|
|
430
587
|
//#region src/core/command-descriptor/command-result.d.ts
|
|
431
588
|
/**
|
|
432
589
|
* The additive typed-result spine (ADR-0008, Phase 1 step 6).
|
|
@@ -443,7 +600,8 @@ type KeyboardCommandResult = {
|
|
|
443
600
|
* interaction trio. Batch 3 adds `clipboard` (a closed `read`/`write` union) and
|
|
444
601
|
* `appstate` (a closed `platform` union — Apple session state with the iOS-only
|
|
445
602
|
* device locators, or Android package/activity). Batch 4 adds `keyboard` (a
|
|
446
|
-
* closed flat shape).
|
|
603
|
+
* closed flat shape). Batch 5 adds the compact daemon projections for `wait`,
|
|
604
|
+
* `prepare`, `push`, and `trigger-app-event`. Each entry is grounded in a
|
|
447
605
|
* re-read of the handler's literal return; see the per-type docstrings.
|
|
448
606
|
*/
|
|
449
607
|
interface CommandResultMap {
|
|
@@ -460,6 +618,11 @@ interface CommandResultMap {
|
|
|
460
618
|
clipboard: ClipboardCommandResult;
|
|
461
619
|
appstate: AppStateCommandResult;
|
|
462
620
|
keyboard: KeyboardCommandResult;
|
|
621
|
+
'tv-remote': TvRemoteCommandResult;
|
|
622
|
+
wait: WaitCommandResult;
|
|
623
|
+
prepare: PrepareCommandResult;
|
|
624
|
+
push: PushCommandResult;
|
|
625
|
+
'trigger-app-event': TriggerAppEventCommandResult;
|
|
463
626
|
}
|
|
464
627
|
/**
|
|
465
628
|
* The typed result for a command named `N`. Seeded commands resolve to their
|
|
@@ -658,6 +821,7 @@ type AppOpenResult = {
|
|
|
658
821
|
sessionStateDir?: string;
|
|
659
822
|
runnerLogPath?: string;
|
|
660
823
|
requestLogPath?: string;
|
|
824
|
+
eventLogPath?: string;
|
|
661
825
|
appName?: string;
|
|
662
826
|
appBundleId?: string;
|
|
663
827
|
appId?: string;
|
|
@@ -787,6 +951,7 @@ type CaptureSnapshotResult = {
|
|
|
787
951
|
type CaptureScreenshotOptions = AgentDeviceRequestOverrides & {
|
|
788
952
|
path?: string;
|
|
789
953
|
overlayRefs?: boolean;
|
|
954
|
+
pixelDensity?: number;
|
|
790
955
|
fullscreen?: boolean;
|
|
791
956
|
maxSize?: number;
|
|
792
957
|
stabilize?: boolean;
|
|
@@ -862,6 +1027,10 @@ type ClipboardCommandOptions = (DeviceCommandBaseOptions & {
|
|
|
862
1027
|
action: 'write';
|
|
863
1028
|
text: string;
|
|
864
1029
|
});
|
|
1030
|
+
type TvRemoteCommandOptions = DeviceCommandBaseOptions & {
|
|
1031
|
+
button: TvRemoteButton;
|
|
1032
|
+
durationMs?: number;
|
|
1033
|
+
};
|
|
865
1034
|
type ReactNativeCommandOptions = DeviceCommandBaseOptions & {
|
|
866
1035
|
action: 'dismiss-overlay';
|
|
867
1036
|
};
|
|
@@ -878,7 +1047,7 @@ type ViewportCommandOptions = DeviceCommandBaseOptions & {
|
|
|
878
1047
|
height: number;
|
|
879
1048
|
};
|
|
880
1049
|
type AgentDeviceCommandClient = {
|
|
881
|
-
wait: (options: WaitCommandOptions) => Promise<
|
|
1050
|
+
wait: (options: WaitCommandOptions) => Promise<CommandResult<'wait'>>;
|
|
882
1051
|
alert: (options?: AlertCommandOptions) => Promise<CommandRequestResult>;
|
|
883
1052
|
appState: (options?: AppStateCommandOptions) => Promise<CommandResult<'appstate'>>;
|
|
884
1053
|
back: (options?: BackCommandOptions) => Promise<CommandResult<'back'>>;
|
|
@@ -887,13 +1056,14 @@ type AgentDeviceCommandClient = {
|
|
|
887
1056
|
appSwitcher: (options?: AppSwitcherCommandOptions) => Promise<CommandResult<'app-switcher'>>;
|
|
888
1057
|
keyboard: (options?: KeyboardCommandOptions) => Promise<CommandResult<'keyboard'>>;
|
|
889
1058
|
clipboard: (options: ClipboardCommandOptions) => Promise<CommandResult<'clipboard'>>;
|
|
1059
|
+
tvRemote: (options: TvRemoteCommandOptions) => Promise<CommandResult<'tv-remote'>>;
|
|
890
1060
|
reactNative: (options: ReactNativeCommandOptions) => Promise<CommandRequestResult>;
|
|
891
1061
|
doctor: (options?: DoctorCommandOptions) => Promise<CommandRequestResult>;
|
|
892
1062
|
/**
|
|
893
1063
|
* JSON prepare results include timing.additiveParts for additive wall-clock phases.
|
|
894
1064
|
* Top-level buildMs/connectMs/healthCheckMs are diagnostics and may overlap.
|
|
895
1065
|
*/
|
|
896
|
-
prepare: (options: PrepareCommandOptions) => Promise<
|
|
1066
|
+
prepare: (options: PrepareCommandOptions) => Promise<CommandResult<'prepare'>>;
|
|
897
1067
|
viewport: (options: ViewportCommandOptions) => Promise<CommandResult<'viewport'>>;
|
|
898
1068
|
};
|
|
899
1069
|
type SelectorSnapshotCommandOptions = Pick<CaptureSnapshotOptions, 'depth' | 'scope' | 'raw'>;
|
|
@@ -934,11 +1104,11 @@ type DeviceBootOptions = DeviceCommandBaseOptions & {
|
|
|
934
1104
|
type DeviceShutdownOptions = DeviceCommandBaseOptions;
|
|
935
1105
|
type AppPushOptions = DeviceCommandBaseOptions & {
|
|
936
1106
|
app: string;
|
|
937
|
-
payload: string |
|
|
1107
|
+
payload: string | JsonObject;
|
|
938
1108
|
};
|
|
939
1109
|
type AppTriggerEventOptions = DeviceCommandBaseOptions & {
|
|
940
1110
|
event: string;
|
|
941
|
-
payload?:
|
|
1111
|
+
payload?: JsonObject;
|
|
942
1112
|
};
|
|
943
1113
|
type CaptureDiffOptions = DeviceCommandBaseOptions & Pick<CaptureSnapshotOptions, 'interactiveOnly' | 'depth' | 'scope' | 'raw'> & {
|
|
944
1114
|
kind: 'snapshot';
|
|
@@ -1044,7 +1214,7 @@ type IsTextPredicateOptions = DeviceCommandBaseOptions & SelectorSnapshotCommand
|
|
|
1044
1214
|
value: string;
|
|
1045
1215
|
};
|
|
1046
1216
|
type IsStatePredicateOptions = DeviceCommandBaseOptions & SelectorSnapshotCommandOptions & {
|
|
1047
|
-
predicate: 'visible' | 'hidden' | 'exists' | 'editable' | 'selected';
|
|
1217
|
+
predicate: 'visible' | 'hidden' | 'exists' | 'editable' | 'selected' | 'focused';
|
|
1048
1218
|
selector: string;
|
|
1049
1219
|
value?: never;
|
|
1050
1220
|
};
|
|
@@ -1066,7 +1236,8 @@ type FindOptions = (FindBaseOptions & {
|
|
|
1066
1236
|
});
|
|
1067
1237
|
type ReplayRunOptions = AgentDeviceRequestOverrides & AgentDeviceSelectionOptions & {
|
|
1068
1238
|
path: string;
|
|
1069
|
-
update?: boolean;
|
|
1239
|
+
update?: boolean;
|
|
1240
|
+
/** @deprecated Use backend: 'maestro'. */
|
|
1070
1241
|
maestro?: boolean;
|
|
1071
1242
|
backend?: string;
|
|
1072
1243
|
env?: string[];
|
|
@@ -1074,7 +1245,8 @@ type ReplayRunOptions = AgentDeviceRequestOverrides & AgentDeviceSelectionOption
|
|
|
1074
1245
|
};
|
|
1075
1246
|
type ReplayTestOptions = AgentDeviceRequestOverrides & AgentDeviceSelectionOptions & {
|
|
1076
1247
|
paths: string[];
|
|
1077
|
-
update?: boolean;
|
|
1248
|
+
update?: boolean;
|
|
1249
|
+
/** @deprecated Use backend: 'maestro'. */
|
|
1078
1250
|
maestro?: boolean;
|
|
1079
1251
|
backend?: string;
|
|
1080
1252
|
env?: string[];
|
|
@@ -1082,7 +1254,8 @@ type ReplayTestOptions = AgentDeviceRequestOverrides & AgentDeviceSelectionOptio
|
|
|
1082
1254
|
timeoutMs?: number;
|
|
1083
1255
|
retries?: number;
|
|
1084
1256
|
recordVideo?: boolean;
|
|
1085
|
-
artifactsDir?: string;
|
|
1257
|
+
artifactsDir?: string;
|
|
1258
|
+
/** @deprecated Use the CLI --reporter junit:<path> or --report-junit <path>. */
|
|
1086
1259
|
reportJunit?: string;
|
|
1087
1260
|
shardAll?: number;
|
|
1088
1261
|
shardSplit?: number;
|
|
@@ -1112,6 +1285,10 @@ type LogsOptions = AgentDeviceRequestOverrides & {
|
|
|
1112
1285
|
message?: string;
|
|
1113
1286
|
restart?: boolean;
|
|
1114
1287
|
};
|
|
1288
|
+
type EventsOptions = AgentDeviceRequestOverrides & {
|
|
1289
|
+
cursor?: string;
|
|
1290
|
+
limit?: number;
|
|
1291
|
+
};
|
|
1115
1292
|
type NetworkOptions = AgentDeviceRequestOverrides & {
|
|
1116
1293
|
action?: 'dump' | 'log';
|
|
1117
1294
|
limit?: number;
|
|
@@ -1130,6 +1307,7 @@ type RecordOptions = AgentDeviceRequestOverrides & {
|
|
|
1130
1307
|
maxSize?: number;
|
|
1131
1308
|
quality?: RecordingExportQuality;
|
|
1132
1309
|
hideTouches?: boolean;
|
|
1310
|
+
recordingScope?: RecordingScope;
|
|
1133
1311
|
};
|
|
1134
1312
|
type TraceOptions = AgentDeviceRequestOverrides & {
|
|
1135
1313
|
action: 'start' | 'stop';
|
|
@@ -1190,8 +1368,8 @@ type AgentDeviceClient = {
|
|
|
1190
1368
|
list: (options?: AppListOptions) => Promise<string[]>;
|
|
1191
1369
|
open: (options: AppOpenOptions) => Promise<AppOpenResult>;
|
|
1192
1370
|
close: (options?: AppCloseOptions) => Promise<AppCloseResult>;
|
|
1193
|
-
push: (options: AppPushOptions) => Promise<
|
|
1194
|
-
triggerEvent: (options: AppTriggerEventOptions) => Promise<
|
|
1371
|
+
push: (options: AppPushOptions) => Promise<CommandResult<'push'>>;
|
|
1372
|
+
triggerEvent: (options: AppTriggerEventOptions) => Promise<CommandResult<'trigger-app-event'>>;
|
|
1195
1373
|
};
|
|
1196
1374
|
materializations: {
|
|
1197
1375
|
release: (options: MaterializationReleaseOptions) => Promise<MaterializationReleaseResult>;
|
|
@@ -1242,6 +1420,7 @@ type AgentDeviceClient = {
|
|
|
1242
1420
|
observability: {
|
|
1243
1421
|
perf: (options?: PerfOptions) => Promise<CommandRequestResult>;
|
|
1244
1422
|
logs: (options?: LogsOptions) => Promise<CommandRequestResult>;
|
|
1423
|
+
events: (options?: EventsOptions) => Promise<CommandRequestResult>;
|
|
1245
1424
|
network: (options?: NetworkOptions) => Promise<CommandRequestResult>;
|
|
1246
1425
|
audio: (options?: AudioOptions) => Promise<CommandRequestResult>;
|
|
1247
1426
|
};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{t as e}from"./rolldown-runtime.js";import{F as t}from"./sdk-contracts.js";import{j as n,u as r}from"./sdk-android-adb.js";import{
|
|
2
|
-
`);for(let[r,
|
|
3
|
-
`&&(e<32||e>126))return!1}return!0}function Z(e){return e.replace(/ /g,`%s`)}function
|
|
1
|
+
import{t as e}from"./rolldown-runtime.js";import{F as t}from"./sdk-contracts.js";import{j as n,u as r}from"./sdk-android-adb.js";import{i,st as a}from"./tv-remote.js";import{t as o}from"./timeouts.js";import{p as s,r as c}from"./android-input-ownership.js";import{r as l}from"./device-input-state.js";import{p as u}from"./snapshot-helper.js";import{Et as d}from"./internal/daemon.js";function ee(e,t){if(!t)return{expected:e,actual:null,failureReason:`text_mismatch`,targetInput:null,actualInput:null};let n=h(t),r={failureReason:t.reason??`text_mismatch`,targetInput:m(t.targetInput),actualInput:m(t.actualInput)};return n?{...r,expectedLength:Array.from(e).length,actual:null,masked:!0,actualLength:Array.from(t.actual??``).length}:{...r,expected:e,actual:t.actual}}function f(e){return e?e.password?!0:p(e.text):!1}function p(e){return e?Array.from(e).every(te):!1}function m(e){if(!e)return null;let t=f(e);return{...e,text:t?null:e.text,...t?{textRedacted:!0}:{}}}function te(e){return e===`•`||e===`*`||e===`●`}function h(e){return e.masked===!0||f(e.targetInput)||f(e.actualInput)}async function g(e,t,n,r){let i=[0,150,350],a=null,s=null,c=await ae(e);for(let l of i){l>0&&await o(l);let i=await S(e,t,n,r,c);if(a=i,i.reason===`ime_capture`)return i;s=i.ok?i:null}return s??a??{ok:!1,actual:null,reason:`text_mismatch`,targetInput:null,actualInput:null}}async function _(e,t,n){return y(await d(e),t,n)}function v(e,t,n,r,i={}){let a=C(e,t,n,i);return w(a)?{ok:!1,actual:a.actualInput?.text??null,reason:`ime_capture`,targetInput:a.targetInput,actualInput:a.actualInput}:T(a,r)??E(a,r)}function y(e,t,n){return C(e,t,n).actualInput?.text??null}function b(e){return e?.reason===`ime_capture`?`Android fill input was captured by the active keyboard instead of the app field`:e?.reason===`masked_unverified`?`Android fill verification could not confirm masked text value`:`Android fill verification failed`}function x(e,t){let n=ee(e,t);return t?.reason===`ime_capture`&&(n.hint=`The focused input belongs to the Android keyboard/IME, not the app field. Disable handwriting/stylus input or switch to a standard IME, then retry fill.`),n}async function S(e,t,n,r,i){return v(await d(e),t,n,r,i)}function C(e,t,n,r={}){let i={focusedEdit:null,editAtPoint:null,anyAtPoint:null};for(let a of u(e)){let e=ie(a,r);e&&oe(i,e,t,n)}return ce(i)}function w(e){let{targetInput:t,actualInput:n}=e;return!t||!n||n===t?!1:n.inputMethodOwned&&!t.inputMethodOwned}function T(e,t){let n=e.actualInput;if(!n||!A(n))return null;let r=n.text??null,i=Array.from(r??``).length,a=Array.from(t).length,o=r!==null&&i>0&&a>0&&i===a;return{ok:o,actual:r,reason:o?void 0:`masked_unverified`,masked:!0,targetInput:e.targetInput,actualInput:n}}function E(e,t){let n=e.actualInput?.text??null;return{ok:ne(n,t),actual:n,reason:`text_mismatch`,targetInput:e.targetInput,actualInput:e.actualInput}}function ne(e,t){if(e===t)return!0;let n=D(e),r=D(t);return!n||!r?!1:!!(n===r||re(n,r))}function D(e){return(e??``).replace(/\s+/g,` `).trim()}function re(e,t){if(e.length!==t.length||e.length===0||e.slice(1)!==t.slice(1))return!1;let n=e[0],r=t[0];return!n||!r?!1:r.toLowerCase()===r&&n===r.toUpperCase()}function ie(e,t){if(!e.rect)return null;let n=e.text??``,r=Math.max(1,e.rect.width*e.rect.height);return{text:n||null,className:e.className,resourceId:e.resourceId,packageName:e.packageName,rect:e.rect,focused:e.focused??!1,password:e.password===!0,inputMethodOwned:c({packageName:e.packageName,resourceId:e.resourceId,activeInputMethodPackage:t.activeInputMethodPackage}),area:r,editText:k(e.className??``)}}async function ae(e){try{return{activeInputMethodPackage:(await l(e)).inputMethodPackage}}catch(e){return n({level:`warn`,phase:`android_fill_verification_input_method_probe_failed`,data:{error:e instanceof Error?e.message:String(e)}}),{}}}function oe(e,t,n,r){let i=se(t.rect,n,r);if(i&&t.editText&&(e.editAtPoint=O(e.editAtPoint,t)),t.focused&&t.editText){e.focusedEdit=O(e.focusedEdit,t);return}i&&t.text&&(e.anyAtPoint=O(e.anyAtPoint,t))}function se(e,t,n){return t>=e.x&&t<=e.x+e.width&&n>=e.y&&n<=e.y+e.height}function O(e,t){return e&&e.area<t.area?e:t}function ce(e){let t=e.editAtPoint??e.anyAtPoint;return{targetInput:t,actualInput:(e.focusedEdit?.text?e.focusedEdit:null)??t}}function k(e){let t=e.toLowerCase();return t.includes(`edittext`)||t.includes(`textfield`)}function A(e){return f(e)}var j=e({appSwitcherAndroid:()=>z,backAndroid:()=>F,fillAndroid:()=>U,focusAndroid:()=>H,getAndroidScreenSize:()=>q,homeAndroid:()=>I,longPressAndroid:()=>B,pressAndroid:()=>M,pressAndroidEnter:()=>L,pressAndroidTvRemote:()=>N,readAndroidTextAtPoint:()=>_,rotateAndroid:()=>R,scrollAndroid:()=>G,swipeAndroid:()=>P,typeAndroid:()=>V});async function M(e,t,n){await s(e,[`shell`,`input`,`tap`,String(t),String(n)])}async function N(e,t,n){let r=i(t);await s(e,[`shell`,`input`,...n&&n>0?[`keyevent`,`--longpress`]:[`keyevent`],r])}async function P(e,t,n,r,i,a=250){await s(e,[`shell`,`input`,`swipe`,String(t),String(n),String(r),String(i),String(a)])}async function F(e){await s(e,[`shell`,`input`,`keyevent`,`4`])}async function I(e){await s(e,[`shell`,`input`,`keyevent`,`3`])}async function L(e){await s(e,[`shell`,`input`,`keyevent`,`ENTER`])}async function R(e,t){let n=le(t);await s(e,[`shell`,`settings`,`put`,`system`,`accelerometer_rotation`,`0`]),await s(e,[`shell`,`settings`,`put`,`system`,`user_rotation`,n])}async function z(e){await s(e,[`shell`,`input`,`keyevent`,`187`])}async function B(e,t,n,r=800){await s(e,[`shell`,`input`,`swipe`,String(t),String(n),String(t),String(n),String(r)])}async function V(e,t,n=0){let i=r(e);if(i){await i({action:`type`,text:t,delayMs:n}),$(`type`,`provider-native`,t);return}if(X(t),await K(e,`type`),n>0&&Array.from(t).length>1){await Y(e,{action:`type`,text:t,chunkSize:1,delayMs:n});return}await Y(e,{action:`type`,text:t,chunkSize:J,delayMs:0})}async function H(e,t,n){await M(e,t,n)}async function U(e,t,n,i,a=0){let o=r(e);if(o){await o({action:`fill`,target:{x:t,y:n},text:i,delayMs:a}),$(`fill`,`provider-native`,i);let r=await g(e,t,n,i);if(r.ok)return;W(i,r)}X(i);let s=Array.from(i).length,c=[{clearPadding:12,minClear:8,maxClear:48,chunkSize:a>0?1:J,inputDelayMs:a},{clearPadding:24,minClear:16,maxClear:96,chunkSize:a>0?1:4,inputDelayMs:a>0?a:15}],l=null;for(let r of c){await H(e,t,n),await K(e,`fill`),await me(e,he(s+r.clearPadding,r.minClear,r.maxClear)),await Y(e,{action:`fill`,text:i,chunkSize:r.chunkSize,delayMs:r.inputDelayMs});let a=await g(e,t,n,i);if(l=a,a.ok)return;a.reason===`ime_capture`&&W(i,a)}W(i,l)}function W(e,n){throw new t(`COMMAND_FAILED`,b(n),x(e,n))}async function G(e,t,n){let r=await q(e),i=a({direction:t,amount:n?.amount,pixels:n?.pixels,referenceWidth:r.width,referenceHeight:r.height}),o=n?.durationMs??300;return await s(e,[`shell`,`input`,`swipe`,String(i.x1),String(i.y1),String(i.x2),String(i.y2),String(o)]),{...i,...n?.durationMs===void 0?{}:{durationMs:n.durationMs}}}function le(e){switch(e){case`portrait`:return`0`;case`landscape-left`:return`1`;case`portrait-upside-down`:return`2`;case`landscape-right`:return`3`;default:throw new t(`INVALID_ARGS`,`Unsupported Android rotation: ${e}`)}}async function K(e,r){let i;try{i=await l(e)}catch(e){n({level:`warn`,phase:`android_input_ownership_probe_failed`,data:{action:r,error:e instanceof Error?e.message:String(e)}});return}if(i.inputOwner===`ime`)throw new t(`COMMAND_FAILED`,`KEYBOARD_OVERLAY_BLOCKING: Android text input is blocked because the focused input belongs to the active keyboard/IME.`,{failureReason:`ime_capture`,action:r,inputOwner:i.inputOwner,inputType:i.inputType,type:i.type,inputMethodPackage:i.inputMethodPackage,focusedPackage:i.focusedPackage,focusedResourceId:i.focusedResourceId,nextAction:`Focused input appears to be owned by the keyboard/IME; dismiss or change the IME before retrying text entry.`})}async function q(e){let n=(await s(e,[`shell`,`wm`,`size`])).stdout.match(/Physical size:\s*(\d+)x(\d+)/);if(!n)throw new t(`COMMAND_FAILED`,`Unable to read screen size`);return{width:Number(n[1]),height:Number(n[2])}}const J=8;async function Y(e,t){let n=t.text.split(`
|
|
2
|
+
`);for(let[r,i]of n.entries()){let a=pe(i,t.chunkSize);for(let[i,s]of a.entries())await ue(e,s),t.delayMs>0&&(i+1<a.length||r+1<n.length)&&await o(t.delayMs);r+1<n.length&&await s(e,[`shell`,`input`,`keyevent`,`ENTER`])}$(t.action,`adb-shell`,t.text)}async function ue(e,t){if(t)try{await s(e,[`shell`,`input`,`text`,Z(t)])}catch(e){throw fe(e)?Q(t,e):e}}function X(e){if(!de(e))throw Q(e)}function de(e){for(let t of e){let e=t.codePointAt(0);if(e!==void 0&&t!==`
|
|
3
|
+
`&&(e<32||e>126))return!1}return!0}function Z(e){return e.replace(/ /g,`%s`)}function fe(e){if(!(e instanceof t)||e.code!==`COMMAND_FAILED`)return!1;let n=e.details?.stderr,r=(typeof n==`string`?n:``).toLowerCase();return!!(r.includes(`exception occurred while executing 'text'`)||r.includes(`nullpointerexception`)&&r.includes(`inputshellcommand.sendtext`))}function Q(e,n){return new t(`COMMAND_FAILED`,`Android text input requires provider-native text injection for non-ASCII/control characters; the current adb-shell fallback supports ASCII text only.`,{backend:`adb-shell`,textLength:Array.from(e).length,textPreview:e.slice(0,32)},n instanceof Error?n:void 0)}function pe(e,t){let n=Math.max(1,Math.floor(t)),r=[],i=Array.from(e);for(let e=0;e<i.length;e+=n)r.push(i.slice(e,e+n).join(``));return r.length>0?r:[``]}function $(e,t,r){n({phase:`android_text_injection`,data:{action:e,backend:t,textLength:Array.from(r).length}})}async function me(e,t){let n=Math.max(0,t);await s(e,[`shell`,`input`,`keyevent`,`KEYCODE_MOVE_END`],{allowFailure:!0});for(let t=0;t<n;t+=24){let r=Math.min(24,n-t);await s(e,[`shell`,`input`,`keyevent`,...Array(r).fill(`KEYCODE_DEL`)],{allowFailure:!0})}}function he(e,t,n){return Math.max(t,Math.min(n,e))}export{q as a,B as c,R as d,G as f,H as i,M as l,V as m,F as n,I as o,P as p,U as r,j as s,z as t,N as u};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{j as e}from"./sdk-android-adb.js";import{t}from"./snapshot-quality.js";import{
|
|
1
|
+
import{j as e}from"./sdk-android-adb.js";import{t}from"./snapshot-quality.js";import{It as n,Lt as r,Mt as i,Pt as a,Rt as o,St as s,Ut as c,Wt as l,xt as u}from"./internal/daemon.js";import{a as d}from"./input-actions.js";function f(e){let{session:t,sessionStore:i,command:a,positionals:s,retryPositionals:d,flags:f,result:p,responseData:m,actionStartedAt:h,actionFinishedAt:g,androidFreshnessBaseline:_}=e,v=o(f);return i.recordAction(t,{command:a,positionals:s,flags:v??{},result:p}),r({session:t,command:a,positionals:d??s,flags:f,preSnapshot:t.snapshot}),c(a)&&l(t,a,_??t.snapshot),n(t,a,d??s,f),u(t,a,s,p,v??{},h,g),{ok:!0,data:m}}async function p(e){let{session:t,flags:n,sessionStore:r,contextFromFlags:i,captureSnapshotForSession:a}=e;if(!t.recording)return;if(t.recording.touchReferenceFrame)return t.recording.touchReferenceFrame;if(t.device.platform===`android`){let e=await d(t.device),n={referenceWidth:e.width,referenceHeight:e.height};return t.recording&&(t.recording.touchReferenceFrame=n),n}let o=s(t.snapshot);if(o)return t.recording&&(t.recording.touchReferenceFrame=o),o;if(!t.recording)return;let c=s(await a(t,n,r,i,{interactiveOnly:!0}));return c&&t.recording&&(t.recording.touchReferenceFrame=c),c}async function m(t){try{return await p(t)}catch(n){e({level:`warn`,phase:`touch_reference_frame_resolve_failed`,data:{platform:t.session.device.platform,error:n instanceof Error?n.message:String(n)}});return}}function h(e){return s({nodes:e,createdAt:0})}async function g(e,n,r,o,s){let c={...n??{},snapshotInteractiveOnly:s.interactiveOnly},l=o(c,e.appBundleId,e.trace?.outPath),{snapshot:u}=await a({device:e.device,session:e,flags:c,outPath:c.out,logPath:l.logPath??``,includeRects:s.includeRects,androidFreshnessMode:s.androidFreshnessMode});return t(u.snapshotQuality)||(i(e,u),r.set(e.name,e)),u}export{f as i,h as n,m as r,g as t};
|
package/dist/src/interaction.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{B as e,F as t,I as n,b as r,m as i}from"./sdk-contracts.js";import{j as a}from"./sdk-android-adb.js";import{d as o,u as s,w as c}from"./sdk-batch.js";import{_t as l,gn as u,gt as d,ht as ee}from"./device-rotation.js";import{t as f}from"./runtime.js";import{Et as p,Ht as m,Ot as h,Qt as g,St as _,Tt as v,Wt as y,Xt as b,Yt as x,Zt as S,kt as C,xt as w,zt as te}from"./internal/daemon.js";import{n as ne}from"./provider.js";import{_ as T,c as re,d as ie,f as ae,g as E,h as oe,l as se,m as D,n as O,o as k,p as A,r as ce,s as le,u as ue,v as de,y as j}from"./selector-runtime.js";import{i as M,n as N,r as fe,t as P}from"./interaction-snapshot.js";function F(e){let{source:t,referenceFrame:n,extra:r}=e;if(t.kind===`runner-payload`){let e={targetKind:t.targetKind,...r??{}};return{result:R({data:t.data,fallbackX:t.point.x,fallbackY:t.point.y,referenceFrame:n,extra:e}),responseData:R({data:B(t.data),fallbackX:t.point.x,fallbackY:t.point.y,referenceFrame:n,extra:e})}}let{result:i}=t,a=ae(i),o={targetKind:i.kind,...a,...I(i.settle,e.settleRefsGeneration),...r??{}},s=R({data:i.backendResult,fallbackX:i.point?.x,fallbackY:i.point?.y,referenceFrame:n,extra:o}),c=R({data:B(i.backendResult),fallbackX:i.point?.x,fallbackY:i.point?.y,referenceFrame:n,extra:o}),l=L(`warning`in i?i.warning:void 0,e.staleRefsWarning);return l&&(s.warning=l,c.warning=l),{result:s,responseData:c}}function I(e,t){return!e?.diff||t===void 0?{}:{settle:{...e,refsGeneration:t}}}function L(e,t){return t?e?`${e} ${t}`:t:e}function R(e){let{data:t,fallbackX:n,fallbackY:r,referenceFrame:i,extra:a}=e,o=pe(a,n,r)??(typeof t?.message==`string`?t.message:void 0);return z({...t??{},...n===void 0||r===void 0?{}:{x:n,y:r},...i??{},...a??{},...u(o)})}function z(e){return Object.fromEntries(Object.entries(e).filter(([,e])=>e!==void 0))}function B(e){if(!e)return;let t=Object.fromEntries(Object.entries(e).filter(([e,t])=>V(e,t)));return Object.keys(t).length>0?t:void 0}function V(e,t){switch(e){case`gestureStartUptimeMs`:case`gestureEndUptimeMs`:case`sequenceResults`:return!1;case`count`:return t!==1;case`intervalMs`:case`holdMs`:case`jitterPx`:return t!==0;case`doubleTap`:return t!==!1;default:return!0}}function pe(e,t,n){let r=H(e,`text`);if(r!==void 0)return`Filled ${Array.from(r).length} chars`;let i=me(t,n),a=he(e);if(a)return _e(a,e??{},i);if(i)return ge(e,i)}function H(e,t){let n=e?.[t];return typeof n==`string`?n:void 0}function me(e,t){return e===void 0||t===void 0?``:` (${e}, ${t})`}function he(e){let t=H(e,`ref`);return t===void 0?H(e,`selector`):`@${t}`}function ge(e,t){return e?.gesture===`longpress`?`Long pressed${t}`:`Tapped${t}`}function _e(e,t,n){let r=typeof t.button==`string`?t.button:void 0;return t.gesture===`longpress`?`Long pressed ${e}${n}`:r&&r!==`primary`?`Clicked ${r} ${e}${n}`:`Tapped ${e}${n}`}function U(e,t){return!i(e.device)||e.surface!==`desktop`&&e.surface!==`menubar`||e.surface===`menubar`&&(t===`click`||t===`press`)?null:b(`UNSUPPORTED_OPERATION`,`${t} is not supported on macOS ${e.surface} sessions yet. Open an app session to act, or use the ${e.surface} surface to inspect.`)}function W(e){let n=e.sessionStore.get(e.sessionName);if(!n)throw new t(`SESSION_NOT_FOUND`,x);return f({backend:ve({...e,session:n}),...k(`interaction commands`,{plural:!0}),sessions:v({sessionName:e.sessionName,getSession:()=>n,recordOptions:{includeSnapshot:!0},setRecord:t=>{t.snapshot&&(C(n,t.snapshot),e.sessionStore.set(e.sessionName,n))}})})}function ve(e){let{req:t,session:n}=e,i=ye(n);return{platform:r(n.device),captureSnapshot:async(r,i)=>({snapshot:await e.captureSnapshotForSession(n,t.flags,e.sessionStore,e.contextFromFlags,{interactiveOnly:i?.interactiveOnly===!0,includeRects:i?.includeRects===!0})}),tap:async(r,i)=>G(await m(n.device,`press`,[String(i.x),String(i.y)],t.flags?.out,e.contextFromFlags(t.flags,n.appBundleId,n.trace?.outPath))),tapTarget:i?.clickRef?async(e,t)=>(await i.clickRef?.(t.ref),{ref:E(t.ref)}):void 0,fill:async(r,i,a)=>G(await m(n.device,`fill`,[String(i.x),String(i.y),a],t.flags?.out,e.contextFromFlags(t.flags,n.appBundleId,n.trace?.outPath))),fillTarget:i?.fillRef?async(e,t,n,r)=>(await i.fillRef?.(t.ref,n,r),{ref:E(t.ref),text:n,delayMs:r?.delayMs??0}):void 0,longPress:async(r,i,a)=>G(await m(n.device,`longpress`,[String(i.x),String(i.y),...a?.durationMs===void 0?[]:[String(a.durationMs)]],t.flags?.out,e.contextFromFlags(t.flags,n.appBundleId,n.trace?.outPath))),typeText:async(r,i)=>G(await m(n.device,`type`,[i],t.flags?.out,e.contextFromFlags(t.flags,n.appBundleId,n.trace?.outPath)))}}function ye(e){if(e.device.platform!==`web`)return;let t=ne();return t.clickRef||t.fillRef?t:void 0}function G(e){return e&&typeof e==`object`?e:void 0}async function be(e){switch(e.req.command){case`press`:return await K(e,`press`);case`click`:return await K(e,`click`);case`longpress`:return await K(e,`longpress`);case`fill`:return await ke(e);default:return null}}async function K(e,t){let{req:n,sessionName:i,sessionStore:a}=e,o=a.get(i);if(!o)return S();let s=t===`click`?`click`:t,c=t===`longpress`?`longpress`:`press`,u=U(o,s);if(u)return u;let f=g(c,o.device);if(f)return f;let p=j(t,n.flags);if(p)return p;let m=l(n.flags),_=ee(m);if(t!==`longpress`&&m!==`primary`){let e=d({commandLabel:s,platform:r(o.device),button:m,count:n.flags?.count,intervalMs:n.flags?.intervalMs,holdMs:n.flags?.holdMs,jitterPx:n.flags?.jitterPx,doubleTap:n.flags?.doubleTap});if(e)return b(e.code,e.message,e.details)}let v=t===`longpress`?D(n.positionals??[]):oe(n.positionals??[],s);if(!v.ok)return v.response;let y=v.target.kind===`ref`?h({session:o,ref:v.target.ref,mintedGeneration:v.refGeneration}):void 0,x;if(v.target.kind===`ref`){let r=e.refSnapshotFlagGuardResponse(t===`longpress`?`longpress`:`press`,n.flags);if(r)return r;x=await Q(e,o)}let C=Ce({session:o,commandLabel:s,target:v.target,flags:n.flags});if(C){let t=await Te(e,o,C);if(t)return t}let w=t===`longpress`?v.durationMs:void 0;return await Z(e,{androidFreshnessBaseline:x,run:async e=>await q({runtime:e,command:t,target:v.target,sessionName:i,requestId:n.meta?.requestId,clickButton:m,flags:n.flags,durationMs:w}),afterRun:async e=>{o.lease?.leaseProvider||await se(o,ie(v.target,e))},buildPayloads:async n=>{let r=Se(n);return await xe({params:e,session:o,result:n,staleRefsWarning:y,extra:t===`longpress`?{...r===void 0?{}:{durationMs:r},gesture:`longpress`}:_})}})}async function q(e){let{runtime:t,command:n,target:r,sessionName:i,requestId:a,flags:o}=e,s=T(o);if(n===`longpress`)return await t.interactions.longPress(r,{session:i,requestId:a,durationMs:e.durationMs,settle:s});let c={session:i,requestId:a,button:e.clickButton,count:o?.count,intervalMs:o?.intervalMs,holdMs:o?.holdMs,jitterPx:o?.jitterPx,doubleTap:o?.doubleTap,verify:o?.verify,settle:s};return n===`click`?await t.interactions.click(r,c):await t.interactions.press(r,c)}async function xe(e){let{params:t,session:n,result:r,extra:i}=e,a=r.kind===`point`?await fe({session:n,flags:t.req.flags,sessionStore:t.sessionStore,contextFromFlags:t.contextFromFlags,captureSnapshotForSession:t.captureSnapshotForSession}):N(n.snapshot?.nodes??[]);return F({source:{kind:`runtime`,result:r},referenceFrame:a,extra:i,staleRefsWarning:e.staleRefsWarning,settleRefsGeneration:J(n,r)})}function J(e,t){if(t.settle?.diff)return p(e),e.snapshotGeneration}function Se(e){return`durationMs`in e?e.durationMs:void 0}function Ce(e){let{session:t,commandLabel:n,target:r,flags:i}=e;return n!==`click`||r.kind!==`selector`||we(i)||o(n)&&i?.verify===!0||s(n)&&i?.settle===!0?null:Y(t,r.selector,i)}function Y(e,t,n){let r=re({session:e,selectorExpression:t});return r?{...r,...n?.maestro?.allowNonHittableCoordinateFallback?{allowNonHittableCoordinateFallback:!0}:{}}:null}function we(e){return e?.count!==void 0||e?.intervalMs!==void 0||e?.holdMs!==void 0||e?.jitterPx!==void 0||e?.doubleTap!==void 0||e?.clickButton!==void 0&&e.clickButton!==`primary`}async function Te(e,t,n){return await X({params:e,session:t,selector:n,command:`press`,positionals:[],extra:{selector:n.raw},fallbackPhase:`ios_direct_selector_tap_fallback`})}async function X(t){let{params:n,session:r,selector:i,command:o,positionals:s,extra:c,fallbackPhase:l}=t,u=Date.now();try{let e=await m(r.device,o,s,n.req.flags?.out,{...n.contextFromFlags(n.req.flags,r.appBundleId,r.trace?.outPath),directElementSelector:i,surface:r.surface})??{},t=Date.now(),a=De(e),{result:l,responseData:d}=F({source:{kind:`runner-payload`,targetKind:`selector`,data:e,point:a},referenceFrame:Oe(e),extra:{...c,...Ee(i,e)}});return M({session:r,sessionStore:n.sessionStore,command:n.req.command,positionals:n.req.positionals??[],retryPositionals:$(a),flags:n.req.flags,result:l,responseData:d,actionStartedAt:u,actionFinishedAt:t})}catch(t){return le(t,{delegateSemanticFailures:i.allowNonHittableCoordinateFallback!==!0})?(a({level:`debug`,phase:l,data:{selector:i.raw,error:t instanceof Error?t.message:String(t)}}),null):{ok:!1,error:e(t)}}}function Ee(e,t){if(!e.allowNonHittableCoordinateFallback)return{};let n=t.message===y;return{maestroNonHittableCoordinateFallbackAllowed:!0,maestroNonHittableCoordinateFallbackUsed:n,...n?{maestroFallbackReason:`non-hittable-coordinate`}:{}}}function De(e){let t=typeof e.x==`number`?e.x:void 0,n=typeof e.y==`number`?e.y:void 0;return t!==void 0&&n!==void 0?{x:t,y:n}:{x:0,y:0}}function Oe(e){return typeof e.referenceWidth==`number`&&typeof e.referenceHeight==`number`?{referenceWidth:e.referenceWidth,referenceHeight:e.referenceHeight}:void 0}async function ke(e){let{req:t,sessionName:n,sessionStore:r}=e,i=r.get(n);if(i){let e=U(i,`fill`);if(e)return e;let t=g(`fill`,i.device);if(t)return t}if(!i)return S();let a=j(`fill`,t.flags);if(a)return a;let o=A(t.positionals??[]);if(!o.ok)return o.response;let s=await Ae(e,i,o.target,o.refGeneration);if(s.response)return s.response;let{staleRefsWarning:c}=s;return await je(e,i,o.target,o.text)||await Z(e,{run:async e=>await e.interactions.fill(o.target,o.text,{session:n,requestId:t.meta?.requestId,delayMs:t.flags?.delayMs,verify:t.flags?.verify,settle:T(t.flags)}),buildPayloads:e=>Me({session:i,result:e,text:o.text,staleRefsWarning:c})})}async function Ae(e,t,n,r){if(n.kind!==`ref`)return{};let i=h({session:t,ref:n.ref,mintedGeneration:r}),a=e.refSnapshotFlagGuardResponse(`fill`,e.req.flags);return a?{response:a,staleRefsWarning:i}:(await Q(e,t),{staleRefsWarning:i})}async function je(e,t,n,r){let i=Ne({session:t,target:n,flags:e.req.flags});return i?await Pe(e,t,i,r):null}function Me(e){let{session:t,result:n}=e,r=n.kind===`point`?void 0:N(t.snapshot?.nodes??[]);return F({source:{kind:`runtime`,result:n},referenceFrame:r,extra:{text:e.text},staleRefsWarning:e.staleRefsWarning,settleRefsGeneration:J(t,n)})}function Ne(e){let{session:t,target:n,flags:r}=e;return n.kind!==`selector`||o(`fill`)&&r?.verify===!0||s(`fill`)&&r?.settle===!0?null:Y(t,n.selector,r)}async function Pe(e,t,n,r){return await X({params:e,session:t,selector:n,command:`fill`,positionals:[r],extra:{selector:n.raw,text:r},fallbackPhase:`ios_direct_selector_fill_fallback`})}async function Z(e,t){let r=e.sessionStore.get(e.sessionName);if(!r)return S();let i=W(e),a=Date.now();try{let{readiness:n,runtimeResult:o}=await Fe(r,e.req.command,async()=>{let e=await t.run(i);return await t.afterRun?.(e),e}),s=Date.now(),{result:c,responseData:l}=await t.buildPayloads(o);if(n.status===`recovered`){let e=typeof l.warning==`string`?`${l.warning} ${n.warning}`:n.warning;c.warning=e,l.warning=e}return M({session:r,sessionStore:e.sessionStore,command:e.req.command,positionals:e.req.positionals??[],retryPositionals:Le(e.req.command,o),flags:e.req.flags,result:c,responseData:l,actionStartedAt:a,actionFinishedAt:s,androidFreshnessBaseline:t.androidFreshnessBaseline})}catch(e){let t=n(e);if(ue(t))throw t;return Ie(e)}}async function Fe(e,t,n){if(e.lease?.leaseProvider)return{readiness:{status:`clear`},runtimeResult:await n()};let r=await w({session:e,command:t,phase:`before-command`}),i=await n();return await w({session:e,command:t,phase:`after-command`}),{readiness:r,runtimeResult:i}}async function Q(e,t){if(!te(t))return;let n=t.snapshot?.comparisonSafe===!0?t.snapshot:void 0;try{await e.captureSnapshotForSession(t,e.req.flags,e.sessionStore,e.contextFromFlags,{interactiveOnly:!0,androidFreshnessMode:`ref-refresh`})}catch(t){a({level:`warn`,phase:`android_ref_snapshot_refresh_failed`,data:{command:e.req.command,error:t instanceof Error?t.message:String(t)}})}return n}function Ie(t){return{ok:!1,error:e(t)}}function Le(e,t){if(!(t.kind===`ref`&&!t.node)&&(e===`click`||e===`press`))return t.point?$(t.point):void 0}function $(e){return[String(e.x),String(e.y)]}async function Re(e){let t=await be({...e,captureSnapshotForSession:P,refSnapshotFlagGuardResponse:de});if(t)return t;switch(e.req.command){case c.type:return await ze({...e,captureSnapshotForSession:P});case`get`:return await O(e);case`is`:return await ce(e);default:return null}}async function ze(e){let{sessionName:t,sessionStore:n}=e,r=n.get(t);return r?g(c.type,r.device)||await Be(r)||await Ve(e,r):S()}async function Be(e){return e.device.platform===`android`&&e.recording&&(await _({session:e})).status===`failed`?b(`COMMAND_FAILED`,`Android system dialog blocked the recording session`):null}async function Ve(t,n){let{req:r,sessionName:i,sessionStore:a}=t,o=(r.positionals??[]).join(` `),s=W(t),c=Date.now();try{let e=await w({session:n,command:r.command,phase:`before-command`}),t=await s.interactions.typeText(o,{session:i,requestId:r.meta?.requestId,delayMs:r.flags?.delayMs});await w({session:n,command:r.command,phase:`after-command`});let l=Date.now(),d={...t.backendResult??{},text:t.text,delayMs:t.delayMs,...u(t.message??`Typed ${Array.from(t.text).length} chars`)};return e.status===`recovered`&&(d.warning=e.warning),M({session:n,sessionStore:a,command:r.command,positionals:r.positionals??[],flags:r.flags,result:d,responseData:d,actionStartedAt:c,actionFinishedAt:l})}catch(t){return{ok:!1,error:e(t)}}}export{Re as handleInteractionCommands};
|
|
1
|
+
import{B as e,F as t,I as n,b as r,f as i,m as a}from"./sdk-contracts.js";import{j as o}from"./sdk-android-adb.js";import{d as s,f as c,h as l,u}from"./sdk-batch.js";import{Ct as d,Qn as f,St as ee,wn as p,xt as m}from"./tv-remote.js";import{t as h}from"./runtime.js";import{$t as g,Gt as _,Ht as v,Mt as y,Ot as b,Qt as x,Tt as S,en as C,jt as w,kt as te,qt as ne,tn as T,wt as E}from"./internal/daemon.js";import{n as D}from"./provider.js";import{_ as O,c as re,d as ie,f as ae,g as k,h as oe,l as se,m as ce,n as le,o as ue,p as de,r as fe,s as pe,u as me,v as he,y as A}from"./selector-runtime.js";import{i as j,n as M,r as N,t as P}from"./interaction-snapshot.js";const F=new Set(c());function I(e){return R({fields:L(e.command),input:e.input??{},data:e.data,controlledFields:F})}function L(e){let t=l(e);if(!t)throw Error(`Missing response data transform descriptor for ${e}`);return t.fields}function R(e){let t=Object.fromEntries(Object.entries(e.data??{}).filter(([t])=>!e.controlledFields.has(t)));for(let[n,r]of Object.entries(e.fields)){let i=e.input[n]===void 0?r.defaultValue:e.input[n];if(i===void 0||r.omitDefault===!0&&i===r.defaultValue){delete t[n];continue}t[n]=i}return Object.fromEntries(Object.entries(t).filter(([,e])=>e!==void 0))}const ge=new Set([`currentUptimeMs`,`gestureEndUptimeMs`,`gestureStartUptimeMs`,`sequenceResults`]);function _e(e){if(e)return Object.fromEntries(Object.entries(e).filter(([e])=>!ge.has(e)))}function z(e){let{source:t,referenceFrame:n,extra:r}=e;if(t.kind===`runner-payload`){let e={targetKind:t.targetKind,...r??{}};return{result:B({data:t.data,fallbackX:t.point.x,fallbackY:t.point.y,referenceFrame:n,extra:e}),responseData:B({data:t.publicData,fallbackX:t.point.x,fallbackY:t.point.y,referenceFrame:n,extra:e})}}let{result:i}=t,a=ae(i),o={targetKind:i.kind,...a,...ve(i.settle,e.settleRefsGeneration),...r??{}},s=B({data:i.backendResult,fallbackX:i.point?.x,fallbackY:i.point?.y,referenceFrame:n,extra:o}),c=B({data:t.publicData,fallbackX:i.point?.x,fallbackY:i.point?.y,referenceFrame:n,extra:o}),l=ye(`warning`in i?i.warning:void 0,e.staleRefsWarning);return l&&(s.warning=l,c.warning=l),{result:s,responseData:c}}function ve(e,t){return!e?.diff||t===void 0?{}:{settle:{...e,refsGeneration:t}}}function ye(e,t){return t?e?`${e} ${t}`:t:e}function B(e){let{data:t,fallbackX:n,fallbackY:r,referenceFrame:i,extra:a}=e,o=xe(a,n,r)??(typeof t?.message==`string`?t.message:void 0);return be({...t??{},...n===void 0||r===void 0?{}:{x:n,y:r},...i??{},...a??{},...p(o)})}function be(e){return Object.fromEntries(Object.entries(e).filter(([,e])=>e!==void 0))}function xe(e,t,n){let r=V(e,`text`);if(r!==void 0)return`Filled ${Array.from(r).length} chars`;let i=Se(t,n),a=Ce(e);if(a)return Te(a,e??{},i);if(i)return we(e,i)}function V(e,t){let n=e?.[t];return typeof n==`string`?n:void 0}function Se(e,t){return e===void 0||t===void 0?``:` (${e}, ${t})`}function Ce(e){let t=V(e,`ref`);return t===void 0?V(e,`selector`):`@${t}`}function we(e,t){return e?.gesture===`longpress`?`Long pressed${t}`:`Tapped${t}`}function Te(e,t,n){let r=typeof t.button==`string`?t.button:void 0;return t.gesture===`longpress`?`Long pressed ${e}${n}`:r&&r!==`primary`?`Clicked ${r} ${e}${n}`:`Tapped ${e}${n}`}function H(e,t){return!a(e.device)||e.surface!==`desktop`&&e.surface!==`menubar`||e.surface===`menubar`&&(t===`click`||t===`press`)?null:g(`UNSUPPORTED_OPERATION`,`${t} is not supported on macOS ${e.surface} sessions yet. Open an app session to act, or use the ${e.surface} surface to inspect.`)}function U(e){let n=e.sessionStore.get(e.sessionName);if(!n)throw new t(`SESSION_NOT_FOUND`,x);return h({backend:Ee({...e,session:n}),...ue(`interaction commands`,{plural:!0}),sessions:b({sessionName:e.sessionName,getSession:()=>n,recordOptions:{includeSnapshot:!0},setRecord:t=>{t.snapshot&&(y(n,t.snapshot),e.sessionStore.set(e.sessionName,n))}})})}function Ee(e){let{req:t,session:n}=e,i=De(n);return{platform:r(n.device),captureSnapshot:async(r,i)=>({snapshot:await e.captureSnapshotForSession(n,t.flags,e.sessionStore,e.contextFromFlags,{interactiveOnly:i?.interactiveOnly===!0,includeRects:i?.includeRects===!0})}),tap:async(r,i)=>W(await _(n.device,`press`,[String(i.x),String(i.y)],t.flags?.out,e.contextFromFlags(t.flags,n.appBundleId,n.trace?.outPath))),tapTarget:i?.clickRef?async(e,t)=>(await i.clickRef?.(t.ref),{ref:k(t.ref)}):void 0,fill:async(r,i,a)=>W(await _(n.device,`fill`,[String(i.x),String(i.y),a],t.flags?.out,e.contextFromFlags(t.flags,n.appBundleId,n.trace?.outPath))),fillTarget:i?.fillRef?async(e,t,n,r)=>(await i.fillRef?.(t.ref,n,r),{ref:k(t.ref),text:n,delayMs:r?.delayMs??0}):void 0,longPress:async(r,i,a)=>W(await _(n.device,`longpress`,[String(i.x),String(i.y),...a?.durationMs===void 0?[]:[String(a.durationMs)]],t.flags?.out,e.contextFromFlags(t.flags,n.appBundleId,n.trace?.outPath))),typeText:async(r,i)=>W(await _(n.device,`type`,[i],t.flags?.out,e.contextFromFlags(t.flags,n.appBundleId,n.trace?.outPath)))}}function De(e){if(e.device.platform!==`web`)return;let t=D();return t.clickRef||t.fillRef?t:void 0}function W(e){return e&&typeof e==`object`?e:void 0}async function Oe(e){switch(e.req.command){case`press`:return await G(e,`press`);case`click`:return await G(e,`click`);case`longpress`:return await G(e,`longpress`);case`fill`:return await ze(e);default:return null}}async function G(e,t){let{req:n,sessionName:i,sessionStore:a}=e,o=a.get(i);if(!o)return C();let s=t===`click`?`click`:t,c=t===`longpress`?`longpress`:`press`,l=H(o,s);if(l)return l;let u=T(c,o.device);if(u)return u;let f=A(t,n.flags);if(f)return f;let p=d(n.flags),h=m(p);if(t!==`longpress`&&p!==`primary`){let e=ee({commandLabel:s,platform:r(o.device),button:p,count:n.flags?.count,intervalMs:n.flags?.intervalMs,holdMs:n.flags?.holdMs,jitterPx:n.flags?.jitterPx,doubleTap:n.flags?.doubleTap});if(e)return g(e.code,e.message,e.details)}let _=t===`longpress`?ce(n.positionals??[]):oe(n.positionals??[],s);if(!_.ok)return _.response;let v=_.target.kind===`ref`?w({session:o,ref:_.target.ref,mintedGeneration:_.refGeneration}):void 0,y;if(_.target.kind===`ref`){let r=e.refSnapshotFlagGuardResponse(t===`longpress`?`longpress`:`press`,n.flags);if(r)return r;y=await Z(e,o)}let b=Me({session:o,commandLabel:s,target:_.target,flags:n.flags});if(b){let t=await Pe(e,o,b);if(t)return t}let x=t===`longpress`?_.durationMs:void 0;return await X(e,{androidFreshnessBaseline:y,run:async e=>await ke({runtime:e,command:t,target:_.target,sessionName:i,requestId:n.meta?.requestId,clickButton:p,flags:n.flags,durationMs:x}),afterRun:async e=>{o.lease?.leaseProvider||await se(o,ie(_.target,e))},buildPayloads:async r=>{let i=je(r);return await Ae({params:e,session:o,result:r,staleRefsWarning:v,publicData:Y({session:o,command:t===`longpress`?void 0:t,flags:n.flags,data:r.backendResult}),extra:t===`longpress`?{...i===void 0?{}:{durationMs:i},gesture:`longpress`}:h})}})}async function ke(e){let{runtime:t,command:n,target:r,sessionName:i,requestId:a,flags:o}=e,s=O(o);if(n===`longpress`)return await t.interactions.longPress(r,{session:i,requestId:a,durationMs:e.durationMs,settle:s});let c={session:i,requestId:a,button:e.clickButton,count:o?.count,intervalMs:o?.intervalMs,holdMs:o?.holdMs,jitterPx:o?.jitterPx,doubleTap:o?.doubleTap,verify:o?.verify,settle:s};return n===`click`?await t.interactions.click(r,c):await t.interactions.press(r,c)}async function Ae(e){let{params:t,session:n,result:r,publicData:i,extra:a}=e,o=r.kind===`point`?await N({session:n,flags:t.req.flags,sessionStore:t.sessionStore,contextFromFlags:t.contextFromFlags,captureSnapshotForSession:t.captureSnapshotForSession}):M(n.snapshot?.nodes??[]);return z({source:{kind:`runtime`,result:r,publicData:i},referenceFrame:o,extra:a,staleRefsWarning:e.staleRefsWarning,settleRefsGeneration:K(n,r)})}function K(e,t){if(t.settle?.diff)return te(e),e.snapshotGeneration}function je(e){return`durationMs`in e?e.durationMs:void 0}function Me(e){let{session:t,commandLabel:n,target:r,flags:i}=e;return n!==`click`||r.kind!==`selector`||Ne(i)||s(n)&&i?.verify===!0||u(n)&&i?.settle===!0?null:q(t,r.selector,i)}function q(e,t,n){let r=re({session:e,selectorExpression:t});return r?{...r,...n?.maestro?.allowNonHittableCoordinateFallback?{allowNonHittableCoordinateFallback:!0}:{}}:null}function Ne(e){return e?.count!==void 0||e?.intervalMs!==void 0||e?.holdMs!==void 0||e?.jitterPx!==void 0||e?.doubleTap!==void 0||e?.clickButton!==void 0&&e.clickButton!==`primary`}async function Pe(e,t,n){return await J({params:e,session:t,selector:n,command:`press`,positionals:[],extra:{selector:n.raw},fallbackPhase:`ios_direct_selector_tap_fallback`})}async function J(t){let{params:n,session:r,selector:i,command:a,positionals:s,extra:c,fallbackPhase:l}=t,u=Date.now();try{let e=await _(r.device,a,s,n.req.flags?.out,{...n.contextFromFlags(n.req.flags,r.appBundleId,r.trace?.outPath),directElementSelector:i,surface:r.surface})??{},t=Date.now(),o=Le(e),{result:l,responseData:d}=z({source:{kind:`runner-payload`,targetKind:`selector`,data:e,publicData:Y({session:r,command:Fe(n.req.command,a),flags:n.req.flags,data:e}),point:o},referenceFrame:Re(e),extra:{...c,...Ie(i,e)}});return j({session:r,sessionStore:n.sessionStore,command:n.req.command,positionals:n.req.positionals??[],retryPositionals:$(o),flags:n.req.flags,result:l,responseData:d,actionStartedAt:u,actionFinishedAt:t})}catch(t){return pe(t,{delegateSemanticFailures:i.allowNonHittableCoordinateFallback!==!0})?(o({level:`debug`,phase:l,data:{selector:i.raw,error:t instanceof Error?t.message:String(t)}}),null):{ok:!1,error:e(t)}}}function Y(e){let t=i(e.session.device.platform)?_e(e.data):e.data;return e.command?I({command:e.command,input:e.flags,data:t}):t}function Fe(e,t){return e===`click`||e===`press`||e===`fill`?e:t}function Ie(e,t){if(!e.allowNonHittableCoordinateFallback)return{};let n=t.message===ne;return{maestroNonHittableCoordinateFallbackAllowed:!0,maestroNonHittableCoordinateFallbackUsed:n,...n?{maestroFallbackReason:`non-hittable-coordinate`}:{}}}function Le(e){let t=typeof e.x==`number`?e.x:void 0,n=typeof e.y==`number`?e.y:void 0;return t!==void 0&&n!==void 0?{x:t,y:n}:{x:0,y:0}}function Re(e){return typeof e.referenceWidth==`number`&&typeof e.referenceHeight==`number`?{referenceWidth:e.referenceWidth,referenceHeight:e.referenceHeight}:void 0}async function ze(e){let{req:t,sessionName:n,sessionStore:r}=e,i=r.get(n);if(i){let e=H(i,`fill`);if(e)return e;let t=T(`fill`,i.device);if(t)return t}if(!i)return C();let a=A(`fill`,t.flags);if(a)return a;let o=de(t.positionals??[]);if(!o.ok)return o.response;let s=await Be(e,i,o.target,o.refGeneration);if(s.response)return s.response;let{staleRefsWarning:c}=s;return await Ve(e,i,o.target,o.text)||await X(e,{run:async e=>await e.interactions.fill(o.target,o.text,{session:n,requestId:t.meta?.requestId,delayMs:t.flags?.delayMs,verify:t.flags?.verify,settle:O(t.flags)}),buildPayloads:e=>He({session:i,result:e,text:o.text,flags:t.flags,staleRefsWarning:c})})}async function Be(e,t,n,r){if(n.kind!==`ref`)return{};let i=w({session:t,ref:n.ref,mintedGeneration:r}),a=e.refSnapshotFlagGuardResponse(`fill`,e.req.flags);return a?{response:a,staleRefsWarning:i}:(await Z(e,t),{staleRefsWarning:i})}async function Ve(e,t,n,r){let i=Ue({session:t,target:n,flags:e.req.flags});return i?await We(e,t,i,r):null}function He(e){let{session:t,result:n}=e,r=n.kind===`point`?void 0:M(t.snapshot?.nodes??[]);return z({source:{kind:`runtime`,result:n,publicData:Y({session:t,command:`fill`,flags:e.flags,data:n.backendResult})},referenceFrame:r,extra:{text:e.text},staleRefsWarning:e.staleRefsWarning,settleRefsGeneration:K(t,n)})}function Ue(e){let{session:t,target:n,flags:r}=e;return n.kind!==`selector`||s(`fill`)&&r?.verify===!0||u(`fill`)&&r?.settle===!0?null:q(t,n.selector,r)}async function We(e,t,n,r){return await J({params:e,session:t,selector:n,command:`fill`,positionals:[r],extra:{selector:n.raw,text:r},fallbackPhase:`ios_direct_selector_fill_fallback`})}async function X(e,t){let r=e.sessionStore.get(e.sessionName);if(!r)return C();let i=U(e),a=Date.now();try{let{readiness:n,runtimeResult:o}=await Ge(r,e.req.command,async()=>{let e=await t.run(i);return await t.afterRun?.(e),e}),s=Date.now(),{result:c,responseData:l}=await t.buildPayloads(o);if(n.status===`recovered`){let e=typeof l.warning==`string`?`${l.warning} ${n.warning}`:n.warning;c.warning=e,l.warning=e}return j({session:r,sessionStore:e.sessionStore,command:e.req.command,positionals:e.req.positionals??[],retryPositionals:Ke(e.req.command,o),flags:e.req.flags,result:c,responseData:l,actionStartedAt:a,actionFinishedAt:s,androidFreshnessBaseline:t.androidFreshnessBaseline})}catch(e){let t=n(e);if(me(t))throw t;return Q(e)}}async function Ge(e,t,n){if(e.lease?.leaseProvider)return{readiness:{status:`clear`},runtimeResult:await n()};let r=await E({session:e,command:t,phase:`before-command`}),i=await n();return await E({session:e,command:t,phase:`after-command`}),{readiness:r,runtimeResult:i}}async function Z(e,t){if(!v(t))return;let n=t.snapshot?.comparisonSafe===!0?t.snapshot:void 0;try{await e.captureSnapshotForSession(t,e.req.flags,e.sessionStore,e.contextFromFlags,{interactiveOnly:!0,androidFreshnessMode:`ref-refresh`})}catch(t){o({level:`warn`,phase:`android_ref_snapshot_refresh_failed`,data:{command:e.req.command,error:t instanceof Error?t.message:String(t)}})}return n}function Q(t){return{ok:!1,error:e(t)}}function Ke(e,t){if(!(t.kind===`ref`&&!t.node)&&(e===`click`||e===`press`))return t.point?$(t.point):void 0}function $(e){return[String(e.x),String(e.y)]}async function qe(e){let t=await Oe({...e,captureSnapshotForSession:P,refSnapshotFlagGuardResponse:he});if(t)return t;switch(e.req.command){case f.type:return await Je({...e,captureSnapshotForSession:P});case`get`:return await le(e);case`is`:return await fe(e);default:return null}}async function Je(e){let{sessionName:t,sessionStore:n}=e,r=n.get(t);return r?T(f.type,r.device)||await Ye(r)||await Xe(e,r):C()}async function Ye(e){return e.device.platform===`android`&&e.recording&&(await S({session:e})).status===`failed`?g(`COMMAND_FAILED`,`Android system dialog blocked the recording session`):null}async function Xe(t,n){let{req:r,sessionName:i,sessionStore:a}=t,o=(r.positionals??[]).join(` `),s=U(t),c=Date.now();try{let e=await E({session:n,command:r.command,phase:`before-command`}),t=await s.interactions.typeText(o,{session:i,requestId:r.meta?.requestId,delayMs:r.flags?.delayMs});await E({session:n,command:r.command,phase:`after-command`});let l=Date.now(),u={...t.backendResult??{},text:t.text,delayMs:t.delayMs,...p(t.message??`Typed ${Array.from(t.text).length} chars`)};return e.status===`recovered`&&(u.warning=e.warning),j({session:n,sessionStore:a,command:r.command,positionals:r.positionals??[],flags:r.flags,result:u,responseData:u,actionStartedAt:c,actionFinishedAt:l})}catch(t){return{ok:!1,error:e(t)}}}export{qe as handleInteractionCommands};
|
package/dist/src/interactor.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{F as e,_ as t,m as n,p as r}from"./sdk-contracts.js";import{F as i}from"./sdk-android-adb.js";import{
|
|
2
|
-
`?void 0:`append`,appBundleId:t.appBundleId},n)},fillElementSelector:async(r,i,a)=>await
|
|
1
|
+
import{F as e,_ as t,m as n,p as r}from"./sdk-contracts.js";import{F as i}from"./sdk-android-adb.js";import{a,gt as o,ot as s,st as c,yt as l}from"./tv-remote.js";import{n as u}from"./snapshot-quality.js";import{i as d}from"./runner-client.js";import{o as f}from"./helper.js";import{c as p,i as m,n as h,o as g,r as _,s as v,u as y}from"./apps.js";import{n as b,t as x}from"./runner-sequence.js";function S(e,t,n){return{command:`remotePress`,remoteButton:e,...n===void 0?{}:{durationMs:n},...t===void 0?{}:{appBundleId:t}}}function C(e,t,n,r={includeDuration:!0}){let i=T(e.referenceWidth),a=T(e.referenceHeight);if(i===void 0||a===void 0)return E(e,{amount:n?.amount});let o=c({direction:t,amount:n?.amount,pixels:n?.pixels,referenceWidth:i,referenceHeight:a});return E(e,{amount:n?.amount,pixels:o.pixels,durationMs:r?.includeDuration?n?.durationMs:void 0,preferProvidedPixels:!0})}function w(e,t={includeDuration:!0}){return{...e?.amount===void 0?{}:{amount:e.amount},...e?.pixels===void 0?{}:{pixels:e.pixels},...t?.includeDuration&&e?.durationMs!==void 0?{durationMs:e.durationMs}:{}}}function T(e){return typeof e==`number`&&Number.isFinite(e)?e:void 0}function E(e,t){let{x1:n,y1:r,x2:i,y2:a}=O(e),o=T(e.referenceWidth),s=T(e.referenceHeight),c=D(t,n!==void 0&&i!==void 0?Math.round(Math.abs(i-n)):void 0,r!==void 0&&a!==void 0?Math.round(Math.abs(a-r)):void 0);return{...n===void 0?{}:{x1:n},...r===void 0?{}:{y1:r},...i===void 0?{}:{x2:i},...a===void 0?{}:{y2:a},...o===void 0?{}:{referenceWidth:o},...s===void 0?{}:{referenceHeight:s},...t?.amount===void 0?{}:{amount:t.amount},...c===void 0?{}:{pixels:c},...t?.durationMs===void 0?{}:{durationMs:t.durationMs}}}function D(e,t,n){if(e?.preferProvidedPixels&&e.pixels!==void 0)return e.pixels;if(t!==void 0&&t>0)return t;if(n!==void 0&&n>0)return n}function O(e){let t=T(e.x),n=T(e.y),r=T(e.x2),i=T(e.y2);return{...t===void 0?{}:{x1:t},...n===void 0?{}:{y1:n},...r===void 0?{}:{x2:r},...i===void 0?{}:{y2:i}}}async function k(e,t,n,r,i,a){return C(await e(t,{command:`desktopScroll`,direction:i,...w(a,{includeDuration:!0}),appBundleId:n.appBundleId},r),i,a,{includeDuration:!0})}function A(e){return e===`system`?`backSystem`:`backInApp`}function j(e,t){let n={verbose:t.verbose,logPath:t.logPath,traceLogPath:t.traceLogPath,requestId:t.requestId,iosXctestrunFile:t.iosXctestrunFile,iosXctestDerivedDataPath:t.iosXctestDerivedDataPath,iosXctestEnvDir:t.iosXctestEnvDir,runnerLeaseContext:t.runnerLeaseContext};return{runnerOpts:n,overrides:{tap:async(r,i)=>await d(e,M(e,t,r,i),n),tapElementSelector:async r=>await d(e,{command:`tap`,selectorKey:r.key,selectorValue:r.value,allowNonHittableCoordinateFallback:r.allowNonHittableCoordinateFallback,appBundleId:t.appBundleId},n),doubleTap:async(r,i)=>{let a=await d(e,x([{kind:`doubleTap`,x:r,y:i}],t.appBundleId),n);return b(a),a},swipe:async(r,i,a,o,s)=>await d(e,P(e,t,r,i,a,o,s,{defaultDurationMs:250,synthesized:N(e)}),n),pan:async(r,i,a,o,s)=>await d(e,P(e,t,r,i,a,o,s,{defaultDurationMs:500,legacyDefaultDurationMs:500,synthesized:N(e)}),n),fling:async(r,i,a,o,s)=>await d(e,P(e,t,r,i,a,o,s,{defaultDurationMs:16,legacyDefaultDurationMs:16,synthesized:N(e)}),n),longPress:async(r,i,a)=>await d(e,{command:`longPress`,x:r,y:i,durationMs:a,appBundleId:t.appBundleId},n),focus:async(r,i)=>await d(e,M(e,t,r,i),n),type:async(r,i)=>{await d(e,{command:`type`,text:r,delayMs:i,textEntryMode:r===`
|
|
2
|
+
`?void 0:`append`,appBundleId:t.appBundleId},n)},fillElementSelector:async(r,i,a)=>await d(e,{command:`type`,selectorKey:r.key,selectorValue:r.value,allowNonHittableCoordinateFallback:r.allowNonHittableCoordinateFallback,text:i,delayMs:a,textEntryMode:`replace`,appBundleId:t.appBundleId},n),fill:async(r,i,a,o)=>await d(e,{command:`type`,x:r,y:i,text:a,delayMs:o,textEntryMode:`replace`,appBundleId:t.appBundleId},n),scroll:async(r,i)=>await I(d,e,t,n,r,i),pinch:async(r,i,a)=>{await d(e,{command:`pinch`,scale:r,x:i,y:a,appBundleId:t.appBundleId},n)},rotateGesture:async(r,i,a,o)=>{await d(e,{command:`rotateGesture`,degrees:r,x:i,y:a,velocity:o,appBundleId:t.appBundleId},n)},transformGesture:async r=>await d(e,{command:`transformGesture`,x:r.x,y:r.y,dx:r.dx,dy:r.dy,scale:r.scale,degrees:r.degrees,durationMs:r.durationMs,appBundleId:t.appBundleId},n)}}}function M(e,t,n,r){return{command:`tap`,x:n,y:r,...N(e)?{synthesized:!0}:{},appBundleId:t.appBundleId}}function N(e){return r(e)&&!t(e)}function P(e,n,i,a,o,s,c,l){let u=r(e)&&!t(e)?F(c,l.defaultDurationMs):c??l.legacyDefaultDurationMs;return{command:`drag`,x:i,y:a,x2:o,y2:s,...u===void 0?{}:{durationMs:u},...l.synthesized===!0?{synthesized:!0}:{},appBundleId:n.appBundleId}}function F(e,t){return e===void 0?t:Math.min(1e4,Math.max(16,Math.round(e)))}async function I(e,r,i,a,c,u){return l(u?.durationMs,{invalidMessage:`scroll durationMs must be a non-negative integer at most ${o}`}),t(r)?E(await e(r,S(c,i.appBundleId,u?.durationMs),a),{amount:u?.amount,durationMs:u?.durationMs}):(s(u??{}),n(r)?await k(e,r,i,a,c,u):C(await e(r,{command:`scroll`,direction:c,...w(u),appBundleId:i.appBundleId},a),c,u))}function L(n,r){if(n.appleOs===`watchos`)throw new e(`UNSUPPORTED_PLATFORM`,`watchOS is not supported: XCUITest cannot drive watchOS UI, so this device has no runner backend.`);let{overrides:o,runnerOpts:s}=j(n,r);return{open:(e,t)=>v(n,e,{appBundleId:t?.appBundleId,launchConsole:t?.launchConsole,launchArgs:t?.launchArgs,terminateRunningApp:t?.terminateRunningApp,url:t?.url}),openDevice:()=>p(n),close:e=>g(n,e),screenshot:(e,t)=>R(n,e,t,s),snapshot:async t=>{let r=B(await i(`snapshot_capture`,async()=>await d(n,{command:`snapshot`,appBundleId:t?.appBundleId,interactiveOnly:t?.interactiveOnly,depth:t?.depth,scope:t?.scope,raw:t?.raw},s),{backend:`xctest`})),a=r.nodes??[];if(a.length===0&&n.kind===`simulator`)throw new e(`COMMAND_FAILED`,`XCTest snapshot returned 0 nodes on iOS simulator.`);return{nodes:a,truncated:r.truncated??!1,backend:`xctest`,...r.quality?{quality:r.quality}:{},...!r.quality&&r.message?{warnings:[r.message]}:{}}},back:async e=>{if(t(n)){await d(n,S(`menu`,r.appBundleId),s);return}await d(n,{command:A(e),appBundleId:r.appBundleId},s)},home:async()=>{if(t(n)){await d(n,S(`home`,r.appBundleId),s);return}await d(n,{command:`home`,appBundleId:r.appBundleId},s)},rotate:async e=>{await d(n,{command:`rotate`,orientation:e,appBundleId:r.appBundleId},s)},appSwitcher:async()=>{await d(n,{command:`appSwitcher`,appBundleId:r.appBundleId},s)},tvRemote:async(e,t)=>{await d(n,S(a(e),r.appBundleId,t),s)},readClipboard:()=>_(n),writeClipboard:e=>m(n,e),setSetting:(e,t,r,i)=>h(n,e,t,r,i),...o}}async function R(e,t,n={},r){if(z(e,n.surface)){await f(t,{surface:n.surface,fullscreen:n.fullscreen});return}await y(e,t,{appBundleId:n.appBundleId,pixelDensity:n.pixelDensity,fullscreen:n.fullscreen,runnerOptions:r,normalizeStatusBar:n.normalizeStatusBar,skipIosSimulatorBootCheck:n.skipIosSimulatorBootCheck})}function z(e,t){return n(e)&&t!==void 0&&t!==`app`}function B(e){return{nodes:Array.isArray(e.nodes)?e.nodes:void 0,truncated:typeof e.truncated==`boolean`?e.truncated:void 0,quality:u(e.snapshotQuality),message:typeof e.message==`string`&&e.message.trim().length>0?e.message:void 0}}export{L as createAppleInteractor};
|
package/dist/src/internal/bin.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=process.argv.slice(2);t(e)||(e[0]===`mcp`&&!e.includes(`--help`)&&!e.includes(`-h`)?import(`../server.js`).then(({runAgentDeviceMcpServer:e})=>e()).catch(m):p(e));function t(e){return n(e)||r(e)||i(e)}function n(e){return e.length!==1||!f(e[0])?!1:(process.stdout.write(`0.19.
|
|
1
|
+
const e=process.argv.slice(2);t(e)||(e[0]===`mcp`&&!e.includes(`--help`)&&!e.includes(`-h`)?import(`../server.js`).then(({runAgentDeviceMcpServer:e})=>e()).catch(m):p(e));function t(e){return n(e)||r(e)||i(e)}function n(e){return e.length!==1||!f(e[0])?!1:(process.stdout.write(`0.19.1
|
|
2
2
|
`),!0)}function r(e){return e.length===0?(import(`../cli-help.js`).then(({buildUsageText:e})=>{process.stdout.write(`${e()}\n`),process.exit(1)}).catch(m),!0):!1}function i(e){let t=a(e);return t===void 0?!1:(import(`../cli-help.js`).then(({buildCommandUsageText:n,buildUsageText:r})=>{if(t===null){process.stdout.write(`${r()}\n`);return}let i=n(l(t));if(i){process.stdout.write(i);return}p(e)}).catch(m),!0)}function a(e){switch(e.length){case 1:return o(e[0]);case 2:return s(e[0],e[1]);default:return}}function o(e){return e===`help`||d(e)?null:void 0}function s(e,t){return u(e)?t:c(e,t)}function c(e,t){return d(t)?e:void 0}function l(e){return e===`long-press`?`longpress`:e===`metrics`?`perf`:e}function u(e){return e===`help`}function d(e){return e===`--help`||e===`-h`}function f(e){return e===`--version`||e===`-V`}function p(e){import(`../cli.js`).then(({runCli:t})=>t(e)).catch(m)}function m(e){process.stderr.write(`${e instanceof Error?e.message:String(e)}\n`),process.exit(1)}export{};
|