agent-device 0.20.1 → 0.20.3

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 (108) hide show
  1. package/README.md +0 -2
  2. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.20.1.apk → agent-device-android-ime-helper-0.20.3.apk} +0 -0
  3. package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.3.apk.sha256 +1 -0
  4. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.20.1.manifest.json → agent-device-android-ime-helper-0.20.3.manifest.json} +4 -4
  5. package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.20.1.apk → agent-device-android-snapshot-helper-0.20.3.apk} +0 -0
  6. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.3.apk.sha256 +1 -0
  7. package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.20.1.manifest.json → agent-device-android-snapshot-helper-0.20.3.manifest.json} +6 -6
  8. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Alert.swift +2 -0
  9. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +1 -35
  10. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +0 -208
  11. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Keyboard.swift +184 -0
  12. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Orientation.swift +92 -0
  13. package/dist/src/agent-device-client.js +2 -2
  14. package/dist/src/android-adb.d.ts +3 -26
  15. package/dist/src/android-adb.js +1 -1
  16. package/dist/src/android.js +1 -1
  17. package/dist/src/app-helpers.js +1 -0
  18. package/dist/src/app-lifecycle.js +5 -5
  19. package/dist/src/app-log-request-scope.js +1 -1
  20. package/dist/src/app-resolution.js +1 -1
  21. package/dist/src/apps.js +5 -5
  22. package/dist/src/cli-config.js +1 -1
  23. package/dist/src/cli-help.js +6 -6
  24. package/dist/src/cli-runner.js +1 -1
  25. package/dist/src/cli.js +14 -14
  26. package/dist/src/click-button.d.ts +5 -0
  27. package/dist/src/client-metro.js +1 -0
  28. package/dist/src/command-schema.js +3 -3
  29. package/dist/src/context.js +1 -1
  30. package/dist/src/contracts.d.ts +1 -1
  31. package/dist/src/device-input-state.d.ts +26 -0
  32. package/dist/src/device-input-state.js +1 -1
  33. package/dist/src/device.js +9 -0
  34. package/dist/src/devices2.js +1 -1
  35. package/dist/src/find.js +1 -1
  36. package/dist/src/generic.js +1 -1
  37. package/dist/src/gesture-plan-types.js +1 -0
  38. package/dist/src/gesture-plan.js +1 -0
  39. package/dist/src/index.d.ts +1174 -1413
  40. package/dist/src/input-actions.js +4 -4
  41. package/dist/src/install-artifact.js +5 -1
  42. package/dist/src/install-artifact2.js +1 -0
  43. package/dist/src/interaction-snapshot.js +1 -1
  44. package/dist/src/interaction.d.ts +3 -6
  45. package/dist/src/interaction.js +1 -1
  46. package/dist/src/interactor.js +2 -2
  47. package/dist/src/interactor2.js +1 -1
  48. package/dist/src/internal/bin.js +1 -1
  49. package/dist/src/internal/daemon.js +14 -22
  50. package/dist/src/lease-context.js +1 -1
  51. package/dist/src/lease.js +1 -1
  52. package/dist/src/limrun.d.ts +437 -0
  53. package/dist/src/limrun.js +1 -0
  54. package/dist/src/linux.js +1 -1
  55. package/dist/src/logcat.js +1 -5
  56. package/dist/src/metro.d.ts +71 -2
  57. package/dist/src/metro.js +1 -1
  58. package/dist/src/metro2.js +1 -1
  59. package/dist/src/notifications.js +1 -1
  60. package/dist/src/physical-device-control.js +1 -0
  61. package/dist/src/plist.js +1 -0
  62. package/dist/src/react-native.js +1 -1
  63. package/dist/src/recording-export-quality.js +12 -13
  64. package/dist/src/register-builtins.js +1 -1
  65. package/dist/src/registry.js +18 -18
  66. package/dist/src/remote-config.d.ts +5 -2
  67. package/dist/src/remote-config.js +1 -1
  68. package/dist/src/remote-config2.js +1 -0
  69. package/dist/src/reporting.js +8 -8
  70. package/dist/src/runner-client.js +1 -1
  71. package/dist/src/runner-disposal.js +1 -2
  72. package/dist/src/runner-lease.js +1 -1
  73. package/dist/src/runtime-transport.js +1 -1
  74. package/dist/src/runtime.js +3 -3
  75. package/dist/src/runtime2.js +1 -1
  76. package/dist/src/sdk-android-adb.d.ts +4 -2
  77. package/dist/src/sdk-batch-runner.d.ts +13 -3
  78. package/dist/src/sdk-batch-runner.js +1 -1
  79. package/dist/src/sdk-contracts.d.ts +28 -2
  80. package/dist/src/sdk-contracts.js +2 -2
  81. package/dist/src/sdk-finders.d.ts +1 -1
  82. package/dist/src/sdk-remote-config.d.ts +119 -4
  83. package/dist/src/selector-runtime.js +1 -1
  84. package/dist/src/selector-vocabulary.js +1 -1
  85. package/dist/src/selectors.d.ts +1 -1
  86. package/dist/src/server.js +2 -2
  87. package/dist/src/session-target-evidence.js +1 -1
  88. package/dist/src/session.js +8 -8
  89. package/dist/src/simulator.js +1 -1
  90. package/dist/src/snapshot-diagnostics.js +4 -4
  91. package/dist/src/snapshot2.js +1 -1
  92. package/dist/src/tool-provider.js +3 -3
  93. package/dist/src/tool-provider2.js +1 -1
  94. package/dist/src/tool-provider3.js +1 -1
  95. package/dist/src/tv-remote.d.ts +213 -0
  96. package/dist/src/xml.js +2 -0
  97. package/package.json +49 -30
  98. package/server.json +2 -2
  99. package/smithery.yaml +1 -1
  100. package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.1.apk.sha256 +0 -1
  101. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.1.apk.sha256 +0 -1
  102. package/dist/src/android-system-chrome.js +0 -1
  103. package/dist/src/client-metro-companion.js +0 -1
  104. package/dist/src/metro-types.d.ts +0 -52
  105. package/dist/src/project-runtime.js +0 -1
  106. package/dist/src/scoped-provider.js +0 -1
  107. package/dist/src/simctl.js +0 -1
  108. package/dist/src/snapshot-quality.js +0 -1
@@ -1,979 +1,635 @@
1
- import { C as normalizeAgentDeviceError, D as ScreenshotOverlayRef, F as DeviceKind, I as DeviceTarget, M as SnapshotVisibility, N as centerOfRect, O as SnapshotNode, P as AppleOS, R as PlatformSelector, S as isAgentDeviceError, _ as SessionIsolationMode, a as DaemonLockPolicy, b as NormalizedError, c as DaemonResponseData, g as ResponseLevel, i as DaemonInstallSource, j as SnapshotUnchanged, k as SnapshotQualityVerdict, m as NetworkIncludeMode, n as DaemonArtifactType, o as DaemonRequest, p as LeaseBackend, r as DaemonError, s as DaemonResponse, t as DaemonArtifact, v as SessionRuntimeHints, y as AppError, z as PublicPlatform } from "./sdk-contracts.js";
2
- import { a as GesturePointerCount, c as SwipePreset, d as AndroidSnapshotHelperInstallReason, f as AndroidSnapshotHelperTransport, l as TransformGestureParams, o as ScrollDirection, s as SwipePattern, u as AndroidSnapshotCaptureMode } from "./sdk-android-adb.js";
1
+ import { A as SnapshotNode, B as DeviceTarget, C as normalizeAgentDeviceError, F as SnapshotVisibility, H as PlatformSelector, I as centerOfRect, L as AppleOS, P as SnapshotUnchanged, S as isAgentDeviceError, U as PublicPlatform, _ as SessionIsolationMode, a as DaemonLockPolicy, b as NormalizedError, c as DaemonResponseData, g as ResponseLevel, i as DaemonInstallSource, m as NetworkIncludeMode, o as DaemonRequest, p as LeaseBackend, r as DaemonError, s as DaemonResponse, t as DaemonArtifact, v as SessionRuntimeHints, y as AppError, z as DeviceKind } from "./sdk-contracts.js";
2
+ import { c as ScrollDirection, d as SwipePreset, f as TransformGestureParams, l as ScrollInputDirection, s as GesturePointerCount, u as SwipePattern } from "./sdk-android-adb.js";
3
3
  import { t as AppsFilter } from "./sdk-app-inventory.js";
4
4
  import { t as BatchRunResult } from "./sdk-batch-runner.js";
5
5
  import { r as FindLocator } from "./sdk-finders.js";
6
- import { a as LongPressCommandResponseData, i as FindCommandResponseData, o as PressCommandResponseData, r as FillCommandResponseData, s as ClickButton, t as ClickCommandResponseData } from "./interaction.js";
6
+ import { a as RemoteConnectionProfileFields, c as MetroPrepareResult, i as CloudProviderProfileFields, l as MetroReloadOptions, s as MetroPrepareOptions, u as MetroReloadResult } from "./sdk-remote-config.js";
7
+ import { c as RecordingExportQuality, d as PublicSnapshotCaptureAnnotations, i as AgentArtifactsResult, l as ScreenshotResultData, m as JsonObject, n as DeviceRotation, o as CloudProviderSessionResult, p as SessionSurface, r as AlertAction, s as BackMode, t as TvRemoteButton, u as SnapshotDiagnosticsSummary } from "./tv-remote.js";
8
+ import { t as ClickButton } from "./click-button.js";
9
+ import { a as LongPressCommandResponseData, i as FindCommandResponseData, o as PressCommandResponseData, r as FillCommandResponseData, t as ClickCommandResponseData } from "./interaction.js";
7
10
  import { p as createLocalArtifactAdapter } from "./sdk-io.js";
