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.
Files changed (84) hide show
  1. package/README.md +5 -1
  2. 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
  3. package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.19.1.apk.sha256 +1 -0
  4. 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
  5. 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
  6. package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.19.1.apk.sha256 +1 -0
  7. 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
  8. package/dist/apple-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+AXSnapshotFallback.swift +24 -7
  9. package/dist/apple-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +506 -119
  10. package/dist/apple-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +153 -48
  11. package/dist/apple-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Navigation.swift +172 -0
  12. package/dist/apple-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SequenceExecution.swift +76 -5
  13. package/dist/apple-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +60 -52
  14. package/dist/apple-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCapturePlan.swift +159 -56
  15. package/dist/apple-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedGesturePolicy.swift +142 -0
  16. package/dist/apple-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests.swift +16 -14
  17. package/dist/src/android-adb.d.ts +1 -2
  18. package/dist/src/android-adb.js +1 -1
  19. package/dist/src/android-input-ownership.js +6 -0
  20. package/dist/src/android.js +1 -1
  21. package/dist/src/app-lifecycle.js +3 -3
  22. package/dist/src/apple-runner-options.js +1 -1
  23. package/dist/src/apps.js +5 -5
  24. package/dist/src/cli-help.js +131 -34
  25. package/dist/src/cli-runner.js +1 -1
  26. package/dist/src/cli.js +11 -11
  27. package/dist/src/client.js +2 -2
  28. package/dist/src/command-metadata.js +1 -1
  29. package/dist/src/command-schema.js +3 -3
  30. package/dist/src/device-input-state.js +2 -2
  31. package/dist/src/devices2.js +1 -1
  32. package/dist/src/find.js +1 -1
  33. package/dist/src/generic.js +1 -1
  34. package/dist/src/index.d.ts +199 -20
  35. package/dist/src/input-actions.js +3 -3
  36. package/dist/src/interaction-snapshot.js +1 -1
  37. package/dist/src/interaction.js +1 -1
  38. package/dist/src/interactor.js +2 -2
  39. package/dist/src/internal/bin.js +1 -1
  40. package/dist/src/internal/daemon.js +17 -15
  41. package/dist/src/lease.js +1 -1
  42. package/dist/src/linux.js +1 -1
  43. package/dist/src/metro.d.ts +0 -1
  44. package/dist/src/notifications.js +1 -1
  45. package/dist/src/points.js +1 -1
  46. package/dist/src/project-runtime.js +1 -1
  47. package/dist/src/providers.js +1 -1
  48. package/dist/src/react-native.js +1 -1
  49. package/dist/src/record-trace-recording.js +2 -2
  50. package/dist/src/record-trace.js +1 -1
  51. package/dist/src/registry.js +24 -23
  52. package/dist/src/reporting.js +3 -3
  53. package/dist/src/runner-client.js +1 -1
  54. package/dist/src/runtime.js +2 -2
  55. package/dist/src/sdk-android-adb.d.ts +2 -2
  56. package/dist/src/sdk-batch-runner.d.ts +0 -1
  57. package/dist/src/sdk-batch.js +2 -2
  58. package/dist/src/sdk-finders.d.ts +1 -2
  59. package/dist/src/sdk-finders.js +1 -1
  60. package/dist/src/sdk-io.d.ts +0 -1
  61. package/dist/src/sdk-remote-config.d.ts +1 -2
  62. package/dist/src/sdk-remote-config.js +1 -1
  63. package/dist/src/sdk-selectors.js +1 -1
  64. package/dist/src/selector-runtime.js +1 -1
  65. package/dist/src/selectors.d.ts +0 -1
  66. package/dist/src/selectors.js +1 -1
  67. package/dist/src/selectors2.js +1 -1
  68. package/dist/src/server.js +3 -3
  69. package/dist/src/session.js +10 -10
  70. package/dist/src/simctl.js +1 -1
  71. package/dist/src/simulator.js +1 -1
  72. package/dist/src/snapshot-diagnostics.js +2 -2
  73. package/dist/src/snapshot-helper.js +4 -4
  74. package/dist/src/snapshot-quality.js +1 -1
  75. package/dist/src/snapshot2.js +2 -2
  76. package/dist/src/tv-remote.js +14 -0
  77. package/dist/src/web.js +1 -1
  78. package/package.json +5 -4
  79. package/server.json +2 -2
  80. package/skills/agent-device/SKILL.md +8 -7
  81. package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.19.0.apk.sha256 +0 -1
  82. package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.19.0.apk.sha256 +0 -1
  83. package/dist/src/device-rotation.js +0 -14
  84. package/dist/src/logcat.js +0 -6
