agent-device 0.21.19 → 0.21.20

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 (114) hide show
  1. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.19.apk → agent-device-android-ime-helper-0.21.20.apk} +0 -0
  2. package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.20.apk.sha256 +1 -0
  3. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.19.manifest.json → agent-device-android-ime-helper-0.21.20.manifest.json} +4 -4
  4. package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.21.19.apk → agent-device-android-snapshot-helper-0.21.20.apk} +0 -0
  5. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.20.apk.sha256 +1 -0
  6. package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.21.19.manifest.json → agent-device-android-snapshot-helper-0.21.20.manifest.json} +6 -6
  7. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunner/AgentDeviceRunnerApp.m +12 -0
  8. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandJournal.swift +1 -14
  9. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +14 -16
  10. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +40 -14
  11. package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotModels.swift +20 -5
  12. package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotPresentationProjection.swift +2 -15
  13. package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotVisibilityFold.swift +10 -25
  14. package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotVisibilityFoldProjection.swift +1 -18
  15. package/dist/src/adapter.js +1 -1
  16. package/dist/src/adb-failure.js +1 -1
  17. package/dist/src/agent-browser-process-record.js +1 -1
  18. package/dist/src/agent-browser-provider.js +1 -1
  19. package/dist/src/agent-browser-tool.js +1 -1
  20. package/dist/src/agent-device-client.js +2 -2
  21. package/dist/src/alert-runtime.js +1 -1
  22. package/dist/src/alert.js +1 -0
  23. package/dist/src/android-input-ownership.js +1 -1
  24. package/dist/src/app-launch.js +2 -2
  25. package/dist/src/app-lifecycle.js +1 -1
  26. package/dist/src/app-resolution.js +2 -2
  27. package/dist/src/apple-runner-platform.js +1 -1
  28. package/dist/src/archive.js +2 -2
  29. package/dist/src/browser-launch.js +1 -1
  30. package/dist/src/cache.js +1 -1
  31. package/dist/src/cli-config.js +1 -1
  32. package/dist/src/cli-help.js +287 -301
  33. package/dist/src/cli-runner.js +1 -1
  34. package/dist/src/cli.js +1 -1
  35. package/dist/src/client-metro-companion.js +1 -1
  36. package/dist/src/client-metro.js +1 -1
  37. package/dist/src/client-types.d.ts +14 -2
  38. package/dist/src/{scroll-command.d.ts → cloud-artifacts.d.ts} +242 -238
  39. package/dist/src/command-schema.js +3 -3
  40. package/dist/src/command-tools.js +2 -2
  41. package/dist/src/command.js +1 -1
  42. package/dist/src/config.js +1 -1
  43. package/dist/src/connection-runtime.js +1 -1
  44. package/dist/src/daemon-client-lifecycle.js +1 -1
  45. package/dist/src/daemon-client-transport.js +1 -1
  46. package/dist/src/daemon-registration.js +1 -1
  47. package/dist/src/debug-symbols-facade.js +3 -3
  48. package/dist/src/device-rotation.js +1 -1
  49. package/dist/src/devicectl.js +1 -1
  50. package/dist/src/display-inventory.js +1 -1
  51. package/dist/src/exec.js +1 -1
  52. package/dist/src/hdc.js +1 -1
  53. package/dist/src/helper.js +2 -2
  54. package/dist/src/host.js +1 -1
  55. package/dist/src/index.d.ts +1 -1
  56. package/dist/src/interactor.js +5 -5
  57. package/dist/src/interactor2.js +1 -1
  58. package/dist/src/internal/bin.js +1 -1
  59. package/dist/src/internal/daemon.js +2 -2
  60. package/dist/src/launch-confirmation.js +1 -0
  61. package/dist/src/limrun-runtime-dependencies.js +1 -1
  62. package/dist/src/limrun.d.ts +50 -42
  63. package/dist/src/mechanics.js +16 -16
  64. package/dist/src/owner-identity.js +1 -1
  65. package/dist/src/perf-facade.js +1 -1
  66. package/dist/src/perf-target.js +1 -1
  67. package/dist/src/physical-device-control.js +1 -1
  68. package/dist/src/platform-runtime-android-adb-host.js +1 -1
  69. package/dist/src/platform-runtime-app-log-process.js +1 -1
  70. package/dist/src/platform-runtime-host.js +1 -1
  71. package/dist/src/platform-runtime-operation-host.js +2 -2
  72. package/dist/src/platform-runtime-runtime-hints.js +1 -1
  73. package/dist/src/platform-runtime-screen-recording-apple-simulator-host.js +1 -1
  74. package/dist/src/platform-runtime-screen-recording-finalizer-host.js +1 -1
  75. package/dist/src/provider-session-ownership.js +1 -1
  76. package/dist/src/provider-webdriver.js +1 -1
  77. package/dist/src/registry.js +20 -4
  78. package/dist/src/result-serialization.js +1 -1
  79. package/dist/src/runner-cache-metadata.js +3 -3
  80. package/dist/src/runner-client.js +1 -1
  81. package/dist/src/runner-dev-tools-security.js +1 -1
  82. package/dist/src/runner-device-readiness.js +1 -1
  83. package/dist/src/runner-disposal.js +1 -1
  84. package/dist/src/runner-error-classification.js +1 -1
  85. package/dist/src/runner-exchange.js +1 -1
  86. package/dist/src/runner-operations-facade.js +1 -1
  87. package/dist/src/runner-session-types.js +1 -1
  88. package/dist/src/runner-start-budget.js +1 -1
  89. package/dist/src/runner-startup-transport.js +1 -1
  90. package/dist/src/runner-xctestrun.js +1 -1
  91. package/dist/src/runtime.js +1 -1
  92. package/dist/src/runtime10.js +1 -1
  93. package/dist/src/runtime2.js +1 -1
  94. package/dist/src/runtime4.js +5 -5
  95. package/dist/src/screenshot-result.js +1 -1
  96. package/dist/src/screenshot-runtime.js +1 -1
  97. package/dist/src/screenshot3.js +1 -1
  98. package/dist/src/sdk-contracts.d.ts +2 -0
  99. package/dist/src/sdk-contracts.js +2 -2
  100. package/dist/src/sdk-selectors.d.ts +4 -4
  101. package/dist/src/session2.js +1 -1
  102. package/dist/src/simulator-boot.js +1 -1
  103. package/dist/src/simulator.js +1 -1
  104. package/dist/src/snapshot-runtime.js +1 -1
  105. package/dist/src/tool-provider.js +3 -3
  106. package/dist/src/tool-provider2.js +1 -1
  107. package/dist/src/tool-provider3.js +1 -1
  108. package/dist/src/toolchain-probe.js +1 -1
  109. package/dist/src/update-check.js +1 -1
  110. package/dist/src/video.js +1 -1
  111. package/package.json +1 -1
  112. package/server.json +2 -2
  113. package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.19.apk.sha256 +0 -1
  114. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.19.apk.sha256 +0 -1
@@ -1,5 +1,242 @@
1
1
  import { L as SnapshotQualityVerdict, P as SnapshotNode, R as SnapshotState, T as PublicPlatform, j as ScreenshotOverlayRef, n as DaemonArtifactType } from "./sdk-contracts.js";
2
2
  import { _ as SettleObservation } from "./sdk-selectors.js";