8
- import { i as MetroPrepareKind, n as RemoteConnectionProfileFields, r as CloudProviderProfileFields } from "./sdk-remote-config.js";
9
- import { n as MetroBridgeResult, r as MetroRuntimeHints } from "./metro-types.js";
10
- //#region src/platforms/android/snapshot-types.d.ts
11
- type AndroidSnapshotBackendMetadata = {
12
- backend: 'android-helper';
13
- helperVersion?: string;
14
- helperApiVersion?: string;
15
- helperTransport?: AndroidSnapshotHelperTransport;
16
- helperSessionReused?: boolean;
17
- installReason?: AndroidSnapshotHelperInstallReason;
18
- waitForIdleTimeoutMs?: number;
19
- waitForIdleQuietMs?: number;
20
- timeoutMs?: number;
21
- maxDepth?: number;
22
- maxNodes?: number;
23
- rootPresent?: boolean;
24
- captureMode?: AndroidSnapshotCaptureMode;
25
- systemSurfaceOnly?: boolean;
26
- windowCount?: number;
27
- nodeCount?: number;
28
- helperTruncated?: boolean;
29
- elapsedMs?: number;
30
- };
31
- //#endregion
32
- //#region src/contracts/snapshot-capture-annotations.d.ts
33
- type SnapshotCaptureAnalysis = {
34
- rawNodeCount: number;
35
- maxDepth: number;
11
+ //#region src/contracts/client-connection.d.ts
12
+ type AgentDeviceDaemonTransport = (req: Omit<DaemonRequest, 'token'>) => Promise<DaemonResponse>;
13
+ type AgentDeviceClientConfig = RemoteConnectionProfileFields & CloudProviderProfileFields & {
14
+ session?: string;
15
+ lockPolicy?: DaemonLockPolicy;
16
+ lockPlatform?: PlatformSelector;
17
+ requestId?: string;
18
+ sessionIsolation?: SessionIsolationMode;
19
+ leaseBackend?: LeaseBackend;
20
+ leaseTtlMs?: number;
21
+ runtime?: SessionRuntimeHints;
22
+ cwd?: string;
23
+ debug?: boolean;
24
+ cost?: boolean;
25
+ responseLevel?: ResponseLevel;
26
+ iosXctestrunFile?: string;
27
+ iosXctestDerivedDataPath?: string;
28
+ iosXctestEnvDir?: string;
36
29
  };
37
- type SnapshotCaptureFreshness = {
38
- action: string;
39
- retryCount: number;
40
- staleAfterRetries: boolean;
41
- reason?: 'empty-interactive' | 'sharp-drop' | 'stuck-route';
42
- };
43
- type SnapshotCaptureAnnotations = {
44
- analysis?: SnapshotCaptureAnalysis;
45
- androidSnapshot?: AndroidSnapshotBackendMetadata;
46
- freshness?: SnapshotCaptureFreshness;
47
- quality?: SnapshotQualityVerdict;
48
- warnings?: string[];
30
+ type AgentDeviceRequestOverrides = Pick<AgentDeviceClientConfig, 'session' | 'lockPolicy' | 'lockPlatform' | 'requestId' | 'daemonBaseUrl' | 'daemonAuthToken' | 'daemonTransport' | 'daemonServerMode' | 'tenant' | 'sessionIsolation' | 'runId' | 'leaseId' | 'leaseBackend' | 'leaseProvider' | 'deviceKey' | 'clientId' | 'providerApp' | 'providerOsVersion' | 'providerProject' | 'providerBuild' | 'providerSessionName' | 'awsProjectArn' | 'awsDeviceArn' | 'awsAppArn' | 'awsRegion' | 'awsInteractionMode' | 'leaseTtlMs' | 'cwd' | 'debug' | 'cost' | 'responseLevel' | 'iosXctestrunFile' | 'iosXctestDerivedDataPath' | 'iosXctestEnvDir'>;
31
+ type AgentDeviceIdentifiers = {
32
+ session?: string;
33
+ deviceId?: string;
34
+ deviceName?: string;
35
+ udid?: string;
36
+ serial?: string;
37
+ appId?: string;
38
+ appBundleId?: string;
39
+ package?: string;
49
40
  };
50
- type PublicSnapshotCaptureAnnotations = Pick<SnapshotCaptureAnnotations, 'androidSnapshot' | 'warnings'> & {
51
- snapshotQuality?: SnapshotQualityVerdict;
41
+ type AgentDeviceSelectionOptions = {
42
+ platform?: PlatformSelector;
43
+ target?: DeviceTarget;
44
+ device?: string;
45
+ udid?: string;
46
+ serial?: string;
47
+ iosSimulatorDeviceSet?: string;
48
+ androidDeviceAllowlist?: string;
52
49
  };
50
+ type DeviceCommandBaseOptions = AgentDeviceRequestOverrides & AgentDeviceSelectionOptions;
53
51
  //#endregion
54
- //#region src/contracts/snapshot-diagnostics.d.ts
55
- type SnapshotTimingStats = {
56
- count: number;
57
- p50Ms: number;
58
- p95Ms: number;
59
- maxMs: number;
60
- slowThresholdMs: number;
61
- platform?: PublicPlatform;
62
- backends?: Record<string, number>;
63
- };
64
- type SnapshotDiagnosticsSummary = {
65
- stats: SnapshotTimingStats;
66
- warning?: string;
52
+ //#region src/contracts/target-shutdown-contract.d.ts
53
+ type TargetShutdownResult = {
54
+ success: boolean;
55
+ exitCode: number;
56
+ stdout: string;
57
+ stderr: string;
58
+ error?: NormalizedError;
67
59
  };
68
60
  //#endregion
69
- //#region src/contracts/back-mode.d.ts
70
- declare const BACK_MODES: readonly ['in-app', 'system'];
71
- type BackMode = (typeof BACK_MODES)[number];
72
- //#endregion
73
- //#region src/contracts/device-rotation.d.ts
74
- declare const DEVICE_ROTATIONS: readonly ['portrait', 'portrait-upside-down', 'landscape-left', 'landscape-right'];
75
- type DeviceRotation = (typeof DEVICE_ROTATIONS)[number];
76
- //#endregion
77
- //#region src/contracts/tv-remote.d.ts
78
- declare const TV_REMOTE_BUTTON_DEFINITIONS: {
79
- readonly up: {
80
- readonly aliases: readonly [];
81
- readonly androidKeyevent: 'KEYCODE_DPAD_UP';
82
- readonly appleRemoteButton: 'up';
83
- readonly vegaKey: 'KEY_UP';
84
- };
85
- readonly down: {
86
- readonly aliases: readonly [];
87
- readonly androidKeyevent: 'KEYCODE_DPAD_DOWN';
88
- readonly appleRemoteButton: 'down';
89
- readonly vegaKey: 'KEY_DOWN';
90
- };
91
- readonly left: {
92
- readonly aliases: readonly [];
93
- readonly androidKeyevent: 'KEYCODE_DPAD_LEFT';
94
- readonly appleRemoteButton: 'left';
95
- readonly vegaKey: 'KEY_LEFT';
61
+ //#region src/contracts/client-device-view.d.ts
62
+ type AgentDeviceDevice = {
63
+ platform: PublicPlatform;
64
+ target: DeviceTarget;
65
+ kind: DeviceKind;
66
+ id: string;
67
+ name: string;
68
+ booted?: boolean;
69
+ /**
70
+ * Additive Apple-OS discriminant (iPhone/iPad/tvOS/visionOS/macOS). Present only for
71
+ * Apple devices; `platform` still carries the leaf (`ios`/`macos`).
72
+ */
73
+ appleOs?: AppleOS;
74
+ identifiers: AgentDeviceIdentifiers;
75
+ ios?: {
76
+ udid: string;
96
77
  };
97
- readonly right: {
98
- readonly aliases: readonly [];
99
- readonly androidKeyevent: 'KEYCODE_DPAD_RIGHT';
100
- readonly appleRemoteButton: 'right';
101
- readonly vegaKey: 'KEY_RIGHT';
78
+ android?: {
79
+ serial: string;
102
80
  };
103
- readonly select: {
104
- readonly aliases: readonly ["ok", "center", "enter"];
105
- readonly androidKeyevent: 'KEYCODE_DPAD_CENTER';
106
- readonly appleRemoteButton: 'select';
107
- readonly vegaKey: 'KEY_ENTER';
81
+ vega?: {
82
+ serial: string;
108
83
  };
109
- readonly menu: {
110
- readonly aliases: readonly [];
111
- readonly androidKeyevent: 'KEYCODE_MENU';
112
- readonly appleRemoteButton: 'menu';
113
- readonly vegaKey: 'KEY_MENU';
84
+ };
85
+ type AgentDeviceCapabilitiesResult = {
86
+ device: AgentDeviceDevice;
87
+ availableCommands: string[];
88
+ };
89
+ type AgentDeviceSessionDevice = {
90
+ platform: PublicPlatform;
91
+ target: DeviceTarget;
92
+ id: string;
93
+ name: string;
94
+ /**
95
+ * Additive Apple-OS discriminant (iPhone/iPad/tvOS/visionOS/macOS). Present only for
96
+ * Apple devices; `platform` still carries the leaf (`ios`/`macos`).
97
+ */
98
+ appleOs?: AppleOS;
99
+ identifiers: AgentDeviceIdentifiers;
100
+ ios?: {
101
+ udid: string;
102
+ simulatorSetPath?: string | null;
114
103
  };
115
- readonly home: {
116
- readonly aliases: readonly [];
117
- readonly androidKeyevent: 'KEYCODE_HOME';
118
- readonly appleRemoteButton: 'home';
119
- readonly vegaKey: 'KEY_HOMEPAGE';
104
+ android?: {
105
+ serial: string;
120
106
  };
121
- readonly back: {
122
- readonly aliases: readonly [];
123
- readonly androidKeyevent: 'KEYCODE_BACK';
124
- readonly appleRemoteButton: 'menu';
125
- readonly vegaKey: 'KEY_BACK';
107
+ vega?: {
108
+ serial: string;
126
109
  };
127
110
  };
128
- declare const TV_REMOTE_BUTTONS: (keyof typeof TV_REMOTE_BUTTON_DEFINITIONS)[];
129
- type TvRemoteButton = (typeof TV_REMOTE_BUTTONS)[number];
130
- //#endregion
131
- //#region src/contracts/navigation.d.ts
132
- /**
133
- * Closed results of the navigation/global action commands. Each mirrors the
134
- * dispatch handler's literal return EXACTLY (src/core/dispatch.ts
135
- * `DISPATCH_HANDLERS`): a fixed `action` discriminant plus the always-present
136
- * `successText` message (the handlers always pass a non-empty message, so it is
137
- * required here). The handlers spread nothing else, so the shapes are closed —
138
- * consistent with the `viewport` contract, the generic-dispatch Android
139
- * dialog-recovery `warning` annotation is intentionally not part of the contract.
140
- */
141
- /** `home` — `{ action: 'home', message: 'Home' }`. */
142
- type HomeCommandResult = {
143
- action: 'home';
144
- message: string;
111
+ type AgentDeviceSession = {
112
+ name: string;
113
+ createdAt: number;
114
+ sessionStateDir?: string;
115
+ runnerLogPath?: string;
116
+ device: AgentDeviceSessionDevice;
117
+ identifiers: AgentDeviceIdentifiers;
145
118
  };
146
- /** `back` — `{ action: 'back', mode, message: 'Back' }`; `mode` defaults to `'in-app'`. */
147
- type BackCommandResult = {
148
- action: 'back';
149
- mode: BackMode;
150
- message: string;
119
+ type StartupPerfSample = {
120
+ durationMs: number;
121
+ measuredAt: string;
122
+ method: string;
123
+ appTarget?: string;
124
+ appBundleId?: string;
151
125
  };
152
- /** `orientation` — `{ action: 'orientation', orientation, message: 'Rotated to <orientation>' }`. */
153
- type OrientationCommandResult = {
154
- action: 'orientation';
155
- orientation: DeviceRotation;
156
- message: string;
126
+ type DeviceBootOptions = DeviceCommandBaseOptions & {
127
+ headless?: boolean;
157
128
  };
158
- /**
159
- * @deprecated The `rotate` command was renamed to `orientation`. This is the
160
- * legacy response contract (`action: 'rotate'`) that shipped in v0.18/v0.19,
161
- * retained for existing SDK consumers until the next major version. New code
162
- * should use {@link OrientationCommandResult}.
163
- */
164
- type RotateCommandResult = {
165
- action: 'rotate';
166
- orientation: DeviceRotation;
167
- message: string;
129
+ type DeviceShutdownOptions = DeviceCommandBaseOptions;
130
+ //#endregion
131
+ //#region src/contracts/client-app.d.ts
132
+ type AppInstallOptions = AgentDeviceRequestOverrides & AgentDeviceSelectionOptions & {
133
+ app?: string;
134
+ appPath: string;
168
135
  };
169
- /** `app-switcher` — `{ action: 'app-switcher', message: 'Opened app switcher' }`. */
170
- type AppSwitcherCommandResult = {
171
- action: 'app-switcher';
172
- message: string;
136
+ type AppDeployOptions = AgentDeviceRequestOverrides & AgentDeviceSelectionOptions & {
137
+ app: string;
138
+ appPath: string;
173
139
  };
174
- /** `tv-remote` — `{ action: 'tv-remote', button, durationMs?, message }`. */
175
- type TvRemoteCommandResult = {
176
- action: 'tv-remote';
177
- button: TvRemoteButton;
178
- durationMs?: number;
179
- message: string;
140
+ type AppDeployResult = {
141
+ app: string;
142
+ appPath: string;
143
+ platform: PublicPlatform;
144
+ appId?: string;
145
+ bundleId?: string;
146
+ package?: string;
147
+ identifiers: AgentDeviceIdentifiers;
180
148
  };
181
- //#endregion
182
- //#region src/contracts/recording-export-quality.d.ts
183
- declare const RECORDING_EXPORT_QUALITIES: readonly ['medium', 'high'];
184
- type RecordingExportQuality = (typeof RECORDING_EXPORT_QUALITIES)[number];
185
- //#endregion
186
- //#region src/contracts/recording-scope.d.ts
187
- declare const RECORDING_SCOPE_VALUES: readonly ['app', 'device', 'system'];
188
- type RecordingScope = (typeof RECORDING_SCOPE_VALUES)[number];
189
- //#endregion
190
- //#region src/contracts/alert-contract.d.ts
191
- declare const ALERT_ACTIONS: readonly ['get', 'accept', 'dismiss', 'wait'];
192
- type AlertAction = (typeof ALERT_ACTIONS)[number];
193
- //#endregion
194
- //#region src/contracts/json.d.ts
195
- type JsonPrimitive = string | number | boolean | null;
196
- type JsonValue = JsonPrimitive | JsonObject | JsonValue[];
197
- type JsonObject = {
198
- [key: string]: JsonValue;
149
+ type AppOpenOptions = AgentDeviceRequestOverrides & AgentDeviceSelectionOptions & {
150
+ app?: string;
151
+ url?: string;
152
+ surface?: SessionSurface;
153
+ activity?: string;
154
+ launchConsole?: string;
155
+ launchArgs?: string[];
156
+ relaunch?: boolean;
157
+ saveScript?: boolean | string;
158
+ /** #1258: overwrite an existing --save-script target instead of refusing. Alias: --overwrite. */
159
+ force?: boolean;
160
+ deviceHub?: boolean;
161
+ testIme?: boolean;
162
+ noRecord?: boolean;
163
+ runtime?: SessionRuntimeHints;
199
164
  };
200
- //#endregion
201
- //#region src/commands/command-contract.d.ts
202
- type JsonSchema = {
203
- type?: string | readonly string[];
204
- description?: string;
205
- properties?: Record<string, JsonSchema>;
206
- required?: readonly string[];
207
- additionalProperties?: boolean | JsonSchema;
208
- items?: JsonSchema;
209
- prefixItems?: readonly JsonSchema[];
210
- oneOf?: readonly JsonSchema[];
211
- enum?: readonly unknown[];
212
- const?: unknown;
213
- minimum?: number;
214
- maximum?: number;
165
+ type AppOpenResult = {
166
+ session: string;
167
+ warnings?: string[];
168
+ sessionStateDir?: string;
169
+ runnerLogPath?: string;
170
+ requestLogPath?: string;
171
+ eventLogPath?: string;
172
+ appName?: string;
173
+ appBundleId?: string;
174
+ appId?: string;
175
+ startup?: StartupPerfSample;
176
+ runtime?: SessionRuntimeHints;
177
+ device?: AgentDeviceSessionDevice;
178
+ identifiers: AgentDeviceIdentifiers;
215
179
  };
216
- type ExecutableCommandProjection<ClientMethod extends string = string> = {
217
- clientMethod: ClientMethod;
218
- outputSchema: JsonSchema;
180
+ type AppCloseOptions = AgentDeviceRequestOverrides & {
181
+ app?: string;
182
+ shutdown?: boolean;
183
+ saveScript?: boolean | string;
184
+ /** #1258: overwrite an existing --save-script target instead of refusing. Alias: --overwrite. */
185
+ force?: boolean;
219
186
  };
220
- //#endregion
221
- //#region src/contracts/session-surface.d.ts
222
- declare const SESSION_SURFACES: readonly ['app', 'frontmost-app', 'desktop', 'menubar'];
223
- type SessionSurface = (typeof SESSION_SURFACES)[number];
224
- //#endregion
225
- //#region src/utils/screenshot-result.d.ts
226
- type ScreenshotResultData = {
227
- path?: string;
228
- width?: number;
229
- height?: number;
230
- logicalWidth?: number;
231
- logicalHeight?: number;
232
- pixelDensity?: number;
233
- overlayRefs?: ScreenshotOverlayRef[];
187
+ type AppCloseResult = {
188
+ session: string;
189
+ closedApp?: string;
190
+ shutdown?: TargetShutdownResult;
191
+ /**
192
+ * #1258: absolute path of the committed session/healed script when this close
193
+ * published one (`close --save-script`, or a repair-armed session's finalize)
194
+ * — so a client that requested publication learns where the file landed.
195
+ */
196
+ savedScript?: string;
197
+ identifiers: AgentDeviceIdentifiers;
234
198
  };
235
- //#endregion
236
- //#region src/commands/interaction/runtime/gestures.d.ts
237
- declare const SCROLL_INPUT_DIRECTIONS: readonly ['up', 'down', 'left', 'right', 'top', 'bottom'];
238
- type ScrollInputDirection = (typeof SCROLL_INPUT_DIRECTIONS)[number];
239
- //#endregion
240
- //#region src/commands/system/navigation-projection.d.ts
241
- declare const navigationCommandProjectionType: unique symbol;
242
- type NavigationCommandProjection<Options, Result, Required extends boolean, ClientMethod extends string> = ExecutableCommandProjection<ClientMethod> & {
243
- readonly [navigationCommandProjectionType]?: {
244
- options: Options;
245
- result: Result;
246
- required: Required;
247
- };
199
+ type AppInstallFromSourceOptions = AgentDeviceRequestOverrides & AgentDeviceSelectionOptions & {
200
+ source: DaemonInstallSource;
201
+ retainPaths?: boolean;
202
+ retentionMs?: number;
248
203
  };
249
- declare const NAVIGATION_COMMAND_PROJECTIONS: {
250
- readonly back: NavigationCommandProjection<{
251
- mode?: BackMode;
252
- }, BackCommandResult, false, "back">;
253
- readonly home: NavigationCommandProjection<{}, HomeCommandResult, false, "home">;
254
- readonly orientation: NavigationCommandProjection<{
255
- orientation: DeviceRotation;
256
- }, OrientationCommandResult, true, "orientation">;
257
- readonly 'app-switcher': NavigationCommandProjection<{}, AppSwitcherCommandResult, false, "appSwitcher">;
258
- readonly 'tv-remote': NavigationCommandProjection<{
259
- button: TvRemoteButton;
260
- durationMs?: number;
261
- }, TvRemoteCommandResult, true, "tvRemote">;
204
+ type AppInstallFromSourceResult = {
205
+ appName?: string;
206
+ appId?: string;
207
+ bundleId?: string;
208
+ packageName?: string;
209
+ launchTarget: string;
210
+ installablePath?: string;
211
+ archivePath?: string;
212
+ materializationId?: string;
213
+ materializationExpiresAt?: string;
214
+ identifiers: AgentDeviceIdentifiers;
262
215
  };
263
- type NavigationCommandName = keyof typeof NAVIGATION_COMMAND_PROJECTIONS;
264
- type NavigationCommandOptions<Name extends NavigationCommandName> = (typeof NAVIGATION_COMMAND_PROJECTIONS)[Name] extends NavigationCommandProjection<infer Options, unknown, boolean, string> ? Options : never;
265
- type ProjectedNavigationCommandMethod<BaseOptions, Projection> = Projection extends NavigationCommandProjection<infer Options, infer Result, infer Required, string> ? Required extends true ? (options: BaseOptions & Options) => Promise<Result> : (options?: BaseOptions & Options) => Promise<Result> : never;
266
- type ProjectedNavigationCommandClient<BaseOptions> = { [Name in NavigationCommandName as (typeof NAVIGATION_COMMAND_PROJECTIONS)[Name]['clientMethod']]: ProjectedNavigationCommandMethod<BaseOptions, (typeof NAVIGATION_COMMAND_PROJECTIONS)[Name]>; };
267
- //#endregion
268
- //#region src/contracts/logs.d.ts
269
- declare const LOG_ACTION_VALUES: readonly ['path', 'start', 'stop', 'doctor', 'mark', 'clear'];
270
- type LogAction = (typeof LOG_ACTION_VALUES)[number];
271
- //#endregion
272
- //#region src/client/client-companion-tunnel-contract.d.ts
273
- type CompanionTunnelScope = {
274
- tenantId: string;
275
- runId: string;
276
- leaseId: string;
216
+ type AppListOptions = AgentDeviceRequestOverrides & AgentDeviceSelectionOptions & {
217
+ appsFilter?: AppsFilter;
277
218
  };
278
- type MetroBridgeScope = CompanionTunnelScope;
279
- //#endregion
280
- //#region src/metro/client-metro.d.ts
281
- type ResolvedMetroKind = Exclude<MetroPrepareKind, 'auto'>;
282
- type PrepareMetroRuntimeResult = {
283
- projectRoot: string;
284
- kind: ResolvedMetroKind;
285
- dependenciesInstalled: boolean;
286
- packageManager: string | null;
287
- started: boolean;
288
- reused: boolean;
289
- pid: number;
290
- logPath: string;
291
- statusUrl: string;
292
- runtimeFilePath: string | null;
293
- iosRuntime: MetroRuntimeHints;
294
- androidRuntime: MetroRuntimeHints;
295
- bridge: MetroBridgeResult | null;
219
+ type AppPushOptions = DeviceCommandBaseOptions & {
220
+ app: string;
221
+ payload: string | JsonObject;
296
222
  };
297
- /**
298
- * `transport` says which channel delivered the reload: `http` for the classic GET /reload route,
299
- * `message-socket` for the /message websocket broadcast used when the server has no HTTP reload
300
- * route (Expo). `status`/`body` always describe the HTTP probe; on the websocket path `reloadUrl`
301
- * is the ws(s) message-socket URL.
302
- */
303
- type ReloadMetroResult = {
304
- reloaded: true;
305
- reloadUrl: string;
306
- status: number;
307
- body: string;
308
- transport: 'http' | 'message-socket';
223
+ type AppTriggerEventOptions = DeviceCommandBaseOptions & {
224
+ event: string;
225
+ payload?: JsonObject;
309
226
  };
310
- //#endregion
311
- //#region src/contracts/target-shutdown-contract.d.ts
312
- type TargetShutdownResult = {
313
- success: boolean;
314
- exitCode: number;
315
- stdout: string;
316
- stderr: string;
317
- error?: NormalizedError;
227
+ type MaterializationReleaseOptions = AgentDeviceRequestOverrides & {
228
+ materializationId: string;
229
+ };
230
+ type MaterializationReleaseResult = {
231
+ released: boolean;
232
+ materializationId: string;
233
+ identifiers: AgentDeviceIdentifiers;
318
234
  };
319
235
  //#endregion
320
- //#region src/contracts/perf.d.ts
321
- declare const PERF_AREA_VALUES: readonly ['metrics', 'frames', 'memory', 'cpu', 'trace'];
322
- declare const PERF_ACTION_VALUES: readonly ['sample', 'snapshot', 'start', 'stop', 'report'];
323
- declare const PERF_SUBJECT_VALUES: readonly ['profile'];
324
- declare const PERF_KIND_VALUES: readonly ['xctrace', 'simpleperf', 'perfetto', 'android-hprof', 'memgraph'];
325
- type PerfArea = (typeof PERF_AREA_VALUES)[number];
326
- type PerfAction = (typeof PERF_ACTION_VALUES)[number];
327
- type PerfSubject = (typeof PERF_SUBJECT_VALUES)[number];
328
- type PerfKind = (typeof PERF_KIND_VALUES)[number];
329
- //#endregion
330
- //#region src/contracts/debug-symbols.d.ts
331
- type DebugSymbolsOptions = {
332
- action?: 'symbols';
333
- artifact: string;
334
- dsym?: string;
335
- searchPath?: string;
336
- out?: string;
337
- cwd?: string;
236
+ //#region src/contracts/client-capture.d.ts
237
+ type CaptureSnapshotOptions = AgentDeviceRequestOverrides & AgentDeviceSelectionOptions & {
238
+ interactiveOnly?: boolean;
239
+ depth?: number;
240
+ scope?: string;
241
+ raw?: boolean;
242
+ forceFull?: boolean;
243
+ timeoutMs?: number;
244
+ /**
245
+ * #1271 stage 2 (ADR 0012 amendment): `snapshot` is observation-only and
246
+ * excluded from a repair-armed heal by default; `record` forces it
247
+ * through. Mutually exclusive with `noRecord`.
248
+ */
249
+ noRecord?: boolean;
250
+ record?: boolean;
338
251
  };
339
- type DebugSymbolsImage = {
340
- name: string;
341
- uuid: string;
342
- arch?: string;
343
- dsymPath: string;
344
- binaryPath: string;
252
+ type CaptureSnapshotResult = {
253
+ nodes: SnapshotNode[];
254
+ truncated: boolean;
255
+ appName?: string;
256
+ appBundleId?: string;
257
+ visibility?: SnapshotVisibility;
258
+ unchanged?: SnapshotUnchanged;
259
+ snapshotDiagnostics?: SnapshotDiagnosticsSummary;
260
+ identifiers: AgentDeviceIdentifiers;
261
+ /**
262
+ * ADR 0014: the response-level ref-frame epoch the plain node refs were minted
263
+ * from. A ref-issuing snapshot carries it ONCE (nodes stay plain `@e12` for the
264
+ * token budget); pair a ref with it (`@e12~s<refsGeneration>`) before a mutation.
265
+ */
266
+ refsGeneration?: number;
267
+ /**
268
+ * Digest response view only: a capped list of `{ ref, label? }` pairs taken
269
+ * from the full `nodes` tree so the MCP layer can still pin refs when the
270
+ * default-level `nodes` payload is intentionally omitted.
271
+ */
272
+ refs?: Array<{
273
+ ref: string;
274
+ label?: string;
275
+ }>;
276
+ } & PublicSnapshotCaptureAnnotations;
277
+ type CaptureScreenshotOptions = AgentDeviceRequestOverrides & {
278
+ path?: string;
279
+ overlayRefs?: boolean;
280
+ pixelDensity?: number;
281
+ fullscreen?: boolean;
282
+ maxSize?: number;
283
+ stabilize?: boolean;
284
+ normalizeStatusBar?: boolean;
285
+ surface?: SessionSurface;
345
286
  };
346
- type DebugSymbolsCrashFrame = {
347
- index: number;
348
- image: string;
349
- address: string;
350
- symbol?: string;
287
+ type CaptureScreenshotResult = ScreenshotResultData & {
288
+ path: string;
289
+ identifiers: AgentDeviceIdentifiers;
351
290
  };
352
- type DebugSymbolsCrashSummary = {
353
- format: 'ips' | 'text';
354
- appName?: string;
355
- bundleId?: string;
356
- version?: string;
357
- incident?: string;
358
- timestamp?: string;
359
- exceptionType?: string;
360
- exceptionCodes?: string;
361
- terminationReason?: string;
362
- crashedThread?: number;
363
- topFrames: DebugSymbolsCrashFrame[];
364
- findings: string[];
291
+ type CaptureDiffOptions = DeviceCommandBaseOptions & Pick<CaptureSnapshotOptions, 'interactiveOnly' | 'depth' | 'scope' | 'raw'> & {
292
+ kind: 'snapshot';
293
+ out?: string;
365
294
  };
366
- type DebugSymbolsResult = {
367
- kind: 'debugSymbols';
368
- platform: 'apple';
369
- artifactPath: string;
370
- outPath: string;
371
- crash: DebugSymbolsCrashSummary;
372
- matchedImages: DebugSymbolsImage[];
373
- symbolicatedFrames: number;
374
- skippedImages: number;
375
- warnings?: string[];
376
- message: string;
295
+ type SelectorSnapshotCommandOptions = Pick<CaptureSnapshotOptions, 'depth' | 'scope' | 'raw'>;
296
+ type FindSnapshotCommandOptions = Pick<CaptureSnapshotOptions, 'depth' | 'raw'>;
297
+ //#endregion
298
+ //#region src/contracts/client-target.d.ts
299
+ type PointTarget = {
300
+ x: number;
301
+ y: number;
302
+ ref?: never;
303
+ selector?: never;
304
+ label?: never;
305
+ };
306
+ type RefTarget = {
307
+ ref: string;
308
+ label?: string;
309
+ x?: never;
310
+ y?: never;
311
+ selector?: never;
312
+ };
313
+ type SelectorTarget = {
314
+ selector: string;
315
+ x?: never;
316
+ y?: never;
317
+ ref?: never;
318
+ label?: never;
377
319
  };
320
+ type InteractionTarget = PointTarget | RefTarget | SelectorTarget;
321
+ type ElementTarget = RefTarget | SelectorTarget;
378
322
  //#endregion
379
- //#region src/contracts/device.d.ts
323
+ //#region src/contracts/client-gesture.d.ts
324
+ type RepeatedPressOptions = {
325
+ count?: number;
326
+ intervalMs?: number;
327
+ holdMs?: number;
328
+ jitterPx?: number;
329
+ doubleTap?: boolean;
330
+ };
380
331
  /**
381
- * Closed result of the `boot` command. Mirrors the daemon handler's only
382
- * success return EXACTLY (src/daemon/handlers/session-state.ts) — the fixed
383
- * object literal `{ platform, target, device, id, kind, booted }` plus the
384
- * additive `appleOs` discriminant, emitted only for Apple devices.
332
+ * Opt-in (#1101): after the action, wait for the UI to go quiet and return the
333
+ * settled diff vs the pre-action tree (`settle` on the result) in the same
334
+ * response. Best-effort — never fails the action. `settleQuietMs` tunes the
335
+ * quiet window (default 500ms); `timeoutMs` bounds the settle wait (default
336
+ * 10s) when `settle` is true. A bare `timeoutMs` without `settle` is ignored
337
+ * for compatibility; `settleQuietMs` still requires `settle`.
385
338
  */
386
- type BootCommandResult = {
387
- platform: PublicPlatform;
388
- target: DeviceTarget;
389
- /** Human-readable device name (`device.name`). */
390
- device: string;
391
- /** Stable device id (`device.id`). */
392
- id: string;
393
- kind: DeviceKind;
394
- /** Always `true` on the success path. */
395
- booted: true;
339
+ type SettleCommandOptions = {
340
+ settle?: boolean;
341
+ settleQuietMs?: number;
342
+ timeoutMs?: number;
343
+ };
344
+ type ClickOptions = DeviceCommandBaseOptions & SelectorSnapshotCommandOptions & InteractionTarget & RepeatedPressOptions & SettleCommandOptions & {
345
+ button?: ClickButton;
396
346
  /**
397
- * Additive Apple-OS discriminant (`device.appleOs`): iPhone/iPad/tvOS/visionOS/macOS.
398
- * Present only for Apple devices; absent for non-Apple platforms. `platform` stays the
399
- * leaf (`ios`/`macos`) — this is an extra field, not a replacement.
347
+ * Opt-in (#1047): return cheap post-action evidence (AX digest, node counts,
348
+ * changedFromBefore) in the response instead of requiring a follow-up
349
+ * snapshot to confirm the action had an effect.
400
350
  */
401
- appleOs?: AppleOS;
351
+ verify?: boolean;
402
352
  };
403
- /**
404
- * Closed result of the `shutdown` command. Mirrors the daemon handler's success
405
- * return EXACTLY (src/daemon/handlers/session-state.ts) — the fixed object
406
- * literal `{ platform, target, device, id, kind, shutdown }` plus the additive
407
- * `appleOs` discriminant (Apple devices only). The `shutdown` field is the raw
408
- * {@link TargetShutdownResult} from `shutdownDeviceTarget`.
409
- */
410
- type ShutdownCommandResult = {
411
- platform: PublicPlatform;
412
- target: DeviceTarget;
413
- /** Human-readable device name (`device.name`). */
414
- device: string;
415
- /** Stable device id (`device.id`). */
416
- id: string;
417
- kind: DeviceKind;
418
- shutdown: TargetShutdownResult;
419
- /**
420
- * Additive Apple-OS discriminant (`device.appleOs`): iPhone/iPad/tvOS/visionOS/macOS.
421
- * Present only for Apple devices; absent for non-Apple platforms. `platform` stays the
422
- * leaf (`ios`/`macos`) — this is an extra field, not a replacement.
423
- */
424
- appleOs?: AppleOS;
425
- };
426
- //#endregion
427
- //#region src/contracts/viewport.d.ts
428
- /**
429
- * Closed result of the `viewport` command. Mirrors the dispatch handler's return
430
- * EXACTLY (src/core/dispatch.ts `handleViewportCommand`) — `{ width, height }`
431
- * plus the always-present `successText` message. The generic dispatch path
432
- * returns this object unchanged (viewport has no Android dialog guard, so no
433
- * `warning` is ever appended), so the shape is intentionally closed.
434
- */
435
- type ViewportCommandResult = {
436
- width: number;
437
- height: number;
438
- message: string;
439
- };
440
- //#endregion
441
- //#region src/contracts/clipboard.d.ts
442
- /**
443
- * Closed result of the `clipboard` command. Mirrors the dispatch handler's
444
- * literal return EXACTLY (src/core/dispatch.ts `handleClipboardCommand`): a
445
- * discriminated union on `action`. `read` returns the clipboard `text`; `write`
446
- * reports the written `textLength` plus the `successText` message. The handler
447
- * spreads nothing else, so each branch is closed.
448
- */
449
- type ClipboardCommandResult = {
450
- action: 'read';
451
- text: string;
452
- } | {
453
- action: 'write';
454
- textLength: number;
455
- message: string;
456
- };
457
- //#endregion
458
- //#region src/contracts/app-state.d.ts
459
- /**
460
- * Closed result of the `appstate` command, grounded in the daemon handler's
461
- * success returns (src/daemon/handlers/session-state.ts `handleAppStateCommand`).
462
- * A discriminated union on `platform`:
463
- * - Apple (`ios` / `macos`) session state, with iOS-only device locators that
464
- * the previous hand-written mirror omitted; and
465
- * - Android foreground `package` / `activity`.
466
- *
467
- * The handler returns one of these fixed objects (errors take the `ok: false`
468
- * path), so each branch is closed.
469
- */
470
- type AppStateCommandResult = {
471
- platform: 'ios' | 'macos';
472
- appName: string;
473
- appBundleId?: string;
474
- source: 'session';
475
- surface: SessionSurface;
476
- /** iOS only — the session device's UDID. */
477
- device_udid?: string;
478
- /** iOS only — the simulator set path, or `null` when unknown. */
479
- ios_simulator_device_set?: string | null;
480
- } | {
481
- platform: 'android';
482
- package: string;
483
- activity: string;
484
- };
485
- //#endregion
486
- //#region src/contracts/keyboard.d.ts
487
- /**
488
- * Closed result of the `keyboard` command, grounded in the dispatch handlers'
489
- * literal returns (src/core/dispatch.ts `handleAndroidKeyboardCommand` /
490
- * `handleIosKeyboardCommand`).
491
- *
492
- * `platform` and `action` are always present; the remaining fields appear per
493
- * branch (Android `status`/`dismiss` carry the keyboard-state fields; `enter`
494
- * and iOS `dismiss` carry a `message`). It is kept as a flat closed shape rather
495
- * than a five-way `platform`×`action` union because the per-branch field sets
496
- * overlap heavily and the underlying Android keyboard-state types live in the
497
- * platform layer (below the public contract). The `Record` index signature of
498
- * the previous hand-written mirror is dropped, and the spurious `| null`s are
499
- * removed (the handler never returns `null` for these).
500
- */
501
- type KeyboardCommandResult = {
502
- platform: 'android' | 'ios';
503
- action: 'status' | 'dismiss' | 'enter';
504
- visible?: boolean;
505
- wasVisible?: boolean;
506
- dismissed?: boolean;
507
- attempts?: number;
508
- inputType?: string;
509
- type?: 'text' | 'number' | 'email' | 'phone' | 'password' | 'datetime' | 'unknown';
510
- inputMethodPackage?: string;
511
- focusedPackage?: string;
512
- focusedResourceId?: string;
513
- inputOwner?: 'app' | 'ime' | 'unknown';
514
- message?: string;
353
+ type PressOptions = DeviceCommandBaseOptions & SelectorSnapshotCommandOptions & InteractionTarget & RepeatedPressOptions & SettleCommandOptions & {
354
+ verify?: boolean;
515
355
  };
516
- //#endregion
517
- //#region src/contracts/wait.d.ts
518
- /**
519
- * Public daemon result for `wait`. The runtime-local result carries a `kind`
520
- * discriminant, but `toDaemonWaitData` intentionally projects the normal daemon
521
- * payload to this compact shape. The direct iOS selector fast path may still
522
- * include `kind: 'selector'` additively.
523
- */
524
- type WaitCommandResult = {
525
- waitedMs: number;
526
- kind?: 'selector';
527
- text?: string;
528
- selector?: string;
529
- captures?: number;
530
- nodeCount?: number;
531
- hint?: string;
532
- warning?: string;
356
+ type LongPressOptions = DeviceCommandBaseOptions & SelectorSnapshotCommandOptions & InteractionTarget & SettleCommandOptions & {
357
+ durationMs?: number;
533
358
  };
534
- //#endregion
535
- //#region src/contracts/prepare.d.ts
536
- type PrepareIosRunnerCacheKind = 'exact' | 'restore-key' | 'miss' | 'external';
537
- type PrepareIosRunnerArtifactState = 'valid' | 'rebuilt';
538
- type PrepareIosRunnerTiming = {
539
- totalMs: number;
540
- additiveParts: {
541
- buildMs?: number;
542
- connectAfterBuildMs: number;
543
- healthCheckMs: number;
359
+ type SwipeOptions = DeviceCommandBaseOptions & {
360
+ from: {
361
+ x: number;
362
+ y: number;
544
363
  };
545
- containment: {
546
- connectMs?: ['buildMs'];
547
- healthCheckMs: [];
364
+ to: {
365
+ x: number;
366
+ y: number;
548
367
  };
549
- note: string;
368
+ count?: number;
369
+ pauseMs?: number;
370
+ pattern?: SwipePattern;
550
371
  };
551
- /**
552
- * Public daemon result for `prepare ios-runner`. The runner-local prepare result
553
- * is projected by `prepareIosRunnerResponseData` with device identity and timing
554
- * guidance before it reaches the client.
555
- */
556
- type PrepareCommandResult = {
557
- action: 'ios-runner';
558
- platform: PublicPlatform;
559
- deviceId: string;
560
- deviceName: string;
561
- kind: DeviceKind;
562
- durationMs: number;
563
- runner: JsonObject;
564
- cache?: PrepareIosRunnerCacheKind;
565
- artifact?: PrepareIosRunnerArtifactState;
566
- buildMs?: number;
567
- connectMs: number;
568
- healthCheckMs: number;
569
- xctestrunPath?: string;
570
- recoveryReason?: string;
571
- failureReason?: string;
572
- timing: PrepareIosRunnerTiming;
573
- message: string;
372
+ type PanOptions = DeviceCommandBaseOptions & {
373
+ x: number;
374
+ y: number;
375
+ dx: number;
376
+ dy: number;
377
+ pointerCount?: GesturePointerCount;
378
+ durationMs?: number;
574
379
  };
575
- //#endregion
576
- //#region src/contracts/push.d.ts
577
- type PushCommandResult = {
578
- platform: 'ios';
579
- bundleId: string;
580
- message: string;
581
- } | {
582
- platform: 'android';
583
- package: string;
584
- action: string;
585
- extrasCount: number;
586
- message: string;
380
+ type FlingOptions = DeviceCommandBaseOptions & {
381
+ direction: ScrollDirection;
382
+ x: number;
383
+ y: number;
384
+ distance?: number;
587
385
  };
588
- //#endregion
589
- //#region src/contracts/app-events.d.ts
590
- type TriggerAppEventCommandResult = {
591
- event: string;
592
- eventUrl: string;
593
- transport: 'deep-link';
594
- message: string;
386
+ type SwipeGestureOptions = DeviceCommandBaseOptions & {
387
+ preset: SwipePreset;
595
388
  };
596
- //#endregion
597
- //#region src/contracts/doctor.d.ts
598
- type DoctorStatus = 'pass' | 'warn' | 'fail' | 'info';
599
- type DoctorKind = 'auto' | 'react-native' | 'expo' | 'repack';
600
- type DoctorCheck = {
601
- id: string;
602
- status: DoctorStatus;
603
- summary: string;
604
- hint?: string;
605
- command?: string;
606
- evidence?: Record<string, unknown>;
389
+ type FocusOptions = DeviceCommandBaseOptions & {
390
+ x: number;
391
+ y: number;
607
392
  };
608
- type DoctorCommandResult = {
609
- status: DoctorStatus;
610
- summary: string;
611
- kind: DoctorKind;
612
- platform?: PlatformSelector;
613
- target?: DeviceTarget;
614
- targetApp?: string;
615
- metro?: {
616
- host: string;
617
- port: number;
618
- };
619
- checks: DoctorCheck[];
393
+ type TypeTextOptions = DeviceCommandBaseOptions & {
394
+ text: string;
395
+ delayMs?: number;
620
396
  };
621
- //#endregion
622
- //#region src/snapshot/snapshot-diff.d.ts
623
- type SnapshotDiffLine = {
624
- kind: 'added' | 'removed' | 'unchanged';
397
+ type FillOptions = DeviceCommandBaseOptions & SelectorSnapshotCommandOptions & InteractionTarget & SettleCommandOptions & {
625
398
  text: string;
626
- /**
627
- * Plain ref body (`e12`) of the CURRENT-tree node behind an added line.
628
- * Only populated with `withRefs` (interaction `--settle`, #1101) so the
629
- * `diff` command's wire shape stays byte-identical. Removed/unchanged lines
630
- * never carry it: a removed line's ref names a node of the replaced tree.
631
- */
632
- ref?: string;
399
+ delayMs?: number;
400
+ /** Publish this fill value as `${VAR}` when script recording is armed. */
401
+ recordAs?: string;
402
+ verify?: boolean;
633
403
  };
634
- type SnapshotDiffSummary = {
635
- additions: number;
636
- removals: number;
637
- unchanged: number;
404
+ type PinchOptions = DeviceCommandBaseOptions & {
405
+ scale: number;
406
+ x?: number;
407
+ y?: number;
638
408
  };
639
- //#endregion
640
- //#region src/contracts/diff.d.ts
641
- type DiffSnapshotCommandResult = {
642
- mode: 'snapshot';
643
- baselineInitialized: boolean;
644
- summary: SnapshotDiffSummary;
645
- lines: SnapshotDiffLine[];
646
- warnings?: string[];
409
+ type RotateGestureOptions = DeviceCommandBaseOptions & {
410
+ degrees: number;
411
+ x?: number;
412
+ y?: number;
413
+ };
414
+ type TransformGestureOptions = DeviceCommandBaseOptions & TransformGestureParams;
415
+ type ScrollOptions = DeviceCommandBaseOptions & {
416
+ direction: ScrollInputDirection;
417
+ amount?: number;
418
+ pixels?: number;
419
+ durationMs?: number;
647
420
  };
648
421
  //#endregion
649
- //#region src/contracts/recording.d.ts
650
- type RecordingAppIdentity = {
651
- bundleId: string;
652
- name?: string;
422
+ //#region src/contracts/client-lease.d.ts
423
+ type Lease = {
424
+ leaseId: string;
425
+ tenantId: string;
426
+ runId: string;
427
+ backend: LeaseBackend;
428
+ leaseProvider?: string;
429
+ deviceKey?: string;
430
+ clientId?: string;
431
+ createdAt?: number;
432
+ heartbeatAt?: number;
433
+ expiresAt?: number;
653
434
  };
654
- type RecordingStartCommandResult = {
655
- recording: 'started';
656
- outPath: string;
657
- sessionStateDir: string;
658
- recordingBackend?: string;
659
- recordingScope?: RecordingScope;
660
- recordOnlySession?: boolean;
661
- activeSessionApp?: RecordingAppIdentity;
662
- showTouches: boolean;
435
+ type LeaseOptions = AgentDeviceRequestOverrides & AgentDeviceSelectionOptions & {
436
+ ttlMs?: number;
663
437
  };
664
- type RecordingStopCommandResult = {
665
- recording: 'stopped';
666
- outPath: string;
667
- telemetryPath?: string;
668
- artifacts: DaemonArtifact[];
669
- recordingBackend?: string;
670
- recordingScope?: RecordingScope;
671
- recordOnlySession?: boolean;
672
- activeSessionApp?: RecordingAppIdentity;
673
- durationMs: number;
674
- showTouches: boolean;
675
- warning?: string;
676
- overlayWarning?: string;
677
- chunks?: Array<{
678
- index: number;
679
- path: string;
680
- }>;
438
+ type LeaseAllocateOptions = LeaseOptions & {
439
+ tenant: string;
440
+ runId: string;
441
+ leaseBackend?: LeaseBackend;
442
+ leaseProvider?: string;
443
+ provider?: string;
444
+ deviceKey?: string;
445
+ clientId?: string;
681
446
  };
682
- type RecordingCommandResult = RecordingStartCommandResult | RecordingStopCommandResult;
683
- type TraceCommandResult = {
684
- trace: 'started';
685
- outPath: string;
686
- } | {
687
- trace: 'stopped';
688
- outPath: string;
447
+ type LeaseScopedOptions = LeaseOptions & {
448
+ tenant?: string;
449
+ runId?: string;
450
+ leaseId: string;
451
+ leaseBackend?: LeaseBackend;
452
+ leaseProvider?: string;
453
+ provider?: string;
454
+ deviceKey?: string;
455
+ clientId?: string;
456
+ };
457
+ type CloudArtifactsOptions = AgentDeviceRequestOverrides & {
458
+ provider?: string;
459
+ providerSessionId?: string;
689
460
  };
690
461
  //#endregion
691
- //#region src/contracts/replay.d.ts
692
- type ReplayCommandResult = {
693
- replayed: number;
694
- healed: number;
695
- session: string;
696
- /**
697
- * True iff `session` still exists in the daemon's session store when the
698
- * response is built — i.e. the replayed script had no terminal `close`
699
- * (ADR 0016's consumption contract). The client uses this, not script
700
- * parsing, to decide whether an owned one-shot daemon must stay alive so
701
- * the caller can keep addressing this session.
702
- */
703
- sessionActive: boolean;
704
- artifactPaths: string[];
705
- warnings?: string[];
706
- snapshotDiagnostics?: SnapshotDiagnosticsSummary;
707
- message: string;
462
+ //#region src/contracts/logs.d.ts
463
+ declare const LOG_ACTION_VALUES: readonly ['path', 'start', 'stop', 'doctor', 'mark', 'clear'];
464
+ type LogAction = (typeof LOG_ACTION_VALUES)[number];
465
+ //#endregion
466
+ //#region src/contracts/perf.d.ts
467
+ declare const PERF_AREA_VALUES: readonly ['metrics', 'frames', 'memory', 'cpu', 'trace'];
468
+ declare const PERF_ACTION_VALUES: readonly ['sample', 'snapshot', 'start', 'stop', 'report'];
469
+ declare const PERF_SUBJECT_VALUES: readonly ['profile'];
470
+ declare const PERF_KIND_VALUES: readonly ['xctrace', 'simpleperf', 'perfetto', 'android-hprof', 'memgraph'];
471
+ type PerfArea = (typeof PERF_AREA_VALUES)[number];
472
+ type PerfAction = (typeof PERF_ACTION_VALUES)[number];
473
+ type PerfSubject = (typeof PERF_SUBJECT_VALUES)[number];
474
+ type PerfKind = (typeof PERF_KIND_VALUES)[number];
475
+ //#endregion
476
+ //#region src/contracts/recording-scope.d.ts
477
+ declare const RECORDING_SCOPE_VALUES: readonly ['app', 'device', 'system'];
478
+ type RecordingScope = (typeof RECORDING_SCOPE_VALUES)[number];
479
+ //#endregion
480
+ //#region src/contracts/client-observability.d.ts
481
+ type PerfOptions = DeviceCommandBaseOptions & {
482
+ area?: PerfArea;
483
+ subject?: PerfSubject;
484
+ action?: PerfAction;
485
+ kind?: PerfKind;
486
+ template?: string;
487
+ out?: string;
488
+ tracePath?: string;
708
489
  };
709
- type ReplaySuiteTestSkipReason = 'skipped-by-filter';
710
- type ReplaySuiteAttemptFailure = {
711
- attempt: number;
712
- message: string;
713
- durationMs?: number;
490
+ type LogsOptions = AgentDeviceRequestOverrides & {
491
+ action?: LogAction;
492
+ message?: string;
493
+ restart?: boolean;
714
494
  };
715
- type ReplaySuiteTestPassed = {
716
- file: string;
717
- title?: string;
718
- session: string;
719
- status: 'passed';
720
- durationMs: number;
721
- finalAttemptDurationMs?: number;
722
- attempts: number;
723
- artifactsDir?: string;
724
- replayed: number;
725
- healed: number;
726
- warnings?: string[];
727
- attemptFailures?: ReplaySuiteAttemptFailure[];
728
- shardIndex?: number;
729
- shardCount?: number;
730
- deviceId?: string;
731
- deviceName?: string;
732
- snapshotDiagnostics?: SnapshotDiagnosticsSummary;
495
+ type EventsOptions = AgentDeviceRequestOverrides & {
496
+ cursor?: string;
497
+ limit?: number;
733
498
  };
734
- type ReplaySuiteTestFailed = {
735
- file: string;
736
- title?: string;
737
- session: string;
738
- status: 'failed';
739
- durationMs: number;
740
- attempts: number;
741
- artifactsDir?: string;
742
- error: DaemonError;
743
- shardIndex?: number;
744
- shardCount?: number;
745
- deviceId?: string;
746
- deviceName?: string;
747
- snapshotDiagnostics?: SnapshotDiagnosticsSummary;
499
+ type NetworkOptions = DeviceCommandBaseOptions & {
500
+ action?: 'dump' | 'log';
501
+ limit?: number;
502
+ include?: NetworkIncludeMode;
748
503
  };
749
- type ReplaySuiteTestSkipped = {
750
- file: string;
751
- title?: string;
752
- status: 'skipped';
753
- durationMs: 0;
754
- reason: ReplaySuiteTestSkipReason;
755
- message: string;
504
+ type AudioOptions = DeviceCommandBaseOptions & {
505
+ action?: 'probe';
506
+ probeAction?: 'start' | 'status' | 'stop';
507
+ durationMs?: number;
508
+ bucketMs?: number;
756
509
  };
757
- type ReplaySuiteTestResult = ReplaySuiteTestPassed | ReplaySuiteTestFailed | ReplaySuiteTestSkipped;
758
- type ReplaySuiteResult = {
759
- total: number;
760
- executed: number;
761
- passed: number;
762
- failed: number;
763
- skipped: number;
764
- notRun: number;
765
- durationMs: number;
766
- failures: ReplaySuiteTestFailed[];
767
- tests: ReplaySuiteTestResult[];
768
- snapshotDiagnostics?: SnapshotDiagnosticsSummary;
510
+ type RecordOptions = AgentDeviceRequestOverrides & {
511
+ action: 'start' | 'stop';
512
+ path?: string;
513
+ fps?: number;
514
+ maxSize?: number;
515
+ quality?: RecordingExportQuality;
516
+ hideTouches?: boolean;
517
+ recordingScope?: RecordingScope;
518
+ };
519
+ type TraceOptions = AgentDeviceRequestOverrides & {
520
+ action: 'start' | 'stop';
521
+ path?: string;
769
522
  };
770
523
  //#endregion
771
- //#region src/core/command-descriptor/command-result.d.ts
772
- /**
773
- * The additive typed-result spine (ADR-0008, Phase 1 step 6).
774
- *
775
- * Maps a command name to the per-command result type from `src/contracts/*`. It
776
- * is SEEDED, not exhaustive: a command is listed here only once its accurate,
777
- * closed result shape lives in the contracts layer. Commands whose daemon
778
- * handler spreads dynamic/Record data (screenshot overlays, gesture
779
- * visualization, perf, logs, …) are deliberately omitted rather than given an
780
- * invented shape.
781
- *
782
- * Batches 1-2 wired `boot` / `shutdown` / `viewport` and the navigation/action
783
- * commands `home` / `back` / `orientation` / `app-switcher` alongside the seed
784
- * interaction quartet. Batch 3 adds `clipboard` (a closed `read`/`write` union) and
785
- * `appstate` (a closed `platform` union — Apple session state with the iOS-only
786
- * device locators, or Android package/activity). Batch 4 adds `keyboard` (a
787
- * closed flat shape). Batch 5 adds the compact daemon projections for `wait`,
788
- * `prepare`, `push`, and `trigger-app-event`. Each entry is grounded in a
789
- * re-read of the handler's literal return; see the per-type docstrings.
790
- */
791
- interface CommandResultMap {
792
- press: PressCommandResponseData;
793
- click: ClickCommandResponseData;
794
- fill: FillCommandResponseData;
795
- longpress: LongPressCommandResponseData;
796
- find: FindCommandResponseData;
797
- boot: BootCommandResult;
798
- shutdown: ShutdownCommandResult;
799
- viewport: ViewportCommandResult;
800
- home: HomeCommandResult;
801
- back: BackCommandResult;
802
- orientation: OrientationCommandResult;
803
- 'app-switcher': AppSwitcherCommandResult;
804
- clipboard: ClipboardCommandResult;
805
- appstate: AppStateCommandResult;
806
- keyboard: KeyboardCommandResult;
807
- 'tv-remote': TvRemoteCommandResult;
808
- wait: WaitCommandResult;
809
- prepare: PrepareCommandResult;
810
- push: PushCommandResult;
811
- 'trigger-app-event': TriggerAppEventCommandResult;
812
- doctor: DoctorCommandResult;
813
- diff: DiffSnapshotCommandResult;
814
- replay: ReplayCommandResult;
815
- test: ReplaySuiteResult;
816
- record: RecordingCommandResult;
817
- trace: TraceCommandResult;
818
- }
819
- /**
820
- * The typed result for a command named `N`. Seeded commands resolve to their
821
- * contract result type from {@link CommandResultMap}; every other (unmigrated)
822
- * command falls back to the untyped `Record<string, unknown>` bag. That default
823
- * branch is what keeps the mapping total over every command name, so consumers
824
- * can switch to `CommandResult<Name>` without first migrating every command.
825
- */
826
- type CommandResult<N extends string> = N extends keyof CommandResultMap ? CommandResultMap[N] : Record<string, unknown>;
827
- //#endregion
828
- //#region src/contracts/cloud-artifacts.d.ts
829
- declare const CLOUD_ARTIFACT_KINDS: readonly ['video', 'appium-log', 'device-log', 'automation-log', 'provider-session', 'raw'];
830
- type CloudArtifactKind = (typeof CLOUD_ARTIFACT_KINDS)[number];
831
- type CloudArtifactAvailability = 'ready' | 'pending' | 'unavailable' | 'expired';
832
- type CloudArtifact = {
833
- provider: string;
834
- kind: CloudArtifactKind;
835
- name: string;
836
- url?: string;
837
- providerSessionId?: string;
838
- providerArtifactId?: string;
839
- contentType?: string;
840
- extension?: string;
841
- availability?: CloudArtifactAvailability;
842
- metadata?: Record<string, unknown>;
843
- };
844
- type CloudArtifactsStatus = 'ready' | 'pending' | 'unavailable';
845
- type CloudArtifactsResult = {
846
- provider: string;
847
- status: CloudArtifactsStatus;
848
- cloudArtifacts: CloudArtifact[];
849
- providerSessionId?: string;
850
- message?: string;
851
- };
852
- type DaemonArtifactInventoryEntry = {
853
- id: string;
854
- artifactType?: DaemonArtifactType;
855
- filename: string;
856
- mimeType: string;
857
- sizeBytes: number;
858
- createdAt: string;
859
- expiresAt: string;
860
- };
861
- type DaemonArtifactsResult = {
862
- source: 'daemon';
863
- status: 'ready';
864
- artifacts: DaemonArtifactInventoryEntry[];
865
- message?: string;
524
+ //#region src/contracts/client-replay.d.ts
525
+ type ReplayRunOptions = AgentDeviceRequestOverrides & AgentDeviceSelectionOptions & {
526
+ path: string;
527
+ runtime?: SessionRuntimeHints;
528
+ /**
529
+ * @deprecated ADR 0012 migration step 6: `--update` no longer rewrites
530
+ * the script. Accepted for backward compatibility; every divergence
531
+ * already carries ranked selector suggestions regardless of this flag.
532
+ */
533
+ update?: boolean;
534
+ /** @deprecated Use backend: 'maestro'. */
535
+ maestro?: boolean;
536
+ backend?: string;
537
+ env?: string[];
538
+ timeoutMs?: number;
539
+ /**
540
+ * ADR 0012 decision 4 / migration step 5: resume at this 1-based plan
541
+ * step, skipping `1..resumeFrom-1` without executing them. Requires
542
+ * `resumePlanDigest` from the divergence report that reported this
543
+ * step as the failure. `replay` only — `test` has no resume fields.
544
+ */
545
+ resumeFrom?: number;
546
+ /** The `resume.planDigest` from the divergence report `resumeFrom` came from. */
547
+ resumePlanDigest?: string;
548
+ /**
549
+ * ADR 0012 decision 6, R1/R6: arms agent-supervised re-record repair
550
+ * from this replay attempt onward. Optional string value is the healed
551
+ * `.ad`'s output path; absent one, it defaults to the `<path>` sibling
552
+ * `<stem>.healed.ad` when the repair ends with `close --save-script`.
553
+ */
554
+ saveScript?: boolean | string;
555
+ /** #1258: overwrite an existing --save-script target instead of refusing. Alias: --overwrite. */
556
+ force?: boolean;
866
557
  };
867
- type AgentArtifactsResult = CloudArtifactsResult | DaemonArtifactsResult;
868
- type CloudProviderSessionResult = {
869
- provider?: string;
870
- providerSessionId?: string;
871
- cloudArtifacts?: CloudArtifactsResult;
872
- } & Record<string, unknown>;
873
- //#endregion
874
- //#region src/client/client-types.d.ts
875
- type AgentDeviceDaemonTransport = (req: Omit<DaemonRequest, 'token'>) => Promise<DaemonResponse>;
876
- type AgentDeviceClientConfig = RemoteConnectionProfileFields & CloudProviderProfileFields & {
877
- session?: string;
878
- lockPolicy?: DaemonLockPolicy;
879
- lockPlatform?: PlatformSelector;
880
- requestId?: string;
881
- sessionIsolation?: SessionIsolationMode;
882
- leaseBackend?: LeaseBackend;
883
- leaseTtlMs?: number;
558
+ type ReplayTestOptions = AgentDeviceRequestOverrides & AgentDeviceSelectionOptions & {
559
+ paths: string[];
884
560
  runtime?: SessionRuntimeHints;
885
- cwd?: string;
886
- debug?: boolean;
887
- cost?: boolean;
888
- responseLevel?: ResponseLevel;
889
- iosXctestrunFile?: string;
890
- iosXctestDerivedDataPath?: string;
891
- iosXctestEnvDir?: string;
561
+ update?: boolean;
562
+ /** @deprecated Use backend: 'maestro'. */
563
+ maestro?: boolean;
564
+ backend?: string;
565
+ env?: string[];
566
+ failFast?: boolean;
567
+ timeoutMs?: number;
568
+ retries?: number;
569
+ recordVideo?: boolean;
570
+ artifactsDir?: string;
571
+ /** @deprecated Use the CLI --reporter junit:<path> or --report-junit <path>. */
572
+ reportJunit?: string;
573
+ shardAll?: number;
574
+ shardSplit?: number;
892
575
  };
893
- type AgentDeviceRequestOverrides = Pick<AgentDeviceClientConfig, 'session' | 'lockPolicy' | 'lockPlatform' | 'requestId' | 'daemonBaseUrl' | 'daemonAuthToken' | 'daemonTransport' | 'daemonServerMode' | 'tenant' | 'sessionIsolation' | 'runId' | 'leaseId' | 'leaseBackend' | 'leaseProvider' | 'deviceKey' | 'clientId' | 'providerApp' | 'providerOsVersion' | 'providerProject' | 'providerBuild' | 'providerSessionName' | 'awsProjectArn' | 'awsDeviceArn' | 'awsAppArn' | 'awsRegion' | 'awsInteractionMode' | 'leaseTtlMs' | 'cwd' | 'debug' | 'cost' | 'responseLevel' | 'iosXctestrunFile' | 'iosXctestDerivedDataPath' | 'iosXctestEnvDir'>;
894
- type AgentDeviceIdentifiers = {
895
- session?: string;
896
- deviceId?: string;
897
- deviceName?: string;
898
- udid?: string;
899
- serial?: string;
900
- appId?: string;
901
- appBundleId?: string;
902
- package?: string;
576
+ type BatchStep = {
577
+ command: string;
578
+ input: Record<string, unknown>;
579
+ runtime?: SessionRuntimeHints;
903
580
  };
904
- type AgentDeviceSelectionOptions = {
905
- platform?: PlatformSelector;
906
- target?: DeviceTarget;
907
- device?: string;
908
- udid?: string;
909
- serial?: string;
910
- iosSimulatorDeviceSet?: string;
911
- androidDeviceAllowlist?: string;
581
+ type BatchRunOptions = AgentDeviceRequestOverrides & {
582
+ steps: BatchStep[];
583
+ onError?: 'stop';
584
+ maxSteps?: number;
585
+ out?: string;
912
586
  };
913
- type AgentDeviceDevice = {
914
- platform: PublicPlatform;
915
- target: DeviceTarget;
916
- kind: DeviceKind;
917
- id: string;
918
- name: string;
919
- booted?: boolean;
920
- /**
921
- * Additive Apple-OS discriminant (iPhone/iPad/tvOS/visionOS/macOS). Present only for
922
- * Apple devices; `platform` still carries the leaf (`ios`/`macos`).
923
- */
924
- appleOs?: AppleOS;
925
- identifiers: AgentDeviceIdentifiers;
926
- ios?: {
927
- udid: string;
928
- };
929
- android?: {
930
- serial: string;
931
- };
932
- vega?: {
933
- serial: string;
934
- };
587
+ //#endregion
588
+ //#region src/contracts/client-request.d.ts
589
+ type CommandRequestResult = DaemonResponseData;
590
+ //#endregion
591
+ //#region src/contracts/client-selector-read.d.ts
592
+ /**
593
+ * #1271 stage 2 (ADR 0012 amendment): `get`/`is`/`find` are observation-only
594
+ * and excluded from a repair-armed heal by default. `record` forces this
595
+ * action through (the corrective-read case); `noRecord` continues to opt the
596
+ * action out entirely. Mutually exclusive.
597
+ */
598
+ type RecordControlOptions = {
599
+ noRecord?: boolean;
600
+ record?: boolean;
935
601
  };
936
- type AgentDeviceCapabilitiesResult = {
937
- device: AgentDeviceDevice;
938
- availableCommands: string[];
602
+ type GetOptions = DeviceCommandBaseOptions & SelectorSnapshotCommandOptions & ElementTarget & RecordControlOptions & {
603
+ format: 'text' | 'attrs';
939
604
  };
940
- type AgentDeviceSessionDevice = {
941
- platform: PublicPlatform;
942
- target: DeviceTarget;
943
- id: string;
944
- name: string;
945
- /**
946
- * Additive Apple-OS discriminant (iPhone/iPad/tvOS/visionOS/macOS). Present only for
947
- * Apple devices; `platform` still carries the leaf (`ios`/`macos`).
948
- */
949
- appleOs?: AppleOS;
950
- identifiers: AgentDeviceIdentifiers;
951
- ios?: {
952
- udid: string;
953
- simulatorSetPath?: string | null;
954
- };
955
- android?: {
956
- serial: string;
957
- };
958
- vega?: {
959
- serial: string;
960
- };
605
+ type IsTextPredicateOptions = DeviceCommandBaseOptions & SelectorSnapshotCommandOptions & RecordControlOptions & {
606
+ predicate: 'text';
607
+ selector: string;
608
+ value: string;
961
609
  };
962
- type AgentDeviceSession = {
963
- name: string;
964
- createdAt: number;
965
- sessionStateDir?: string;
966
- runnerLogPath?: string;
967
- device: AgentDeviceSessionDevice;
968
- identifiers: AgentDeviceIdentifiers;
610
+ type IsStatePredicateOptions = DeviceCommandBaseOptions & SelectorSnapshotCommandOptions & RecordControlOptions & {
611
+ predicate: 'visible' | 'hidden' | 'exists' | 'editable' | 'selected' | 'focused';
612
+ selector: string;
613
+ value?: never;
969
614
  };
970
- type StartupPerfSample = {
971
- durationMs: number;
972
- measuredAt: string;
973
- method: string;
974
- appTarget?: string;
975
- appBundleId?: string;
615
+ type IsOptions = IsTextPredicateOptions | IsStatePredicateOptions;
616
+ type FindBaseOptions = DeviceCommandBaseOptions & FindSnapshotCommandOptions & RecordControlOptions & {
617
+ locator?: FindLocator;
618
+ query: string;
619
+ first?: boolean;
620
+ last?: boolean;
976
621
  };
622
+ type FindOptions = (FindBaseOptions & {
623
+ action?: 'click' | 'focus' | 'exists' | 'getText' | 'getAttrs';
624
+ }) | (FindBaseOptions & {
625
+ action: 'wait';
626
+ timeoutMs?: number;
627
+ }) | (FindBaseOptions & {
628
+ action: 'fill' | 'type';
629
+ value: string;
630
+ });
631
+ //#endregion
632
+ //#region src/contracts/client-session.d.ts
977
633
  type SessionCloseResult = {
978
634
  session: string;
979
635
  shutdown?: TargetShutdownResult;
@@ -997,222 +653,41 @@ type SessionSaveScriptResult = {
997
653
  actionCount: number;
998
654
  identifiers: AgentDeviceIdentifiers;
999
655
  };
1000
- type CloudArtifactsOptions = AgentDeviceRequestOverrides & {
1001
- provider?: string;
1002
- providerSessionId?: string;
1003
- };
1004
- type AppInstallOptions = AgentDeviceRequestOverrides & AgentDeviceSelectionOptions & {
1005
- app?: string;
1006
- appPath: string;
1007
- };
1008
- type AppDeployOptions = AgentDeviceRequestOverrides & AgentDeviceSelectionOptions & {
1009
- app: string;
1010
- appPath: string;
1011
- };
1012
- type AppDeployResult = {
1013
- app: string;
1014
- appPath: string;
1015
- platform: PublicPlatform;
1016
- appId?: string;
1017
- bundleId?: string;
1018
- package?: string;
1019
- identifiers: AgentDeviceIdentifiers;
1020
- };
1021
- type AppOpenOptions = AgentDeviceRequestOverrides & AgentDeviceSelectionOptions & {
656
+ //#endregion
657
+ //#region src/contracts/client-settings.d.ts
658
+ type PermissionTarget = 'camera' | 'microphone' | 'photos' | 'contacts' | 'contacts-limited' | 'notifications' | 'calendar' | 'location' | 'location-always' | 'media-library' | 'motion' | 'reminders' | 'siri' | 'accessibility' | 'screen-recording' | 'input-monitoring';
659
+ type SettingsUpdateOptions = (DeviceCommandBaseOptions & {
660
+ setting: 'clear-app-state';
661
+ state: 'clear';
1022
662
  app?: string;
1023
- url?: string;
1024
- surface?: SessionSurface;
1025
- activity?: string;
1026
- launchConsole?: string;
1027
- launchArgs?: string[];
1028
- relaunch?: boolean;
1029
- saveScript?: boolean | string;
1030
- /** #1258: overwrite an existing --save-script target instead of refusing. Alias: --overwrite. */
1031
- force?: boolean;
1032
- deviceHub?: boolean;
1033
- testIme?: boolean;
1034
- noRecord?: boolean;
1035
- runtime?: SessionRuntimeHints;
1036
- };
1037
- type AppOpenResult = {
1038
- session: string;
1039
- warnings?: string[];
1040
- sessionStateDir?: string;
1041
- runnerLogPath?: string;
1042
- requestLogPath?: string;
1043
- eventLogPath?: string;
1044
- appName?: string;
1045
- appBundleId?: string;
1046
- appId?: string;
1047
- startup?: StartupPerfSample;
1048
- runtime?: SessionRuntimeHints;
1049
- device?: AgentDeviceSessionDevice;
1050
- identifiers: AgentDeviceIdentifiers;
1051
- };
1052
- type AppCloseOptions = AgentDeviceRequestOverrides & {
1053
- app?: string;
1054
- shutdown?: boolean;
1055
- saveScript?: boolean | string;
1056
- /** #1258: overwrite an existing --save-script target instead of refusing. Alias: --overwrite. */
1057
- force?: boolean;
1058
- };
1059
- type AppCloseResult = {
1060
- session: string;
1061
- closedApp?: string;
1062
- shutdown?: TargetShutdownResult;
1063
- /**
1064
- * #1258: absolute path of the committed session/healed script when this close
1065
- * published one (`close --save-script`, or a repair-armed session's finalize)
1066
- * — so a client that requested publication learns where the file landed.
1067
- */
1068
- savedScript?: string;
1069
- identifiers: AgentDeviceIdentifiers;
1070
- };
1071
- type AppInstallFromSourceOptions = AgentDeviceRequestOverrides & AgentDeviceSelectionOptions & {
1072
- source: DaemonInstallSource;
1073
- retainPaths?: boolean;
1074
- retentionMs?: number;
1075
- };
1076
- type AppInstallFromSourceResult = {
1077
- appName?: string;
1078
- appId?: string;
1079
- bundleId?: string;
1080
- packageName?: string;
1081
- launchTarget: string;
1082
- installablePath?: string;
1083
- archivePath?: string;
1084
- materializationId?: string;
1085
- materializationExpiresAt?: string;
1086
- identifiers: AgentDeviceIdentifiers;
1087
- };
1088
- type AppListOptions = AgentDeviceRequestOverrides & AgentDeviceSelectionOptions & {
1089
- appsFilter?: AppsFilter;
1090
- };
1091
- type MaterializationReleaseOptions = AgentDeviceRequestOverrides & {
1092
- materializationId: string;
1093
- };
1094
- type MaterializationReleaseResult = {
1095
- released: boolean;
1096
- materializationId: string;
1097
- identifiers: AgentDeviceIdentifiers;
1098
- };
1099
- type Lease = {
1100
- leaseId: string;
1101
- tenantId: string;
1102
- runId: string;
1103
- backend: LeaseBackend;
1104
- leaseProvider?: string;
1105
- deviceKey?: string;
1106
- clientId?: string;
1107
- createdAt?: number;
1108
- heartbeatAt?: number;
1109
- expiresAt?: number;
1110
- };
1111
- type LeaseOptions = AgentDeviceRequestOverrides & AgentDeviceSelectionOptions & {
1112
- ttlMs?: number;
1113
- };
1114
- type LeaseAllocateOptions = LeaseOptions & {
1115
- tenant: string;
1116
- runId: string;
1117
- leaseBackend?: LeaseBackend;
1118
- leaseProvider?: string;
1119
- provider?: string;
1120
- deviceKey?: string;
1121
- clientId?: string;
1122
- };
1123
- type LeaseScopedOptions = LeaseOptions & {
1124
- tenant?: string;
1125
- runId?: string;
1126
- leaseId: string;
1127
- leaseBackend?: LeaseBackend;
1128
- leaseProvider?: string;
1129
- provider?: string;
1130
- deviceKey?: string;
1131
- clientId?: string;
1132
- };
1133
- type MetroPrepareOptions = {
1134
- projectRoot?: string;
1135
- kind?: MetroPrepareKind;
1136
- publicBaseUrl?: string;
1137
- proxyBaseUrl?: string;
1138
- bearerToken?: string;
1139
- bridgeScope?: MetroBridgeScope;
1140
- launchUrl?: string;
1141
- companionProfileKey?: string;
1142
- companionConsumerKey?: string;
1143
- port?: number;
1144
- listenHost?: string;
1145
- statusHost?: string;
1146
- startupTimeoutMs?: number;
1147
- probeTimeoutMs?: number;
1148
- reuseExisting?: boolean;
1149
- installDependenciesIfNeeded?: boolean;
1150
- runtimeFilePath?: string;
1151
- logPath?: string;
1152
- };
1153
- type MetroPrepareResult = PrepareMetroRuntimeResult;
1154
- type MetroReloadOptions = {
1155
- metroHost?: string;
1156
- metroPort?: number;
1157
- bundleUrl?: string;
1158
- timeoutMs?: number;
1159
- };
1160
- type MetroReloadResult = ReloadMetroResult;
1161
- type CaptureSnapshotOptions = AgentDeviceRequestOverrides & AgentDeviceSelectionOptions & {
1162
- interactiveOnly?: boolean;
1163
- depth?: number;
1164
- scope?: string;
1165
- raw?: boolean;
1166
- forceFull?: boolean;
1167
- timeoutMs?: number;
1168
- /**
1169
- * #1271 stage 2 (ADR 0012 amendment): `snapshot` is observation-only and
1170
- * excluded from a repair-armed heal by default; `record` forces it
1171
- * through. Mutually exclusive with `noRecord`.
1172
- */
1173
- noRecord?: boolean;
1174
- record?: boolean;
1175
- };
1176
- type CaptureSnapshotResult = {
1177
- nodes: SnapshotNode[];
1178
- truncated: boolean;
1179
- appName?: string;
1180
- appBundleId?: string;
1181
- visibility?: SnapshotVisibility;
1182
- unchanged?: SnapshotUnchanged;
1183
- snapshotDiagnostics?: SnapshotDiagnosticsSummary;
1184
- identifiers: AgentDeviceIdentifiers;
1185
- /**
1186
- * ADR 0014: the response-level ref-frame epoch the plain node refs were minted
1187
- * from. A ref-issuing snapshot carries it ONCE (nodes stay plain `@e12` for the
1188
- * token budget); pair a ref with it (`@e12~s<refsGeneration>`) before a mutation.
1189
- */
1190
- refsGeneration?: number;
1191
- /**
1192
- * Digest response view only: a capped list of `{ ref, label? }` pairs taken
1193
- * from the full `nodes` tree so the MCP layer can still pin refs when the
1194
- * default-level `nodes` payload is intentionally omitted.
1195
- */
1196
- refs?: Array<{
1197
- ref: string;
1198
- label?: string;
1199
- }>;
1200
- } & PublicSnapshotCaptureAnnotations;
1201
- type CaptureScreenshotOptions = AgentDeviceRequestOverrides & {
1202
- path?: string;
1203
- overlayRefs?: boolean;
1204
- pixelDensity?: number;
1205
- fullscreen?: boolean;
1206
- maxSize?: number;
1207
- stabilize?: boolean;
1208
- normalizeStatusBar?: boolean;
1209
- surface?: SessionSurface;
1210
- };
1211
- type CaptureScreenshotResult = ScreenshotResultData & {
1212
- path: string;
1213
- identifiers: AgentDeviceIdentifiers;
1214
- };
1215
- type DeviceCommandBaseOptions = AgentDeviceRequestOverrides & AgentDeviceSelectionOptions;
663
+ }) | (DeviceCommandBaseOptions & {
664
+ setting: 'wifi' | 'airplane' | 'location';
665
+ state: 'on' | 'off';
666
+ }) | (DeviceCommandBaseOptions & {
667
+ setting: 'location';
668
+ state: 'set';
669
+ latitude: number;
670
+ longitude: number;
671
+ }) | (DeviceCommandBaseOptions & {
672
+ setting: 'animations';
673
+ state: 'on' | 'off';
674
+ }) | (DeviceCommandBaseOptions & {
675
+ setting: 'appearance';
676
+ state: 'light' | 'dark' | 'toggle';
677
+ }) | (DeviceCommandBaseOptions & {
678
+ setting: 'faceid' | 'touchid';
679
+ state: 'match' | 'nonmatch' | 'enroll' | 'unenroll';
680
+ }) | (DeviceCommandBaseOptions & {
681
+ setting: 'fingerprint';
682
+ state: 'match' | 'nonmatch';
683
+ }) | (DeviceCommandBaseOptions & {
684
+ setting: 'permission';
685
+ state: 'grant' | 'deny' | 'reset';
686
+ permission: PermissionTarget;
687
+ mode?: 'full' | 'limited';
688
+ });
689
+ //#endregion
690
+ //#region src/contracts/client-system.d.ts
1216
691
  type WaitCommandTarget = {
1217
692
  durationMs: number;
1218
693
  text?: never;
@@ -1260,9 +735,6 @@ type AlertCommandOptions = DeviceCommandBaseOptions & {
1260
735
  timeoutMs?: number;
1261
736
  };
1262
737
  type AppStateCommandOptions = DeviceCommandBaseOptions;
1263
- type OrientationCommandOptions = DeviceCommandBaseOptions & NavigationCommandOptions<'orientation'>;
1264
- /** @deprecated Renamed to `OrientationCommandOptions`. Retained until the next major. */
1265
- type RotateCommandOptions = OrientationCommandOptions;
1266
738
  type KeyboardCommandOptions = DeviceCommandBaseOptions & {
1267
739
  action?: 'status' | 'dismiss' | 'enter' | 'return';
1268
740
  };
@@ -1287,343 +759,632 @@ type ViewportCommandOptions = DeviceCommandBaseOptions & {
1287
759
  width: number;
1288
760
  height: number;
1289
761
  };
1290
- type NonNavigationCommandClient = {
1291
- wait: (options: WaitCommandOptions) => Promise<CommandResult<'wait'>>;
1292
- alert: (options?: AlertCommandOptions) => Promise<CommandRequestResult>;
1293
- appState: (options?: AppStateCommandOptions) => Promise<CommandResult<'appstate'>>;
1294
- keyboard: (options?: KeyboardCommandOptions) => Promise<CommandResult<'keyboard'>>;
1295
- clipboard: (options: ClipboardCommandOptions) => Promise<CommandResult<'clipboard'>>;
1296
- reactNative: (options: ReactNativeCommandOptions) => Promise<CommandRequestResult>;
1297
- doctor: (options?: DoctorCommandOptions) => Promise<CommandResult<'doctor'>>;
1298
- /**
1299
- * JSON prepare results include timing.additiveParts for additive wall-clock phases.
1300
- * Top-level buildMs/connectMs/healthCheckMs are diagnostics and may overlap.
1301
- */
1302
- prepare: (options: PrepareCommandOptions) => Promise<CommandResult<'prepare'>>;
1303
- viewport: (options: ViewportCommandOptions) => Promise<CommandResult<'viewport'>>;
762
+ //#endregion
763
+ //#region src/contracts/navigation.d.ts
764
+ /**
765
+ * Closed results of the navigation/global action commands. Each mirrors the
766
+ * dispatch handler's literal return EXACTLY (src/core/dispatch.ts
767
+ * `DISPATCH_HANDLERS`): a fixed `action` discriminant plus the always-present
768
+ * `successText` message (the handlers always pass a non-empty message, so it is
769
+ * required here). The handlers spread nothing else, so the shapes are closed —
770
+ * consistent with the `viewport` contract, the generic-dispatch Android
771
+ * dialog-recovery `warning` annotation is intentionally not part of the contract.
772
+ */
773
+ /** `home` — `{ action: 'home', message: 'Home' }`. */
774
+ type HomeCommandResult = {
775
+ action: 'home';
776
+ message: string;
1304
777
  };
1305
- type AgentDeviceCommandClient = ProjectedNavigationCommandClient<DeviceCommandBaseOptions> & NonNavigationCommandClient & DeprecatedCommandClient;
1306
- /** Renamed command methods retained for existing consumers until the next major. */
1307
- type DeprecatedCommandClient = {
1308
- /**
1309
- * @deprecated Renamed to `orientation`. Delegates to it and returns the legacy
1310
- * `action: 'rotate'` response contract. Retained until the next major version.
1311
- */
1312
- rotate: (options: RotateCommandOptions) => Promise<RotateCommandResult>;
778
+ /** `back` — `{ action: 'back', mode, message: 'Back' }`; `mode` defaults to `'in-app'`. */
779
+ type BackCommandResult = {
780
+ action: 'back';
781
+ mode: BackMode;
782
+ message: string;
1313
783
  };
1314
- type SelectorSnapshotCommandOptions = Pick<CaptureSnapshotOptions, 'depth' | 'scope' | 'raw'>;
1315
- type FindSnapshotCommandOptions = Pick<CaptureSnapshotOptions, 'depth' | 'raw'>;
1316
- type PointTarget = {
1317
- x: number;
1318
- y: number;
1319
- ref?: never;
1320
- selector?: never;
1321
- label?: never;
784
+ /** `orientation` — `{ action: 'orientation', orientation, message: 'Rotated to <orientation>' }`. */
785
+ type OrientationCommandResult = {
786
+ action: 'orientation';
787
+ orientation: DeviceRotation;
788
+ message: string;
1322
789
  };
1323
- type RefTarget = {
1324
- ref: string;
1325
- label?: string;
1326
- x?: never;
1327
- y?: never;
1328
- selector?: never;
790
+ /**
791
+ * @deprecated The `rotate` command was renamed to `orientation`. This is the
792
+ * legacy response contract (`action: 'rotate'`) that shipped in v0.18/v0.19,
793
+ * retained for existing SDK consumers until the next major version. New code
794
+ * should use {@link OrientationCommandResult}.
795
+ */
796
+ type RotateCommandResult = {
797
+ action: 'rotate';
798
+ orientation: DeviceRotation;
799
+ message: string;
1329
800
  };
1330
- type SelectorTarget = {
1331
- selector: string;
1332
- x?: never;
1333
- y?: never;
1334
- ref?: never;
1335
- label?: never;
1336
- };
1337
- type InteractionTarget = PointTarget | RefTarget | SelectorTarget;
1338
- type ElementTarget = RefTarget | SelectorTarget;
1339
- type RepeatedPressOptions = {
1340
- count?: number;
1341
- intervalMs?: number;
1342
- holdMs?: number;
1343
- jitterPx?: number;
1344
- doubleTap?: boolean;
1345
- };
1346
- type DeviceBootOptions = DeviceCommandBaseOptions & {
1347
- headless?: boolean;
1348
- };
1349
- type DeviceShutdownOptions = DeviceCommandBaseOptions;
1350
- type AppPushOptions = DeviceCommandBaseOptions & {
1351
- app: string;
1352
- payload: string | JsonObject;
1353
- };
1354
- type AppTriggerEventOptions = DeviceCommandBaseOptions & {
1355
- event: string;
1356
- payload?: JsonObject;
1357
- };
1358
- type CaptureDiffOptions = DeviceCommandBaseOptions & Pick<CaptureSnapshotOptions, 'interactiveOnly' | 'depth' | 'scope' | 'raw'> & {
1359
- kind: 'snapshot';
1360
- out?: string;
1361
- };
1362
- /**
1363
- * Opt-in (#1101): after the action, wait for the UI to go quiet and return the
1364
- * settled diff vs the pre-action tree (`settle` on the result) in the same
1365
- * response. Best-effort — never fails the action. `settleQuietMs` tunes the
1366
- * quiet window (default 500ms); `timeoutMs` bounds the settle wait (default
1367
- * 10s) when `settle` is true. A bare `timeoutMs` without `settle` is ignored
1368
- * for compatibility; `settleQuietMs` still requires `settle`.
1369
- */
1370
- type SettleCommandOptions = {
1371
- settle?: boolean;
1372
- settleQuietMs?: number;
1373
- timeoutMs?: number;
1374
- };
1375
- type ClickOptions = DeviceCommandBaseOptions & SelectorSnapshotCommandOptions & InteractionTarget & RepeatedPressOptions & SettleCommandOptions & {
1376
- button?: ClickButton;
1377
- /**
1378
- * Opt-in (#1047): return cheap post-action evidence (AX digest, node counts,
1379
- * changedFromBefore) in the response instead of requiring a follow-up
1380
- * snapshot to confirm the action had an effect.
1381
- */
1382
- verify?: boolean;
1383
- };
1384
- type PressOptions = DeviceCommandBaseOptions & SelectorSnapshotCommandOptions & InteractionTarget & RepeatedPressOptions & SettleCommandOptions & {
1385
- verify?: boolean;
801
+ /** `app-switcher` — `{ action: 'app-switcher', message: 'Opened app switcher' }`. */
802
+ type AppSwitcherCommandResult = {
803
+ action: 'app-switcher';
804
+ message: string;
1386
805
  };
1387
- type LongPressOptions = DeviceCommandBaseOptions & SelectorSnapshotCommandOptions & InteractionTarget & SettleCommandOptions & {
806
+ /** `tv-remote` — `{ action: 'tv-remote', button, durationMs?, message }`. */
807
+ type TvRemoteCommandResult = {
808
+ action: 'tv-remote';
809
+ button: TvRemoteButton;
1388
810
  durationMs?: number;
811
+ message: string;
1389
812
  };
1390
- type SwipeOptions = DeviceCommandBaseOptions & {
1391
- from: {
1392
- x: number;
1393
- y: number;
1394
- };
1395
- to: {
1396
- x: number;
1397
- y: number;
1398
- };
1399
- count?: number;
1400
- pauseMs?: number;
1401
- pattern?: SwipePattern;
1402
- };
1403
- type PanOptions = DeviceCommandBaseOptions & {
1404
- x: number;
1405
- y: number;
1406
- dx: number;
1407
- dy: number;
1408
- pointerCount?: GesturePointerCount;
1409
- durationMs?: number;
813
+ //#endregion
814
+ //#region src/commands/command-contract.d.ts
815
+ type JsonSchema = {
816
+ type?: string | readonly string[];
817
+ description?: string;
818
+ properties?: Record<string, JsonSchema>;
819
+ required?: readonly string[];
820
+ additionalProperties?: boolean | JsonSchema;
821
+ items?: JsonSchema;
822
+ prefixItems?: readonly JsonSchema[];
823
+ oneOf?: readonly JsonSchema[];
824
+ enum?: readonly unknown[];
825
+ const?: unknown;
826
+ minimum?: number;
827
+ maximum?: number;
1410
828
  };
1411
- type FlingOptions = DeviceCommandBaseOptions & {
1412
- direction: ScrollDirection;
1413
- x: number;
1414
- y: number;
1415
- distance?: number;
829
+ type ExecutableCommandProjection<ClientMethod extends string = string> = {
830
+ clientMethod: ClientMethod;
831
+ outputSchema: JsonSchema;
1416
832
  };
1417
- type SwipeGestureOptions = DeviceCommandBaseOptions & {
1418
- preset: SwipePreset;
833
+ //#endregion
834
+ //#region src/commands/system/navigation-projection.d.ts
835
+ declare const navigationCommandProjectionType: unique symbol;
836
+ type NavigationCommandProjection<Options, Result, Required extends boolean, ClientMethod extends string> = ExecutableCommandProjection<ClientMethod> & {
837
+ readonly [navigationCommandProjectionType]?: {
838
+ options: Options;
839
+ result: Result;
840
+ required: Required;
841
+ };
1419
842
  };
1420
- type FocusOptions = DeviceCommandBaseOptions & {
1421
- x: number;
1422
- y: number;
843
+ declare const NAVIGATION_COMMAND_PROJECTIONS: {
844
+ readonly back: NavigationCommandProjection<{
845
+ mode?: BackMode;
846
+ }, BackCommandResult, false, "back">;
847
+ readonly home: NavigationCommandProjection<{}, HomeCommandResult, false, "home">;
848
+ readonly orientation: NavigationCommandProjection<{
849
+ orientation: DeviceRotation;
850
+ }, OrientationCommandResult, true, "orientation">;
851
+ readonly 'app-switcher': NavigationCommandProjection<{}, AppSwitcherCommandResult, false, "appSwitcher">;
852
+ readonly 'tv-remote': NavigationCommandProjection<{
853
+ button: TvRemoteButton;
854
+ durationMs?: number;
855
+ }, TvRemoteCommandResult, true, "tvRemote">;
1423
856
  };
1424
- type TypeTextOptions = DeviceCommandBaseOptions & {
1425
- text: string;
1426
- delayMs?: number;
857
+ type NavigationCommandName = keyof typeof NAVIGATION_COMMAND_PROJECTIONS;
858
+ type NavigationCommandOptions<Name extends NavigationCommandName> = (typeof NAVIGATION_COMMAND_PROJECTIONS)[Name] extends NavigationCommandProjection<infer Options, unknown, boolean, string> ? Options : never;
859
+ type ProjectedNavigationCommandMethod<BaseOptions, Projection> = Projection extends NavigationCommandProjection<infer Options, infer Result, infer Required, string> ? Required extends true ? (options: BaseOptions & Options) => Promise<Result> : (options?: BaseOptions & Options) => Promise<Result> : never;
860
+ type ProjectedNavigationCommandClient<BaseOptions> = { [Name in NavigationCommandName as (typeof NAVIGATION_COMMAND_PROJECTIONS)[Name]['clientMethod']]: ProjectedNavigationCommandMethod<BaseOptions, (typeof NAVIGATION_COMMAND_PROJECTIONS)[Name]>; };
861
+ //#endregion
862
+ //#region src/contracts/debug-symbols.d.ts
863
+ type DebugSymbolsOptions = {
864
+ action?: 'symbols';
865
+ artifact: string;
866
+ dsym?: string;
867
+ searchPath?: string;
868
+ out?: string;
869
+ cwd?: string;
1427
870
  };
1428
- type FillOptions = DeviceCommandBaseOptions & SelectorSnapshotCommandOptions & InteractionTarget & SettleCommandOptions & {
1429
- text: string;
1430
- delayMs?: number;
1431
- /** Publish this fill value as `${VAR}` when script recording is armed. */
1432
- recordAs?: string;
1433
- verify?: boolean;
871
+ type DebugSymbolsImage = {
872
+ name: string;
873
+ uuid: string;
874
+ arch?: string;
875
+ dsymPath: string;
876
+ binaryPath: string;
1434
877
  };
1435
- type ScrollOptions = DeviceCommandBaseOptions & {
1436
- direction: ScrollInputDirection;
1437
- amount?: number;
1438
- pixels?: number;
1439
- durationMs?: number;
878
+ type DebugSymbolsCrashFrame = {
879
+ index: number;
880
+ image: string;
881
+ address: string;
882
+ symbol?: string;
1440
883
  };
1441
- type PinchOptions = DeviceCommandBaseOptions & {
1442
- scale: number;
1443
- x?: number;
1444
- y?: number;
884
+ type DebugSymbolsCrashSummary = {
885
+ format: 'ips' | 'text';
886
+ appName?: string;
887
+ bundleId?: string;
888
+ version?: string;
889
+ incident?: string;
890
+ timestamp?: string;
891
+ exceptionType?: string;
892
+ exceptionCodes?: string;
893
+ terminationReason?: string;
894
+ crashedThread?: number;
895
+ topFrames: DebugSymbolsCrashFrame[];
896
+ findings: string[];
1445
897
  };
1446
- type RotateGestureOptions = DeviceCommandBaseOptions & {
1447
- degrees: number;
1448
- x?: number;
1449
- y?: number;
898
+ type DebugSymbolsResult = {
899
+ kind: 'debugSymbols';
900
+ platform: 'apple';
901
+ artifactPath: string;
902
+ outPath: string;
903
+ crash: DebugSymbolsCrashSummary;
904
+ matchedImages: DebugSymbolsImage[];
905
+ symbolicatedFrames: number;
906
+ skippedImages: number;
907
+ warnings?: string[];
908
+ message: string;
1450
909
  };
1451
- type TransformGestureOptions = DeviceCommandBaseOptions & TransformGestureParams;
910
+ //#endregion
911
+ //#region src/contracts/device.d.ts
1452
912
  /**
1453
- * #1271 stage 2 (ADR 0012 amendment): `get`/`is`/`find` are observation-only
1454
- * and excluded from a repair-armed heal by default. `record` forces this
1455
- * action through (the corrective-read case); `noRecord` continues to opt the
1456
- * action out entirely. Mutually exclusive.
913
+ * Closed result of the `boot` command. Mirrors the daemon handler's only
914
+ * success return EXACTLY (src/daemon/handlers/session-state.ts) — the fixed
915
+ * object literal `{ platform, target, device, id, kind, booted }` plus the
916
+ * additive `appleOs` discriminant, emitted only for Apple devices.
1457
917
  */
1458
- type RecordControlOptions = {
1459
- noRecord?: boolean;
1460
- record?: boolean;
918
+ type BootCommandResult = {
919
+ platform: PublicPlatform;
920
+ target: DeviceTarget;
921
+ /** Human-readable device name (`device.name`). */
922
+ device: string;
923
+ /** Stable device id (`device.id`). */
924
+ id: string;
925
+ kind: DeviceKind;
926
+ /** Always `true` on the success path. */
927
+ booted: true;
928
+ /**
929
+ * Additive Apple-OS discriminant (`device.appleOs`): iPhone/iPad/tvOS/visionOS/macOS.
930
+ * Present only for Apple devices; absent for non-Apple platforms. `platform` stays the
931
+ * leaf (`ios`/`macos`) — this is an extra field, not a replacement.
932
+ */
933
+ appleOs?: AppleOS;
1461
934
  };
1462
- type GetOptions = DeviceCommandBaseOptions & SelectorSnapshotCommandOptions & ElementTarget & RecordControlOptions & {
1463
- format: 'text' | 'attrs';
935
+ /**
936
+ * Closed result of the `shutdown` command. Mirrors the daemon handler's success
937
+ * return EXACTLY (src/daemon/handlers/session-state.ts) — the fixed object
938
+ * literal `{ platform, target, device, id, kind, shutdown }` plus the additive
939
+ * `appleOs` discriminant (Apple devices only). The `shutdown` field is the raw
940
+ * {@link TargetShutdownResult} from `shutdownDeviceTarget`.
941
+ */
942
+ type ShutdownCommandResult = {
943
+ platform: PublicPlatform;
944
+ target: DeviceTarget;
945
+ /** Human-readable device name (`device.name`). */
946
+ device: string;
947
+ /** Stable device id (`device.id`). */
948
+ id: string;
949
+ kind: DeviceKind;
950
+ shutdown: TargetShutdownResult;
951
+ /**
952
+ * Additive Apple-OS discriminant (`device.appleOs`): iPhone/iPad/tvOS/visionOS/macOS.
953
+ * Present only for Apple devices; absent for non-Apple platforms. `platform` stays the
954
+ * leaf (`ios`/`macos`) — this is an extra field, not a replacement.
955
+ */
956
+ appleOs?: AppleOS;
1464
957
  };
1465
- type IsTextPredicateOptions = DeviceCommandBaseOptions & SelectorSnapshotCommandOptions & RecordControlOptions & {
1466
- predicate: 'text';
1467
- selector: string;
1468
- value: string;
958
+ //#endregion
959
+ //#region src/contracts/viewport.d.ts
960
+ /**
961
+ * Closed result of the `viewport` command. Mirrors the dispatch handler's return
962
+ * EXACTLY (src/core/dispatch.ts `handleViewportCommand`) — `{ width, height }`
963
+ * plus the always-present `successText` message. The generic dispatch path
964
+ * returns this object unchanged (viewport has no Android dialog guard, so no
965
+ * `warning` is ever appended), so the shape is intentionally closed.
966
+ */
967
+ type ViewportCommandResult = {
968
+ width: number;
969
+ height: number;
970
+ message: string;
1469
971
  };
1470
- type IsStatePredicateOptions = DeviceCommandBaseOptions & SelectorSnapshotCommandOptions & RecordControlOptions & {
1471
- predicate: 'visible' | 'hidden' | 'exists' | 'editable' | 'selected' | 'focused';
1472
- selector: string;
1473
- value?: never;
972
+ //#endregion
973
+ //#region src/contracts/clipboard.d.ts
974
+ /**
975
+ * Closed result of the `clipboard` command. Mirrors the dispatch handler's
976
+ * literal return EXACTLY (src/core/dispatch.ts `handleClipboardCommand`): a
977
+ * discriminated union on `action`. `read` returns the clipboard `text`; `write`
978
+ * reports the written `textLength` plus the `successText` message. The handler
979
+ * spreads nothing else, so each branch is closed.
980
+ */
981
+ type ClipboardCommandResult = {
982
+ action: 'read';
983
+ text: string;
984
+ } | {
985
+ action: 'write';
986
+ textLength: number;
987
+ message: string;
1474
988
  };
1475
- type IsOptions = IsTextPredicateOptions | IsStatePredicateOptions;
1476
- type FindBaseOptions = DeviceCommandBaseOptions & FindSnapshotCommandOptions & RecordControlOptions & {
1477
- locator?: FindLocator;
1478
- query: string;
1479
- first?: boolean;
1480
- last?: boolean;
989
+ //#endregion
990
+ //#region src/contracts/app-state.d.ts
991
+ /**
992
+ * Closed result of the `appstate` command, grounded in the daemon handler's
993
+ * success returns (src/daemon/handlers/session-state.ts `handleAppStateCommand`).
994
+ * A discriminated union on `platform`:
995
+ * - Apple (`ios` / `macos`) session state, with iOS-only device locators that
996
+ * the previous hand-written mirror omitted; and
997
+ * - Android foreground `package` / `activity`.
998
+ *
999
+ * The handler returns one of these fixed objects (errors take the `ok: false`
1000
+ * path), so each branch is closed.
1001
+ */
1002
+ type AppStateCommandResult = {
1003
+ platform: 'ios' | 'macos';
1004
+ appName: string;
1005
+ appBundleId?: string;
1006
+ source: 'session';
1007
+ surface: SessionSurface;
1008
+ /** iOS only — the session device's UDID. */
1009
+ device_udid?: string;
1010
+ /** iOS only — the simulator set path, or `null` when unknown. */
1011
+ ios_simulator_device_set?: string | null;
1012
+ } | {
1013
+ platform: 'android';
1014
+ package: string;
1015
+ activity: string;
1481
1016
  };
1482
- type FindOptions = (FindBaseOptions & {
1483
- action?: 'click' | 'focus' | 'exists' | 'getText' | 'getAttrs';
1484
- }) | (FindBaseOptions & {
1485
- action: 'wait';
1486
- timeoutMs?: number;
1487
- }) | (FindBaseOptions & {
1488
- action: 'fill' | 'type';
1489
- value: string;
1490
- });
1491
- type ReplayRunOptions = AgentDeviceRequestOverrides & AgentDeviceSelectionOptions & {
1492
- path: string;
1493
- runtime?: SessionRuntimeHints;
1494
- /**
1495
- * @deprecated ADR 0012 migration step 6: `--update` no longer rewrites
1496
- * the script. Accepted for backward compatibility; every divergence
1497
- * already carries ranked selector suggestions regardless of this flag.
1498
- */
1499
- update?: boolean;
1500
- /** @deprecated Use backend: 'maestro'. */
1501
- maestro?: boolean;
1502
- backend?: string;
1503
- env?: string[];
1504
- timeoutMs?: number;
1505
- /**
1506
- * ADR 0012 decision 4 / migration step 5: resume at this 1-based plan
1507
- * step, skipping `1..resumeFrom-1` without executing them. Requires
1508
- * `resumePlanDigest` from the divergence report that reported this
1509
- * step as the failure. `replay` only — `test` has no resume fields.
1510
- */
1511
- resumeFrom?: number;
1512
- /** The `resume.planDigest` from the divergence report `resumeFrom` came from. */
1513
- resumePlanDigest?: string;
1017
+ //#endregion
1018
+ //#region src/contracts/keyboard.d.ts
1019
+ /**
1020
+ * Closed result of the `keyboard` command, grounded in the dispatch handlers'
1021
+ * literal returns (src/core/dispatch.ts `handleAndroidKeyboardCommand` /
1022
+ * `handleIosKeyboardCommand`).
1023
+ *
1024
+ * `platform` and `action` are always present; the remaining fields appear per
1025
+ * branch (Android `status`/`dismiss` carry the keyboard-state fields; `enter`
1026
+ * and iOS `dismiss` carry a `message`). It is kept as a flat closed shape rather
1027
+ * than a five-way `platform`×`action` union because the per-branch field sets
1028
+ * overlap heavily and the underlying Android keyboard-state types live in the
1029
+ * platform layer (below the public contract). The `Record` index signature of
1030
+ * the previous hand-written mirror is dropped, and the spurious `| null`s are
1031
+ * removed (the handler never returns `null` for these).
1032
+ */
1033
+ type KeyboardCommandResult = {
1034
+ platform: 'android' | 'ios';
1035
+ action: 'status' | 'dismiss' | 'enter';
1036
+ visible?: boolean;
1037
+ wasVisible?: boolean;
1038
+ dismissed?: boolean;
1039
+ attempts?: number;
1040
+ inputType?: string;
1041
+ type?: 'text' | 'number' | 'email' | 'phone' | 'password' | 'datetime' | 'unknown';
1042
+ inputMethodPackage?: string;
1043
+ focusedPackage?: string;
1044
+ focusedResourceId?: string;
1045
+ inputOwner?: 'app' | 'ime' | 'unknown';
1046
+ message?: string;
1047
+ };
1048
+ //#endregion
1049
+ //#region src/contracts/wait.d.ts
1050
+ /**
1051
+ * Public daemon result for `wait`. The runtime-local result carries a `kind`
1052
+ * discriminant, but `toDaemonWaitData` intentionally projects the normal daemon
1053
+ * payload to this compact shape. The direct iOS selector fast path may still
1054
+ * include `kind: 'selector'` additively.
1055
+ */
1056
+ type WaitCommandResult = {
1057
+ waitedMs: number;
1058
+ kind?: 'selector';
1059
+ text?: string;
1060
+ selector?: string;
1061
+ captures?: number;
1062
+ nodeCount?: number;
1063
+ hint?: string;
1064
+ warning?: string;
1065
+ };
1066
+ //#endregion
1067
+ //#region src/contracts/prepare.d.ts
1068
+ type PrepareIosRunnerCacheKind = 'exact' | 'restore-key' | 'miss' | 'external';
1069
+ type PrepareIosRunnerArtifactState = 'valid' | 'rebuilt';
1070
+ type PrepareIosRunnerTiming = {
1071
+ totalMs: number;
1072
+ additiveParts: {
1073
+ buildMs?: number;
1074
+ connectAfterBuildMs: number;
1075
+ healthCheckMs: number;
1076
+ };
1077
+ containment: {
1078
+ connectMs?: ['buildMs'];
1079
+ healthCheckMs: [];
1080
+ };
1081
+ note: string;
1082
+ };
1083
+ /**
1084
+ * Public daemon result for `prepare ios-runner`. The runner-local prepare result
1085
+ * is projected by `prepareIosRunnerResponseData` with device identity and timing
1086
+ * guidance before it reaches the client.
1087
+ */
1088
+ type PrepareCommandResult = {
1089
+ action: 'ios-runner';
1090
+ platform: PublicPlatform;
1091
+ deviceId: string;
1092
+ deviceName: string;
1093
+ kind: DeviceKind;
1094
+ durationMs: number;
1095
+ runner: JsonObject;
1096
+ cache?: PrepareIosRunnerCacheKind;
1097
+ artifact?: PrepareIosRunnerArtifactState;
1098
+ buildMs?: number;
1099
+ connectMs: number;
1100
+ healthCheckMs: number;
1101
+ xctestrunPath?: string;
1102
+ recoveryReason?: string;
1103
+ failureReason?: string;
1104
+ timing: PrepareIosRunnerTiming;
1105
+ message: string;
1106
+ };
1107
+ //#endregion
1108
+ //#region src/contracts/push.d.ts
1109
+ type PushCommandResult = {
1110
+ platform: 'ios';
1111
+ bundleId: string;
1112
+ message: string;
1113
+ } | {
1114
+ platform: 'android';
1115
+ package: string;
1116
+ action: string;
1117
+ extrasCount: number;
1118
+ message: string;
1119
+ };
1120
+ //#endregion
1121
+ //#region src/contracts/app-events.d.ts
1122
+ type TriggerAppEventCommandResult = {
1123
+ event: string;
1124
+ eventUrl: string;
1125
+ transport: 'deep-link';
1126
+ message: string;
1127
+ };
1128
+ //#endregion
1129
+ //#region src/contracts/doctor.d.ts
1130
+ type DoctorStatus = 'pass' | 'warn' | 'fail' | 'info';
1131
+ type DoctorKind = 'auto' | 'react-native' | 'expo' | 'repack';
1132
+ type DoctorCheck = {
1133
+ id: string;
1134
+ status: DoctorStatus;
1135
+ summary: string;
1136
+ hint?: string;
1137
+ command?: string;
1138
+ evidence?: Record<string, unknown>;
1139
+ };
1140
+ type DoctorCommandResult = {
1141
+ status: DoctorStatus;
1142
+ summary: string;
1143
+ kind: DoctorKind;
1144
+ platform?: PlatformSelector;
1145
+ target?: DeviceTarget;
1146
+ targetApp?: string;
1147
+ metro?: {
1148
+ host: string;
1149
+ port: number;
1150
+ };
1151
+ checks: DoctorCheck[];
1152
+ };
1153
+ //#endregion
1154
+ //#region src/snapshot/snapshot-diff.d.ts
1155
+ type SnapshotDiffLine = {
1156
+ kind: 'added' | 'removed' | 'unchanged';
1157
+ text: string;
1514
1158
  /**
1515
- * ADR 0012 decision 6, R1/R6: arms agent-supervised re-record repair
1516
- * from this replay attempt onward. Optional string value is the healed
1517
- * `.ad`'s output path; absent one, it defaults to the `<path>` sibling
1518
- * `<stem>.healed.ad` when the repair ends with `close --save-script`.
1159
+ * Plain ref body (`e12`) of the CURRENT-tree node behind an added line.
1160
+ * Only populated with `withRefs` (interaction `--settle`, #1101) so the
1161
+ * `diff` command's wire shape stays byte-identical. Removed/unchanged lines
1162
+ * never carry it: a removed line's ref names a node of the replaced tree.
1519
1163
  */
1520
- saveScript?: boolean | string;
1521
- /** #1258: overwrite an existing --save-script target instead of refusing. Alias: --overwrite. */
1522
- force?: boolean;
1164
+ ref?: string;
1523
1165
  };
1524
- type ReplayTestOptions = AgentDeviceRequestOverrides & AgentDeviceSelectionOptions & {
1525
- paths: string[];
1526
- runtime?: SessionRuntimeHints;
1527
- update?: boolean;
1528
- /** @deprecated Use backend: 'maestro'. */
1529
- maestro?: boolean;
1530
- backend?: string;
1531
- env?: string[];
1532
- failFast?: boolean;
1533
- timeoutMs?: number;
1534
- retries?: number;
1535
- recordVideo?: boolean;
1536
- artifactsDir?: string;
1537
- /** @deprecated Use the CLI --reporter junit:<path> or --report-junit <path>. */
1538
- reportJunit?: string;
1539
- shardAll?: number;
1540
- shardSplit?: number;
1166
+ type SnapshotDiffSummary = {
1167
+ additions: number;
1168
+ removals: number;
1169
+ unchanged: number;
1170
+ };
1171
+ //#endregion
1172
+ //#region src/contracts/diff.d.ts
1173
+ type DiffSnapshotCommandResult = {
1174
+ mode: 'snapshot';
1175
+ baselineInitialized: boolean;
1176
+ summary: SnapshotDiffSummary;
1177
+ lines: SnapshotDiffLine[];
1178
+ warnings?: string[];
1179
+ };
1180
+ //#endregion
1181
+ //#region src/contracts/recording.d.ts
1182
+ type RecordingAppIdentity = {
1183
+ bundleId: string;
1184
+ name?: string;
1185
+ };
1186
+ type RecordingStartCommandResult = {
1187
+ recording: 'started';
1188
+ outPath: string;
1189
+ sessionStateDir: string;
1190
+ recordingBackend?: string;
1191
+ recordingScope?: RecordingScope;
1192
+ recordOnlySession?: boolean;
1193
+ activeSessionApp?: RecordingAppIdentity;
1194
+ showTouches: boolean;
1195
+ };
1196
+ type RecordingStopCommandResult = {
1197
+ recording: 'stopped';
1198
+ outPath: string;
1199
+ telemetryPath?: string;
1200
+ artifacts: DaemonArtifact[];
1201
+ recordingBackend?: string;
1202
+ recordingScope?: RecordingScope;
1203
+ recordOnlySession?: boolean;
1204
+ activeSessionApp?: RecordingAppIdentity;
1205
+ durationMs: number;
1206
+ showTouches: boolean;
1207
+ warning?: string;
1208
+ overlayWarning?: string;
1209
+ chunks?: Array<{
1210
+ index: number;
1211
+ path: string;
1212
+ }>;
1541
1213
  };
1542
- type BatchStep = {
1543
- command: string;
1544
- input: Record<string, unknown>;
1545
- runtime?: SessionRuntimeHints;
1214
+ type RecordingCommandResult = RecordingStartCommandResult | RecordingStopCommandResult;
1215
+ type TraceCommandResult = {
1216
+ trace: 'started';
1217
+ outPath: string;
1218
+ } | {
1219
+ trace: 'stopped';
1220
+ outPath: string;
1546
1221
  };
1547
- type BatchRunOptions = AgentDeviceRequestOverrides & {
1548
- steps: BatchStep[];
1549
- onError?: 'stop';
1550
- maxSteps?: number;
1551
- out?: string;
1222
+ //#endregion
1223
+ //#region src/contracts/replay.d.ts
1224
+ type ReplayCommandResult = {
1225
+ replayed: number;
1226
+ healed: number;
1227
+ session: string;
1228
+ /**
1229
+ * True iff `session` still exists in the daemon's session store when the
1230
+ * response is built — i.e. the replayed script had no terminal `close`
1231
+ * (ADR 0016's consumption contract). The client uses this, not script
1232
+ * parsing, to decide whether an owned one-shot daemon must stay alive so
1233
+ * the caller can keep addressing this session.
1234
+ */
1235
+ sessionActive: boolean;
1236
+ artifactPaths: string[];
1237
+ warnings?: string[];
1238
+ snapshotDiagnostics?: SnapshotDiagnosticsSummary;
1239
+ message: string;
1552
1240
  };
1553
- type PerfOptions = DeviceCommandBaseOptions & {
1554
- area?: PerfArea;
1555
- subject?: PerfSubject;
1556
- action?: PerfAction;
1557
- kind?: PerfKind;
1558
- template?: string;
1559
- out?: string;
1560
- tracePath?: string;
1241
+ type ReplaySuiteTestSkipReason = 'skipped-by-filter';
1242
+ type ReplaySuiteAttemptFailure = {
1243
+ attempt: number;
1244
+ message: string;
1245
+ durationMs?: number;
1561
1246
  };
1562
- type LogsOptions = AgentDeviceRequestOverrides & {
1563
- action?: LogAction;
1564
- message?: string;
1565
- restart?: boolean;
1247
+ type ReplaySuiteTestPassed = {
1248
+ file: string;
1249
+ title?: string;
1250
+ session: string;
1251
+ status: 'passed';
1252
+ durationMs: number;
1253
+ finalAttemptDurationMs?: number;
1254
+ attempts: number;
1255
+ artifactsDir?: string;
1256
+ replayed: number;
1257
+ healed: number;
1258
+ warnings?: string[];
1259
+ attemptFailures?: ReplaySuiteAttemptFailure[];
1260
+ shardIndex?: number;
1261
+ shardCount?: number;
1262
+ deviceId?: string;
1263
+ deviceName?: string;
1264
+ snapshotDiagnostics?: SnapshotDiagnosticsSummary;
1566
1265
  };
1567
- type EventsOptions = AgentDeviceRequestOverrides & {
1568
- cursor?: string;
1569
- limit?: number;
1266
+ type ReplaySuiteTestFailed = {
1267
+ file: string;
1268
+ title?: string;
1269
+ session: string;
1270
+ status: 'failed';
1271
+ durationMs: number;
1272
+ attempts: number;
1273
+ artifactsDir?: string;
1274
+ error: DaemonError;
1275
+ shardIndex?: number;
1276
+ shardCount?: number;
1277
+ deviceId?: string;
1278
+ deviceName?: string;
1279
+ snapshotDiagnostics?: SnapshotDiagnosticsSummary;
1570
1280
  };
1571
- type NetworkOptions = AgentDeviceRequestOverrides & {
1572
- action?: 'dump' | 'log';
1573
- limit?: number;
1574
- include?: NetworkIncludeMode;
1281
+ type ReplaySuiteTestSkipped = {
1282
+ file: string;
1283
+ title?: string;
1284
+ status: 'skipped';
1285
+ durationMs: 0;
1286
+ reason: ReplaySuiteTestSkipReason;
1287
+ message: string;
1575
1288
  };
1576
- type AudioOptions = AgentDeviceRequestOverrides & {
1577
- action?: 'probe';
1578
- probeAction?: 'start' | 'status' | 'stop';
1579
- durationMs?: number;
1580
- bucketMs?: number;
1289
+ type ReplaySuiteTestResult = ReplaySuiteTestPassed | ReplaySuiteTestFailed | ReplaySuiteTestSkipped;
1290
+ type ReplaySuiteResult = {
1291
+ total: number;
1292
+ executed: number;
1293
+ passed: number;
1294
+ failed: number;
1295
+ skipped: number;
1296
+ notRun: number;
1297
+ durationMs: number;
1298
+ failures: ReplaySuiteTestFailed[];
1299
+ tests: ReplaySuiteTestResult[];
1300
+ snapshotDiagnostics?: SnapshotDiagnosticsSummary;
1581
1301
  };
1582
- type RecordOptions = AgentDeviceRequestOverrides & {
1583
- action: 'start' | 'stop';
1584
- path?: string;
1585
- fps?: number;
1586
- maxSize?: number;
1587
- quality?: RecordingExportQuality;
1588
- hideTouches?: boolean;
1589
- recordingScope?: RecordingScope;
1302
+ //#endregion
1303
+ //#region src/core/command-descriptor/command-result.d.ts
1304
+ /**
1305
+ * The additive typed-result spine (ADR-0008, Phase 1 step 6).
1306
+ *
1307
+ * Maps a command name to the per-command result type from `src/contracts/*`. It
1308
+ * is SEEDED, not exhaustive: a command is listed here only once its accurate,
1309
+ * closed result shape lives in the contracts layer. Commands whose daemon
1310
+ * handler spreads dynamic/Record data (screenshot overlays, gesture
1311
+ * visualization, perf, logs, …) are deliberately omitted rather than given an
1312
+ * invented shape.
1313
+ *
1314
+ * Batches 1-2 wired `boot` / `shutdown` / `viewport` and the navigation/action
1315
+ * commands `home` / `back` / `orientation` / `app-switcher` alongside the seed
1316
+ * interaction quartet. Batch 3 adds `clipboard` (a closed `read`/`write` union) and
1317
+ * `appstate` (a closed `platform` union — Apple session state with the iOS-only
1318
+ * device locators, or Android package/activity). Batch 4 adds `keyboard` (a
1319
+ * closed flat shape). Batch 5 adds the compact daemon projections for `wait`,
1320
+ * `prepare`, `push`, and `trigger-app-event`. Each entry is grounded in a
1321
+ * re-read of the handler's literal return; see the per-type docstrings.
1322
+ */
1323
+ interface CommandResultMap {
1324
+ press: PressCommandResponseData;
1325
+ click: ClickCommandResponseData;
1326
+ fill: FillCommandResponseData;
1327
+ longpress: LongPressCommandResponseData;
1328
+ find: FindCommandResponseData;
1329
+ boot: BootCommandResult;
1330
+ shutdown: ShutdownCommandResult;
1331
+ viewport: ViewportCommandResult;
1332
+ home: HomeCommandResult;
1333
+ back: BackCommandResult;
1334
+ orientation: OrientationCommandResult;
1335
+ 'app-switcher': AppSwitcherCommandResult;
1336
+ clipboard: ClipboardCommandResult;
1337
+ appstate: AppStateCommandResult;
1338
+ keyboard: KeyboardCommandResult;
1339
+ 'tv-remote': TvRemoteCommandResult;
1340
+ wait: WaitCommandResult;
1341
+ prepare: PrepareCommandResult;
1342
+ push: PushCommandResult;
1343
+ 'trigger-app-event': TriggerAppEventCommandResult;
1344
+ doctor: DoctorCommandResult;
1345
+ diff: DiffSnapshotCommandResult;
1346
+ replay: ReplayCommandResult;
1347
+ test: ReplaySuiteResult;
1348
+ record: RecordingCommandResult;
1349
+ trace: TraceCommandResult;
1350
+ }
1351
+ /**
1352
+ * The typed result for a command named `N`. Seeded commands resolve to their
1353
+ * contract result type from {@link CommandResultMap}; every other (unmigrated)
1354
+ * command falls back to the untyped `Record<string, unknown>` bag. That default
1355
+ * branch is what keeps the mapping total over every command name, so consumers
1356
+ * can switch to `CommandResult<Name>` without first migrating every command.
1357
+ */
1358
+ type CommandResult<N extends string> = N extends keyof CommandResultMap ? CommandResultMap[N] : Record<string, unknown>;
1359
+ //#endregion
1360
+ //#region src/client/client-types.d.ts
1361
+ type OrientationCommandOptions = DeviceCommandBaseOptions & NavigationCommandOptions<'orientation'>;
1362
+ /** @deprecated Renamed to `OrientationCommandOptions`. Retained until the next major. */
1363
+ type RotateCommandOptions = OrientationCommandOptions;
1364
+ type NonNavigationCommandClient = {
1365
+ wait: (options: WaitCommandOptions) => Promise<CommandResult<'wait'>>;
1366
+ alert: (options?: AlertCommandOptions) => Promise<CommandRequestResult>;
1367
+ appState: (options?: AppStateCommandOptions) => Promise<CommandResult<'appstate'>>;
1368
+ keyboard: (options?: KeyboardCommandOptions) => Promise<CommandResult<'keyboard'>>;
1369
+ clipboard: (options: ClipboardCommandOptions) => Promise<CommandResult<'clipboard'>>;
1370
+ reactNative: (options: ReactNativeCommandOptions) => Promise<CommandRequestResult>;
1371
+ doctor: (options?: DoctorCommandOptions) => Promise<CommandResult<'doctor'>>;
1372
+ /**
1373
+ * JSON prepare results include timing.additiveParts for additive wall-clock phases.
1374
+ * Top-level buildMs/connectMs/healthCheckMs are diagnostics and may overlap.
1375
+ */
1376
+ prepare: (options: PrepareCommandOptions) => Promise<CommandResult<'prepare'>>;
1377
+ viewport: (options: ViewportCommandOptions) => Promise<CommandResult<'viewport'>>;
1590
1378
  };
1591
- type TraceOptions = AgentDeviceRequestOverrides & {
1592
- action: 'start' | 'stop';
1593
- path?: string;
1379
+ type AgentDeviceCommandClient = ProjectedNavigationCommandClient<DeviceCommandBaseOptions> & NonNavigationCommandClient & DeprecatedCommandClient;
1380
+ /** Renamed command methods retained for existing consumers until the next major. */
1381
+ type DeprecatedCommandClient = {
1382
+ /**
1383
+ * @deprecated Renamed to `orientation`. Delegates to it and returns the legacy
1384
+ * `action: 'rotate'` response contract. Retained until the next major version.
1385
+ */
1386
+ rotate: (options: RotateCommandOptions) => Promise<RotateCommandResult>;
1594
1387
  };
1595
- type PermissionTarget = 'camera' | 'microphone' | 'photos' | 'contacts' | 'contacts-limited' | 'notifications' | 'calendar' | 'location' | 'location-always' | 'media-library' | 'motion' | 'reminders' | 'siri' | 'accessibility' | 'screen-recording' | 'input-monitoring';
1596
- type SettingsUpdateOptions = (DeviceCommandBaseOptions & {
1597
- setting: 'clear-app-state';
1598
- state: 'clear';
1599
- app?: string;
1600
- }) | (DeviceCommandBaseOptions & {
1601
- setting: 'wifi' | 'airplane' | 'location';
1602
- state: 'on' | 'off';
1603
- }) | (DeviceCommandBaseOptions & {
1604
- setting: 'location';
1605
- state: 'set';
1606
- latitude: number;
1607
- longitude: number;
1608
- }) | (DeviceCommandBaseOptions & {
1609
- setting: 'animations';
1610
- state: 'on' | 'off';
1611
- }) | (DeviceCommandBaseOptions & {
1612
- setting: 'appearance';
1613
- state: 'light' | 'dark' | 'toggle';
1614
- }) | (DeviceCommandBaseOptions & {
1615
- setting: 'faceid' | 'touchid';
1616
- state: 'match' | 'nonmatch' | 'enroll' | 'unenroll';
1617
- }) | (DeviceCommandBaseOptions & {
1618
- setting: 'fingerprint';
1619
- state: 'match' | 'nonmatch';
1620
- }) | (DeviceCommandBaseOptions & {
1621
- setting: 'permission';
1622
- state: 'grant' | 'deny' | 'reset';
1623
- permission: PermissionTarget;
1624
- mode?: 'full' | 'limited';
1625
- });
1626
- type CommandRequestResult = DaemonResponseData;
1627
1388
  type AgentDeviceClient = {
1628
1389
  command: AgentDeviceCommandClient;
1629
1390
  devices: {