agent-device 0.8.6 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/README.md +106 -22
  2. package/dist/src/224.js +2 -2
  3. package/dist/src/bin.js +65 -58
  4. package/dist/src/client-normalizers.d.ts +1 -2
  5. package/dist/src/client-shared.d.ts +1 -2
  6. package/dist/src/client-types.d.ts +0 -19
  7. package/dist/src/client.d.ts +1 -1
  8. package/dist/src/core/capabilities.d.ts +1 -1
  9. package/dist/src/core/click-button.d.ts +20 -0
  10. package/dist/src/core/dispatch-resolve.d.ts +7 -6
  11. package/dist/src/core/dispatch.d.ts +1 -0
  12. package/dist/src/daemon/context.d.ts +1 -0
  13. package/dist/src/daemon/handlers/interaction-common.d.ts +12 -0
  14. package/dist/src/daemon/handlers/interaction-fill.d.ts +3 -0
  15. package/dist/src/daemon/handlers/interaction-flags.d.ts +4 -0
  16. package/dist/src/daemon/handlers/interaction-get.d.ts +3 -0
  17. package/dist/src/daemon/handlers/interaction-is.d.ts +3 -0
  18. package/dist/src/daemon/handlers/interaction-press.d.ts +3 -0
  19. package/dist/src/daemon/handlers/interaction-scroll.d.ts +3 -0
  20. package/dist/src/daemon/handlers/interaction-selector.d.ts +27 -0
  21. package/dist/src/daemon/handlers/interaction-snapshot.d.ts +8 -0
  22. package/dist/src/daemon/handlers/interaction-targeting.d.ts +28 -0
  23. package/dist/src/daemon/handlers/interaction.d.ts +5 -12
  24. package/dist/src/daemon/handlers/session-device-utils.d.ts +1 -0
  25. package/dist/src/daemon/handlers/session-runtime.d.ts +3 -8
  26. package/dist/src/daemon/handlers/session.d.ts +8 -0
  27. package/dist/src/daemon/handlers/snapshot-alert.d.ts +13 -0
  28. package/dist/src/daemon/handlers/snapshot-capture.d.ts +27 -0
  29. package/dist/src/daemon/handlers/snapshot-session.d.ts +15 -0
  30. package/dist/src/daemon/handlers/snapshot-settings.d.ts +24 -0
  31. package/dist/src/daemon/handlers/snapshot-wait.d.ts +37 -0
  32. package/dist/src/daemon/handlers/snapshot.d.ts +4 -20
  33. package/dist/src/daemon/is-predicates.d.ts +2 -1
  34. package/dist/src/daemon/script-utils.d.ts +14 -2
  35. package/dist/src/daemon/selectors-build.d.ts +2 -1
  36. package/dist/src/daemon/selectors-match.d.ts +3 -2
  37. package/dist/src/daemon/selectors-resolve.d.ts +3 -2
  38. package/dist/src/daemon/session-open-script.d.ts +7 -0
  39. package/dist/src/daemon/session-store.d.ts +1 -0
  40. package/dist/src/daemon/snapshot-processing.d.ts +2 -1
  41. package/dist/src/daemon/types.d.ts +6 -5
  42. package/dist/src/daemon.js +35 -34
  43. package/dist/src/index.d.ts +1 -1
  44. package/dist/src/platforms/android/devices.d.ts +4 -0
  45. package/dist/src/platforms/android/sdk.d.ts +2 -0
  46. package/dist/src/platforms/ios/app-filter.d.ts +2 -0
  47. package/dist/src/platforms/ios/devices.d.ts +2 -1
  48. package/dist/src/platforms/ios/macos-apps.d.ts +12 -0
  49. package/dist/src/platforms/ios/runner-client.d.ts +3 -1
  50. package/dist/src/platforms/ios/runner-macos-products.d.ts +3 -0
  51. package/dist/src/platforms/ios/runner-xctestrun-products.d.ts +2 -0
  52. package/dist/src/platforms/ios/runner-xctestrun.d.ts +20 -2
  53. package/dist/src/utils/args.d.ts +1 -1
  54. package/dist/src/utils/cli-config.d.ts +2 -1
  55. package/dist/src/utils/command-schema.d.ts +7 -3
  56. package/dist/src/utils/device.d.ts +13 -5
  57. package/dist/src/utils/remote-config.d.ts +15 -0
  58. package/dist/src/utils/remote-open.d.ts +9 -0
  59. package/ios-runner/AgentDeviceRunner/AgentDeviceRunner.xcodeproj/project.pbxproj +58 -50
  60. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/AgentDeviceRunnerUITests.entitlements +10 -0
  61. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +35 -1
  62. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +83 -9
  63. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Lifecycle.swift +39 -7
  64. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +2 -0
  65. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScreenRecorder.swift +5 -6
  66. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +132 -112
  67. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SystemModal.swift +4 -0
  68. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests.swift +22 -5
  69. package/package.json +3 -2
  70. package/skills/agent-device/SKILL.md +28 -9
  71. package/skills/agent-device/references/macos-desktop.md +89 -0
  72. package/skills/agent-device/references/snapshot-refs.md +11 -2