3
+ //#region packages/contracts/src/back-mode.d.ts
4
+ declare const BACK_MODES: readonly ['in-app', 'system'];
5
+ type BackMode = (typeof BACK_MODES)[number];
6
+ //#endregion
7
+ //#region packages/contracts/src/device-rotation.d.ts
8
+ /** Single source of truth for the discriminator the Apple owner sets and the MCP schema advertises. */
9
+ declare const FOLD_SCREEN_COORDINATE_SPACE: 'native-panel';
10
+ type FoldScreenCoordinateSpace = typeof FOLD_SCREEN_COORDINATE_SPACE;
11
+ declare const DEVICE_ROTATIONS: readonly ['portrait', 'portrait-upside-down', 'landscape-left', 'landscape-right'];
12
+ type DeviceRotation = (typeof DEVICE_ROTATIONS)[number];
13
+ /**
14
+ * The three hinge poses a foldable Apple device can be put in, named after what an agent sees
15
+ * rather than after Apple's `UIHinge.Status` cases: `closed` lights the outer panel only,
16
+ * `half-open` and `open` light the inner panel. Device Hub calls them Closed, Book, and Open;
17
+ * `UIHinge.Status` calls them `.closed`, `.partiallyOpen`, and `.fullyOpen`.
18
+ */
19
+ declare const FOLD_POSES: readonly ['closed', 'half-open', 'open'];
20
+ type FoldPose = (typeof FOLD_POSES)[number];
21
+ type FoldKeyframe = Readonly<{
22
+ atMs: number;
23
+ angle: number;
24
+ }>;
25
+ type SetFoldPoseInput = Readonly<{
26
+ pose: FoldPose;
27
+ keyframes?: never;
28
+ }> | Readonly<{
29
+ keyframes: readonly FoldKeyframe[];
30
+ pose?: never;
31
+ }>;
32
+ //#endregion
33
+ //#region packages/contracts/src/scroll-gesture.d.ts
34
+ declare const SCROLL_INPUT_DIRECTIONS: readonly ['up', 'down', 'left', 'right', 'top', 'bottom'];
35
+ type ScrollInputDirection = (typeof SCROLL_INPUT_DIRECTIONS)[number];
36
+ declare const SCROLL_DIRECTIONS: readonly ['up', 'down', 'left', 'right'];
37
+ type ScrollDirection = (typeof SCROLL_DIRECTIONS)[number];
38
+ declare const SWIPE_PRESETS: readonly ['left', 'right', 'left-edge', 'right-edge'];
39
+ type SwipePreset = (typeof SWIPE_PRESETS)[number];
40
+ declare const SWIPE_PATTERNS: readonly ['one-way', 'ping-pong'];
41
+ type SwipePattern = (typeof SWIPE_PATTERNS)[number];
42
+ type TransformGestureParams = {
43
+ x: number;
44
+ y: number;
45
+ dx: number;
46
+ dy: number;
47
+ scale: number;
48
+ degrees: number;
49
+ durationMs?: number;
50
+ };
51
+ //#endregion
52
+ //#region packages/contracts/src/scroll-command.d.ts
53
+ type ScrollReleaseBehavior = 'controlled' | 'inertial';
54
+ /**
55
+ * What a directional scroll actually SAW after its gesture, which is the only evidence that can
56
+ * back the distance the same response reports (#2714).
57
+ *
58
+ * - `'moved'`: the post-gesture surface differs from the pre-gesture one, so content did move.
59
+ * - `'at-edge'`: the surface is identical and the resolved container names no hidden content in
60
+ * that direction — the scroll was a legitimate no-op at the end of the content.
61
+ * - `'unchanged'`: the surface is identical and the direction has no end-of-content signal to read
62
+ * (a horizontal scroll: the hidden-content analyzer only covers the vertical axis), so the
63
+ * response says what it measured without guessing which of the two it was.
64
+ * - `'unobserved'`: nothing comparable was available, so the distance rests on the gesture plan
65
+ * alone. Callers that need the effect confirmed ask for a capture or a `--settle` observation.
66
+ *
67
+ * A directional scroll that measures an unchanged surface WITH hidden content still in that
68
+ * direction does not answer at all: it fails with `scroll_no_progress`.
69
+ */
70
+ type ScrollMovementObservation = 'moved' | 'at-edge' | 'unchanged' | 'unobserved';
71
+ type ScrollDistanceOptions = {
72
+ amount?: number;
73
+ pixels?: number;
74
+ };
75
+ type ScrollTimingOptions = {
76
+ durationMs?: number;
77
+ };
78
+ type ScrollCommandOptions = ScrollDistanceOptions & ScrollTimingOptions;
79
+ type ScrollExecutionOptions = ScrollCommandOptions & {
80
+ releaseBehavior?: ScrollReleaseBehavior;
81
+ };
82
+ /**
83
+ * `scroll` — the generic-route result built by `buildDispatchedScrollResult`
84
+ * (src/core/dispatch-scroll.ts): the resolved direction, the edge-pass
85
+ * bookkeeping for `top`/`bottom` scrolls, the honored distance/timing echo,
86
+ * and the success message. Platform leaves add gesture-plan coordinates
87
+ * (`x1`/`y1`/`x2`/`y2`, reference frame) on top; the output schema stays
88
+ * non-strict so those additive fields validate. The one field the dispatcher
89
+ * itself may add: `settle`, the opt-in `--settle` observation (#1638),
90
+ * attached after the command — same shape as `BackCommandResult`.
91
+ */
92
+ type ScrollCommandResult = {
93
+ direction: ScrollDirection;
94
+ /** Set for `top`/`bottom` requests: the extreme being scrolled to. */
95
+ edge?: 'top' | 'bottom';
96
+ /** Set for `--until` requests: the selector the passes stopped on. */
97
+ until?: string;
98
+ /** Edge and until scrolls only: how many scroll-and-check passes ran. */
99
+ passes?: number;
100
+ amount?: number;
101
+ pixels?: number;
102
+ durationMs?: number;
103
+ message?: string;
104
+ settle?: SettleObservation;
105
+ /**
106
+ * The observation that gated this response's distance claim. See
107
+ * {@link ScrollMovementObservation}: `scroll` answers with what it measured after the gesture,
108
+ * and only `'moved'` and `'at-edge'` confirm the surface's fate. Absent on the tiers that verify
109
+ * per pass instead of per gesture (`scroll top`/`bottom` and `--until`), and on platforms whose
110
+ * scroll owner never dispatches a swipe (the Linux wheel).
111
+ */
112
+ movement?: ScrollMovementObservation;
113
+ /**
114
+ * Set only when an on-screen keyboard made the owner clip the swipe into the band above it
115
+ * (#2500). Absent means the swipe was not clipped, which is not the same claim as `false`: a
116
+ * platform that never runs the clip has nothing to report. The platform leaf's `referenceHeight`
117
+ * names the shortened axis the reported `pixels` were planned against, and `keyboardMinY` names
118
+ * where the keyboard began. A surface the owner refused to swipe at all fails instead, under the
119
+ * `scroll_keyboard_occludes_surface` reason.
120
+ */
121
+ keyboardAvoided?: true;
122
+ /** The keyboard's edge in the same unit as the gesture coordinates, when the swipe was clipped. */
123
+ keyboardMinY?: number;
124
+ };
125
+ //#endregion
126
+ //#region packages/contracts/src/tv-remote.d.ts
127
+ declare const TV_REMOTE_BUTTON_DEFINITIONS: {
128
+ readonly up: {
129
+ readonly aliases: readonly [];
130
+ readonly androidKeyevent: 'KEYCODE_DPAD_UP';
131
+ readonly appleRemoteButton: 'up';
132
+ readonly vegaKey: 'KEY_UP';
133
+ };
134
+ readonly down: {
135
+ readonly aliases: readonly [];
136
+ readonly androidKeyevent: 'KEYCODE_DPAD_DOWN';
137
+ readonly appleRemoteButton: 'down';
138
+ readonly vegaKey: 'KEY_DOWN';
139
+ };
140
+ readonly left: {
141
+ readonly aliases: readonly [];
142
+ readonly androidKeyevent: 'KEYCODE_DPAD_LEFT';
143
+ readonly appleRemoteButton: 'left';
144
+ readonly vegaKey: 'KEY_LEFT';
145
+ };
146
+ readonly right: {
147
+ readonly aliases: readonly [];
148
+ readonly androidKeyevent: 'KEYCODE_DPAD_RIGHT';
149
+ readonly appleRemoteButton: 'right';
150
+ readonly vegaKey: 'KEY_RIGHT';
151
+ };
152
+ readonly select: {
153
+ readonly aliases: readonly ["ok", "center", "enter"];
154
+ readonly androidKeyevent: 'KEYCODE_DPAD_CENTER';
155
+ readonly appleRemoteButton: 'select';
156
+ readonly vegaKey: 'KEY_ENTER';
157
+ };
158
+ readonly menu: {
159
+ readonly aliases: readonly [];
160
+ readonly androidKeyevent: 'KEYCODE_MENU';
161
+ readonly appleRemoteButton: 'menu';
162
+ readonly vegaKey: 'KEY_MENU';
163
+ };
164
+ readonly home: {
165
+ readonly aliases: readonly [];
166
+ readonly androidKeyevent: 'KEYCODE_HOME';
167
+ readonly appleRemoteButton: 'home';
168
+ readonly vegaKey: 'KEY_HOMEPAGE';
169
+ };
170
+ readonly back: {
171
+ readonly aliases: readonly [];
172
+ readonly androidKeyevent: 'KEYCODE_BACK';
173
+ readonly appleRemoteButton: 'menu';
174
+ readonly vegaKey: 'KEY_BACK';
175
+ };
176
+ };
177
+ declare const TV_REMOTE_BUTTONS: (keyof typeof TV_REMOTE_BUTTON_DEFINITIONS)[];
178
+ type TvRemoteButton = (typeof TV_REMOTE_BUTTONS)[number];
179
+ //#endregion
180
+ //#region packages/contracts/src/settings.d.ts
181
+ /**
182
+ * The `settings permission` vocabulary, declared once. These collections are what the parsers
183
+ * below, the public client permission types, the CLI's membership sets, and the permission-name
184
+ * fragments of `settings` help and its invalid-args message are built from, and their order is
185
+ * the order `settings` help lists the names in.
186
+ *
187
+ * Acceptance is not support: each backend keeps its own target mapping and its own support check,
188
+ * so a name accepted here never promises that the selected platform serves it.
189
+ */
190
+ declare const PERMISSION_ACTIONS: readonly ['grant', 'deny', 'reset'];
191
+ declare const PERMISSION_MODES: readonly ['full', 'limited'];
192
+ /** The app-scoped targets, the only ones `parsePermissionTarget` accepts. */
193
+ declare const MOBILE_PERMISSION_TARGETS: readonly ['all', 'camera', 'microphone', 'photos', 'contacts', 'contacts-limited', 'notifications', 'calendar', 'location', 'location-always', 'media-library', 'motion', 'reminders', 'siri'];
194
+ /** The desktop targets the CLI and the public client accept; `parsePermissionTarget` refuses them. */
195
+ declare const MACOS_PERMISSION_TARGETS: readonly ['accessibility', 'screen-recording', 'input-monitoring'];
196
+ type PermissionAction = (typeof PERMISSION_ACTIONS)[number];
197
+ type PermissionMode = (typeof PERMISSION_MODES)[number];
198
+ /**
199
+ * The preferred-text-size ladder `settings text-size` accepts, in the order `settings` help lists
200
+ * it. Apple serves it natively — `simctl ui <device> content_size` reads and writes exactly these
201
+ * names — and Android serves it through its `system font_scale` multiplier, so this ladder is the
202
+ * cross-platform vocabulary and each owner maps it in its own native terms. Acceptance is not
203
+ * support: an owner that cannot serve the ladder refuses at admission, on its own fact.
204
+ */
205
+ declare const TEXT_SIZE_CATEGORIES: readonly ['extra-small', 'small', 'medium', 'large', 'extra-large', 'extra-extra-large', 'extra-extra-extra-large', 'accessibility-medium', 'accessibility-large', 'accessibility-extra-large', 'accessibility-extra-extra-large', 'accessibility-extra-extra-extra-large'];
206
+ type TextSizeCategory = (typeof TEXT_SIZE_CATEGORIES)[number];
207
+ /**
208
+ * The settings that answer a bare `settings <setting>` with the value the target holds. This is the
209
+ * vocabulary every settings type and every settings owner reads it from; the matching value is
210
+ * `READABLE_SETTINGS` in `platform-runtime-operations.ts`, where the CLI hub can evaluate it, and
211
+ * that module pins the two equal in both directions at compile time.
212
+ */
213
+ type ReadableSetting = 'text-size';
214
+ /**
215
+ * What `text-size` answers with. The ladder is shared across platforms, so a read names the
216
+ * category the ladder calls the device's value *and* the value the platform itself reported: an
217
+ * Apple content-size name, or an Android `font_scale` multiplier. The ladder is coarser than any
218
+ * one platform's own scale, and `platformValue` is what keeps a normalized answer auditable.
219
+ */
220
+ type TextSizeSettingPayload = Readonly<{
221
+ setting: 'text-size';
222
+ category: TextSizeCategory;
223
+ platformValue: string;
224
+ }>;
225
+ /**
226
+ * The payload a readable setting answers with, keyed by the setting that answered. Each readable
227
+ * setting has its own shape — a category and a multiplier are not the same observation — so the
228
+ * discriminant is what lets a response be composed, recorded, and printed from one place without
229
+ * assuming every setting is a ladder rung. A second readable setting joins this union and supplies
230
+ * its own sentence in `describeSettingRead`, which is where the compiler then asks for it.
231
+ */
232
+ type ReadSettingResult = TextSizeSettingPayload;
233
+ type SettingOptions = {
234
+ permissionTarget?: string;
235
+ permissionMode?: string;
236
+ latitude?: number;
237
+ longitude?: number;
238
+ };
239
+ //#endregion
3
240
  //#region packages/contracts/src/session-surface.d.ts
4
241
  declare const SESSION_SURFACES: readonly ['app', 'frontmost-app', 'desktop', 'menubar'];
5
242
  type SessionSurface = (typeof SESSION_SURFACES)[number];
@@ -27,6 +264,8 @@ type ScreenshotResultData = {
27
264
  logicalWidth?: number;
28
265
  logicalHeight?: number;
29
266
  pixelDensity?: number;
267
+ /** Display rotation the capture was rendered in; absent when the target reports none. */
268
+ displayRotation?: DeviceRotation;
30
269
  overlayRefs?: ScreenshotOverlayRef[];
31
270
  warnings?: string[];
32
271
  };
@@ -88,25 +327,6 @@ type AndroidSnapshotBackendMetadata = {
88
327
  };
89
328
  type FindLocator = 'any' | 'text' | 'label' | 'value' | 'role' | 'id';
90
329
  //#endregion