@@ -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[]; /** Present (true) when lines were capped to the response bound. */
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; /** Human-readable device name (`device.name`). */
276
- device: string; /** Stable device id (`device.id`). */
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; /** Always `true` on the success path. */
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; /** Human-readable device name (`device.name`). */
297
- device: string; /** Stable device id (`device.id`). */
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; /** iOS only — the session device's UDID. */
391
- device_udid?: string; /** iOS only — the simulator set path, or `null` when unknown. */
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). Each entry is grounded in a
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<CommandRequestResult>;
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<CommandRequestResult>;
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 | Record<string, unknown>;
1107
+ payload: string | JsonObject;
938
1108
  };
939
1109
  type AppTriggerEventOptions = DeviceCommandBaseOptions & {
940
1110
  event: string;
941
- payload?: Record<string, unknown>;
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; /** @deprecated Use backend: 'maestro'. */
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; /** @deprecated Use backend: 'maestro'. */
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; /** @deprecated Use the CLI --reporter junit:<path> or --report-junit <path>. */
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<CommandRequestResult>;
1194
- triggerEvent: (options: AppTriggerEventOptions) => Promise<CommandRequestResult>;
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{t as i}from"./timeouts.js";import{tt as a}from"./device-rotation.js";import{s as o}from"./logcat.js";import{l as s,r as c}from"./device-input-state.js";import{p as l}from"./snapshot-helper.js";import{Ct as u}from"./internal/daemon.js";function ee(e,t){if(!t)return{expected:e,actual:null,failureReason:`text_mismatch`,targetInput:null,actualInput:null};let n=ne(t),r={failureReason:t.reason??`text_mismatch`,targetInput:p(t.targetInput),actualInput:p(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 d(e){return e?e.password?!0:f(e.text):!1}function f(e){return e?Array.from(e).every(te):!1}function p(e){if(!e)return null;let t=d(e);return{...e,text:t?null:e.text,...t?{textRedacted:!0}:{}}}function te(e){return e===`•`||e===`*`||e===`●`}function ne(e){return e.masked===!0||d(e.targetInput)||d(e.actualInput)}async function m(e,t,n,r){let a=[0,150,350],o=null,s=null,c=await D(e);for(let l of a){l>0&&await i(l);let a=await v(e,t,n,r,c);if(o=a,a.reason===`ime_capture`)return a;s=a.ok?a:null}return s??o??{ok:!1,actual:null,reason:`text_mismatch`,targetInput:null,actualInput:null}}async function re(e,t,n){return h(await u(e),t,n)}function ie(e,t,n,r,i={}){let a=y(e,t,n,i);return b(a)?{ok:!1,actual:a.actualInput?.text??null,reason:`ime_capture`,targetInput:a.targetInput,actualInput:a.actualInput}:x(a,r)??S(a,r)}function h(e,t,n){return y(e,t,n).actualInput?.text??null}function g(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 _(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 v(e,t,n,r,i){return ie(await u(e),t,n,r,i)}function y(e,t,n,r={}){let i={focusedEdit:null,editAtPoint:null,anyAtPoint:null};for(let a of l(e)){let e=E(a,r);e&&O(i,e,t,n)}return oe(i)}function b(e){let{targetInput:t,actualInput:n}=e;return!t||!n||n===t?!1:n.inputMethodOwned&&!t.inputMethodOwned}function x(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 S(e,t){let n=e.actualInput?.text??null;return{ok:C(n,t),actual:n,reason:`text_mismatch`,targetInput:e.targetInput,actualInput:e.actualInput}}function C(e,t){if(e===t)return!0;let n=w(e),r=w(t);return!n||!r?!1:!!(n===r||T(n,r))}function w(e){return(e??``).replace(/\s+/g,` `).trim()}function T(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 E(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:s({packageName:e.packageName,resourceId:e.resourceId,activeInputMethodPackage:t.activeInputMethodPackage}),area:r,editText:se(e.className??``)}}async function D(e){try{return{activeInputMethodPackage:(await c(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 O(e,t,n,r){let i=ae(t.rect,n,r);if(i&&t.editText&&(e.editAtPoint=k(e.editAtPoint,t)),t.focused&&t.editText){e.focusedEdit=k(e.focusedEdit,t);return}i&&t.text&&(e.anyAtPoint=k(e.anyAtPoint,t))}function ae(e,t,n){return t>=e.x&&t<=e.x+e.width&&n>=e.y&&n<=e.y+e.height}function k(e,t){return e&&e.area<t.area?e:t}function oe(e){let t=e.editAtPoint??e.anyAtPoint;return{targetInput:t,actualInput:(e.focusedEdit?.text?e.focusedEdit:null)??t}}function se(e){let t=e.toLowerCase();return t.includes(`edittext`)||t.includes(`textfield`)}function A(e){return d(e)}var j=e({appSwitcherAndroid:()=>R,backAndroid:()=>P,fillAndroid:()=>H,focusAndroid:()=>V,getAndroidScreenSize:()=>q,homeAndroid:()=>F,longPressAndroid:()=>z,pressAndroid:()=>M,pressAndroidEnter:()=>I,readAndroidTextAtPoint:()=>re,rotateAndroid:()=>L,scrollAndroid:()=>W,swipeAndroid:()=>N,typeAndroid:()=>B});async function M(e,t,n){await o(e,[`shell`,`input`,`tap`,String(t),String(n)])}async function N(e,t,n,r,i,a=250){await o(e,[`shell`,`input`,`swipe`,String(t),String(n),String(r),String(i),String(a)])}async function P(e){await o(e,[`shell`,`input`,`keyevent`,`4`])}async function F(e){await o(e,[`shell`,`input`,`keyevent`,`3`])}async function I(e){await o(e,[`shell`,`input`,`keyevent`,`ENTER`])}async function L(e,t){let n=G(t);await o(e,[`shell`,`settings`,`put`,`system`,`accelerometer_rotation`,`0`]),await o(e,[`shell`,`settings`,`put`,`system`,`user_rotation`,n])}async function R(e){await o(e,[`shell`,`input`,`keyevent`,`187`])}async function z(e,t,n,r=800){await o(e,[`shell`,`input`,`swipe`,String(t),String(n),String(t),String(n),String(r)])}async function B(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 V(e,t,n){await M(e,t,n)}async function H(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 m(e,t,n,i);if(r.ok)return;U(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 V(e,t,n),await K(e,`fill`),await fe(e,pe(s+r.clearPadding,r.minClear,r.maxClear)),await Y(e,{action:`fill`,text:i,chunkSize:r.chunkSize,delayMs:r.inputDelayMs});let a=await m(e,t,n,i);if(l=a,a.ok)return;a.reason===`ime_capture`&&U(i,a)}U(i,l)}function U(e,n){throw new t(`COMMAND_FAILED`,g(n),_(e,n))}async function W(e,t,n){let r=await q(e),i=a({direction:t,amount:n?.amount,pixels:n?.pixels,referenceWidth:r.width,referenceHeight:r.height}),s=n?.durationMs??300;return await o(e,[`shell`,`input`,`swipe`,String(i.x1),String(i.y1),String(i.x2),String(i.y2),String(s)]),{...i,...n?.durationMs===void 0?{}:{durationMs:n.durationMs}}}function G(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 c(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 o(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,a]of n.entries()){let s=de(a,t.chunkSize);for(let[a,o]of s.entries())await ce(e,o),t.delayMs>0&&(a+1<s.length||r+1<n.length)&&await i(t.delayMs);r+1<n.length&&await o(e,[`shell`,`input`,`keyevent`,`ENTER`])}$(t.action,`adb-shell`,t.text)}async function ce(e,t){if(t)try{await o(e,[`shell`,`input`,`text`,Z(t)])}catch(e){throw ue(e)?Q(t,e):e}}function X(e){if(!le(e))throw Q(e)}function le(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 ue(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 de(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 fe(e,t){let n=Math.max(0,t);await o(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 o(e,[`shell`,`input`,`keyevent`,...Array(r).fill(`KEYCODE_DEL`)],{allowFailure:!0})}}function pe(e,t,n){return Math.max(t,Math.min(n,e))}export{q as a,z as c,W as d,N as f,V as i,M as l,P as n,F as o,B as p,H as r,j as s,R as t,L as u};
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{Bt as n,Ft as r,Nt as i,Pt as a,Vt as o,jt as s,kt as c,vt as l,yt as u}from"./internal/daemon.js";import{a as d}from"./input-actions.js";function f(e){let{session:t,sessionStore:s,command:c,positionals:u,retryPositionals:d,flags:f,result:p,responseData:m,actionStartedAt:h,actionFinishedAt:g,androidFreshnessBaseline:_}=e,v=r(f);return s.recordAction(t,{command:c,positionals:u,flags:v??{},result:p}),a({session:t,command:c,positionals:d??u,flags:f,preSnapshot:t.snapshot}),n(c)&&o(t,c,_??t.snapshot),i(t,c,d??u,f),l(t,c,u,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=u(t.snapshot);if(o)return t.recording&&(t.recording.touchReferenceFrame=o),o;if(!t.recording)return;let s=u(await a(t,n,r,i,{interactiveOnly:!0}));return s&&t.recording&&(t.recording.touchReferenceFrame=s),s}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 u({nodes:e,createdAt:0})}async function g(e,n,r,i,a){let o={...n??{},snapshotInteractiveOnly:a.interactiveOnly},l=i(o,e.appBundleId,e.trace?.outPath),{snapshot:u}=await s({device:e.device,session:e,flags:o,outPath:o.out,logPath:l.logPath??``,includeRects:a.includeRects,androidFreshnessMode:a.androidFreshnessMode});return t(u.snapshotQuality)||(c(e,u),r.set(e.name,e)),u}export{f as i,h as n,m as r,g as t};
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};
@@ -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};
@@ -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{et as a,pt as o,tt as s,ut as c}from"./device-rotation.js";import{n as l}from"./snapshot-quality.js";import{i as u}from"./runner-client.js";import{o as d}from"./helper.js";import{c as f,i as p,n as m,o as h,r as g,s as _,u as v}from"./apps.js";import{n as y,t as b}from"./runner-sequence.js";function x(e,t,n){return{command:`remotePress`,remoteButton:e,...n===void 0?{}:{durationMs:n},...t===void 0?{}:{appBundleId:t}}}function S(e,t,n,r={includeDuration:!0}){let i=w(e.referenceWidth),a=w(e.referenceHeight);if(i===void 0||a===void 0)return T(e,{amount:n?.amount});let o=s({direction:t,amount:n?.amount,pixels:n?.pixels,referenceWidth:i,referenceHeight:a});return T(e,{amount:n?.amount,pixels:o.pixels,durationMs:r?.includeDuration?n?.durationMs:void 0,preferProvidedPixels:!0})}function C(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 w(e){return typeof e==`number`&&Number.isFinite(e)?e:void 0}function T(e,t){let{x1:n,y1:r,x2:i,y2:a}=D(e),o=w(e.referenceWidth),s=w(e.referenceHeight),c=E(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 E(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 D(e){let t=w(e.x),n=w(e.y),r=w(e.x2),i=w(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 O(e,t,n,r,i,a){return S(await e(t,{command:`desktopScroll`,direction:i,...C(a,{includeDuration:!0}),appBundleId:n.appBundleId},r),i,a,{includeDuration:!0})}function k(e){return e===`system`?`backSystem`:`backInApp`}function A(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 u(e,j(e,t,r,i),n),tapElementSelector:async r=>await u(e,{command:`tap`,selectorKey:r.key,selectorValue:r.value,allowNonHittableCoordinateFallback:r.allowNonHittableCoordinateFallback,appBundleId:t.appBundleId},n),doubleTap:async(r,i)=>{let a=await u(e,b([{kind:`doubleTap`,x:r,y:i}],t.appBundleId),n);return y(a),a},swipe:async(r,i,a,o,s)=>await u(e,N(e,t,r,i,a,o,s,{defaultDurationMs:250,synthesized:M(e)}),n),pan:async(r,i,a,o,s)=>await u(e,N(e,t,r,i,a,o,s,{defaultDurationMs:500,legacyDefaultDurationMs:500,synthesized:M(e)}),n),fling:async(r,i,a,o,s)=>await u(e,N(e,t,r,i,a,o,s,{defaultDurationMs:16,legacyDefaultDurationMs:16,synthesized:M(e)}),n),longPress:async(r,i,a)=>await u(e,{command:`longPress`,x:r,y:i,durationMs:a,appBundleId:t.appBundleId},n),focus:async(r,i)=>await u(e,j(e,t,r,i),n),type:async(r,i)=>{await u(e,{command:`type`,text:r,delayMs:i,textEntryMode:r===`
2
- `?void 0:`append`,appBundleId:t.appBundleId},n)},fillElementSelector:async(r,i,a)=>await u(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 u(e,{command:`type`,x:r,y:i,text:a,delayMs:o,textEntryMode:`replace`,appBundleId:t.appBundleId},n),scroll:async(r,i)=>await F(u,e,t,n,r,i),pinch:async(r,i,a)=>{await u(e,{command:`pinch`,scale:r,x:i,y:a,appBundleId:t.appBundleId},n)},rotateGesture:async(r,i,a,o)=>{await u(e,{command:`rotateGesture`,degrees:r,x:i,y:a,velocity:o,appBundleId:t.appBundleId},n)},transformGesture:async r=>await u(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 j(e,t,n,r){return{command:`tap`,x:n,y:r,...M(e)?{synthesized:!0}:{},appBundleId:t.appBundleId}}function M(e){return r(e)&&!t(e)}function N(e,n,i,a,o,s,c,l){let u=r(e)&&!t(e)?P(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 P(e,t){return e===void 0?t:Math.min(1e4,Math.max(16,Math.round(e)))}async function F(e,r,i,s,l,u){return o(u?.durationMs,{invalidMessage:`scroll durationMs must be a non-negative integer at most ${c}`}),t(r)?T(await e(r,x(l,i.appBundleId,u?.durationMs),s),{amount:u?.amount,durationMs:u?.durationMs}):(a(u??{}),n(r)?await O(e,r,i,s,l,u):S(await e(r,{command:`scroll`,direction:l,...C(u),appBundleId:i.appBundleId},s),l,u))}function I(r,a){if(r.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}=A(r,a);return{open:(e,t)=>_(r,e,{appBundleId:t?.appBundleId,launchConsole:t?.launchConsole,launchArgs:t?.launchArgs,terminateRunningApp:t?.terminateRunningApp,url:t?.url}),openDevice:()=>f(r),close:e=>h(r,e),screenshot:async(e,t)=>{if(n(r)&&t?.surface&&t.surface!==`app`){await d(e,{surface:t.surface,fullscreen:t.fullscreen});return}await v(r,e,{appBundleId:t?.appBundleId,fullscreen:t?.fullscreen,runnerOptions:s,normalizeStatusBar:t?.normalizeStatusBar,skipIosSimulatorBootCheck:t?.skipIosSimulatorBootCheck})},snapshot:async t=>{let n=L(await i(`snapshot_capture`,async()=>await u(r,{command:`snapshot`,appBundleId:t?.appBundleId,interactiveOnly:t?.interactiveOnly,depth:t?.depth,scope:t?.scope,raw:t?.raw},s),{backend:`xctest`})),a=n.nodes??[];if(a.length===0&&r.kind===`simulator`)throw new e(`COMMAND_FAILED`,`XCTest snapshot returned 0 nodes on iOS simulator.`);return{nodes:a,truncated:n.truncated??!1,backend:`xctest`,...n.quality?{quality:n.quality}:{},...!n.quality&&n.message?{warnings:[n.message]}:{}}},back:async e=>{if(t(r)){await u(r,x(`menu`,a.appBundleId),s);return}await u(r,{command:k(e),appBundleId:a.appBundleId},s)},home:async()=>{if(t(r)){await u(r,x(`home`,a.appBundleId),s);return}await u(r,{command:`home`,appBundleId:a.appBundleId},s)},rotate:async e=>{await u(r,{command:`rotate`,orientation:e,appBundleId:a.appBundleId},s)},appSwitcher:async()=>{await u(r,{command:`appSwitcher`,appBundleId:a.appBundleId},s)},readClipboard:()=>g(r),writeClipboard:e=>p(r,e),setSetting:(e,t,n,i)=>m(r,e,t,n,i),...o}}function L(e){return{nodes:Array.isArray(e.nodes)?e.nodes:void 0,truncated:typeof e.truncated==`boolean`?e.truncated:void 0,quality:l(e.snapshotQuality),message:typeof e.message==`string`&&e.message.trim().length>0?e.message:void 0}}export{I as createAppleInteractor};
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};
@@ -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.0
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{};