@@ -1,4 +1,4 @@
1
- export { createAgentDeviceClient, type AgentDeviceClient, type AgentDeviceClientConfig, type AgentDeviceDevice, type AgentDeviceIdentifiers, type AgentDeviceSelectionOptions, type AgentDeviceSession, type AgentDeviceSessionDevice, type AppCloseOptions, type AppCloseResult, type AppDeployOptions, type AppDeployResult, type AppInstallFromSourceOptions, type AppInstallFromSourceResult, type AppOpenOptions, type AppOpenResult, type CaptureScreenshotOptions, type CaptureScreenshotResult, type CaptureSnapshotOptions, type CaptureSnapshotResult, type EnsureSimulatorOptions, type EnsureSimulatorResult, type MaterializationReleaseOptions, type MaterializationReleaseResult, type MetroPrepareOptions, type MetroPrepareResult, type RuntimeResult, type RuntimeSetOptions, type RuntimeShowOptions, type SessionCloseResult, type StartupPerfSample, } from './client.ts';
1
+ export { createAgentDeviceClient, type AgentDeviceClient, type AgentDeviceClientConfig, type AgentDeviceDevice, type AgentDeviceIdentifiers, type AgentDeviceSelectionOptions, type AgentDeviceSession, type AgentDeviceSessionDevice, type AppCloseOptions, type AppCloseResult, type AppDeployOptions, type AppDeployResult, type AppInstallFromSourceOptions, type AppInstallFromSourceResult, type AppOpenOptions, type AppOpenResult, type CaptureScreenshotOptions, type CaptureScreenshotResult, type CaptureSnapshotOptions, type CaptureSnapshotResult, type EnsureSimulatorOptions, type EnsureSimulatorResult, type MaterializationReleaseOptions, type MaterializationReleaseResult, type MetroPrepareOptions, type MetroPrepareResult, type SessionCloseResult, type StartupPerfSample, } from './client.ts';
2
2
  export { AppError, type NormalizedError } from './utils/errors.ts';
3
3
  export type { MetroPrepareKind, MetroRuntimeHints } from './client-metro.ts';
4
4
  export type { SessionRuntimeHints } from './daemon/types.ts';
@@ -1,7 +1,11 @@
1
+ import { runCmd } from '../../utils/exec.ts';
1
2
  import type { DeviceInfo } from '../../utils/device.ts';
2
3
  type AndroidDeviceDiscoveryOptions = {
3
4
  serialAllowlist?: ReadonlySet<string>;
4
5
  };
6
+ type AndroidAdbRunner = typeof runCmd;
7
+ export declare function parseAndroidEmulatorAvdNameOutput(rawOutput: string): string | undefined;
8
+ export declare function resolveAndroidEmulatorAvdName(serial: string, runAdb?: AndroidAdbRunner): Promise<string | undefined>;
5
9
  export declare function parseAndroidTargetFromCharacteristics(rawOutput: string): 'tv' | null;
6
10
  export declare function parseAndroidFeatureListForTv(rawOutput: string): boolean;
7
11
  export declare function listAndroidDevices(options?: AndroidDeviceDiscoveryOptions): Promise<DeviceInfo[]>;