91
- //#region packages/contracts/src/scroll-gesture.d.ts
92
- declare const SCROLL_INPUT_DIRECTIONS: readonly ['up', 'down', 'left', 'right', 'top', 'bottom'];
93
- type ScrollInputDirection = (typeof SCROLL_INPUT_DIRECTIONS)[number];
94
- declare const SCROLL_DIRECTIONS: readonly ['up', 'down', 'left', 'right'];
95
- type ScrollDirection = (typeof SCROLL_DIRECTIONS)[number];
96
- declare const SWIPE_PRESETS: readonly ['left', 'right', 'left-edge', 'right-edge'];
97
- type SwipePreset = (typeof SWIPE_PRESETS)[number];
98
- declare const SWIPE_PATTERNS: readonly ['one-way', 'ping-pong'];
99
- type SwipePattern = (typeof SWIPE_PATTERNS)[number];
100
- type TransformGestureParams = {
101
- x: number;
102
- y: number;
103
- dx: number;
104
- dy: number;
105
- scale: number;
106
- degrees: number;
107
- durationMs?: number;
108
- };
109
- //#endregion
110
330
  //#region packages/contracts/src/cloud-artifacts.d.ts
111
331
  declare const CLOUD_ARTIFACT_KINDS: readonly ['video', 'appium-log', 'device-log', 'automation-log', 'provider-session', 'raw'];
112
332
  type CloudArtifactKind = (typeof CLOUD_ARTIFACT_KINDS)[number];
@@ -139,6 +359,8 @@ type DaemonArtifactInventoryEntry = {
139
359
  sizeBytes: number;
140
360
  createdAt: string;
141
361
  expiresAt: string;
362
+ /** Display rotation a screenshot was rendered in; absent when the capture reported none. */
363
+ displayRotation?: DeviceRotation;
142
364
  };
143
365
  type DaemonArtifactsResult = {
144
366
  source: 'daemon';
@@ -166,222 +388,4 @@ type CloudArtifactProvider = {
166
388
  listCloudArtifacts?: (query: CloudArtifactsQuery) => Promise<CloudArtifactsResult | undefined>;
167
389
  };
168
390
  //#endregion
169
- //#region packages/contracts/src/settings.d.ts
170
- /**
171
- * The `settings permission` vocabulary, declared once. These collections are what the parsers
172
- * below, the public client permission types, the CLI's membership sets, and the permission-name
173
- * fragments of `settings` help and its invalid-args message are built from, and their order is
174
- * the order `settings` help lists the names in.
175
- *
176
- * Acceptance is not support: each backend keeps its own target mapping and its own support check,
177
- * so a name accepted here never promises that the selected platform serves it.
178
- */
179
- declare const PERMISSION_ACTIONS: readonly ['grant', 'deny', 'reset'];
180
- declare const PERMISSION_MODES: readonly ['full', 'limited'];
181
- /** The app-scoped targets, the only ones `parsePermissionTarget` accepts. */
182
- declare const MOBILE_PERMISSION_TARGETS: readonly ['all', 'camera', 'microphone', 'photos', 'contacts', 'contacts-limited', 'notifications', 'calendar', 'location', 'location-always', 'media-library', 'motion', 'reminders', 'siri'];
183
- /** The desktop targets the CLI and the public client accept; `parsePermissionTarget` refuses them. */
184
- declare const MACOS_PERMISSION_TARGETS: readonly ['accessibility', 'screen-recording', 'input-monitoring'];
185
- type PermissionAction = (typeof PERMISSION_ACTIONS)[number];
186
- type PermissionMode = (typeof PERMISSION_MODES)[number];
187
- /**
188
- * The preferred-text-size ladder `settings text-size` accepts, in the order `settings` help lists
189
- * it. Apple serves it natively — `simctl ui <device> content_size` reads and writes exactly these
190
- * names — and Android serves it through its `system font_scale` multiplier, so this ladder is the
191
- * cross-platform vocabulary and each owner maps it in its own native terms. Acceptance is not
192
- * support: an owner that cannot serve the ladder refuses at admission, on its own fact.
193
- */
194
- declare const TEXT_SIZE_CATEGORIES: readonly ['extra-small', 'small', 'medium', 'large', 'extra-large', 'extra-extra-large', 'extra-extra-extra-large', 'accessibility-medium', 'accessibility-large', 'accessibility-extra-large', 'accessibility-extra-extra-large', 'accessibility-extra-extra-extra-large'];
195
- type TextSizeCategory = (typeof TEXT_SIZE_CATEGORIES)[number];
196
- /**
197
- * The settings that answer a bare `settings <setting>` with the value the target holds. This is the
198
- * vocabulary every settings type and every settings owner reads it from; the matching value is
199
- * `READABLE_SETTINGS` in `platform-runtime-operations.ts`, where the CLI hub can evaluate it, and
200
- * that module pins the two equal in both directions at compile time.
201
- */
202
- type ReadableSetting = 'text-size';
203
- /**
204
- * What `text-size` answers with. The ladder is shared across platforms, so a read names the
205
- * category the ladder calls the device's value *and* the value the platform itself reported: an
206
- * Apple content-size name, or an Android `font_scale` multiplier. The ladder is coarser than any
207
- * one platform's own scale, and `platformValue` is what keeps a normalized answer auditable.
208
- */
209
- type TextSizeSettingPayload = Readonly<{
210
- setting: 'text-size';
211
- category: TextSizeCategory;
212
- platformValue: string;
213
- }>;
214
- /**
215
- * The payload a readable setting answers with, keyed by the setting that answered. Each readable
216
- * setting has its own shape — a category and a multiplier are not the same observation — so the
217
- * discriminant is what lets a response be composed, recorded, and printed from one place without
218
- * assuming every setting is a ladder rung. A second readable setting joins this union and supplies
219
- * its own sentence in `describeSettingRead`, which is where the compiler then asks for it.
220
- */
221
- type ReadSettingResult = TextSizeSettingPayload;
222
- type SettingOptions = {
223
- permissionTarget?: string;
224
- permissionMode?: string;
225
- latitude?: number;
226
- longitude?: number;
227
- };
228
- //#endregion
229
- //#region packages/contracts/src/back-mode.d.ts
230
- declare const BACK_MODES: readonly ['in-app', 'system'];
231
- type BackMode = (typeof BACK_MODES)[number];
232
- //#endregion
233
- //#region packages/contracts/src/device-rotation.d.ts
234
- /** Single source of truth for the discriminator the Apple owner sets and the MCP schema advertises. */
235
- declare const FOLD_SCREEN_COORDINATE_SPACE: 'native-panel';
236
- type FoldScreenCoordinateSpace = typeof FOLD_SCREEN_COORDINATE_SPACE;
237
- declare const DEVICE_ROTATIONS: readonly ['portrait', 'portrait-upside-down', 'landscape-left', 'landscape-right'];
238
- type DeviceRotation = (typeof DEVICE_ROTATIONS)[number];
239
- /**
240
- * The three hinge poses a foldable Apple device can be put in, named after what an agent sees
241
- * rather than after Apple's `UIHinge.Status` cases: `closed` lights the outer panel only,
242
- * `half-open` and `open` light the inner panel. Device Hub calls them Closed, Book, and Open;
243
- * `UIHinge.Status` calls them `.closed`, `.partiallyOpen`, and `.fullyOpen`.
244
- */
245
- declare const FOLD_POSES: readonly ['closed', 'half-open', 'open'];
246
- type FoldPose = (typeof FOLD_POSES)[number];
247
- type FoldKeyframe = Readonly<{
248
- atMs: number;
249
- angle: number;
250
- }>;
251
- type SetFoldPoseInput = Readonly<{
252
- pose: FoldPose;
253
- keyframes?: never;
254
- }> | Readonly<{
255
- keyframes: readonly FoldKeyframe[];
256
- pose?: never;
257
- }>;
258
- //#endregion
259
- //#region packages/contracts/src/tv-remote.d.ts
260
- declare const TV_REMOTE_BUTTON_DEFINITIONS: {
261
- readonly up: {
262
- readonly aliases: readonly [];
263
- readonly androidKeyevent: 'KEYCODE_DPAD_UP';
264
- readonly appleRemoteButton: 'up';
265
- readonly vegaKey: 'KEY_UP';
266
- };
267
- readonly down: {
268
- readonly aliases: readonly [];
269
- readonly androidKeyevent: 'KEYCODE_DPAD_DOWN';
270
- readonly appleRemoteButton: 'down';
271
- readonly vegaKey: 'KEY_DOWN';
272
- };
273
- readonly left: {
274
- readonly aliases: readonly [];
275
- readonly androidKeyevent: 'KEYCODE_DPAD_LEFT';
276
- readonly appleRemoteButton: 'left';
277
- readonly vegaKey: 'KEY_LEFT';
278
- };
279
- readonly right: {
280
- readonly aliases: readonly [];
281
- readonly androidKeyevent: 'KEYCODE_DPAD_RIGHT';
282
- readonly appleRemoteButton: 'right';
283
- readonly vegaKey: 'KEY_RIGHT';
284
- };
285
- readonly select: {
286
- readonly aliases: readonly ["ok", "center", "enter"];
287
- readonly androidKeyevent: 'KEYCODE_DPAD_CENTER';
288
- readonly appleRemoteButton: 'select';
289
- readonly vegaKey: 'KEY_ENTER';
290
- };
291
- readonly menu: {
292
- readonly aliases: readonly [];
293
- readonly androidKeyevent: 'KEYCODE_MENU';
294
- readonly appleRemoteButton: 'menu';
295
- readonly vegaKey: 'KEY_MENU';
296
- };
297
- readonly home: {
298
- readonly aliases: readonly [];
299
- readonly androidKeyevent: 'KEYCODE_HOME';
300
- readonly appleRemoteButton: 'home';
301
- readonly vegaKey: 'KEY_HOMEPAGE';
302
- };
303
- readonly back: {
304
- readonly aliases: readonly [];
305
- readonly androidKeyevent: 'KEYCODE_BACK';
306
- readonly appleRemoteButton: 'menu';
307
- readonly vegaKey: 'KEY_BACK';
308
- };
309
- };
310
- declare const TV_REMOTE_BUTTONS: (keyof typeof TV_REMOTE_BUTTON_DEFINITIONS)[];
311
- type TvRemoteButton = (typeof TV_REMOTE_BUTTONS)[number];
312
- //#endregion
313
- //#region packages/contracts/src/scroll-command.d.ts
314
- type ScrollReleaseBehavior = 'controlled' | 'inertial';
315
- /**
316
- * What a directional scroll actually SAW after its gesture, which is the only evidence that can
317
- * back the distance the same response reports (#2714).
318
- *
319
- * - `'moved'`: the post-gesture surface differs from the pre-gesture one, so content did move.
320
- * - `'at-edge'`: the surface is identical and the resolved container names no hidden content in
321
- * that direction — the scroll was a legitimate no-op at the end of the content.
322
- * - `'unchanged'`: the surface is identical and the direction has no end-of-content signal to read
323
- * (a horizontal scroll: the hidden-content analyzer only covers the vertical axis), so the
324
- * response says what it measured without guessing which of the two it was.
325
- * - `'unobserved'`: nothing comparable was available, so the distance rests on the gesture plan
326
- * alone. Callers that need the effect confirmed ask for a capture or a `--settle` observation.
327
- *
328
- * A directional scroll that measures an unchanged surface WITH hidden content still in that
329
- * direction does not answer at all: it fails with `scroll_no_progress`.
330
- */
331
- type ScrollMovementObservation = 'moved' | 'at-edge' | 'unchanged' | 'unobserved';
332
- type ScrollDistanceOptions = {
333
- amount?: number;
334
- pixels?: number;
335
- };
336
- type ScrollTimingOptions = {
337
- durationMs?: number;
338
- };
339
- type ScrollCommandOptions = ScrollDistanceOptions & ScrollTimingOptions;
340
- type ScrollExecutionOptions = ScrollCommandOptions & {
341
- releaseBehavior?: ScrollReleaseBehavior;
342
- };
343
- /**
344
- * `scroll` — the generic-route result built by `buildDispatchedScrollResult`
345
- * (src/core/dispatch-scroll.ts): the resolved direction, the edge-pass
346
- * bookkeeping for `top`/`bottom` scrolls, the honored distance/timing echo,
347
- * and the success message. Platform leaves add gesture-plan coordinates
348
- * (`x1`/`y1`/`x2`/`y2`, reference frame) on top; the output schema stays
349
- * non-strict so those additive fields validate. The one field the dispatcher
350
- * itself may add: `settle`, the opt-in `--settle` observation (#1638),
351
- * attached after the command — same shape as `BackCommandResult`.
352
- */
353
- type ScrollCommandResult = {
354
- direction: ScrollDirection;
355
- /** Set for `top`/`bottom` requests: the extreme being scrolled to. */
356
- edge?: 'top' | 'bottom';
357
- /** Set for `--until` requests: the selector the passes stopped on. */
358
- until?: string;
359
- /** Edge and until scrolls only: how many scroll-and-check passes ran. */
360
- passes?: number;
361
- amount?: number;
362
- pixels?: number;
363
- durationMs?: number;
364
- message?: string;
365
- settle?: SettleObservation;
366
- /**
367
- * The observation that gated this response's distance claim. See
368
- * {@link ScrollMovementObservation}: `scroll` answers with what it measured after the gesture,
369
- * and only `'moved'` and `'at-edge'` confirm the surface's fate. Absent on the tiers that verify
370
- * per pass instead of per gesture (`scroll top`/`bottom` and `--until`), and on platforms whose
371
- * scroll owner never dispatches a swipe (the Linux wheel).
372
- */
373
- movement?: ScrollMovementObservation;
374
- /**
375
- * Set only when an on-screen keyboard made the owner clip the swipe into the band above it
376
- * (#2500). Absent means the swipe was not clipped, which is not the same claim as `false`: a
377
- * platform that never runs the clip has nothing to report. The platform leaf's `referenceHeight`
378
- * names the shortened axis the reported `pixels` were planned against, and `keyboardMinY` names
379
- * where the keyboard began. A surface the owner refused to swipe at all fails instead, under the
380
- * `scroll_keyboard_occludes_surface` reason.
381
- */
382
- keyboardAvoided?: true;
383
- /** The keyboard's edge in the same unit as the gesture coordinates, when the swipe was clipped. */
384
- keyboardMinY?: number;
385
- };
386
- //#endregion
387
- export { SessionSurface as A, SwipePreset as C, FindLocator as D, BackendSnapshotResult as E, ScreenshotResultData as O, SwipePattern as S, AndroidSnapshotBackendMetadata as T, AgentArtifactsResult as _, FoldPose as a, ScrollDirection as b, BackMode as c, PermissionAction as d, PermissionMode as f, TextSizeCategory as g, SettingOptions as h, DeviceRotation as i, SnapshotDiagnosticsSummary as k, MACOS_PERMISSION_TARGETS as l, ReadableSetting as m, ScrollExecutionOptions as n, FoldScreenCoordinateSpace as o, ReadSettingResult as p, TvRemoteButton as r, SetFoldPoseInput as s, ScrollCommandResult as t, MOBILE_PERMISSION_TARGETS as u, CloudArtifactProvider as v, TransformGestureParams as w, ScrollInputDirection as x, CloudProviderSessionResult as y };
391
+ export { BackMode as A, SwipePattern as C, FoldPose as D, DeviceRotation as E, FoldScreenCoordinateSpace as O, ScrollInputDirection as S, TransformGestureParams as T, TextSizeCategory as _, BackendSnapshotResult as a, ScrollExecutionOptions as b, SnapshotDiagnosticsSummary as c, MOBILE_PERMISSION_TARGETS as d, PermissionAction as f, SettingOptions as g, ReadableSetting as h, AndroidSnapshotBackendMetadata as i, SetFoldPoseInput as k, SessionSurface as l, ReadSettingResult as m, CloudArtifactProvider as n, FindLocator as o, PermissionMode as p, CloudProviderSessionResult as r, ScreenshotResultData as s, AgentArtifactsResult as t, MACOS_PERMISSION_TARGETS as u, TvRemoteButton as v, SwipePreset as w, ScrollDirection as x, ScrollCommandResult as y };
@@ -1,4 +1,4 @@
1
- import{N as e}from"./sdk-contracts.js";import{r as t,w as n,x as r}from"./registry.js";import{r as i}from"./command-metadata.js";const a={cdp:{text:{summary:`Inspect CDP targets, JS heap, and leaks`,description:`Run CDP commands for React Native diagnostics, JS heap usage, heap snapshots, and leak analysis`},usageOverride:`cdp [...args]`,listUsageOverride:`cdp`,positionalArgs:[`args?`],allowsExtraPositionals:!0,supportedFlags:r},auth:{text:{summary:`Manage cloud login state`,description:`Manage cloud login state used by remote daemon and cloud device workflows.`},usageOverride:`auth status|login|logout`,listUsageOverride:`auth`,positionalArgs:[`status|login|logout`],supportedFlags:[`remoteConfig`,`stateDir`]},daemon:{text:{summary:`Stop a local daemon and clean up resources`,description:`Stop a local daemon after verifying its PID/start-time identity. Use --clean to remove retained Apple runner processes and leases owned by that daemon.`},usageOverride:`daemon stop [--state-dir <path>]`,listUsageOverride:`daemon stop`,positionalArgs:[`stop`],allowedFlags:[`clean`],supportedFlags:[`stateDir`]},device:{text:{summary:`Inspect and recover enforced local device ownership without a daemon`,description:`Inspect enforced host-local device ownership claims without starting or contacting a daemon; status --stale only inspects proven-stale claims. release --stale settles a provably dead owner through exact-owner resource reconciliation and clears its claim last — live and uncertain owners always fail closed. Automatic reclamation still occurs during open and daemon startup.`},usageOverride:`device status|release [--platform <platform>] [--udid <udid>] [--serial <serial>]`,listUsageOverride:`device status`,positionalArgs:[`status|release`],allowedFlags:[`stale`],supportedFlags:[`platform`,`device`,`udid`,`serial`]},connect:{text:{summary:`Configure remote or provider state`,description:`Configure remote access without allocating a device. Direct providers validate credentials/resources before saving state and print the exact device/app preparation needed before open. AGENT_DEVICE_CLOUD_BASE_URL is the bridge/control-plane API origin; use AGENT_DEVICE_DAEMON_AUTH_TOKEN=adc_live_... for CI/service-token automation.`},usageOverride:`connect [cloud|proxy|limrun|browserstack|aws-device-farm] [--remote-config <path>] [--daemon-base-url <url>] [--tenant <id>] [--run-id <id>] [--lease-id <id>] [--lease-backend <backend>] [--force] [--no-login]`,usageFlags:[],listUsageOverride:`connect`,positionalArgs:[`provider?`],allowedFlags:`remoteConfig.daemonBaseUrl.tenant.runId.leaseId.leaseBackend.providerApp.providerOsVersion.providerProject.providerBuild.providerSessionName.providerDeviceOrientation.providerGeoLocation.providerTimezone.providerAppiumVersion.providerLanguage.providerLocale.providerNetworkProfile.providerCustomNetwork.providerNoResignApp.awsProjectArn.awsDeviceArn.awsAppArn.awsRegion.awsInteractionMode.force.noLogin`.split(`.`),supportedFlags:[`stateDir`,`daemonAuthToken`,`session`,`platform`,`device`,...n,`launchUrl`]},connection:{text:{summary:`Inspect the saved remote connection`,description:`Inspect active remote connection state`},usageOverride:`connection status`,listUsageOverride:`connection`,positionalArgs:[`status`],supportedFlags:[`remoteConfig`,`stateDir`,`session`]},disconnect:{text:{summary:`Clear remote connection state and release leases`,description:`Disconnect remote daemon state, stop owned Metro companion, and release lease`},listUsageOverride:`disconnect`,allowedFlags:[`shutdown`],supportedFlags:[`remoteConfig`,`stateDir`,`session`]},mcp:{text:{summary:`Start MCP server`,description:`Start the official stdio MCP server. It exposes structured command tools backed by the agent-device client.`}},proxy:{text:{summary:`Expose a local daemon through an HTTP tunnel`,description:`Expose the local daemon HTTP contract through a tunnel-friendly reverse proxy.
1
+ import{N as e}from"./sdk-contracts.js";import{S as t,T as n,r}from"./registry.js";import{r as i}from"./command-metadata.js";const a={cdp:{text:{summary:`Inspect CDP targets, JS heap, and leaks`,description:`Run CDP commands for React Native diagnostics, JS heap usage, heap snapshots, and leak analysis`},usageOverride:`cdp [...args]`,listUsageOverride:`cdp`,positionalArgs:[`args?`],allowsExtraPositionals:!0,supportedFlags:t},auth:{text:{summary:`Manage cloud login state`,description:`Manage cloud login state used by remote daemon and cloud device workflows.`},usageOverride:`auth status|login|logout`,listUsageOverride:`auth`,positionalArgs:[`status|login|logout`],supportedFlags:[`remoteConfig`,`stateDir`]},daemon:{text:{summary:`Stop a local daemon and clean up resources`,description:`Stop a local daemon after verifying its PID/start-time identity. Use --clean to remove retained Apple runner processes and leases owned by that daemon.`},usageOverride:`daemon stop [--state-dir <path>]`,listUsageOverride:`daemon stop`,positionalArgs:[`stop`],allowedFlags:[`clean`],supportedFlags:[`stateDir`]},device:{text:{summary:`Inspect and recover enforced local device ownership without a daemon`,description:`Inspect enforced host-local device ownership claims without starting or contacting a daemon; status --stale only inspects proven-stale claims. release --stale settles a provably dead owner through exact-owner resource reconciliation and clears its claim last — live and uncertain owners always fail closed. Automatic reclamation still occurs during open and daemon startup.`},usageOverride:`device status|release [--platform <platform>] [--udid <udid>] [--serial <serial>]`,listUsageOverride:`device status`,positionalArgs:[`status|release`],allowedFlags:[`stale`],supportedFlags:[`platform`,`device`,`udid`,`serial`]},connect:{text:{summary:`Configure remote or provider state`,description:`Configure remote access without allocating a device. Direct providers validate credentials/resources before saving state and print the exact device/app preparation needed before open. AGENT_DEVICE_CLOUD_BASE_URL is the bridge/control-plane API origin; use AGENT_DEVICE_DAEMON_AUTH_TOKEN=adc_live_... for CI/service-token automation.`},usageOverride:`connect [cloud|proxy|limrun|browserstack|aws-device-farm] [--remote-config <path>] [--daemon-base-url <url>] [--tenant <id>] [--run-id <id>] [--lease-id <id>] [--lease-backend <backend>] [--force] [--no-login]`,usageFlags:[],listUsageOverride:`connect`,positionalArgs:[`provider?`],allowedFlags:`remoteConfig.daemonBaseUrl.tenant.runId.leaseId.leaseBackend.providerApp.providerOsVersion.providerProject.providerBuild.providerSessionName.providerDeviceOrientation.providerGeoLocation.providerTimezone.providerAppiumVersion.providerLanguage.providerLocale.providerNetworkProfile.providerCustomNetwork.providerNoResignApp.awsProjectArn.awsDeviceArn.awsAppArn.awsRegion.awsInteractionMode.force.noLogin`.split(`.`),supportedFlags:[`stateDir`,`daemonAuthToken`,`session`,`platform`,`device`,...n,`launchUrl`]},connection:{text:{summary:`Inspect the saved remote connection`,description:`Inspect active remote connection state`},usageOverride:`connection status`,listUsageOverride:`connection`,positionalArgs:[`status`],supportedFlags:[`remoteConfig`,`stateDir`,`session`]},disconnect:{text:{summary:`Clear remote connection state and release leases`,description:`Disconnect remote daemon state, stop owned Metro companion, and release lease`},listUsageOverride:`disconnect`,allowedFlags:[`shutdown`],supportedFlags:[`remoteConfig`,`stateDir`,`session`]},mcp:{text:{summary:`Start MCP server`,description:`Start the official stdio MCP server. It exposes structured command tools backed by the agent-device client.`}},proxy:{text:{summary:`Expose a local daemon through an HTTP tunnel`,description:`Expose the local daemon HTTP contract through a tunnel-friendly reverse proxy.
2
2
 
3
3
  Run this on the host that has access to simulators/devices, expose the printed local proxy URL through a tunnel, then point another machine at the tunnel URL with connect proxy.
4
4
 
@@ -9,7 +9,7 @@ Use the /agent-device base path when connecting through cloudflared, ngrok, or a
9
9
  Examples:
10
10
  agent-device proxy --port 4310
11
11
  cloudflared tunnel --url http://127.0.0.1:4310
12
- agent-device connect proxy --daemon-base-url https://example.trycloudflare.com/agent-device --daemon-auth-token <token>`},listUsageOverride:`proxy`,allowedFlags:[`proxyHost`,`proxyPort`,`daemonAuthToken`,`stateDir`]},takeover:{text:{summary:`Pause agent interactions while a person controls a device`,description:`Temporarily hand control of the active remote lease device to a person. The foreground command pauses state-changing agent commands, renews the hold until Ctrl+C, and then releases it. Read-only diagnostics remain available. Uses the active connection and --session, with normal tenant and lease admission. status lists holds on that device; release removes a hold owned by the admitted lease. The host-only /admin/human-control/holds API uses the separate local daemon token. Holds do not survive daemon restart. Local takeover without a remote device lease is not supported.`},usageOverride:`takeover [status | release <hold-id>] [--session <name>]`,listUsageOverride:`takeover [status|release]`,positionalArgs:[`status|release?`,`hold-id?`],supportedFlags:[`stateDir`,`session`,`remoteConfig`,`daemonBaseUrl`,`daemonAuthToken`,`daemonTransport`,`tenant`,`runId`,`leaseId`,`leaseBackend`,`sessionIsolation`]},"react-devtools":{text:{summary:`Inspect components, hooks, and render profiles`,description:`Run pinned agent-react-devtools commands for React Native performance profiling, component trees, props/state/hooks, and render analysis`},usageOverride:`react-devtools [...args]`,listUsageOverride:`react-devtools`,positionalArgs:[`args?`],allowsExtraPositionals:!0,supportedFlags:r},web:{text:{summary:`Manage web automation backend`,description:`Install and inspect the managed web automation backend used by --platform web.
12
+ agent-device connect proxy --daemon-base-url https://example.trycloudflare.com/agent-device --daemon-auth-token <token>`},listUsageOverride:`proxy`,allowedFlags:[`proxyHost`,`proxyPort`,`daemonAuthToken`,`stateDir`]},takeover:{text:{summary:`Pause agent interactions while a person controls a device`,description:`Temporarily hand control of the active remote lease device to a person. The foreground command pauses state-changing agent commands, renews the hold until Ctrl+C, and then releases it. Read-only diagnostics remain available. Uses the active connection and --session, with normal tenant and lease admission. status lists holds on that device; release removes a hold owned by the admitted lease. The host-only /admin/human-control/holds API uses the separate local daemon token. Holds do not survive daemon restart. Local takeover without a remote device lease is not supported.`},usageOverride:`takeover [status | release <hold-id>] [--session <name>]`,listUsageOverride:`takeover [status|release]`,positionalArgs:[`status|release?`,`hold-id?`],supportedFlags:[`stateDir`,`session`,`remoteConfig`,`daemonBaseUrl`,`daemonAuthToken`,`daemonTransport`,`tenant`,`runId`,`leaseId`,`leaseBackend`,`sessionIsolation`]},"react-devtools":{text:{summary:`Inspect components, hooks, and render profiles`,description:`Run pinned agent-react-devtools commands for React Native performance profiling, component trees, props/state/hooks, and render analysis`},usageOverride:`react-devtools [...args]`,listUsageOverride:`react-devtools`,positionalArgs:[`args?`],allowsExtraPositionals:!0,supportedFlags:t},web:{text:{summary:`Manage web automation backend`,description:`Install and inspect the managed web automation backend used by --platform web.
13
13
 
14
14
  First-run flow:
15
15
  agent-device web setup
@@ -19,4 +19,4 @@ First-run flow:
19
19
 
20
20
  Runtime web commands do not install the backend implicitly. If the managed backend is missing, run agent-device web setup. The backend is resolved only from the managed install in the effective agent-device state dir.
21
21
 
22
- Use web setup to install or reuse the pinned backend. Use web doctor after setup to verify browser backend health.`},usageOverride:`web setup | web doctor`,listUsageOverride:`web setup|doctor`,positionalArgs:[`setup|doctor`],supportedFlags:[`stateDir`]}},o=t();function s(e){return Object.hasOwn(a,e)?a[e]:void 0}function c(e){return Object.hasOwn(o,e)?o[e]:void 0}const l=new Map(i().map(e=>[e.name,{supportedFlags:r}]));function u(e){if(e)return p(e)}function d(e){let t=p(e);if(!t)throw Error(`Missing command schema for ${e}`);return t}function f(t,n,r){let i=u(t);if(!t||!i||i.allowsExtraPositionals)return;let a=i.positionalArgs?.length??0;if(n.length<=a)return;let o=r?`${r} ${t}`:t;throw new e(`INVALID_ARGS`,`${o} accepts at most ${a} positional argument(s), received ${n.length}: ${n.join(` `)}`)}function p(e){let t=s(e);if(t)return t;let n=l.get(e),r=c(e);if(!(!n||!r))return{...n,...r}}export{d as n,u as r,f as t};
22
+ Use web setup to install or reuse the pinned backend. Use web doctor after setup to verify browser backend health.`},usageOverride:`web setup | web doctor`,listUsageOverride:`web setup|doctor`,positionalArgs:[`setup|doctor`],supportedFlags:[`stateDir`]}},o=r();function s(e){return Object.hasOwn(a,e)?a[e]:void 0}function c(e){return Object.hasOwn(o,e)?o[e]:void 0}const l=new Map(i().map(e=>[e.name,{supportedFlags:t}]));function u(e){if(e)return p(e)}function d(e){let t=p(e);if(!t)throw Error(`Missing command schema for ${e}`);return t}function f(t,n,r){let i=u(t);if(!t||!i||i.allowsExtraPositionals)return;let a=i.positionalArgs?.length??0;if(n.length<=a)return;let o=r?`${r} ${t}`:t;throw new e(`INVALID_ARGS`,`${o} accepts at most ${a} positional argument(s), received ${n.length}: ${n.join(` `)}`)}function p(e){let t=s(e);if(t)return t;let n=l.get(e),r=c(e);if(!(!n||!r))return{...n,...r}}export{d as n,u as r,f as t};
@@ -1,4 +1,4 @@
1
- import{N as e,X as t,Y as n,q as r,r as i}from"./sdk-contracts.js";import{_ as a,h as o}from"./sdk-batch-runner.js";import{a as s,n as c,t as l}from"./sdk-device.js";import{C as u,T as d,c as f,f as p,m}from"./sdk-batch.js";import{A as h,D as g,E as _,F as ee,L as v,M as y,O as b,P as te,R as ne,b as re,c as ie,d as ae,g as oe,h as se,j as x,k as S,l as ce,m as le,p as ue,s as de,u as fe,v as pe}from"./registry.js";import{n as me}from"./success-text.js";import{t as he}from"./output-common.js";import{i as ge,n as C,r as _e,t as w}from"./command-metadata.js";import{r as ve}from"./replay-divergence.js";import{n as ye,t as T}from"./cli-output.js";import{r as E,t as D}from"./recording-stop-observation.js";import{n as O}from"./error.js";import{n as k,r as A,t as j}from"./cli-config.js";import{n as M}from"./result-serialization.js";const N=x({field:y(),artifactType:y(),path:y(),localPath:y(),fileName:y()},[`field`]),P={record:{type:`object`,oneOf:[x({recording:g(`started`),outPath:y(),sessionStateDir:y(),recordingBackend:y(),recordingScope:y(),recordOnlySession:_(),activeSessionApp:S(),showTouches:_()},[`recording`,`outPath`,`sessionStateDir`,`showTouches`]),x({recording:g(`stopped`),outPath:y(),telemetryPath:y(),artifacts:{type:`array`,items:N},recordingBackend:y(),recordingScope:y(),recordOnlySession:_(),activeSessionApp:S(),durationMs:h(),capturedDurationMs:h(),recorder:b(D,`What the recorder was observed doing when the recording was stopped: confirmed, or lost when the session holding it died. ADR 0024 reserves unconfirmed for the step that gains the probe.`),nativePathDisposition:b(E,`What became of the artifact path the recorder writes to: retirable while it still owes a removal, retired once that removal was verified. ADR 0024 reserves pending.`),showTouches:_(),warning:y(),overlayWarning:y(),chunks:{type:`array`,items:S()}},[`recording`,`outPath`,`artifacts`,`durationMs`,`showTouches`])]},trace:{type:`object`,oneOf:[x({trace:g(`started`),outPath:y()},[`trace`,`outPath`]),x({trace:g(`stopped`),outPath:y(),artifacts:{type:`array`,items:N}},[`trace`,`outPath`,`artifacts`])]}},be=x({settled:_(`Whether the UI held the quiet window before the deadline. false is advisory, not failure.`),waitedMs:h(),captures:h(),quietMs:h(),timeoutMs:h(),refsGeneration:h(`Snapshot generation of the stored settled tree; refs on added diff lines were minted from it.`),refs:{type:`array`,items:x({ref:y(`Plain ref body (e12) minted from the stored settled tree.`)},[`ref`])},surfaceChange:oe,diff:x({summary:x({additions:h(),removals:h(),unchanged:h()},[`additions`,`removals`,`unchanged`]),lines:{type:`array`,items:x({kind:b([`added`,`removed`]),text:y(),ref:y(`Plain ref body (e12) for added lines.`)},[`kind`,`text`])},truncated:_(`Lines were capped to the response bound.`)},[`summary`,`lines`],`Settled diff vs the pre-action tree (changed lines only).`),tail:{type:`array`,description:`Unchanged interactive refs tail: still-present, actionable elements from the settled tree, attached only when diff carries zero added-line refs (a modal-dismiss/toast-only diff).`,items:x({ref:y(`Plain ref body (e12) minted from the stored settled tree.`),role:y(),label:y()},[`ref`,`role`])},tailTruncated:_(`Present (true) when tail candidates exceeded the response cap.`),hint:y()},[`settled`,`waitedMs`,`captures`,`quietMs`,`timeoutMs`]);function F(e){return e.oneOf?{...e,oneOf:e.oneOf.map(F)}:{...e,properties:{...e.properties??{},settle:be}}}function xe(e){let t={...e};for(let e of Object.keys(t))m(e)&&(t[e]=F(t[e]));return t}const Se=xe({scroll:x({direction:b([`up`,`down`,`left`,`right`]),edge:b([`top`,`bottom`]),until:y(`Until scrolls only: the selector the passes stopped on.`),passes:h(`Edge and until scrolls only: how many scroll-and-check passes ran.`),amount:h(),pixels:h(),durationMs:h(),message:y(),keyboardAvoided:_(`Present only when an on-screen keyboard forced the swipe into the band above it; the reported pixels were planned against the shorter referenceHeight.`),keyboardMinY:h(`Where the keyboard began, in the same unit as the gesture coordinates. Clipped scrolls only.`),movement:b([`moved`,`at-edge`,`unchanged`,`unobserved`],"Directional scrolls only: what the owner observed after its gesture. `moved` means the content inside the scroller the swipe ran in differs from the tree the session stored immediately before the gesture; `at-edge` and `unchanged` mean it did not change, with no hidden content left to reveal and with no end-of-content signal to read, respectively; `unobserved` means the pair could not back a claim in either direction — nothing comparable was available (no stored tree, a capture from another lineage, a surface that never came to rest), or every difference sits outside the scroller that was swiped, which a changing status bar does on Android — so the reported distance rests on the gesture plan alone. The field is absent — which is never a claim that nothing moved — on the tiers that verify per pass (`scroll top`/`bottom`, `--until`), on a runtime bound without a capture, on a platform whose scroll dispatches no swipe (the Linux wheel), and where the caller already owns that observation (`--settle`, or a replay with `postGestureStabilization: false`).")},[`direction`]),...re,...pe,...ae,...ue,...le,...fe,...ce,...se,...P,...ie,...de}),Ce={devices:{type:`object`,properties:{devices:{type:`array`,items:{type:`object`,properties:{platform:{type:`string`,enum:s},target:{type:`string`,enum:c},kind:{type:`string`,enum:l},id:{type:`string`},name:{type:`string`}},required:[`platform`,`target`,`kind`,`id`,`name`]}}},required:[`devices`]},apps:{type:`object`,properties:{apps:{type:`array`,items:{type:`string`}}},required:[`apps`]}},I={...Se,...Ce},we={stateDir:{schema:{type:`string`,description:`Agent-device state directory.`},audience:v({operatorConfig:!0})},mcpOutputFormat:{schema:{type:`string`,enum:[`optimized`,`json`],description:`MCP text content format. Defaults to optimized agent-friendly text; use json for JSON text. Structured content is always returned separately.`}},includeCost:{schema:{type:`boolean`,description:`Include per-command agent-cost (cost.wallClockMs, …) in structuredContent. Defaults to off; the default response shape is unchanged.`}},responseLevel:{schema:{type:`string`,enum:[`digest`,`default`,`full`],description:`Response verbosity: token-cheap digest / default (today) / full. Defaults to default; the default response shape is unchanged.`}}},L=Object.entries(we),R=new Set(L.map(([e])=>e)),Te=Object.fromEntries(L.flatMap(([e,t])=>t.audience?[[e,t.audience]]:[]));function Ee(){return Object.fromEntries(L.map(([e,t])=>[e,t.schema]))}function z(e){return r(e)}function B(e){let n=[`Error (${e.code}): ${e.message}`];if(e.cause){let t=e.cause.code?`${e.cause.code} `:``;n.push(`Cause: ${t}${e.cause.message}`)}e.hint&&n.push(`Hint: ${e.hint}`);for(let t of me(e.details))n.push(`Warning: ${he(t)}`);n.push(...O(t(e.details))),e.supportedOn&&n.push(`Supported on: ${e.supportedOn}`);let r=ve(e.details);return r&&n.push(r),n.join(`
2
- `)}function De(e,t,n){let r=j({command:e,cwd:process.cwd(),cliFlags:t}),i={};for(let[t,a]of Object.entries(r))Object.hasOwn(n,t)&&A(t,e)&&(i[t]=a);return k(i,t)}const Oe={devices:async e=>({devices:e.map(M)}),apps:async e=>({apps:e})};async function ke(e,t){let n=Oe[e];return n?await n(t):t}function Ae(){let e=new Map;return{pinInput:(t,n,r)=>Ue(t,n,Pe(e,r,n.session)),mergeCommandResult:(t,n,r,i)=>Fe(e,t,n,r,i),mergeErrorDetails:(t,n,r)=>{let i=H(n,r);je(e,i,t),Ve(e,i,t)}}}function je(e,t,r){let i=r?.refsGeneration;typeof i==`number`&&U(e,t,n(r),i)}const V=new Set([`snapshot`,`find`]),Me=new Set(p.map(e=>e.name).filter(C).filter(e=>m(e))),Ne=new Set([`press`,`click`,`fill`,`longpress`,`hover`,`get`]);function Pe(e,t,n){return e.get(H(t,n))}function H(e,t){let n=typeof t==`string`&&t.length>0?t:`default`;return`${e??``}\u0000${n}`}function Fe(e,t,n,r,i){let a=H(r,i);if(Me.has(t)){Re(e,a,ze(n));return}V.has(t)&&(t===`find`?Le(e,a,n):Ie(e,a,n))}function Ie(e,t,n){let r=n.refsGeneration;if(typeof r!=`number`){e.delete(t);return}let i=[];for(let{ref:e}of n.refs??[])i.push(e);for(let e of n.nodes??[])i.push(e.ref);U(e,t,i,r)}function Le(e,t,n){let r=n.refsGeneration;if(typeof r!=`number`)return;let i=[];typeof n.ref==`string`&&n.ref.startsWith(`@`)&&i.push(n.ref.slice(1));for(let e of n.matches??[])typeof e.ref==`string`&&e.ref.length>0&&i.push(e.ref.startsWith(`@`)?e.ref.slice(1):e.ref);U(e,t,i,r)}function Re(e,t,n){n?.refsGeneration!==void 0&&U(e,t,[...n.diff?.lines??[],...n.refs??[],...n.tail??[]].map(e=>e.ref).filter(e=>typeof e==`string`),n.refsGeneration)}function ze(e){let t=e.settle;return typeof t==`object`&&t?t:void 0}function U(e,t,n,r){if(n.length===0)return;let i=e.get(t)??new Map;e.set(t,i),Be(i,n,r)}function Be(e,t,n){for(let r of t)e.delete(r),e.set(r,n);for(;e.size>1e3;)e.delete(e.keys().next().value)}function Ve(e,t,n){let r=o(n?.divergence),i=o(r?.screen);if(i?.state!==`available`)return;let a=i.refsGeneration;if(typeof a!=`number`)return;let s=[];He(i.refs,s),U(e,t,s,a)}function He(e,t){if(Array.isArray(e))for(let n of e){let e=o(n)?.ref;typeof e==`string`&&e.length>0&&t.push(e)}}function Ue(e,t,n){return n===void 0||n.size===0?t:e===`wait`?We(t,n)??t:Ne.has(e)?Ge(t,n)??t:t}function We(e,t){if(typeof e.ref!=`string`)return;let n=W(e.ref,t);return n===e.ref?void 0:{...e,ref:n}}function Ge(e,t){let n=o(e.target);if(n?.kind!==`ref`||typeof n.ref!=`string`)return;let r=W(n.ref,t);return r===n.ref?void 0:{...e,target:{...n,ref:r}}}function W(e,t){if(!e.startsWith(`@`)||e.includes(`~`))return e;let n=t.get(e.slice(1));return n===void 0?e:`${e}~s${n}`}const Ke={config:v({operatorPath:`Point the process serving these tools at a config file with the AGENT_DEVICE_CONFIG environment variable.`}),remoteConfig:v({operatorPath:`Configure the remote profile on the process serving these tools, not per tool call.`})},qe=Object.fromEntries(_e().flatMap(e=>Object.entries(e.inputAudience).filter(([,e])=>e.kind===`operator`)));function G(e){return{...e.inputAudience,...ee,...Te,...Ke,...qe}}function Je(){return ge().map(e=>{let t=e.name in I?I[e.name]:void 0,n=J(e.name,e);return{name:e.name,description:it(e.name,te(e)),inputSchema:n,...t?{outputSchema:t}:{}}})}function K(t={}){let n=Ae();return{execute:async(r,i)=>{if(!C(r))throw new e(`INVALID_ARGS`,`Unknown command tool: ${r}`);let a=w(r),o=Y(r,a,i)??X(a.inputSchema,i,r);if(o)return await q(new e(`INVALID_ARGS`,o),n,void 0,i.session);let s=Q(r,a.inputSchema).properties,c=De(r,i,s),l=Qe(c),u=nt(c),d=n.pinInput(r,u,l.client.stateDir),f=await Xe(t,l.client);try{let e=await(t.runCommand??Ze)(f,r,d);return n.mergeCommandResult(r,e,l.client.stateDir,u.session),{isError:!1,structuredContent:await ke(r,e),content:[{type:`text`,text:await at({name:r,input:u,result:e,outputFormat:l.outputFormat,responseLevel:l.client.responseLevel})}]}}catch(e){return await q(e,n,l.client.stateDir,u.session)}}}}async function q(e,t,n,r){let i=z(e);return t.mergeErrorDetails(i.details,n,r),{isError:!0,structuredContent:i,content:[{type:`text`,text:B(i)}]}}const Ye=K();async function Xe(e,t){if(e.createClient)return await e.createClient(t);let{createAgentDeviceClient:n}=await import(`./agent-device-client.js`).then(e=>e.t);return n(t)}async function Ze(e,t,n){return await(await import(`./command-surface.js`).then(e=>e.t)).runCommand(e,t,n)}function Qe(e){return{client:$e(e),outputFormat:tt(e.mcpOutputFormat)}}function $e(t){let n=t.stateDir,r=t.includeCost,i=t.responseLevel,a={};if(n!==void 0){if(typeof n!=`string`||n.length===0)throw new e(`INVALID_ARGS`,`Expected stateDir to be a non-empty string.`);a.stateDir=n}if(r!==void 0){if(typeof r!=`boolean`)throw new e(`INVALID_ARGS`,`Expected includeCost to be a boolean.`);r&&(a.cost=!0)}let o=et(i);return o!==void 0&&(a.responseLevel=o),a}function et(t){if(t===void 0)return;let n=i.find(e=>e===t);if(n===void 0)throw new e(`INVALID_ARGS`,`Expected responseLevel to be one of 'digest', 'default', or 'full'.`);return n}function tt(t){if(t===void 0)return`optimized`;if(t!==`optimized`&&t!==`json`)throw new e(`INVALID_ARGS`,`Expected mcpOutputFormat to be "optimized" or "json".`);return t}function nt(e){return Object.fromEntries(Object.entries(e).filter(([e])=>!R.has(e)))}function J(e,t){let n=G(t),r=Q(e,t.inputSchema);return{...r,properties:Object.fromEntries(Object.entries(r.properties).filter(([e])=>n[e]?.kind!==`operator`))}}function Y(e,t,n){let r=J(e,t).properties,i=G(t);for(let t of Object.keys(n)){if(Object.hasOwn(r,t))continue;let n=Object.hasOwn(i,t)?i[t]:void 0;if(n?.kind!==`retired`)return n?.kind===`operator`?ne(t,n.source):`${t} is not an accepted argument for the ${e} tool.`}}function X(e,t,n){if(!(!e||t===void 0)){if(Array.isArray(t))return Z(t,(t,r)=>X(e.items,t,`${n}[${r}]`));if(a(t))return Z(e.oneOf??[],e=>X(e,t,n))??Z(Object.entries(e.properties??{}),([e,r])=>Object.hasOwn(t,e)?rt(r,t,e,`${n}.${e}`):void 0)}}function rt(e,t,n,r){let i=e.commandInputFor;if(i===void 0)return X(e,t[n],r);let o=t[n],s=f(t[i]);if(s===void 0||!a(o))return;let c=Y(s,w(s),o);return c===void 0?void 0:`${r}: ${c}`}function Z(e,t){for(let[n,r]of e.entries()){let e=t(r,n);if(e)return e}}function it(e,t){let n=d(e);if(n.envelopeMs===`unbounded`)return`${t} Streams progress; no fixed client timeout.`;let r=Math.round(n.envelopeMs/1e3);return n.budget.source===`none`?`${t} Times out after ${r}s.`:`${t} Times out after ${r}s; a caller-supplied budget extends it.`}function Q(e,t){let n=u(e);return{...t,properties:{...t.properties,...n&&!t.properties?.noRecord?{noRecord:{type:`boolean`,description:`Do not record this action.`}}:{},...Ee()}}}async function at(e){if(e.outputFormat===`json`||e.responseLevel!==void 0&&e.responseLevel!=="default")return $(e.result);let t=await T({name:e.name,input:e.input,result:e.result});return typeof t?.text==`string`?ot(e.name,t):$(t?.data??e.result)}function ot(e,t){let n=t.text??``;if(!ye(e))return n;let r=t.stderr?.trimEnd()??``;return r===``?n:`${n}${n.endsWith(`
1
+ import{N as e,X as t,Y as n,q as r,r as i}from"./sdk-contracts.js";import{_ as a,h as o}from"./sdk-batch-runner.js";import{a as s,n as c,t as l}from"./sdk-device.js";import{C as u,T as d,c as f,f as ee,m as p}from"./sdk-batch.js";import{A as m,D as h,F as te,I as g,M as _,N as v,O as y,R as b,_ as ne,d as re,f as ie,g as ae,h as oe,j as x,k as S,l as se,m as ce,s as le,u as ue,x as de,y as fe,z as pe}from"./registry.js";import{n as me}from"./success-text.js";import{t as he}from"./output-common.js";import{i as ge,n as C,r as _e,t as w}from"./command-metadata.js";import{r as ve}from"./replay-divergence.js";import{n as ye,t as T}from"./cli-output.js";import{r as E,t as D}from"./recording-stop-observation.js";import{n as O}from"./error.js";import{n as k,r as A,t as j}from"./cli-config.js";import{n as M}from"./result-serialization.js";const N=_({field:v(),artifactType:v(),path:v(),localPath:v(),fileName:v()},[`field`]),P={record:{type:`object`,oneOf:[_({recording:y(`started`),outPath:v(),sessionStateDir:v(),recordingBackend:v(),recordingScope:v(),recordOnlySession:h(),activeSessionApp:m(),showTouches:h()},[`recording`,`outPath`,`sessionStateDir`,`showTouches`]),_({recording:y(`stopped`),outPath:v(),telemetryPath:v(),artifacts:{type:`array`,items:N},recordingBackend:v(),recordingScope:v(),recordOnlySession:h(),activeSessionApp:m(),durationMs:x(),capturedDurationMs:x(),recorder:S(D,`What the recorder was observed doing when the recording was stopped: confirmed, or lost when the session holding it died. ADR 0024 reserves unconfirmed for the step that gains the probe.`),nativePathDisposition:S(E,`What became of the artifact path the recorder writes to: retirable while it still owes a removal, retired once that removal was verified. ADR 0024 reserves pending.`),showTouches:h(),warning:v(),overlayWarning:v(),chunks:{type:`array`,items:m()}},[`recording`,`outPath`,`artifacts`,`durationMs`,`showTouches`])]},trace:{type:`object`,oneOf:[_({trace:y(`started`),outPath:v()},[`trace`,`outPath`]),_({trace:y(`stopped`),outPath:v(),artifacts:{type:`array`,items:N}},[`trace`,`outPath`,`artifacts`])]}},be=_({settled:h(`Whether the UI held the quiet window before the deadline. false is advisory, not failure.`),waitedMs:x(),captures:x(),quietMs:x(),timeoutMs:x(),refsGeneration:x(`Snapshot generation of the stored settled tree; refs on added diff lines were minted from it.`),refs:{type:`array`,items:_({ref:v(`Plain ref body (e12) minted from the stored settled tree.`)},[`ref`])},surfaceChange:ne,diff:_({summary:_({additions:x(),removals:x(),unchanged:x()},[`additions`,`removals`,`unchanged`]),lines:{type:`array`,items:_({kind:S([`added`,`removed`]),text:v(),ref:v(`Plain ref body (e12) for added lines.`)},[`kind`,`text`])},truncated:h(`Lines were capped to the response bound.`)},[`summary`,`lines`],`Settled diff vs the pre-action tree (changed lines only).`),tail:{type:`array`,description:`Unchanged interactive refs tail: still-present, actionable elements from the settled tree, attached only when diff carries zero added-line refs (a modal-dismiss/toast-only diff).`,items:_({ref:v(`Plain ref body (e12) minted from the stored settled tree.`),role:v(),label:v()},[`ref`,`role`])},tailTruncated:h(`Present (true) when tail candidates exceeded the response cap.`),hint:v()},[`settled`,`waitedMs`,`captures`,`quietMs`,`timeoutMs`]);function F(e){return e.oneOf?{...e,oneOf:e.oneOf.map(F)}:{...e,properties:{...e.properties??{},settle:be}}}function xe(e){let t={...e};for(let e of Object.keys(t))p(e)&&(t[e]=F(t[e]));return t}const Se=xe({scroll:_({direction:S([`up`,`down`,`left`,`right`]),edge:S([`top`,`bottom`]),until:v(`Until scrolls only: the selector the passes stopped on.`),passes:x(`Edge and until scrolls only: how many scroll-and-check passes ran.`),amount:x(),pixels:x(),durationMs:x(),message:v(),keyboardAvoided:h(`Present only when an on-screen keyboard forced the swipe into the band above it; the reported pixels were planned against the shorter referenceHeight.`),keyboardMinY:x(`Where the keyboard began, in the same unit as the gesture coordinates. Clipped scrolls only.`),movement:S([`moved`,`at-edge`,`unchanged`,`unobserved`],"Directional scrolls only: what the owner observed after its gesture. `moved` means the content inside the scroller the swipe ran in differs from the tree the session stored immediately before the gesture; `at-edge` and `unchanged` mean it did not change, with no hidden content left to reveal and with no end-of-content signal to read, respectively; `unobserved` means the pair could not back a claim in either direction — nothing comparable was available (no stored tree, a capture from another lineage, a surface that never came to rest), or every difference sits outside the scroller that was swiped, which a changing status bar does on Android — so the reported distance rests on the gesture plan alone. The field is absent — which is never a claim that nothing moved — on the tiers that verify per pass (`scroll top`/`bottom`, `--until`), on a runtime bound without a capture, on a platform whose scroll dispatches no swipe (the Linux wheel), and where the caller already owns that observation (`--settle`, or a replay with `postGestureStabilization: false`).")},[`direction`]),...de,...fe,...ie,...ce,...oe,...re,...ue,...ae,...P,...se,...le}),Ce={devices:{type:`object`,properties:{devices:{type:`array`,items:{type:`object`,properties:{platform:{type:`string`,enum:s},target:{type:`string`,enum:c},kind:{type:`string`,enum:l},id:{type:`string`},name:{type:`string`}},required:[`platform`,`target`,`kind`,`id`,`name`]}}},required:[`devices`]},apps:{type:`object`,properties:{apps:{type:`array`,items:{type:`string`}}},required:[`apps`]}},I={...Se,...Ce},we={stateDir:{schema:{type:`string`,description:`Agent-device state directory.`},audience:b({operatorConfig:!0})},mcpOutputFormat:{schema:{type:`string`,enum:[`optimized`,`json`],description:`MCP text content format. Defaults to optimized agent-friendly text; use json for JSON text. Structured content is always returned separately.`}},includeCost:{schema:{type:`boolean`,description:`Include per-command agent-cost (cost.wallClockMs, …) in structuredContent. Defaults to off; the default response shape is unchanged.`}},responseLevel:{schema:{type:`string`,enum:[`digest`,`default`,`full`],description:`Response verbosity: token-cheap digest / default (today) / full. Defaults to default; the default response shape is unchanged.`}}},L=Object.entries(we),R=new Set(L.map(([e])=>e)),Te=Object.fromEntries(L.flatMap(([e,t])=>t.audience?[[e,t.audience]]:[]));function Ee(){return Object.fromEntries(L.map(([e,t])=>[e,t.schema]))}function z(e){return r(e)}function B(e){let n=[`Error (${e.code}): ${e.message}`];if(e.cause){let t=e.cause.code?`${e.cause.code} `:``;n.push(`Cause: ${t}${e.cause.message}`)}e.hint&&n.push(`Hint: ${e.hint}`);for(let t of me(e.details))n.push(`Warning: ${he(t)}`);n.push(...O(t(e.details))),e.supportedOn&&n.push(`Supported on: ${e.supportedOn}`);let r=ve(e.details);return r&&n.push(r),n.join(`
2
+ `)}function De(e,t,n){let r=j({command:e,cwd:process.cwd(),cliFlags:t}),i={};for(let[t,a]of Object.entries(r))Object.hasOwn(n,t)&&A(t,e)&&(i[t]=a);return k(i,t)}const Oe={devices:async e=>({devices:e.map(M)}),apps:async e=>({apps:e})};async function ke(e,t){let n=Oe[e];return n?await n(t):t}function Ae(){let e=new Map;return{pinInput:(t,n,r)=>Ue(t,n,Pe(e,r,n.session)),mergeCommandResult:(t,n,r,i)=>Fe(e,t,n,r,i),mergeErrorDetails:(t,n,r)=>{let i=H(n,r);je(e,i,t),Ve(e,i,t)}}}function je(e,t,r){let i=r?.refsGeneration;typeof i==`number`&&U(e,t,n(r),i)}const V=new Set([`snapshot`,`find`]),Me=new Set(ee.map(e=>e.name).filter(C).filter(e=>p(e))),Ne=new Set([`press`,`click`,`fill`,`longpress`,`hover`,`get`]);function Pe(e,t,n){return e.get(H(t,n))}function H(e,t){let n=typeof t==`string`&&t.length>0?t:`default`;return`${e??``}\u0000${n}`}function Fe(e,t,n,r,i){let a=H(r,i);if(Me.has(t)){Re(e,a,ze(n));return}V.has(t)&&(t===`find`?Le(e,a,n):Ie(e,a,n))}function Ie(e,t,n){let r=n.refsGeneration;if(typeof r!=`number`){e.delete(t);return}let i=[];for(let{ref:e}of n.refs??[])i.push(e);for(let e of n.nodes??[])i.push(e.ref);U(e,t,i,r)}function Le(e,t,n){let r=n.refsGeneration;if(typeof r!=`number`)return;let i=[];typeof n.ref==`string`&&n.ref.startsWith(`@`)&&i.push(n.ref.slice(1));for(let e of n.matches??[])typeof e.ref==`string`&&e.ref.length>0&&i.push(e.ref.startsWith(`@`)?e.ref.slice(1):e.ref);U(e,t,i,r)}function Re(e,t,n){n?.refsGeneration!==void 0&&U(e,t,[...n.diff?.lines??[],...n.refs??[],...n.tail??[]].map(e=>e.ref).filter(e=>typeof e==`string`),n.refsGeneration)}function ze(e){let t=e.settle;return typeof t==`object`&&t?t:void 0}function U(e,t,n,r){if(n.length===0)return;let i=e.get(t)??new Map;e.set(t,i),Be(i,n,r)}function Be(e,t,n){for(let r of t)e.delete(r),e.set(r,n);for(;e.size>1e3;)e.delete(e.keys().next().value)}function Ve(e,t,n){let r=o(n?.divergence),i=o(r?.screen);if(i?.state!==`available`)return;let a=i.refsGeneration;if(typeof a!=`number`)return;let s=[];He(i.refs,s),U(e,t,s,a)}function He(e,t){if(Array.isArray(e))for(let n of e){let e=o(n)?.ref;typeof e==`string`&&e.length>0&&t.push(e)}}function Ue(e,t,n){return n===void 0||n.size===0?t:e===`wait`?We(t,n)??t:Ne.has(e)?Ge(t,n)??t:t}function We(e,t){if(typeof e.ref!=`string`)return;let n=W(e.ref,t);return n===e.ref?void 0:{...e,ref:n}}function Ge(e,t){let n=o(e.target);if(n?.kind!==`ref`||typeof n.ref!=`string`)return;let r=W(n.ref,t);return r===n.ref?void 0:{...e,target:{...n,ref:r}}}function W(e,t){if(!e.startsWith(`@`)||e.includes(`~`))return e;let n=t.get(e.slice(1));return n===void 0?e:`${e}~s${n}`}const Ke={config:b({operatorPath:`Point the process serving these tools at a config file with the AGENT_DEVICE_CONFIG environment variable.`}),remoteConfig:b({operatorPath:`Configure the remote profile on the process serving these tools, not per tool call.`})},qe=Object.fromEntries(_e().flatMap(e=>Object.entries(e.inputAudience).filter(([,e])=>e.kind===`operator`)));function G(e){return{...e.inputAudience,...g,...Te,...Ke,...qe}}function Je(){return ge().map(e=>{let t=e.name in I?I[e.name]:void 0,n=J(e.name,e);return{name:e.name,description:it(e.name,te(e)),inputSchema:n,...t?{outputSchema:t}:{}}})}function K(t={}){let n=Ae();return{execute:async(r,i)=>{if(!C(r))throw new e(`INVALID_ARGS`,`Unknown command tool: ${r}`);let a=w(r),o=Y(r,a,i)??X(a.inputSchema,i,r);if(o)return await q(new e(`INVALID_ARGS`,o),n,void 0,i.session);let s=Q(r,a.inputSchema).properties,c=De(r,i,s),l=Qe(c),u=nt(c),d=n.pinInput(r,u,l.client.stateDir),f=await Xe(t,l.client);try{let e=await(t.runCommand??Ze)(f,r,d);return n.mergeCommandResult(r,e,l.client.stateDir,u.session),{isError:!1,structuredContent:await ke(r,e),content:[{type:`text`,text:await at({name:r,input:u,result:e,outputFormat:l.outputFormat,responseLevel:l.client.responseLevel})}]}}catch(e){return await q(e,n,l.client.stateDir,u.session)}}}}async function q(e,t,n,r){let i=z(e);return t.mergeErrorDetails(i.details,n,r),{isError:!0,structuredContent:i,content:[{type:`text`,text:B(i)}]}}const Ye=K();async function Xe(e,t){if(e.createClient)return await e.createClient(t);let{createAgentDeviceClient:n}=await import(`./agent-device-client.js`).then(e=>e.t);return n(t)}async function Ze(e,t,n){return await(await import(`./command-surface.js`).then(e=>e.t)).runCommand(e,t,n)}function Qe(e){return{client:$e(e),outputFormat:tt(e.mcpOutputFormat)}}function $e(t){let n=t.stateDir,r=t.includeCost,i=t.responseLevel,a={};if(n!==void 0){if(typeof n!=`string`||n.length===0)throw new e(`INVALID_ARGS`,`Expected stateDir to be a non-empty string.`);a.stateDir=n}if(r!==void 0){if(typeof r!=`boolean`)throw new e(`INVALID_ARGS`,`Expected includeCost to be a boolean.`);r&&(a.cost=!0)}let o=et(i);return o!==void 0&&(a.responseLevel=o),a}function et(t){if(t===void 0)return;let n=i.find(e=>e===t);if(n===void 0)throw new e(`INVALID_ARGS`,`Expected responseLevel to be one of 'digest', 'default', or 'full'.`);return n}function tt(t){if(t===void 0)return`optimized`;if(t!==`optimized`&&t!==`json`)throw new e(`INVALID_ARGS`,`Expected mcpOutputFormat to be "optimized" or "json".`);return t}function nt(e){return Object.fromEntries(Object.entries(e).filter(([e])=>!R.has(e)))}function J(e,t){let n=G(t),r=Q(e,t.inputSchema);return{...r,properties:Object.fromEntries(Object.entries(r.properties).filter(([e])=>n[e]?.kind!==`operator`))}}function Y(e,t,n){let r=J(e,t).properties,i=G(t);for(let t of Object.keys(n)){if(Object.hasOwn(r,t))continue;let n=Object.hasOwn(i,t)?i[t]:void 0;if(n?.kind!==`retired`)return n?.kind===`operator`?pe(t,n.source):`${t} is not an accepted argument for the ${e} tool.`}}function X(e,t,n){if(!(!e||t===void 0)){if(Array.isArray(t))return Z(t,(t,r)=>X(e.items,t,`${n}[${r}]`));if(a(t))return Z(e.oneOf??[],e=>X(e,t,n))??Z(Object.entries(e.properties??{}),([e,r])=>Object.hasOwn(t,e)?rt(r,t,e,`${n}.${e}`):void 0)}}function rt(e,t,n,r){let i=e.commandInputFor;if(i===void 0)return X(e,t[n],r);let o=t[n],s=f(t[i]);if(s===void 0||!a(o))return;let c=Y(s,w(s),o);return c===void 0?void 0:`${r}: ${c}`}function Z(e,t){for(let[n,r]of e.entries()){let e=t(r,n);if(e)return e}}function it(e,t){let n=d(e);if(n.envelopeMs===`unbounded`)return`${t} Streams progress; no fixed client timeout.`;let r=Math.round(n.envelopeMs/1e3);return n.budget.source===`none`?`${t} Times out after ${r}s.`:`${t} Times out after ${r}s; a caller-supplied budget extends it.`}function Q(e,t){let n=u(e);return{...t,properties:{...t.properties,...n&&!t.properties?.noRecord?{noRecord:{type:`boolean`,description:`Do not record this action.`}}:{},...Ee()}}}async function at(e){if(e.outputFormat===`json`||e.responseLevel!==void 0&&e.responseLevel!=="default")return $(e.result);let t=await T({name:e.name,input:e.input,result:e.result});return typeof t?.text==`string`?ot(e.name,t):$(t?.data??e.result)}function ot(e,t){let n=t.text??``;if(!ye(e))return n;let r=t.stderr?.trimEnd()??``;return r===``?n:`${n}${n.endsWith(`
3
3
  `)?``:`
4
4
  `}${r}`}function $(e){return typeof e==`string`?e:JSON.stringify(e,null,2)}export{z as a,B as i,K as n,R as o,Je as r,Ye as t};
@@ -1 +1 @@
1
- import{r as e}from"./rolldown-runtime.js";import{_ as t,a as n,c as r,d as i,f as a,g as o,h as s,i as c,l,n as u,o as d,p as f,r as p,s as m,t as h,u as g}from"./exec.js";var _=e({coerceExecResult:()=>h,execFailureDetails:()=>u,isCommandTimeoutError:()=>p,isExecutablePath:()=>c,requireExecSuccess:()=>n,resolveExecutableOverridePath:()=>d,resolveFileOverridePath:()=>m,runCmd:()=>r,runCmdBackground:()=>l,runCmdDetached:()=>g,runCmdDetachedMonitored:()=>i,runCmdStreaming:()=>a,runCmdSync:()=>f,whichCmd:()=>s,withCommandExecutorOverride:()=>o,withoutCommandExecutorOverride:()=>t});export{_ as t};
1
+ import{r as e}from"./rolldown-runtime.js";import{_ as t,a as n,c as r,d as i,f as a,g as o,i as s,l as c,m as l,n as u,o as d,p as f,r as p,s as m,t as h,u as g,v as _,y as v}from"./exec.js";var y=e({coerceExecResult:()=>h,commandDeveloperDir:()=>u,execFailureDetails:()=>p,isCommandTimeoutError:()=>s,isExecutablePath:()=>n,requireExecSuccess:()=>d,resolveExecutableOverridePath:()=>m,resolveFileOverridePath:()=>r,runCmd:()=>c,runCmdBackground:()=>g,runCmdDetached:()=>i,runCmdDetachedMonitored:()=>a,runCmdStreaming:()=>f,runCmdSync:()=>l,whichCmd:()=>o,withCommandExecutorOverride:()=>t,withRequestCommandEnv:()=>_,withoutCommandExecutorOverride:()=>v});export{y as t};
@@ -1 +1 @@
1
- const e=18e4,t=6e4,n=6e4,r=2e4,i=12e4,a=1e4,o=15e3,s=2e4,c=5e3,l=2e4,u=.5,d=15e3,f=2e4,p=1e3,m=5e3;export{i as a,f as c,p as d,m as f,o as h,r as i,t as l,s as m,n,u as o,d as p,e as r,l as s,c as t,a as u};
1
+ const e=18e4,t=6e4,n=6e4,r=2e4,i=12e4,a=1e4,o=15e3,s=2e4,c=2e4,l=5e3,u=2e4,d=.5,f=15e3,p=2e4,m=1e3,h=5e3;export{i as a,p as c,s as d,m as f,o as g,c as h,r as i,t as l,f as m,n,d as o,h as p,e as r,u as s,l as t,a as u};