@@ -0,0 +1,2 @@
1
+ export declare function resolveAndroidSdkRoots(env?: NodeJS.ProcessEnv): string[];
2
+ export declare function ensureAndroidSdkPathConfigured(env?: NodeJS.ProcessEnv): Promise<void>;
@@ -0,0 +1,2 @@
1
+ import type { IosAppInfo } from './devicectl.ts';
2
+ export declare function filterAppleAppsByBundlePrefix(apps: IosAppInfo[], filter: 'user-installed' | 'all'): IosAppInfo[];
@@ -35,5 +35,6 @@ type FindBootableSimulatorOptions = IosDeviceDiscoveryOptions & {
35
35
  * Returns `null` when no suitable simulator can be found.
36
36
  */
37
37
  export declare function findBootableIosSimulator(options?: FindBootableSimulatorOptions): Promise<DeviceInfo | null>;
38
- export declare function listIosDevices(options?: IosDeviceDiscoveryOptions): Promise<DeviceInfo[]>;
38
+ export declare function listAppleDevices(options?: IosDeviceDiscoveryOptions): Promise<DeviceInfo[]>;
39
+ export declare const listIosDevices: typeof listAppleDevices;
39
40
  export {};
@@ -0,0 +1,12 @@
1
+ import type { DeviceInfo } from '../../utils/device.ts';
2
+ import type { IosAppInfo } from './devicectl.ts';
3
+ export declare function resolveMacOsApp(app: string): Promise<string>;
4
+ export declare function openMacOsApp(_device: DeviceInfo, app: string, options?: {
5
+ appBundleId?: string;
6
+ url?: string;
7
+ }): Promise<void>;
8
+ export declare function closeMacOsApp(_device: DeviceInfo, app: string): Promise<void>;
9
+ export declare function readMacOsClipboardText(): Promise<string>;
10
+ export declare function writeMacOsClipboardText(text: string): Promise<void>;
11
+ export declare function setMacOsAppearance(state: string): Promise<void>;
12
+ export declare function listMacApps(filter?: 'user-installed' | 'all'): Promise<IosAppInfo[]>;
@@ -1,11 +1,13 @@
1
1
  import type { DeviceInfo } from '../../utils/device.ts';
2
+ import type { ClickButton } from '../../core/click-button.ts';
2
3
  export type RunnerCommand = {
3
- command: 'tap' | 'tapSeries' | 'longPress' | 'drag' | 'dragSeries' | 'type' | 'swipe' | 'findText' | 'snapshot' | 'screenshot' | 'back' | 'home' | 'appSwitcher' | 'alert' | 'pinch' | 'recordStart' | 'recordStop' | 'shutdown';
4
+ command: 'tap' | 'mouseClick' | 'tapSeries' | 'longPress' | 'drag' | 'dragSeries' | 'type' | 'swipe' | 'findText' | 'snapshot' | 'screenshot' | 'back' | 'home' | 'appSwitcher' | 'alert' | 'pinch' | 'recordStart' | 'recordStop' | 'shutdown';
4
5
  appBundleId?: string;
5
6
  text?: string;
6
7
  action?: 'get' | 'accept' | 'dismiss';
7
8
  x?: number;
8
9
  y?: number;
10
+ button?: ClickButton;
9
11
  count?: number;
10
12
  intervalMs?: number;
11
13
  doubleTap?: boolean;
@@ -0,0 +1,3 @@
1
+ import type { DeviceInfo } from '../../utils/device.ts';
2
+ export declare function repairMacOsRunnerProductsIfNeeded(device: DeviceInfo, productPaths: string[], xctestrunPath: string): Promise<void>;
3
+ export declare function isExpectedRunnerRepairFailure(error: unknown): boolean;
@@ -0,0 +1,2 @@
1
+ export declare function xctestrunReferencesExistingProducts(xctestrunPath: string): boolean;
2
+ export declare function resolveExistingXctestrunProductPaths(xctestrunPath: string): string[] | null;
@@ -1,11 +1,28 @@
1
1
  import { type DeviceInfo } from '../../utils/device.ts';
2
+ export { xctestrunReferencesExistingProducts } from './runner-xctestrun-products.ts';
2
3
  export declare const runnerPrepProcesses: Set<import("child_process").ChildProcess>;
3
4
  export declare const IOS_RUNNER_CONTAINER_BUNDLE_IDS: string[];
5
+ type EnsureXctestrunDeps = {
6
+ findProjectRoot: () => string;
7
+ findXctestrun: (root: string) => string | null;
8
+ xctestrunReferencesProjectRoot: (xctestrunPath: string, projectRoot: string) => boolean;
9
+ resolveExistingXctestrunProductPaths: (xctestrunPath: string) => string[] | null;
10
+ repairRunnerProductsIfNeeded: (device: DeviceInfo, productPaths: string[], xctestrunPath: string) => Promise<void>;
11
+ assertSafeDerivedCleanup: (derivedPath: string) => void;
12
+ cleanRunnerDerivedArtifacts: (derivedPath: string) => void;
13
+ buildRunnerXctestrun: (device: DeviceInfo, projectPath: string, derived: string, options: {
14
+ verbose?: boolean;
15
+ logPath?: string;
16
+ traceLogPath?: string;
17
+ }) => Promise<void>;
18
+ };
4
19
  export declare function ensureXctestrun(device: DeviceInfo, options: {
5
20
  verbose?: boolean;
6
21
  logPath?: string;
7
22
  traceLogPath?: string;
8
- }): Promise<string>;
23
+ }, deps?: EnsureXctestrunDeps): Promise<string>;
24
+ export declare function shouldDeleteRunnerDerivedRootEntry(entryName: string): boolean;
25
+ export declare function xctestrunReferencesProjectRoot(xctestrunPath: string, projectRoot: string): boolean;
9
26
  export declare function prepareXctestrunWithEnv(xctestrunPath: string, envVars: Record<string, string>, suffix: string): Promise<{
10
27
  xctestrunPath: string;
11
28
  jsonPath: string;
@@ -13,6 +30,7 @@ export declare function prepareXctestrunWithEnv(xctestrunPath: string, envVars:
13
30
  export declare function resolveRunnerDestination(device: DeviceInfo): string;
14
31
  export declare function resolveRunnerBuildDestination(device: DeviceInfo): string;
15
32
  export declare function resolveRunnerMaxConcurrentDestinationsFlag(device: DeviceInfo): string;
16
- export declare function resolveRunnerSigningBuildSettings(env?: NodeJS.ProcessEnv, forDevice?: boolean): string[];
33
+ export declare function resolveRunnerSigningBuildSettings(env?: NodeJS.ProcessEnv, forDevice?: boolean, platform?: DeviceInfo['platform']): string[];
17
34
  export declare function resolveRunnerBundleBuildSettings(env?: NodeJS.ProcessEnv): string[];
35
+ export declare function resolveRunnerPerformanceBuildSettings(): string[];
18
36
  export declare function assertSafeDerivedCleanup(derivedPath: string, env?: NodeJS.ProcessEnv): void;
@@ -21,7 +21,7 @@ type FinalizeArgsOptions = ParseArgsOptions & {
21
21
  export declare function parseArgs(argv: string[], options?: FinalizeArgsOptions): ParsedArgs;
22
22
  export declare function parseRawArgs(argv: string[]): RawParsedArgs;
23
23
  export declare function finalizeParsedArgs(parsed: RawParsedArgs, options?: FinalizeArgsOptions): ParsedArgs;
24
- export declare function toDaemonFlags(flags: CliFlags): Omit<CliFlags, 'json' | 'config' | 'help' | 'version'>;
24
+ export declare function toDaemonFlags(flags: CliFlags): Omit<CliFlags, 'json' | 'config' | 'remoteConfig' | 'help' | 'version'>;
25
25
  export declare function usage(): string;
26
26
  export declare function usageForCommand(command: string): string | null;
27
27
  export {};
@@ -1,4 +1,4 @@
1
- import { type CliFlags } from './command-schema.ts';
1
+ import { type CliFlags, type FlagKey } from './command-schema.ts';
2
2
  type EnvMap = Record<string, string | undefined>;
3
3
  export declare function resolveConfigBackedFlagDefaults(options: {
4
4
  command: string | null;
@@ -6,4 +6,5 @@ export declare function resolveConfigBackedFlagDefaults(options: {
6
6
  cliFlags: CliFlags;
7
7
  env?: EnvMap;
8
8
  }): Partial<CliFlags>;
9
+ export declare function readEnvFlagDefaultsForKeys(env: EnvMap, keys: readonly FlagKey[]): Partial<CliFlags>;
9
10
  export {};
@@ -1,6 +1,7 @@
1
1
  export type CliFlags = {
2
2
  json: boolean;
3
3
  config?: string;
4
+ remoteConfig?: string;
4
5
  stateDir?: string;
5
6
  daemonBaseUrl?: string;
6
7
  daemonAuthToken?: string;
@@ -13,8 +14,8 @@ export type CliFlags = {
13
14
  sessionLock?: 'reject' | 'strip';
14
15
  sessionLocked?: boolean;
15
16
  sessionLockConflicts?: 'reject' | 'strip';
16
- platform?: 'ios' | 'android' | 'apple';
17
- target?: 'mobile' | 'tv';
17
+ platform?: 'ios' | 'macos' | 'android' | 'apple';
18
+ target?: 'mobile' | 'tv' | 'desktop';
18
19
  device?: string;
19
20
  udid?: string;
20
21
  serial?: string;
@@ -57,6 +58,7 @@ export type CliFlags = {
57
58
  holdMs?: number;
58
59
  jitterPx?: number;
59
60
  doubleTap?: boolean;
61
+ clickButton?: 'primary' | 'secondary' | 'middle';
60
62
  pauseMs?: number;
61
63
  pattern?: 'one-way' | 'ping-pong';
62
64
  activity?: string;
@@ -97,13 +99,15 @@ export type FlagDefinition = {
97
99
  usageDescription?: string;
98
100
  };
99
101
  type CommandSchema = {
100
- description: string;
102
+ helpDescription: string;
103
+ summary?: string;
101
104
  positionalArgs: readonly string[];
102
105
  allowsExtraPositionals?: boolean;
103
106
  allowedFlags: readonly FlagKey[];
104
107
  defaults?: Partial<CliFlags>;
105
108
  skipCapabilityCheck?: boolean;
106
109
  usageOverride?: string;
110
+ listUsageOverride?: string;
107
111
  };
108
112
  export declare const GLOBAL_FLAG_KEYS: Set<keyof CliFlags>;
109
113
  export declare function getFlagDefinition(token: string): FlagDefinition | undefined;
@@ -1,7 +1,8 @@
1
- export type Platform = 'ios' | 'android';
1
+ export type ApplePlatform = 'ios' | 'macos';
2
+ export type Platform = ApplePlatform | 'android';
2
3
  export type PlatformSelector = Platform | 'apple';
3
4
  export type DeviceKind = 'simulator' | 'emulator' | 'device';
4
- export type DeviceTarget = 'mobile' | 'tv';
5
+ export type DeviceTarget = 'mobile' | 'tv' | 'desktop';
5
6
  export type DeviceInfo = {
6
7
  platform: Platform;
7
8
  id: string;
@@ -12,7 +13,7 @@ export type DeviceInfo = {
12
13
  simulatorSetPath?: string;
13
14
  };
14
15
  type DeviceSelector = {
15
- platform?: Platform;
16
+ platform?: PlatformSelector;
16
17
  target?: DeviceTarget;
17
18
  deviceName?: string;
18
19
  udid?: string;
@@ -21,7 +22,14 @@ type DeviceSelector = {
21
22
  type DeviceSelectionContext = {
22
23
  simulatorSetPath?: string;
23
24
  };
24
- export declare function normalizePlatformSelector(platform: PlatformSelector | undefined): Platform | undefined;
25
- export declare function resolveApplePlatformName(target: DeviceTarget | undefined): 'iOS' | 'tvOS';
25
+ export declare function normalizePlatformSelector(platform: PlatformSelector | undefined): PlatformSelector | undefined;
26
+ export declare function isApplePlatform(platform: Platform | PlatformSelector | undefined): platform is ApplePlatform | 'apple';
27
+ export declare function matchesPlatformSelector(platform: Platform, selector: PlatformSelector | undefined): boolean;
28
+ export declare function resolveApplePlatformName(platformOrTarget: ApplePlatform | DeviceTarget | undefined): 'iOS' | 'tvOS' | 'macOS';
29
+ export declare function resolveAppleSimulatorSetPathForSelector(params: {
30
+ simulatorSetPath?: string;
31
+ platform?: PlatformSelector;
32
+ target?: DeviceTarget;
33
+ }): string | undefined;
26
34
  export declare function resolveDevice(devices: DeviceInfo[], selector: DeviceSelector, context?: DeviceSelectionContext): Promise<DeviceInfo>;
27
35
  export {};
@@ -0,0 +1,15 @@
1
+ import type { CliFlags } from './command-schema.ts';
2
+ type EnvMap = Record<string, string | undefined>;
3
+ export declare const REMOTE_OPEN_FLAG_KEYS: readonly ["remoteConfig", "session", "platform", "daemonBaseUrl", "daemonAuthToken", "daemonTransport", "metroProjectRoot", "metroKind", "metroPublicBaseUrl", "metroProxyBaseUrl", "metroBearerToken", "metroPreparePort", "metroListenHost", "metroStatusHost", "metroStartupTimeoutMs", "metroProbeTimeoutMs", "metroRuntimeFile", "metroNoReuseExisting", "metroNoInstallDeps"];
4
+ export declare function loadRemoteConfigFile(options: {
5
+ configPath: string;
6
+ cwd: string;
7
+ env?: EnvMap;
8
+ }): Partial<CliFlags>;
9
+ export declare function resolveRemoteConfigDefaults(options: {
10
+ cliFlags: CliFlags;
11
+ cwd: string;
12
+ env: EnvMap;
13
+ }): Partial<CliFlags>;
14
+ export declare function pickRemoteOpenDefaults(defaultFlags: Partial<CliFlags>): Partial<CliFlags>;
15
+ export {};
@@ -0,0 +1,9 @@
1
+ import type { AgentDeviceClient } from '../client.ts';
2
+ import type { CliFlags } from './command-schema.ts';
3
+ export declare function resolveRemoteOpenRuntime(flags: CliFlags, client: AgentDeviceClient): Promise<{
4
+ platform?: 'ios' | 'android';
5
+ metroHost?: string;
6
+ metroPort?: number;
7
+ bundleUrl?: string;
8
+ launchUrl?: string;
9
+ } | undefined>;
@@ -253,11 +253,12 @@
253
253
  GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
254
254
  GCC_WARN_UNDECLARED_SELECTOR = YES;
255
255
  GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
256
- GCC_WARN_UNUSED_FUNCTION = YES;
257
- GCC_WARN_UNUSED_VARIABLE = YES;
258
- IPHONEOS_DEPLOYMENT_TARGET = 15.6;
259
- LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
260
- MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
256
+ GCC_WARN_UNUSED_FUNCTION = YES;
257
+ GCC_WARN_UNUSED_VARIABLE = YES;
258
+ IPHONEOS_DEPLOYMENT_TARGET = 15.6;
259
+ LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
260
+ MACOSX_DEPLOYMENT_TARGET = 13.0;
261
+ MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
261
262
  MTL_FAST_MATH = YES;
262
263
  ONLY_ACTIVE_ARCH = YES;
263
264
  SDKROOT = auto;
@@ -313,11 +314,12 @@
313
314
  GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
314
315
  GCC_WARN_UNDECLARED_SELECTOR = YES;
315
316
  GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
316
- GCC_WARN_UNUSED_FUNCTION = YES;
317
- GCC_WARN_UNUSED_VARIABLE = YES;
318
- IPHONEOS_DEPLOYMENT_TARGET = 15.6;
319
- LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
320
- MTL_ENABLE_DEBUG_INFO = NO;
317
+ GCC_WARN_UNUSED_FUNCTION = YES;
318
+ GCC_WARN_UNUSED_VARIABLE = YES;
319
+ IPHONEOS_DEPLOYMENT_TARGET = 15.6;
320
+ LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
321
+ MACOSX_DEPLOYMENT_TARGET = 13.0;
322
+ MTL_ENABLE_DEBUG_INFO = NO;
321
323
  MTL_FAST_MATH = YES;
322
324
  SDKROOT = auto;
323
325
  SWIFT_COMPILATION_MODE = wholemodule;
@@ -338,14 +340,15 @@
338
340
  INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
339
341
  INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
340
342
  INFOPLIST_KEY_UILaunchScreen_Generation = YES;
341
- INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
342
- INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
343
- IPHONEOS_DEPLOYMENT_TARGET = 15.6;
344
- LD_RUNPATH_SEARCH_PATHS = (
345
- "$(inherited)",
346
- "@executable_path/Frameworks",
347
- );
348
- MARKETING_VERSION = 1.0;
343
+ INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
344
+ INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
345
+ IPHONEOS_DEPLOYMENT_TARGET = 15.6;
346
+ LD_RUNPATH_SEARCH_PATHS = (
347
+ "$(inherited)",
348
+ "@executable_path/Frameworks",
349
+ );
350
+ MACOSX_DEPLOYMENT_TARGET = 13.0;
351
+ MARKETING_VERSION = 1.0;
349
352
  PRODUCT_BUNDLE_IDENTIFIER = "$(AGENT_DEVICE_IOS_RUNNER_APP_BUNDLE_ID)";
350
353
  PRODUCT_NAME = "$(TARGET_NAME)";
351
354
  STRING_CATALOG_GENERATE_SYMBOLS = YES;
@@ -354,9 +357,9 @@
354
357
  SWIFT_EMIT_LOC_STRINGS = YES;
355
358
  SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
356
359
  SWIFT_VERSION = 5.0;
357
- SUPPORTED_PLATFORMS = "iphoneos iphonesimulator appletvos appletvsimulator";
358
- TARGETED_DEVICE_FAMILY = "1,2,3";
359
- TVOS_DEPLOYMENT_TARGET = 15.6;
360
+ SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator appletvos appletvsimulator";
361
+ TARGETED_DEVICE_FAMILY = "1,2,3";
362
+ TVOS_DEPLOYMENT_TARGET = 15.6;
360
363
  };
361
364
  name = Debug;
362
365
  };
@@ -373,14 +376,15 @@
373
376
  INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
374
377
  INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
375
378
  INFOPLIST_KEY_UILaunchScreen_Generation = YES;
376
- INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
377
- INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
378
- IPHONEOS_DEPLOYMENT_TARGET = 15.6;
379
- LD_RUNPATH_SEARCH_PATHS = (
380
- "$(inherited)",
381
- "@executable_path/Frameworks",
382
- );
383
- MARKETING_VERSION = 1.0;
379
+ INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
380
+ INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
381
+ IPHONEOS_DEPLOYMENT_TARGET = 15.6;
382
+ LD_RUNPATH_SEARCH_PATHS = (
383
+ "$(inherited)",
384
+ "@executable_path/Frameworks",
385
+ );
386
+ MACOSX_DEPLOYMENT_TARGET = 13.0;
387
+ MARKETING_VERSION = 1.0;
384
388
  PRODUCT_BUNDLE_IDENTIFIER = "$(AGENT_DEVICE_IOS_RUNNER_APP_BUNDLE_ID)";
385
389
  PRODUCT_NAME = "$(TARGET_NAME)";
386
390
  STRING_CATALOG_GENERATE_SYMBOLS = YES;
@@ -389,21 +393,23 @@
389
393
  SWIFT_EMIT_LOC_STRINGS = YES;
390
394
  SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
391
395
  SWIFT_VERSION = 5.0;
392
- SUPPORTED_PLATFORMS = "iphoneos iphonesimulator appletvos appletvsimulator";
393
- TARGETED_DEVICE_FAMILY = "1,2,3";
394
- TVOS_DEPLOYMENT_TARGET = 15.6;
396
+ SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator appletvos appletvsimulator";
397
+ TARGETED_DEVICE_FAMILY = "1,2,3";
398
+ TVOS_DEPLOYMENT_TARGET = 15.6;
395
399
  };
396
400
  name = Release;
397
401
  };
398
402
  20EA2EEE2F2CFC7C001CF0EF /* Debug */ = {
399
403
  isa = XCBuildConfiguration;
400
404
  buildSettings = {
401
- CODE_SIGN_STYLE = Automatic;
402
- CURRENT_PROJECT_VERSION = 1;
403
- DEVELOPMENT_TEAM = 2S799L9W4M;
404
- GENERATE_INFOPLIST_FILE = YES;
405
- IPHONEOS_DEPLOYMENT_TARGET = 15.6;
406
- MARKETING_VERSION = 1.0;
405
+ "CODE_SIGN_ENTITLEMENTS[sdk=macosx*]" = AgentDeviceRunnerUITests/AgentDeviceRunnerUITests.entitlements;
406
+ CODE_SIGN_STYLE = Automatic;
407
+ CURRENT_PROJECT_VERSION = 1;
408
+ DEVELOPMENT_TEAM = 2S799L9W4M;
409
+ GENERATE_INFOPLIST_FILE = YES;
410
+ IPHONEOS_DEPLOYMENT_TARGET = 15.6;
411
+ MACOSX_DEPLOYMENT_TARGET = 13.0;
412
+ MARKETING_VERSION = 1.0;
407
413
  PRODUCT_BUNDLE_IDENTIFIER = "$(AGENT_DEVICE_IOS_RUNNER_TEST_BUNDLE_ID)";
408
414
  PRODUCT_NAME = "$(TARGET_NAME)";
409
415
  STRING_CATALOG_GENERATE_SYMBOLS = NO;
@@ -412,9 +418,9 @@
412
418
  SWIFT_OBJC_BRIDGING_HEADER = "AgentDeviceRunnerUITests/AgentDeviceRunnerUITests-Bridging-Header.h";
413
419
  SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
414
420
  SWIFT_VERSION = 5.0;
415
- SUPPORTED_PLATFORMS = "iphoneos iphonesimulator appletvos appletvsimulator";
416
- TARGETED_DEVICE_FAMILY = "1,2,3";
417
- TVOS_DEPLOYMENT_TARGET = 15.6;
421
+ SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator appletvos appletvsimulator";
422
+ TARGETED_DEVICE_FAMILY = "1,2,3";
423
+ TVOS_DEPLOYMENT_TARGET = 15.6;
418
424
  TEST_TARGET_NAME = AgentDeviceRunner;
419
425
  };
420
426
  name = Debug;
@@ -422,12 +428,14 @@
422
428
  20EA2EEF2F2CFC7C001CF0EF /* Release */ = {
423
429
  isa = XCBuildConfiguration;
424
430
  buildSettings = {
425
- CODE_SIGN_STYLE = Automatic;
426
- CURRENT_PROJECT_VERSION = 1;
427
- DEVELOPMENT_TEAM = 2S799L9W4M;
428
- GENERATE_INFOPLIST_FILE = YES;
429
- IPHONEOS_DEPLOYMENT_TARGET = 15.6;
430
- MARKETING_VERSION = 1.0;
431
+ "CODE_SIGN_ENTITLEMENTS[sdk=macosx*]" = AgentDeviceRunnerUITests/AgentDeviceRunnerUITests.entitlements;
432
+ CODE_SIGN_STYLE = Automatic;
433
+ CURRENT_PROJECT_VERSION = 1;
434
+ DEVELOPMENT_TEAM = 2S799L9W4M;
435
+ GENERATE_INFOPLIST_FILE = YES;
436
+ IPHONEOS_DEPLOYMENT_TARGET = 15.6;
437
+ MACOSX_DEPLOYMENT_TARGET = 13.0;
438
+ MARKETING_VERSION = 1.0;
431
439
  PRODUCT_BUNDLE_IDENTIFIER = "$(AGENT_DEVICE_IOS_RUNNER_TEST_BUNDLE_ID)";
432
440
  PRODUCT_NAME = "$(TARGET_NAME)";
433
441
  STRING_CATALOG_GENERATE_SYMBOLS = NO;
@@ -436,9 +444,9 @@
436
444
  SWIFT_OBJC_BRIDGING_HEADER = "AgentDeviceRunnerUITests/AgentDeviceRunnerUITests-Bridging-Header.h";
437
445
  SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
438
446
  SWIFT_VERSION = 5.0;
439
- SUPPORTED_PLATFORMS = "iphoneos iphonesimulator appletvos appletvsimulator";
440
- TARGETED_DEVICE_FAMILY = "1,2,3";
441
- TVOS_DEPLOYMENT_TARGET = 15.6;
447
+ SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator appletvos appletvsimulator";
448
+ TARGETED_DEVICE_FAMILY = "1,2,3";
449
+ TVOS_DEPLOYMENT_TARGET = 15.6;
442
450
  TEST_TARGET_NAME = AgentDeviceRunner;
443
451
  };
444
452
  name = Release;
@@ -0,0 +1,10 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "https://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>com.apple.security.network.client</key>
6
+ <true/>
7
+ <key>com.apple.security.network.server</key>
8
+ <true/>
9
+ </dict>
10
+ </plist>
@@ -217,6 +217,16 @@ extension RunnerTests {
217
217
  return Response(ok: true, data: DataPayload(message: "tapped"))
218
218
  }
219
219
  return Response(ok: false, error: ErrorPayload(message: "tap requires text or x/y"))
220
+ case .mouseClick:
221
+ guard let x = command.x, let y = command.y else {
222
+ return Response(ok: false, error: ErrorPayload(message: "mouseClick requires x and y"))
223
+ }
224
+ do {
225
+ try mouseClickAt(app: activeApp, x: x, y: y, button: command.button ?? "primary")
226
+ return Response(ok: true, data: DataPayload(message: "clicked"))
227
+ } catch {
228
+ return Response(ok: false, error: ErrorPayload(message: error.localizedDescription))
229
+ }
220
230
  case .tapSeries:
221
231
  guard let x = command.x, let y = command.y else {
222
232
  return Response(ok: false, error: ErrorPayload(message: "tapSeries requires x and y"))
@@ -328,7 +338,7 @@ extension RunnerTests {
328
338
  Thread.sleep(forTimeInterval: 0.5)
329
339
  }
330
340
  let screenshot = XCUIScreen.main.screenshot()
331
- guard let pngData = screenshot.image.pngData() else {
341
+ guard let pngData = runnerPngData(for: screenshot.image) else {
332
342
  return Response(ok: false, error: ErrorPayload(message: "Failed to encode screenshot as PNG"))
333
343
  }
334
344
  let fileName = "screenshot-\(Int(Date().timeIntervalSince1970 * 1000)).png"
@@ -338,21 +348,40 @@ extension RunnerTests {
338
348
  } catch {
339
349
  return Response(ok: false, error: ErrorPayload(message: "Failed to write screenshot: \(error.localizedDescription)"))
340
350
  }
351
+ #if os(macOS)
352
+ return Response(ok: true, data: DataPayload(message: filePath))
353
+ #else
341
354
  // Return path relative to app container root (tmp/ maps to NSTemporaryDirectory)
342
355
  return Response(ok: true, data: DataPayload(message: "tmp/\(fileName)"))
356
+ #endif
343
357
  case .back:
344
358
  if tapNavigationBack(app: activeApp) {
345
359
  return Response(ok: true, data: DataPayload(message: "back"))
346
360
  }
361
+ #if os(macOS)
362
+ return Response(ok: false, error: ErrorPayload(message: "back button is not available on macOS"))
363
+ #else
347
364
  performBackGesture(app: activeApp)
348
365
  return Response(ok: true, data: DataPayload(message: "back"))
366
+ #endif
349
367
  case .home:
368
+ #if os(macOS)
369
+ return Response(ok: false, error: ErrorPayload(message: "home is not supported on macOS"))
370
+ #else
350
371
  pressHomeButton()
351
372
  return Response(ok: true, data: DataPayload(message: "home"))
373
+ #endif
352
374
  case .appSwitcher:
375
+ #if os(macOS)
376
+ return Response(ok: false, error: ErrorPayload(message: "appSwitcher is not supported on macOS"))
377
+ #else
353
378
  performAppSwitcherGesture(app: activeApp)
354
379
  return Response(ok: true, data: DataPayload(message: "appSwitcher"))
380
+ #endif
355
381
  case .alert:
382
+ #if os(macOS)
383
+ return Response(ok: false, error: ErrorPayload(message: "alert is not supported on macOS"))
384
+ #else
356
385
  let action = (command.action ?? "get").lowercased()
357
386
  let alert = activeApp.alerts.firstMatch
358
387
  if !alert.exists {
@@ -370,12 +399,17 @@ extension RunnerTests {
370
399
  }
371
400
  let buttonLabels = alert.buttons.allElementsBoundByIndex.map { $0.label }
372
401
  return Response(ok: true, data: DataPayload(message: alert.label, items: buttonLabels))
402
+ #endif
373
403
  case .pinch:
404
+ #if os(macOS)
405
+ return Response(ok: false, error: ErrorPayload(message: "pinch is not supported on macOS"))
406
+ #else
374
407
  guard let scale = command.scale, scale > 0 else {
375
408
  return Response(ok: false, error: ErrorPayload(message: "pinch requires scale > 0"))
376
409
  }
377
410
  pinch(app: activeApp, scale: scale, x: command.x, y: command.y)
378
411
  return Response(ok: true, data: DataPayload(message: "pinched"))
412
+ #endif
379
413
  }
380
414
  }
381
415
  }