agent-device 0.21.7 → 0.21.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.7.apk → agent-device-android-ime-helper-0.21.9.apk} +0 -0
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.9.apk.sha256 +1 -0
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.7.manifest.json → agent-device-android-ime-helper-0.21.9.manifest.json} +4 -4
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.21.7.apk → agent-device-android-snapshot-helper-0.21.9.apk} +0 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.9.apk.sha256 +1 -0
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.21.7.manifest.json → agent-device-android-snapshot-helper-0.21.9.manifest.json} +6 -6
- package/apple/macos-helper/Package.swift +16 -1
- package/apple/macos-helper/Sources/AgentDeviceMacOSDeviceHub/DeviceHubPose.swift +47 -0
- package/apple/macos-helper/Sources/AgentDeviceMacOSDeviceHub/DeviceHubWindowInventory.swift +65 -0
- package/apple/macos-helper/Sources/AgentDeviceMacOSHelper/DeviceHubPose.swift +225 -0
- package/apple/macos-helper/Sources/AgentDeviceMacOSHelper/DeviceHubSidebar.swift +57 -0
- package/apple/macos-helper/Sources/AgentDeviceMacOSHelper/DeviceHubWindowDiscovery.swift +108 -0
- package/apple/macos-helper/Sources/AgentDeviceMacOSHelper/main.swift +66 -13
- package/apple/macos-helper/Sources/AgentDeviceMacOSInput/MouseClickDelivery.swift +116 -0
- package/apple/macos-helper/Sources/AgentDeviceMacOSInput/MouseClickSchedule.swift +61 -0
- package/apple/macos-helper/Tests/AgentDeviceMacOSDeviceHubTests/DeviceHubPoseTests.swift +30 -0
- package/apple/macos-helper/Tests/AgentDeviceMacOSDeviceHubTests/DeviceHubWindowInventoryTests.swift +65 -0
- package/apple/macos-helper/Tests/AgentDeviceMacOSInputTests/MouseClickScheduleTests.swift +58 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/AgentDeviceRunnerUITests-Bridging-Header.h +1 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAppScreenCapture.swift +175 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedGesture.h +10 -2
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedGesture.m +42 -15
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Alert.swift +8 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +45 -22
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +39 -734
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Keyboard.swift +20 -4
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Lifecycle.swift +63 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +13 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Navigation.swift +25 -10
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +5 -562
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotAcquisition.swift +566 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedGesturePolicy.swift +5 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedInteraction.swift +594 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerXCTestEventBridge.h +35 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerXCTestEventBridge.m +160 -0
- package/dist/apple/runner/AgentDeviceRunner/RecordingScripts/RecordingExportSupport.swift +3 -0
- package/dist/apple/runner/AgentDeviceRunner/RecordingScripts/recording-frames.swift +203 -0
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotCoordinateSpace.swift +5 -0
- package/dist/src/absence-observation-errors.js +1 -1
- package/dist/src/adapter.js +1 -1
- package/dist/src/agent-browser-lifecycle.js +1 -1
- package/dist/src/agent-browser-process-record.js +1 -1
- package/dist/src/agent-device-client.js +2 -2
- package/dist/src/alert-runtime.js +1 -1
- package/dist/src/android-adb.js +1 -1
- package/dist/src/android-input-ownership.js +1 -1
- package/dist/src/android.js +1 -1
- package/dist/src/app-launch.js +1 -1
- package/dist/src/app-log-runtime2.js +3 -3
- package/dist/src/app-resolution.js +2 -2
- package/dist/src/apple-runner-platform.js +1 -1
- package/dist/src/application-lifecycle-interaction.js +1 -1
- package/dist/src/artifact-paths.js +1 -0
- package/dist/src/back-mode.js +1 -1
- package/dist/src/cli-config.js +1 -1
- package/dist/src/cli-help.js +15 -11
- package/dist/src/cli.js +4 -4
- package/dist/src/client-types.d.ts +51 -1
- package/dist/src/command-tools.js +3 -3
- package/dist/src/config.js +1 -1
- package/dist/src/connection-runtime.js +1 -1
- package/dist/src/device-claim-inspection.js +1 -1
- package/dist/src/device-claim-rule.js +2 -2
- package/dist/src/device-input-state.d.ts +1 -1
- package/dist/src/device-rotation.js +1 -1
- package/dist/src/device-selection-resolver.js +1 -1
- package/dist/src/device-session.js +1 -1
- package/dist/src/device.js +1 -1
- package/dist/src/device2.js +1 -1
- package/dist/src/devicectl.js +1 -1
- package/dist/src/dispatch-resolve.js +1 -1
- package/dist/src/display-inventory.js +1 -1
- package/dist/src/doctor-facade.js +1 -1
- package/dist/src/durable-resource.js +1 -1
- package/dist/src/exec.js +1 -1
- package/dist/src/find.js +1 -1
- package/dist/src/finders.js +1 -1
- package/dist/src/fold-runtime.js +1 -0
- package/dist/src/gesture-admission.js +1 -1
- package/dist/src/gesture-runtime.js +1 -1
- package/dist/src/harmonyos.js +1 -1
- package/dist/src/helper.js +2 -2
- package/dist/src/host.js +1 -0
- package/dist/src/interaction-positionals.js +1 -1
- package/dist/src/interaction-ref-policy.js +1 -1
- package/dist/src/interaction.js +1 -1
- package/dist/src/interaction2.js +1 -1
- package/dist/src/interactor-operation-binding.js +1 -0
- package/dist/src/interactor-operation-catalog.js +1 -1
- package/dist/src/interactor.js +4 -5
- package/dist/src/interactor2.js +1 -1
- package/dist/src/interactors.js +1 -1
- package/dist/src/internal/bin.js +1 -1
- package/dist/src/internal/daemon.js +2 -2
- package/dist/src/internal/png-worker.d.ts +5 -0
- package/dist/src/internal/png-worker.js +1 -1
- package/dist/src/inventory2.js +1 -1
- package/dist/src/ios-snapshot-acquisition.js +1 -1
- package/dist/src/ios-snapshot-runtime.js +1 -1
- package/dist/src/lease.js +1 -1
- package/dist/src/linux.js +1 -1
- package/dist/src/local-interactor-operation-set.js +1 -1
- package/dist/src/location-coordinates.js +1 -1
- package/dist/src/macos-facade.js +1 -1
- package/dist/src/managed-device-scope.js +1 -1
- package/dist/src/mechanics.js +17 -16
- package/dist/src/mobile-snapshot-semantics.js +1 -1
- package/dist/src/mp4-duration.js +1 -0
- package/dist/src/multitouch-support.js +1 -1
- package/dist/src/owner-identity.js +1 -1
- package/dist/src/parameterized-recorded-fill.js +1 -1
- package/dist/src/perf-facade.js +2 -2
- package/dist/src/perf-runtime-plan.js +1 -1
- package/dist/src/physical-device-control.js +1 -1
- package/dist/src/platform-request-scope.js +1 -1
- package/dist/src/platform-runtime-managed-owner.js +1 -1
- package/dist/src/platform-runtime-open-target.js +1 -1
- package/dist/src/platform-runtime-operation-host.js +2 -2
- package/dist/src/platform-runtime-runtime-hints.js +1 -1
- package/dist/src/platform-runtime-screen-recording-finalizer-host.js +1 -1
- package/dist/src/platform-runtime-unavailable.js +1 -1
- package/dist/src/platform-runtime.js +1 -1
- package/dist/src/platform-runtime2.js +1 -1
- package/dist/src/png-crop-bytes.js +1 -1
- package/dist/src/png-encode.js +1 -0
- package/dist/src/png-size.js +1 -0
- package/dist/src/png-worker-client.js +1 -1
- package/dist/src/provider-webdriver.js +1 -1
- package/dist/src/quality-warnings.js +1 -1
- package/dist/src/react-native.js +1 -1
- package/dist/src/record-runtime.js +1 -1
- package/dist/src/recording-export-quality.js +1 -1
- package/dist/src/recording-scope.js +1 -0
- package/dist/src/recording.js +3 -0
- package/dist/src/registry.js +35 -35
- package/dist/src/replay.js +1 -1
- package/dist/src/request-admission.js +1 -1
- package/dist/src/request-runtime-binding.js +1 -1
- package/dist/src/result-serialization.js +1 -1
- package/dist/src/runner-cache-metadata.js +2 -2
- package/dist/src/runner-client.js +1 -1
- package/dist/src/runner-contract.js +3 -0
- package/dist/src/runner-dev-tools-security.js +1 -0
- package/dist/src/runner-device-readiness.js +1 -0
- package/dist/src/runner-disposal.js +1 -1
- package/dist/src/runner-operations-facade.js +1 -1
- package/dist/src/runner-presentation.js +1 -1
- package/dist/src/runner.js +1 -1
- package/dist/src/runtime.js +2 -2
- package/dist/src/runtime10.js +2 -1
- package/dist/src/runtime2.js +4 -4
- package/dist/src/runtime4.js +5 -5
- package/dist/src/runtime5.js +1 -1
- package/dist/src/runtime6.js +1 -1
- package/dist/src/runtime7.js +1 -1
- package/dist/src/runtime8.js +1 -1
- package/dist/src/runtime9.js +1 -1
- package/dist/src/screen-recording-admission-ledger.js +1 -1
- package/dist/src/screen-recording-resource-recovery.js +1 -1
- package/dist/src/screen-recording-transport.js +1 -1
- package/dist/src/screenshot-density.js +1 -1
- package/dist/src/screenshot-image.js +1 -0
- package/dist/src/screenshot-overlay-draw.js +1 -0
- package/dist/src/screenshot-runtime.js +1 -1
- package/dist/src/script.js +1 -1
- package/dist/src/scroll-gesture.js +1 -1
- package/dist/src/sdk-batch.js +2 -2
- package/dist/src/sdk-contracts.d.ts +7 -5
- package/dist/src/sdk-contracts.js +2 -2
- package/dist/src/sdk-device.js +1 -1
- package/dist/src/sdk-finders.js +1 -1
- package/dist/src/sdk-selectors.d.ts +58 -6
- package/dist/src/sdk-selectors.js +1 -1
- package/dist/src/selection.js +0 -0
- package/dist/src/selector-runtime.js +1 -1
- package/dist/src/selectors.js +1 -1
- package/dist/src/semantic-index.js +1 -1
- package/dist/src/session-routing.js +1 -1
- package/dist/src/session-snapshot.js +1 -1
- package/dist/src/session-store.js +3 -3
- package/dist/src/session2.js +3 -3
- package/dist/src/simctl.js +1 -1
- package/dist/src/simulator-boot.js +1 -1
- package/dist/src/simulator-facade.js +1 -1
- package/dist/src/simulator.js +1 -1
- package/dist/src/snapshot-runtime-binding.js +1 -1
- package/dist/src/snapshot-runtime.js +1 -1
- package/dist/src/snapshot-state.js +1 -1
- package/dist/src/snapshot4.js +1 -1
- package/dist/src/src.js +1 -1
- package/dist/src/src7.js +1 -1
- package/dist/src/src8.js +1 -1
- package/dist/src/stop-sequence.js +1 -1
- package/dist/src/text-entry-focus.js +1 -1
- package/dist/src/touch-runtime.js +1 -1
- package/dist/src/tree.js +1 -1
- package/dist/src/type-text-runtime.js +1 -1
- package/dist/src/video.js +2 -2
- package/dist/src/web2.js +1 -1
- package/package.json +3 -1
- package/server.json +2 -2
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.7.apk.sha256 +0 -1
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.7.apk.sha256 +0 -1
- package/dist/src/png-transcode.js +0 -1
package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerXCTestEventBridge.m
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
#import "RunnerXCTestEventBridge.h"
|
|
2
|
+
#import "RunnerObjCExceptionCatcher.h"
|
|
3
|
+
#import <CoreGraphics/CoreGraphics.h>
|
|
4
|
+
#import <math.h>
|
|
2
5
|
|
|
3
6
|
NSString * _Nullable RunnerResolveXCTestEventBridge(
|
|
4
7
|
id application,
|
|
@@ -87,3 +90,160 @@ NSString *RunnerFormatXCTestException(NSException *exception, NSString *fallback
|
|
|
87
90
|
NSString *reason = exception.reason ?: fallbackReason;
|
|
88
91
|
return [NSString stringWithFormat:@"%@: %@", name, reason];
|
|
89
92
|
}
|
|
93
|
+
|
|
94
|
+
static BOOL RunnerUsableWindowFrame(CGRect frame) {
|
|
95
|
+
if (CGRectIsEmpty(frame) || CGRectIsInfinite(frame) || CGRectIsNull(frame)) {
|
|
96
|
+
return NO;
|
|
97
|
+
}
|
|
98
|
+
return isfinite(frame.origin.x) && isfinite(frame.origin.y)
|
|
99
|
+
&& isfinite(frame.size.width) && isfinite(frame.size.height);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
static NSString *RunnerApplicationScreenFailureDescription(
|
|
103
|
+
RunnerApplicationScreenFailure failure
|
|
104
|
+
) {
|
|
105
|
+
switch (failure) {
|
|
106
|
+
case RunnerApplicationScreenFailureUnresolvedWindow:
|
|
107
|
+
return @"no resolved application window";
|
|
108
|
+
case RunnerApplicationScreenFailureUnresolvedScreen:
|
|
109
|
+
return @"no resolved window display ID";
|
|
110
|
+
case RunnerApplicationScreenFailureNone:
|
|
111
|
+
return @"application screen resolved";
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// One window read. XCTest answers with a value or raises. The window object is handed back because
|
|
116
|
+
// resolving this instance is what its `screen` will answer from — re-querying `firstMatch` would
|
|
117
|
+
// return an unresolved element that still names the main screen.
|
|
118
|
+
//
|
|
119
|
+
// Both answers are required. An app with no window answers `frame` with `(0,0 0x0)` without raising,
|
|
120
|
+
// which geometry alone would read as a window the runtime has not measured, and only the query
|
|
121
|
+
// itself says whether it has one. Measured on a live Duo: the runner host process, which has no
|
|
122
|
+
// window, answers `exists` NO and `frame` `(0,0 0x0)` (#2728).
|
|
123
|
+
//
|
|
124
|
+
// The frame the read produced is reported even when it is refused: a capture that fails closed has
|
|
125
|
+
// to say what it looked at, or the reason code cannot be told apart from a stale device.
|
|
126
|
+
static RunnerApplicationScreenFailure RunnerResolveUsableWindow(
|
|
127
|
+
id application,
|
|
128
|
+
id _Nullable *window,
|
|
129
|
+
CGRect *observedFrame
|
|
130
|
+
) {
|
|
131
|
+
__block id readWindow = nil;
|
|
132
|
+
__block CGRect frame = CGRectNull;
|
|
133
|
+
__block BOOL resolved = NO;
|
|
134
|
+
NSString *exception = [RunnerObjCExceptionCatcher catchException:^{
|
|
135
|
+
id candidate = [[application valueForKey:@"windows"] valueForKey:@"firstMatch"];
|
|
136
|
+
NSNumber *present = [candidate valueForKey:@"exists"];
|
|
137
|
+
resolved = [present isKindOfClass:NSNumber.class] && present.boolValue;
|
|
138
|
+
NSValue *frameValue = [candidate valueForKey:@"frame"];
|
|
139
|
+
[frameValue getValue:&frame size:sizeof(frame)];
|
|
140
|
+
readWindow = candidate;
|
|
141
|
+
}];
|
|
142
|
+
*observedFrame = frame;
|
|
143
|
+
if (exception != nil || !resolved || !RunnerUsableWindowFrame(frame)) {
|
|
144
|
+
NSLog(
|
|
145
|
+
@"AGENT_DEVICE_RUNNER_APP_SCREEN_UNRESOLVED stage=window frame=(%g,%g %gx%g) raised=%@ resolved=%@",
|
|
146
|
+
frame.origin.x,
|
|
147
|
+
frame.origin.y,
|
|
148
|
+
frame.size.width,
|
|
149
|
+
frame.size.height,
|
|
150
|
+
exception != nil ? @"yes" : @"no",
|
|
151
|
+
resolved ? @"yes" : @"no"
|
|
152
|
+
);
|
|
153
|
+
return RunnerApplicationScreenFailureUnresolvedWindow;
|
|
154
|
+
}
|
|
155
|
+
*window = readWindow;
|
|
156
|
+
return RunnerApplicationScreenFailureNone;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// The screen read that must follow window resolution on that same window instance. Before the
|
|
160
|
+
// frame above is asked for, the window's `screen` can still name main, so this is never merged
|
|
161
|
+
// into the read ahead of it.
|
|
162
|
+
static RunnerApplicationScreenFailure RunnerReadResolvedWindowScreen(
|
|
163
|
+
id window,
|
|
164
|
+
CGRect windowFrame,
|
|
165
|
+
id _Nullable *screen,
|
|
166
|
+
NSUInteger *displayID
|
|
167
|
+
) {
|
|
168
|
+
__block id readScreen = nil;
|
|
169
|
+
__block NSUInteger readDisplayID = 0;
|
|
170
|
+
NSString *exception = [RunnerObjCExceptionCatcher catchException:^{
|
|
171
|
+
id windowScreen = [window valueForKey:@"screen"];
|
|
172
|
+
NSNumber *identifier = [windowScreen valueForKey:@"displayID"];
|
|
173
|
+
if (![identifier isKindOfClass:NSNumber.class] || identifier.unsignedIntegerValue == 0) {
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
readScreen = windowScreen;
|
|
177
|
+
readDisplayID = identifier.unsignedIntegerValue;
|
|
178
|
+
}];
|
|
179
|
+
if (exception != nil || readScreen == nil) {
|
|
180
|
+
NSLog(
|
|
181
|
+
@"AGENT_DEVICE_RUNNER_APP_SCREEN_UNRESOLVED stage=screen frame=(%g,%g %gx%g) raised=%@",
|
|
182
|
+
windowFrame.origin.x,
|
|
183
|
+
windowFrame.origin.y,
|
|
184
|
+
windowFrame.size.width,
|
|
185
|
+
windowFrame.size.height,
|
|
186
|
+
exception != nil ? @"yes" : @"no"
|
|
187
|
+
);
|
|
188
|
+
return RunnerApplicationScreenFailureUnresolvedScreen;
|
|
189
|
+
}
|
|
190
|
+
*screen = readScreen;
|
|
191
|
+
*displayID = readDisplayID;
|
|
192
|
+
return RunnerApplicationScreenFailureNone;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
BOOL RunnerResolveApplicationScreen(
|
|
196
|
+
id application,
|
|
197
|
+
id _Nullable *screen,
|
|
198
|
+
NSUInteger *displayID,
|
|
199
|
+
RunnerApplicationScreenFailure *failure
|
|
200
|
+
) {
|
|
201
|
+
*screen = nil;
|
|
202
|
+
*displayID = 0;
|
|
203
|
+
id window = nil;
|
|
204
|
+
CGRect windowFrame = CGRectNull;
|
|
205
|
+
*failure = RunnerResolveUsableWindow(application, &window, &windowFrame);
|
|
206
|
+
if (*failure != RunnerApplicationScreenFailureNone) {
|
|
207
|
+
return NO;
|
|
208
|
+
}
|
|
209
|
+
*failure = RunnerReadResolvedWindowScreen(window, windowFrame, screen, displayID);
|
|
210
|
+
return *failure == RunnerApplicationScreenFailureNone;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Reads the display ID off a window the caller already resolved, so a synthesized record can be
|
|
214
|
+
// routed by the same window its reference frame was measured on. The window still resolves here:
|
|
215
|
+
// its frame is read before its screen, and a window that answers empty or raises fails closed with
|
|
216
|
+
// the same reasons the application walk gives.
|
|
217
|
+
NSString * _Nullable RunnerResolveWindowDisplayID(id window, NSUInteger *displayID) {
|
|
218
|
+
__block CGRect frame = CGRectNull;
|
|
219
|
+
NSString *frameException = [RunnerObjCExceptionCatcher catchException:^{
|
|
220
|
+
NSValue *frameValue = [window valueForKey:@"frame"];
|
|
221
|
+
[frameValue getValue:&frame size:sizeof(frame)];
|
|
222
|
+
}];
|
|
223
|
+
if (frameException != nil || !RunnerUsableWindowFrame(frame)) {
|
|
224
|
+
NSLog(
|
|
225
|
+
@"AGENT_DEVICE_RUNNER_APP_SCREEN_UNRESOLVED stage=window frame=(%g,%g %gx%g) raised=%@",
|
|
226
|
+
frame.origin.x,
|
|
227
|
+
frame.origin.y,
|
|
228
|
+
frame.size.width,
|
|
229
|
+
frame.size.height,
|
|
230
|
+
frameException != nil ? @"yes" : @"no"
|
|
231
|
+
);
|
|
232
|
+
return [NSString stringWithFormat:
|
|
233
|
+
@"private XCTest event synthesis unavailable: %@",
|
|
234
|
+
RunnerApplicationScreenFailureDescription(RunnerApplicationScreenFailureUnresolvedWindow)
|
|
235
|
+
];
|
|
236
|
+
}
|
|
237
|
+
id screen = nil;
|
|
238
|
+
NSUInteger resolvedDisplayID = 0;
|
|
239
|
+
RunnerApplicationScreenFailure failure =
|
|
240
|
+
RunnerReadResolvedWindowScreen(window, frame, &screen, &resolvedDisplayID);
|
|
241
|
+
if (failure != RunnerApplicationScreenFailureNone) {
|
|
242
|
+
return [NSString stringWithFormat:
|
|
243
|
+
@"private XCTest event synthesis unavailable: %@",
|
|
244
|
+
RunnerApplicationScreenFailureDescription(failure)
|
|
245
|
+
];
|
|
246
|
+
}
|
|
247
|
+
*displayID = resolvedDisplayID;
|
|
248
|
+
return nil;
|
|
249
|
+
}
|
|
@@ -9,11 +9,14 @@ enum RecordingScriptError: Error, CustomStringConvertible {
|
|
|
9
9
|
case invalidArgs(String)
|
|
10
10
|
case missingVideoTrack
|
|
11
11
|
case exportFailed(String)
|
|
12
|
+
case frameWriteFailed(String)
|
|
12
13
|
|
|
13
14
|
var description: String {
|
|
14
15
|
switch self {
|
|
15
16
|
case .invalidArgs(let message):
|
|
16
17
|
return message
|
|
18
|
+
case .frameWriteFailed(let message):
|
|
19
|
+
return message
|
|
17
20
|
case .missingVideoTrack:
|
|
18
21
|
return "Input video does not contain a video track."
|
|
19
22
|
case .exportFailed(let message):
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import AVFoundation
|
|
2
|
+
import Foundation
|
|
3
|
+
import ImageIO
|
|
4
|
+
import UniformTypeIdentifiers
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
struct FrameManifest: Encodable {
|
|
19
|
+
struct Frame: Encodable {
|
|
20
|
+
let index: Int
|
|
21
|
+
let requestedTimeMs: Double
|
|
22
|
+
let actualTimeMs: Double
|
|
23
|
+
let width: Int
|
|
24
|
+
let height: Int
|
|
25
|
+
let path: String
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
struct Skipped: Encodable {
|
|
29
|
+
let index: Int
|
|
30
|
+
let requestedTimeMs: Double
|
|
31
|
+
let reason: String
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
let inputPath: String
|
|
35
|
+
let durationMs: Double
|
|
36
|
+
let frames: [Frame]
|
|
37
|
+
let skipped: [Skipped]
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@main
|
|
43
|
+
enum RecordingFrames {
|
|
44
|
+
static func main() {
|
|
45
|
+
do {
|
|
46
|
+
try run()
|
|
47
|
+
} catch {
|
|
48
|
+
fputs("recording-frames: \(error)\n", stderr)
|
|
49
|
+
exit(1)
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
func run() throws {
|
|
55
|
+
let arguments = Array(CommandLine.arguments.dropFirst())
|
|
56
|
+
let inputURL = URL(fileURLWithPath: try requiredOption(arguments, "--input"))
|
|
57
|
+
let outputDirectoryURL = URL(fileURLWithPath: try requiredOption(arguments, "--output-dir"), isDirectory: true)
|
|
58
|
+
let requestedTimesMs = try parseTimes(try requiredOption(arguments, "--times"))
|
|
59
|
+
let maxWidth = try parseMaxWidth(optionValue(arguments, "--max-width"))
|
|
60
|
+
|
|
61
|
+
guard !requestedTimesMs.isEmpty else {
|
|
62
|
+
throw RecordingScriptError.invalidArgs("--times must name at least one presentation time")
|
|
63
|
+
}
|
|
64
|
+
try FileManager.default.createDirectory(at: outputDirectoryURL, withIntermediateDirectories: true)
|
|
65
|
+
|
|
66
|
+
let asset = AVURLAsset(url: inputURL)
|
|
67
|
+
_ = try sourceVideoTrack(of: asset)
|
|
68
|
+
let durationMs = max(0, asset.duration.seconds * 1000)
|
|
69
|
+
|
|
70
|
+
let generator = AVAssetImageGenerator(asset: asset)
|
|
71
|
+
generator.appliesPreferredTrackTransform = true
|
|
72
|
+
generator.maximumSize = CGSize(width: maxWidth, height: maxWidth)
|
|
73
|
+
generator.requestedTimeToleranceBefore = .zero
|
|
74
|
+
generator.requestedTimeToleranceAfter = .zero
|
|
75
|
+
|
|
76
|
+
var frames: [FrameManifest.Frame] = []
|
|
77
|
+
var skipped: [FrameManifest.Skipped] = []
|
|
78
|
+
|
|
79
|
+
for (index, requestedTimeMs) in requestedTimesMs.enumerated() {
|
|
80
|
+
let requestedTime = CMTime(seconds: requestedTimeMs / 1000, preferredTimescale: 600)
|
|
81
|
+
var actualTime = CMTime.invalid
|
|
82
|
+
let cgImage: CGImage
|
|
83
|
+
do {
|
|
84
|
+
cgImage = try generator.copyCGImage(at: requestedTime, actualTime: &actualTime)
|
|
85
|
+
} catch {
|
|
86
|
+
skipped.append(
|
|
87
|
+
FrameManifest.Skipped(
|
|
88
|
+
index: index,
|
|
89
|
+
requestedTimeMs: requestedTimeMs,
|
|
90
|
+
reason: "\(error)"
|
|
91
|
+
)
|
|
92
|
+
)
|
|
93
|
+
continue
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
guard CMTIME_IS_VALID(actualTime), actualTime.timescale != 0 else {
|
|
100
|
+
skipped.append(
|
|
101
|
+
FrameManifest.Skipped(
|
|
102
|
+
index: index,
|
|
103
|
+
requestedTimeMs: requestedTimeMs,
|
|
104
|
+
reason: "Decoder returned no presentation time for this frame"
|
|
105
|
+
)
|
|
106
|
+
)
|
|
107
|
+
continue
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
let outputURL = outputDirectoryURL.appendingPathComponent(frameFileName(index: index))
|
|
111
|
+
do {
|
|
112
|
+
try writePNG(cgImage: cgImage, to: outputURL)
|
|
113
|
+
} catch {
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
try? FileManager.default.removeItem(at: outputURL)
|
|
118
|
+
throw RecordingScriptError.frameWriteFailed(
|
|
119
|
+
"Could not write frame \(index) at \(requestedTimeMs)ms to \(outputURL.path): \(error)"
|
|
120
|
+
)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
frames.append(
|
|
124
|
+
FrameManifest.Frame(
|
|
125
|
+
index: index,
|
|
126
|
+
requestedTimeMs: requestedTimeMs,
|
|
127
|
+
actualTimeMs: timeIntervalMs(actualTime),
|
|
128
|
+
width: cgImage.width,
|
|
129
|
+
height: cgImage.height,
|
|
130
|
+
path: outputURL.path
|
|
131
|
+
)
|
|
132
|
+
)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
let manifest = FrameManifest(
|
|
136
|
+
inputPath: inputURL.path,
|
|
137
|
+
durationMs: durationMs,
|
|
138
|
+
frames: frames,
|
|
139
|
+
skipped: skipped
|
|
140
|
+
)
|
|
141
|
+
let encoder = JSONEncoder()
|
|
142
|
+
encoder.outputFormatting = [.sortedKeys]
|
|
143
|
+
FileHandle.standardOutput.write(try encoder.encode(manifest))
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
func requiredOption(_ arguments: [String], _ flag: String) throws -> String {
|
|
147
|
+
guard let index = arguments.firstIndex(of: flag) else {
|
|
148
|
+
throw RecordingScriptError.invalidArgs("Missing \(flag)")
|
|
149
|
+
}
|
|
150
|
+
return try recordingOptionValue(arguments, index + 1, flag)
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
func optionValue(_ arguments: [String], _ flag: String) -> String? {
|
|
154
|
+
guard let index = arguments.firstIndex(of: flag), index + 1 < arguments.count else {
|
|
155
|
+
return nil
|
|
156
|
+
}
|
|
157
|
+
return arguments[index + 1]
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
func parseTimes(_ value: String) throws -> [Double] {
|
|
161
|
+
let parts = value.split(separator: ",", omittingEmptySubsequences: true)
|
|
162
|
+
guard !parts.isEmpty else {
|
|
163
|
+
throw RecordingScriptError.invalidArgs("--times must be a comma-separated list of milliseconds")
|
|
164
|
+
}
|
|
165
|
+
return try parts.map { part in
|
|
166
|
+
guard let parsed = Double(part), parsed.isFinite, parsed >= 0 else {
|
|
167
|
+
throw RecordingScriptError.invalidArgs("Invalid sample time: \(part)")
|
|
168
|
+
}
|
|
169
|
+
return parsed
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
func parseMaxWidth(_ value: String?) throws -> Int {
|
|
174
|
+
guard let value else { return 360 }
|
|
175
|
+
guard let parsed = Int(value), parsed > 0 else {
|
|
176
|
+
throw RecordingScriptError.invalidArgs("Invalid --max-width: \(value)")
|
|
177
|
+
}
|
|
178
|
+
return parsed
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
func timeIntervalMs(_ time: CMTime) -> Double {
|
|
182
|
+
guard CMTIME_IS_VALID(time), time.timescale != 0 else { return 0 }
|
|
183
|
+
return CMTimeGetSeconds(time) * 1000
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
func frameFileName(index: Int) -> String {
|
|
187
|
+
String(format: "frame-%04d.png", index)
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
func writePNG(cgImage: CGImage, to url: URL) throws {
|
|
191
|
+
guard let destination = CGImageDestinationCreateWithURL(
|
|
192
|
+
url as CFURL,
|
|
193
|
+
UTType.png.identifier as CFString,
|
|
194
|
+
1,
|
|
195
|
+
nil
|
|
196
|
+
) else {
|
|
197
|
+
throw RecordingScriptError.exportFailed("Failed to open PNG destination for \(url.lastPathComponent)")
|
|
198
|
+
}
|
|
199
|
+
CGImageDestinationAddImage(destination, cgImage, nil)
|
|
200
|
+
guard CGImageDestinationFinalize(destination) else {
|
|
201
|
+
throw RecordingScriptError.exportFailed("Failed to encode PNG for \(url.lastPathComponent)")
|
|
202
|
+
}
|
|
203
|
+
}
|
|
@@ -14,6 +14,11 @@ public enum RunnerInterfaceOrientation {
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
public enum CoordinateSpaceRotation {
|
|
17
|
+
// Dispatch rotates a point about the reference frame's top-left. The origin is localized away
|
|
18
|
+
// and never added back: an XCUIApplication session observes only its own scene surface, so its
|
|
19
|
+
// windows report (0,0)-anchored frames (measured on iPhone landscape both ways and on every
|
|
20
|
+
// system window in window-coordinate-space.json), and displacement between panels or panes is
|
|
21
|
+
// carried by the record's displayID, not by an origin.
|
|
17
22
|
public static func native(
|
|
18
23
|
point: CGPoint,
|
|
19
24
|
in frame: CGRect,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{D as e,O as t}from"./sdk-contracts.js";import{
|
|
1
|
+
import{D as e,O as t}from"./sdk-contracts.js";import{Ir as n,Mr as r,qn as i,rr as a}from"./sdk-batch.js";import{n as o}from"./scroll-indicator.js";function s(e){let t=f(e.label),n=f(e.value),r=f(e.identifier),i=m(r)?r:``;return p(e.type??``)?n||t||i:t||n||i}function c(e,t){if(t===`text-view`||t===`text-field`||t===`search`)return!0;let r=n(e.type??``),i=`${e.role??``} ${e.subrole??``}`.toLowerCase();return r.includes(`textview`)||r.includes(`textarea`)||r.includes(`textfield`)||r.includes(`securetextfield`)||r.includes(`searchfield`)||r.includes(`edittext`)||i.includes(`text area`)||i.includes(`text field`)}function l(e){let t=e.replaceAll(/\s+/g,` `).trim();return t.length<=48?t:`${t.slice(0,45)}...`}function u(e,t){let n=s(e),r=c(e,t);return{text:n,isLargeSurface:r,shouldSummarize:r&&d(n)}}function d(e){return e?e.length>80||/[\r\n]/.test(e):!1}function f(e){return typeof e==`string`?e.trim():``}function p(e){let t=n(e);return t.includes(`textfield`)||t.includes(`securetextfield`)||t.includes(`searchfield`)||t.includes(`edittext`)||t.includes(`textview`)||t.includes(`textarea`)}function m(e){return e?!/^[\w.]+:id\/[\w.-]+$/i.test(e)&&!/^_?NS:\d+$/i.test(e):!1}const h={application:`application`,navigationbar:`navigation-bar`,tabbar:`tab-bar`,button:`button`,imagebutton:`button`,link:`link`,cell:`cell`,statictext:`text`,checkedtextview:`text`,textbox:`text-field`,textfield:`text-field`,edittext:`text-field`,textarea:`text-view`,switch:`switch`,slider:`slider`,image:`image`,imageview:`image`,webview:`webview`,framelayout:`group`,linearlayout:`group`,relativelayout:`group`,constraintlayout:`group`,viewgroup:`group`,view:`group`,listview:`list`,recyclerview:`list`,collectionview:`collection`,searchfield:`search`,heading:`heading`,activityindicator:`activity-indicator`,progressindicator:`progress-indicator`,segmentedcontrol:`segmented-control`,group:`group`,window:`window`,checkbox:`checkbox`,radio:`radio`,menuitem:`menu-item`,toolbar:`toolbar`,scrollarea:`scroll-area`,scrollview:`scroll-area`,nestedscrollview:`scroll-area`,table:`table`};function g(e,t={}){let n=[],r=[];for(let i of e){let e=i.depth??0,a=i.label?.trim()||i.value?.trim()||i.identifier?.trim()||``,o=x(i.type??`Element`),s=i.inheritsLabel===!0||i.inheritsIdentifier===!0;if(o===`group`&&!a&&!s)continue;for(;n.length>0&&e<=n.at(-1);)n.pop();let c=n.length;n.push(e),r.push({node:i,depth:c,type:o,text:_(i,c,!1,o,t)})}return r}function _(e,t,n,r,i={}){let a=r??x(e.type??`Element`),o=u(e,a),s=E(e,a,i,o),c=` `.repeat(t),l=e.ref?`@${e.ref}`:``,d=D(e,a,i,o);!s&&(e.inheritsLabel===!0||e.inheritsIdentifier===!0)&&d.push(`same label as parent`);let f=d.map(e=>` [${e}]`).join(``),p=s?` "${s}"`:``,m=v(e);return n?`${c}${l} [${a}]${f}${m}`.trimEnd():`${c}${l} [${a}]${p}${f}${m}`.trimEnd()}function v(e){let t=e.actions?.filter(e=>e.trim().length>0);return!t||t.length===0?``:` actions: [${t.map(e=>`"${A(y(e))}"`).join(`, `)}]`}function y(e){return e.replaceAll(/\s+/g,` `).replaceAll(/[\u0000-\u001f\u007f-\u009f]/g,``).trim()}function b(e,t){let n=e.label?.trim();if(n&&w(t,n))return``;let r=e.value?.trim();if(C(t)){if(r)return r;if(n)return n}else if(n)return n;if(r)return r;let i=e.identifier?.trim();return!i||T(i)&&(t===`group`||t===`image`||t===`list`||t===`collection`)?``:i}function x(e){let t=e,n=e.replaceAll(/XCUIElementType/gi,``).toLowerCase(),r=t.includes(`.`)&&(t.startsWith(`android.`)||t.startsWith(`androidx.`)||t.startsWith(`com.`));return n.includes(`.`)&&(n=n.replace(/^android\.widget\./,``).replace(/^android\.view\./,``).replace(/^android\.webkit\./,``).replace(/^androidx\./,``).replace(/^com\.google\.android\./,``).replace(/^com\.android\./,``),r&&n.includes(`.`)&&(n=n.slice(n.lastIndexOf(`.`)+1))),n===`textview`?r?`text`:`text-view`:S(n)||n||`element`}function S(e){return Object.prototype.hasOwnProperty.call(h,e)?h[e]:void 0}function C(e){return e===`text-field`||e===`text-view`||e===`search`}function w(e,t){return e!==`scroll-area`&&e!==`list`&&e!==`collection`&&e!==`table`?!1:o(t)}function T(e){return/^[\w.]+:id\/[\w.-]+$/i.test(e)}function E(e,t,n,r){return!n.summarizeTextSurfaces||!r.shouldSummarize?b(e,t):O(e,t,r.text)||b(e,t)}function D(e,t,n,r){let i=[];return e.enabled===!1&&i.push(`disabled`),e.selected===!0&&i.push(`selected`),i.push(...e.presentationHints??[]),!n.summarizeTextSurfaces||(e.focused===!0&&i.push(`focused`),C(t)&&i.push(`editable`),k(e,t)&&i.push(`scrollable`),!r.shouldSummarize)?j(i):(i.push(`preview:"${A(l(r.text))}"`),i.push(`truncated`),j(i))}function O(e,t,n){let r=f(e.label);if(r&&r!==n)return r;let i=f(e.identifier);if(i&&!T(i)&&i!==n)return i;switch(t){case`text`:case`text-view`:return`Text view`;case`text-field`:return`Text field`;case`search`:return`Search field`;default:return``}}function k(e,t){if(t===`scroll-area`)return!0;let n=(e.type??``).toLowerCase(),r=`${e.role??``} ${e.subrole??``}`.toLowerCase();return n.includes(`scroll`)||r.includes(`scroll`)}function A(e){return e.replaceAll(`\\`,String.raw`\\`).replaceAll(`"`,String.raw`\"`)}function j(e){return[...new Set(e)]}const M={state:`sparse`,backend:`tree`,reason:`legacy iOS capture exposed only the application root`,reasonCode:`sparse-tree`};function N(e){if(e.scope!==void 0)return`scope`;if(e.depth!==void 0)return`depth`}function P(e,t=`is`){let n=`${t} absent`;return e===`scope`?`${n} does not support --scope; it requires an unscoped capture`:`${n} does not support --depth; it requires a full-depth capture`}function F(e,t){let n=t[0]?R(t[0]):void 0,r=t.length;if(e.truncated===!0)return{kind:`truncated`,matches:r,...n?{firstMatch:n}:{}};let i=I(e);return i?{kind:`sparse`,matches:r,...n?{firstMatch:n}:{},quality:{state:i.state,backend:i.backend,...i.reason?{reason:i.reason}:{},...i.reasonCode?{reasonCode:i.reasonCode}:{}}}:r===0?{kind:`absent`,matches:0}:{kind:`present`,matches:r,firstMatch:n}}function I(e){let t=e.snapshotQuality;return t?.state===`sparse`?{state:t.state,backend:t.backend,...t.reason?{reason:t.reason}:{},...t.reasonCode?{reasonCode:t.reasonCode}:{}}:L(e)?M:void 0}function L(e){return e.snapshotQuality||e.backend!==`xctest`||e.nodes.length!==1?!1:n(e.nodes[0]?.type??``)===`application`}function R(e){let t=i(e),n=a(r(e),256);return{...t,...n&&n!==t.label?{text:n}:{}}}const z={selectorNotFound:`selector_not_found`,predicateFailed:`predicate_failed`};function B(t,n=`is`){return new e(`INVALID_ARGS`,P(t,n),{command:n,predicate:`absent`,rejectedOption:t})}function V(t,n,r=`is`){let i=`firstMatch`in n?n.firstMatch:void 0,a={command:r,reason:z.predicateFailed,predicate:`absent`,selector:t,matches:n.matches,observation:n.kind,...i?{firstMatch:i}:{},...n.kind===`sparse`?{snapshotQuality:n.quality}:{},...n.kind===`truncated`?{truncated:!0}:{}};if(n.kind===`present`){let i=n.matches>1;return new e(`COMMAND_FAILED`,`${r} absent failed for selector ${t}: ${n.matches} match${i?`es`:``} found`,{...a,...i?{hint:`Refine the selector to match no elements.`}:{}})}return new e(`COMMAND_FAILED`,`${r} absent could not prove absence for selector ${t}: ${n.kind===`sparse`?`capture was sparse`:`capture was truncated`}`,{...a,hint:`Retry after the accessibility capture is complete.`})}function H(n,r,i=`is`){let a=t(r),o=typeof a.details?.reason==`string`?a.details.reason:typeof a.details?.androidSnapshotHelperFailureReason==`string`?a.details.androidSnapshotHelperFailureReason:void 0;return new e(`COMMAND_FAILED`,`${i} absent could not prove absence for selector ${n}: capture was unreadable`,{command:i,reason:z.predicateFailed,predicate:`absent`,selector:n,matches:0,observation:`unreadable`,captureErrorCode:a.code,...o?{captureErrorReason:o}:{},hint:`Retry after the accessibility capture is readable.`},a)}export{N as a,I as c,x as d,_ as f,z as i,g as l,p as m,V as n,F as o,s as p,H as r,L as s,B as t,b as u};
|
package/dist/src/adapter.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{D as e,F as t}from"./sdk-contracts.js";import{Br as n,Vr as r}from"./sdk-batch.js";import{c as i,r as a}from"./diagnostics.js";import{f as o,x as s}from"./owner-identity.js";import{c,l,m as u,r as d}from"./exec.js";import{n as f,t as p}from"./file.js";import"./diagnostics2.js";import"./command.js";import{n as m}from"./retry.js";import{n as ee}from"./version.js";import"./process.js";import{C as te,D as ne,c as re,f as ie,h as ae,n as oe,o as se,w as ce,y as le}from"./host-file.js";import{t as h}from"./apple-runner-platform.js";import{n as ue,r as de,t as fe}from"./snapshot-process.js";import g from"node:path";import{createHash as _,randomUUID as v}from"node:crypto";import pe from"node:net";import{Buffer as y}from"node:buffer";const me={unsupported:`UNSUPPORTED_OPERATION`,"malformed-tree":`COMMAND_FAILED`,"stale-target":`COMMAND_FAILED`,timeout:`COMMAND_FAILED`,cancelled:`COMMAND_FAILED`,"process-crash":`COMMAND_FAILED`,"transport-failure":`COMMAND_FAILED`,preparing:`COMMAND_FAILED`};var b=class extends e{failureKind;failureCode;constructor(e,t,n=`iOS Simulator snapshot source ${e}: ${t}`,r={},i){super(me[e],n,{...r,bridgeFailure:e,bridgeFailureCode:t,...e===`cancelled`?{reason:`request_canceled`}:{}},i),this.name=`SnapshotSourceError`,this.failureKind=e,this.failureCode=t}};function x(e,t,n={},r){return new b(e,t,void 0,n,r)}function S(n){return n instanceof b?n:t(n)?x(`cancelled`,`abort-signal`,{},n):n instanceof e&&typeof n.details?.timeoutMs==`number`?x(`timeout`,`host-operation-timeout`,{timeoutMs:n.details.timeoutMs},n):x(`transport-failure`,`unexpected-host-error`,{error:n instanceof Error?n.message:String(n)},n)}function C(e,t,n=Date.now){if(t?.aborted)throw x(`cancelled`,`abort-signal`);return{clock:m.fromTimeoutMs(e,n()),now:n,signal:t}}function w(e,t){if(e.signal?.aborted)throw x(`cancelled`,`abort-signal`);let n=e.clock.remainingMs(e.now());if(n<=0)throw x(`timeout`,t);return Math.max(1,Math.floor(n))}async function T(e,t,n,r){let i=Math.min(t,w(e,n));await de({waitMs:i,signal:e.signal,stop:r,cancelled:()=>x(`cancelled`,`abort-signal`)})}var he=class{entries=new Map;probeBackAfterUses;constructor(e=8){this.probeBackAfterUses=e}consume(e,t,n){if(n)return{nativeLevels:void 0,reason:`explicit-depth`};let r=this.currentEntry(e);return r===`unidentified`?{nativeLevels:void 0,reason:`unidentified-target`}:!r||r.nativeLevels>=t?{nativeLevels:void 0,reason:`no-hint`}:r.remainingUses<=0?{nativeLevels:void 0,reason:`probe-back`}:(--r.remainingUses,{nativeLevels:r.nativeLevels,reason:`hinted`})}learn(e,t,n,r){return n||!e.targetId?`ignored`:r.rejected>0&&r.acceptedLevels<t?(this.remember(e.targetId,{generation:e.generation,nativeLevels:r.acceptedLevels,remainingUses:this.probeBackAfterUses}),`learned`):r.rejected===0&&r.acceptedLevels>=t?this.entries.delete(e.targetId)?`forgotten`:`ignored`:this.currentEntry(e)?`kept`:`ignored`}currentEntry(e){if(!e.targetId)return`unidentified`;let t=this.entries.get(e.targetId);if(t){if(t.generation!==e.generation){this.entries.delete(e.targetId);return}return t}}remember(e,t){if(this.entries.delete(e),this.entries.size>=32){let e=this.entries.keys().next().value;e!==void 0&&this.entries.delete(e)}this.entries.set(e,t)}};const E=65536;function ge(){return{projectRoot:ee,homeDirectory:ie,run:async(e,t,n)=>await c(e,t,n),start:_e,connect:ve,readText:le,readBinary:ae,writeText:ne,ensureDirectory:se,chmod:oe,exists:re,rename:ce,remove:te,acquireLock:ye,emitDiagnostic:a,withDiagnosticTimer:i,processId:o,readTargetProcessStartTime:fe}}function _e(e,t,n,r={}){if(r.signal?.aborted)throw x(`cancelled`,`abort-signal`);let i=l(`xcrun`,[`simctl`,`spawn`,e,t,`serve`,n,`--idle-timeout`,`60`,`--exit-on-disconnect`,`false`],{allowFailure:!0,captureOutput:!1,detached:!0}),a=i.child.pid??0;if(a<=0)throw x(`transport-failure`,`bridge-process-pid-missing`);let o=``;return i.child.stderr?.setEncoding(`utf8`),i.child.stderr?.on(`data`,e=>{o=be(o,String(e))}),{pid:a,wait:i.wait,isAlive:()=>i.child.exitCode===null&&i.child.signalCode===null,signal:e=>{u(a,e)||i.child.kill(e)},readLog:()=>o}}async function ve(e,t){if(t.signal?.aborted)throw x(`cancelled`,`abort-signal`);let n=Math.max(1,Math.floor(t.timeoutMs));return await new Promise((r,i)=>{let a=pe.createConnection({path:e}),o=!1,s=!1,c=setTimeout(()=>{p(x(`timeout`,`bridge-connect-timeout`)),a.destroy()},n),l=()=>{p(x(`cancelled`,`abort-signal`)),a.destroy()},u=()=>{o=!0,clearTimeout(c),t.signal?.removeEventListener(`abort`,l),a.off(`error`,d),a.off(`close`,f),a.setTimeout(0),r(a)},d=e=>{p(e),a.destroy()},f=()=>{o||p(x(`transport-failure`,`bridge-closed-before-connect`))},p=e=>{s||o||(s=!0,clearTimeout(c),t.signal?.removeEventListener(`abort`,l),a.off(`connect`,u),a.off(`error`,d),a.off(`close`,f),i(e))};a.once(`connect`,u),a.once(`error`,d),a.once(`close`,f),t.signal?.addEventListener(`abort`,l,{once:!0}),t.signal?.aborted&&l()})}async function ye(e,t){let n=o(),r=t.deadline,i=p({lockDirPath:e,owner:{pid:n,startTime:s(n),acquiredAtMs:Date.now()},timeoutMs:w(r,`cache-lock-deadline`),pollMs:100,ownerGraceMs:5e3,description:`iOS Simulator snapshot bridge cache`}),a=r.signal;if(!a)return await i;let c=!1,l,u=new Promise((e,t)=>{l=()=>{c=!0,t(x(`cancelled`,`abort-signal`))},a.addEventListener(`abort`,l,{once:!0}),a.aborted&&l()});try{return await Promise.race([i,u])}catch(e){throw c&&i.then(e=>e().catch(()=>void 0),()=>void 0),r.clock.isExpired()&&!(e instanceof b&&e.failureKind===`cancelled`)?x(`timeout`,`cache-lock-deadline`):e}finally{a.removeEventListener(`abort`,l)}}function be(e,t){let n=e+t;return n.length<=E?n:n.slice(n.length-E)}function xe(e,t,n){let r=_(`sha256`).update(t).digest(`hex`).slice(0,12),i=_(`sha256`).update(n).digest(`hex`).slice(0,12);return g.join(`/tmp`,`agent-device-ax-${r}-${e.processId()}-${i}`,`snapshot.sock`)}const D=new WeakSet;async function O(e,t){let n;try{n=(await t.wait).exitCode}catch{n=void 0}return D.has(t)||(D.add(t),e.emitDiagnostic({level:`error`,phase:`ios.snapshot-source.bridge-process-exit`,data:{pid:t.pid,...n===void 0?{}:{exitCode:n},stderr:Se(t.readLog())}})),x(`process-crash`,`bridge-exited`,{pid:t.pid,...n===void 0?{}:{exitCode:n}})}function Se(e){let t=y.from(e);return t.length<=65536?e:t.subarray(-65536).toString(`utf8`)}const k=`agent-device-simulator-ax-v1.6.0`;Object.freeze([`verb`,`requestId`,`pid`,`generation`,`snapshotTree`,`automationMode`,`maxDepth`,`maxNodes`,`maxDurationMs`,`maxResponseBytes`,`nativeLevelsHint`]),Object.freeze([`protocolVersion`,`sourceVersion`,`requestId`,`generation`,`ok`,`pid`,`tree`,`truncated`,`automationEnabled`,`recovery`,`error_kind`,`error_code`,`error`]),Object.freeze([`XC_kAXXCAttributeElementType`,`XC_kAXXCAttributeElementBaseType`,`XC_kAXXCAttributeLabel`,`XC_kAXXCAttributeValue`,`XC_kAXXCAttributeIdentifier`,`XC_kAXXCAttributeFrame`,`XC_kAXXCAttributeAutomationType`,`XC_kAXXCAttributeTraits`,`XC_kAXXCAttributeChildren`]);const Ce=[`requests`,`rejected`,`continuations`,`acceptedLevels`];function A(e){let t=e.recovery;if(!j(t))throw x(`malformed-tree`,`recovery-invalid`);let n=Ce.map(e=>[e,t[e]]);if(n.some(([,e])=>!Number.isSafeInteger(e)||e<0))throw x(`malformed-tree`,`recovery-invalid`);return Object.freeze(Object.fromEntries(n))}function we(e,t){let n;try{n=y.from(JSON.stringify(e),`utf8`)}catch(e){throw x(`malformed-tree`,`request-not-json`,{},e)}let r=n.length+4;if(r>t.maxRequestBytes)throw x(`transport-failure`,`request-limit-exceeded`,{frameBytes:r,maxRequestBytes:t.maxRequestBytes});let i=y.alloc(4);return i.writeUInt32BE(n.length,0),y.concat([i,n])}var Te=class{header=y.alloc(4);headerBytes=0;chunks=[];payloadBytes=0;expectedBodyBytes;frame;maxFrameBytes;constructor(e){if(!Number.isSafeInteger(e)||e<=0)throw x(`malformed-tree`,`frame-limit-invalid`,{maxFrameBytes:e});this.maxFrameBytes=e}push(e){if(this.frame)return this.acceptTrailingChunk(e);let t=this.readHeader(e);if(t&&(this.appendPayload(e,t.offset,t.bodyBytes),this.payloadBytes===t.bodyBytes))return this.frame=y.concat(this.chunks,t.bodyBytes),this.frame}acceptTrailingChunk(e){if(e.length>0)throw x(`malformed-tree`,`multiple-frames`,{trailingBytes:e.length});return this.frame}readHeader(e){if(this.headerBytes===4)return{offset:0,bodyBytes:this.expectedBodyBytes};let t=Math.min(4-this.headerBytes,e.length);if(e.copy(this.header,this.headerBytes,0,t),this.headerBytes+=t,this.headerBytes<4)return;let n=this.header.readUInt32BE(0);if(n===0||n>this.maxFrameBytes)throw x(`malformed-tree`,`frame-limit-exceeded`,{bodyBytes:n,maxFrameBytes:this.maxFrameBytes});return this.expectedBodyBytes=n,{offset:t,bodyBytes:n}}appendPayload(e,t,n){let r=n-this.payloadBytes,i=e.length-t;if(i>r)throw x(`malformed-tree`,`multiple-frames`,{trailingBytes:i-r});i!==0&&(this.chunks.push(e.subarray(t)),this.payloadBytes+=i)}finish(){if(this.frame)return this.frame;throw x(`transport-failure`,`bridge-frame-incomplete`,{headerBytes:this.headerBytes,payloadBytes:this.payloadBytes,expectedBodyBytes:this.expectedBodyBytes})}};function Ee(e){let t;try{t=JSON.parse(e.toString(`utf8`))}catch(e){throw x(`malformed-tree`,`response-not-json`,{},e)}if(!j(t))throw x(`malformed-tree`,`response-not-object`);return t}function De(e){return Object.freeze({verb:`describe`,requestId:e.requestId,pid:e.pid,generation:e.generation,snapshotTree:!0,automationMode:!0,maxDepth:e.maxDepth,maxNodes:e.maxNodes,maxDurationMs:e.maxDurationMs,maxResponseBytes:e.maxResponseBytes,...e.nativeLevelsHint===void 0?{}:{nativeLevelsHint:e.nativeLevelsHint}})}function Oe(e,t){if(e.protocolVersion!==1)throw x(`transport-failure`,`protocol-version-mismatch`,{expected:1,observed:e.protocolVersion});if(e.sourceVersion!==`agent-device-simulator-ax-v1.6.0`)throw x(`transport-failure`,`source-version-mismatch`,{expected:k,observed:e.sourceVersion});if(e.requestId!==t)throw x(`transport-failure`,`request-id-mismatch`,{expected:t,observed:e.requestId})}function ke(e,t){if(typeof e.pid!=`number`||e.pid!==t.pid)throw x(`stale-target`,`bridge-pid-mismatch`,{expectedPid:t.pid,observedPid:e.pid});if(e.generation!==t.generation)throw x(`stale-target`,`bridge-generation-mismatch`,{expectedGeneration:t.generation,observedGeneration:e.generation})}function Ae(e){let t=e.error_kind,n=typeof e.error_code==`string`?e.error_code:`guest-error`,r=typeof e.error==`string`?e.error:void 0,i=r?{guestMessage:r.slice(0,1024)}:{};throw x(t===`unsupported`?`unsupported`:t===`malformed_tree`?`malformed-tree`:t===`application_not_responding`?`timeout`:t===`application_unavailable`?`transport-failure`:t===`bad_request`?`malformed-tree`:`transport-failure`,n,i)}function j(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}async function je(e){let t=new Te(e.limits.maxResponseBytes-4),n=w(e.deadline,`bridge-request-deadline`);return await new Promise((r,i)=>{let a=!1,o=!1,s=setTimeout(()=>{p(x(`timeout`,`bridge-request-deadline`,{dispatched:o})),e.socket.destroy()},n),c=()=>{p(x(`cancelled`,`abort-signal`,{dispatched:o})),e.socket.destroy()},l=n=>{try{if(!Buffer.isBuffer(n))throw x(`transport-failure`,`bridge-data-invalid`);let r=t.push(n);if(r){let t=Ee(r);if(Oe(t,e.requestId),ke(t,{pid:e.expectedPid,generation:e.expectedGeneration}),t.ok!==!0&&Ae(t),typeof t.truncated!=`boolean`)throw x(`malformed-tree`,`truncated-invalid`);f(t);return}}catch(t){p(t),e.socket.destroy()}},u=e=>p(S(e)),d=()=>{a||(e.process.isAlive()?p(x(`transport-failure`,`bridge-connection-closed`)):O(e.host,e.process).then(p))};e.process.wait.then(()=>{a||O(e.host,e.process).then(p)},e=>{a||p(S(e))});let f=e=>m(()=>r(e)),p=e=>m(()=>i(e)),m=t=>{a||(a=!0,clearTimeout(s),e.deadline.signal?.removeEventListener(`abort`,c),e.socket.off(`data`,l),e.socket.off(`error`,u),e.socket.off(`close`,d),t())};e.socket.on(`data`,l),e.socket.on(`error`,u),e.socket.on(`close`,d),e.deadline.signal?.addEventListener(`abort`,c,{once:!0});try{if(e.deadline.signal?.aborted)throw x(`cancelled`,`abort-signal`);o=!0,e.socket.write(e.frame)}catch(t){p(S(t)),e.socket.destroy()}})}var Me=class{sessions=new Map;requestQueues=new Map;ownerId=v();closed=!1;host;constructor(e){this.host=e}async request(e){if(this.closed)throw x(`unsupported`,`source-closed`);return await this.withSimulatorLock(e.target.udid,e.deadline,()=>this.requestInSimulator(e))}async requestInSimulator(e){if(this.closed)throw x(`unsupported`,`source-closed`);let t=e.deadline;w(t,`bridge-request-deadline`);let n=this.sessions.get(e.target.udid),r=await this.ensureSession(e,t);try{let n=await this.readTargetStartTime(e.target,t),i=await this.exchange(r,e,t);return await this.assertTargetStillCurrent(e.target,n,t),i}catch(e){throw await this.handleRequestFailure(e,r,n)}}async handleRequestFailure(e,t,n){let r=S(e);return Pe(r,t,n)?await this.removeSession(t,!0):r.failureKind===`process-crash`?await this.removeSession(t,!1):r.failureKind===`transport-failure`&&(t.socket?.destroy(),t.socket=void 0),r}async withSimulatorLock(e,t,n){let r=this.requestQueues.get(e)??Promise.resolve(),i,a=new Promise(e=>{i=e}),o=r.then(()=>a);this.requestQueues.set(e,o);try{return await Ne(r,t),await n()}finally{i(),this.requestQueues.get(e)===o&&this.requestQueues.delete(e)}}async close(){if(this.closed)return;this.closed=!0;let e=[...this.sessions.values()];this.sessions.clear(),await Promise.all(e.map(async e=>await this.dispose(e,!0)))}async ensureSession(e,t){let n=e.target.udid,r=this.sessions.get(n);if(r&&r.bridgePath===e.bridge.path&&r.process.isAlive())return(!r.socket||r.socket.destroyed)&&(r.socket=await this.connectUntilReady(r,t)),r;r&&await this.removeSession(r,!0);let i=xe(this.host,e.target.udid,this.ownerId);await this.host.ensureDirectory(g.dirname(i)),await this.host.remove(i);let a=this.host.start(e.target.udid,e.bridge.path,i,{signal:t.signal}),o={udid:e.target.udid,bridgePath:e.bridge.path,socketPath:i,process:a};this.sessions.set(n,o);try{return o.socket=await this.connectUntilReady(o,t),o}catch(e){throw await this.removeSession(o,!0),S(e)}}async connectUntilReady(e,t){let n;for(;;){let r=w(t,`bridge-connect-deadline`);if(!e.process.isAlive())throw await O(this.host,e.process);try{return await this.host.connect(e.socketPath,{signal:t.signal,timeoutMs:Math.min(250,r)})}catch(e){if(n=e,e instanceof b&&e.failureKind===`cancelled`)throw e;let r=Math.min(20,w(t,`bridge-connect-deadline`));try{await T(t,r,`bridge-connect-deadline`)}catch(e){throw S(e)}}if(n instanceof b&&n.failureKind===`timeout`)throw n}}async exchange(e,t,n){(!e.socket||e.socket.destroyed)&&(e.socket=await this.connectUntilReady(e,n));let r=v(),i=we(De({requestId:r,pid:t.target.pid,generation:t.target.generation,maxDepth:Math.min(t.limits.maxTraversalDepth,t.maxDepth),maxNodes:t.limits.maxNodes,maxDurationMs:w(n,`bridge-request-deadline`),maxResponseBytes:t.limits.maxResponseBytes,...t.nativeLevelsHint===void 0?{}:{nativeLevelsHint:t.nativeLevelsHint}}),t.limits);return await je({process:e.process,socket:e.socket,frame:i,requestId:r,deadline:n,limits:t.limits,expectedPid:t.target.pid,expectedGeneration:t.target.generation,host:this.host})}async readTargetStartTime(e,t){let n=await this.host.readTargetProcessStartTime(e.pid,{signal:t.signal,timeoutMs:w(t,`target-identity-deadline`)});if(!n)throw x(`stale-target`,`target-process-unavailable`,{pid:e.pid,generation:e.generation});if(e.processStartTime!==void 0&&e.processStartTime!==n)throw x(`stale-target`,`target-process-changed`,{pid:e.pid,generation:e.generation,expectedStartTime:e.processStartTime,observedStartTime:n});return n}async assertTargetStillCurrent(e,t,n){let r=await this.host.readTargetProcessStartTime(e.pid,{signal:n.signal,timeoutMs:w(n,`target-identity-deadline`)});if(r!==t)throw x(`stale-target`,`target-process-changed`,{pid:e.pid,generation:e.generation,expectedStartTime:t,observedStartTime:r})}async removeSession(e,t){this.sessions.get(e.udid)===e&&this.sessions.delete(e.udid),await this.dispose(e,t)}async dispose(e,t){e.socket?.destroy(),e.socket=void 0,t&&e.process.isAlive()&&(e.process.signal(`SIGTERM`),await M(e.process,500),e.process.isAlive()&&(e.process.signal(`SIGKILL`),await M(e.process,500))),await this.host.remove(e.socketPath)}};async function Ne(e,t){let n=w(t,`bridge-request-deadline`);await Promise.race([e,T(t,n,`bridge-request-deadline`).then(()=>{throw x(`timeout`,`bridge-request-deadline`)})])}function Pe(e,t,n){return(e.failureKind===`cancelled`||e.failureKind===`timeout`)&&(e.details?.dispatched===!0||n!==t)}async function M(e,t){await Promise.race([e.wait.catch(()=>void 0),new Promise(e=>setTimeout(e,t))])}const N=16777216,P=12e4,F=1e4,Fe=Object.freeze({maxRequestBytes:65536,maxResponseBytes:4194304,maxNodes:5e3,maxTraversalDepth:64,maxDurationMs:5e3});function I(t){let n={...Fe,...t??{}};for(let[t,r]of Object.entries(n))if(!Number.isSafeInteger(r)||r<=0)throw new e(`INVALID_ARGS`,`Snapshot source limit ${t} must be a positive integer`,{name:t,value:r});if(n.maxRequestBytes>n.maxResponseBytes)throw new e(`INVALID_ARGS`,`Snapshot source request bytes cannot exceed response bytes`,{maxRequestBytes:n.maxRequestBytes,maxResponseBytes:n.maxResponseBytes});if(n.maxRequestBytes>N||n.maxResponseBytes>N)throw new e(`INVALID_ARGS`,`Snapshot source frame limits exceed the bridge bound`,{maxRequestBytes:n.maxRequestBytes,maxResponseBytes:n.maxResponseBytes,maximumFrameBytes:N});if(n.maxNodes>F||n.maxTraversalDepth>128)throw new e(`INVALID_ARGS`,`Snapshot source tree limits exceed the bridge bound`,{maxNodes:n.maxNodes,maxTraversalDepth:n.maxTraversalDepth,maximumNodes:F,maximumDepth:128});if(n.maxDurationMs>P)throw new e(`INVALID_ARGS`,`Snapshot source duration exceeds the bridge bound`,{maxDurationMs:n.maxDurationMs,maximumDurationMs:P});if(n.maxRequestBytes<=4||n.maxResponseBytes<=4)throw new e(`INVALID_ARGS`,`Snapshot source frame limits must leave room for a body`,{maxRequestBytes:n.maxRequestBytes,maxResponseBytes:n.maxResponseBytes});return Object.freeze(n)}const L=[`SnapshotBridge.m`,`SnapshotBridgeRuntime.m`,`SnapshotBridgeRuntime.h`,`SnapshotBridgeCapture.h`,`SnapshotBridgeCapture.m`],Ie=[`SnapshotBridge.m`,`SnapshotBridgeRuntime.m`,`SnapshotBridgeCapture.m`];async function Le(e,t,n){let r=_(`sha256`);for(let i of L){let a=g.join(t,i);if(w(n,`native-source-fingerprint-deadline`),!e.exists(a))throw x(`unsupported`,`native-source-missing`,{filePath:a});r.update(i),r.update(`\0`),r.update(await e.readBinary(a)),r.update(`\0`)}return r.digest(`hex`)}async function Re(e,t,n){let r=await R(e,`xcodebuild`,[`-version`],n),i=await R(e,`sw_vers`,[`-productVersion`],n),a=await R(e,`sw_vers`,[`-buildVersion`],n),o=await R(e,`uname`,[`-m`],n),s=await R(e,`xcrun`,[`--sdk`,`iphonesimulator`,`--show-sdk-version`],n),c=t.trim();if(!c)throw x(`unsupported`,`simulator-runtime-missing`);if(o!==`arm64`&&o!==`x86_64`)throw x(`unsupported`,`simulator-architecture-unsupported`,{architecture:o});return{xcode:r,macosProductVersion:i,macosBuild:a,architecture:o,simulatorSdk:s,simulatorRuntime:c}}async function R(e,t,n,r){let i=await ze(e,t,n,r);if(i.exitCode!==0)throw x(`unsupported`,`toolchain-probe-failed`,{command:t,exitCode:i.exitCode,stderr:i.stderr.slice(0,1024)});let a=(i.stdout||i.stderr).trim();if(!a)throw x(`unsupported`,`toolchain-probe-empty`,{command:t});return a}async function ze(e,t,n,r){try{return await z(e,t,n,r)}catch(i){if(!d(i))throw i;if(r.signal?.aborted)throw x(`cancelled`,`abort-signal`);if(r.clock.remainingMs(r.now())<=0)throw i;return await z(e,t,n,r)}}function z(e,t,n,r){return e.run(t,n,{allowFailure:!0,signal:r.signal,timeoutMs:Math.min(h,w(r,`toolchain-probe-deadline`))})}const B=`snapshot-bridge`,V=`manifest.json`,H=12e4;async function Be(e){let t=e.deadline,n=e.sourceRoot??Ve(e.host),r=await Le(e.host,n,t),i=await Re(e.host,e.runtime,t),a=Ue({schemaVersion:1,protocolVersion:1,sourceVersion:k,sourceHash:r,toolchain:i}),o=e.cacheRoot??g.join(e.host.homeDirectory(),`.agent-device`,`snapshot-source`),s=g.join(o,a);return await f({acquire:()=>e.host.acquireLock(g.join(o,`${a}.lock`),{deadline:t}),task:async()=>{let c=await He(e.host,s,{sourceHash:r,cacheKey:a,toolchain:i},t);if(c)return c;w(t,`native-build-deadline`),e.host.exists(s)&&await e.host.remove(s),w(t,`native-build-deadline`),await e.host.ensureDirectory(o);let l=g.join(o,`.${a}.${e.host.processId()}.tmp`);w(t,`native-build-deadline`),await e.host.remove(l);try{w(t,`native-build-deadline`),await e.host.ensureDirectory(l);let o=g.join(l,B),c=await e.host.run(`xcrun`,[`--sdk`,`iphonesimulator`,`clang`,`-arch`,i.architecture,`-mios-simulator-version-min=15.0`,`-fobjc-arc`,`-Werror`,`-Wall`,`-Wextra`,`-framework`,`Foundation`,`-framework`,`CoreGraphics`,...Ie.map(e=>g.join(n,e)),`-o`,o],{signal:t.signal,timeoutMs:Math.min(H,w(t,`native-build-deadline`)),allowFailure:!0});if(c.exitCode!==0||!e.host.exists(o))throw x(`unsupported`,`native-build-failed`,{exitCode:c.exitCode,stderr:c.stderr.slice(0,4096)});w(t,`native-build-deadline`),await e.host.chmod(o,493);let u=await U(e.host,o,t),d={schemaVersion:1,protocolVersion:1,sourceVersion:k,sourceHash:r,cacheKey:a,toolchain:i,binarySha256:u};return await e.host.writeText(g.join(l,V),`${JSON.stringify(d,null,2)}\n`),w(t,`native-build-deadline`),await e.host.rename(l,s),{path:g.join(s,B),sourceHash:r,cacheKey:a,protocolVersion:1,sourceVersion:k}}catch(t){throw await e.host.remove(l),t}}})}function Ve(e){let t=e.projectRoot(),n=g.join(t,`apple`,`snapshot-bridge`);if(L.every(t=>e.exists(g.join(n,t))))return n;let r=g.join(t,`dist`,`apple`,`snapshot-bridge`);if(L.every(t=>e.exists(g.join(r,t))))return r;throw x(`unsupported`,`native-source-missing`,{projectRoot:t})}async function He(e,t,n,r){let i=g.join(t,B);if(!(!e.exists(i)||!e.exists(g.join(t,V))))try{let a=JSON.parse(await e.readText(g.join(t,V)));return a.schemaVersion!==1||a.protocolVersion!==1||a.sourceVersion!==`agent-device-simulator-ax-v1.6.0`||a.sourceHash!==n.sourceHash||a.cacheKey!==n.cacheKey||JSON.stringify(a.toolchain)!==JSON.stringify(n.toolchain)||typeof a.binarySha256!=`string`||await U(e,i,r)!==a.binarySha256?void 0:{path:i,sourceHash:n.sourceHash,cacheKey:n.cacheKey,protocolVersion:1,sourceVersion:k}}catch(e){if(e instanceof b&&(e.failureKind===`cancelled`||e.failureKind===`timeout`))throw e;return}}async function U(e,t,n){return w(n,`native-cache-hash-deadline`),_(`sha256`).update(await e.readBinary(t)).digest(`hex`)}function Ue(e){return _(`sha256`).update(JSON.stringify(e)).digest(`hex`).slice(0,32)}const We=h+H;function Ge(e){let t=e.now??Date.now,n=new Map,r=ue({waitMs:2e3,waitGrant:`first-caller`,retryAfterMs:6e4,now:t}),i=async(r,i)=>{let a=C(We,i,t);try{let t=await e.host.withDiagnosticTimer(`ios.snapshot-source.prepare`,async()=>await Be({host:e.host,runtime:r,limits:e.limits,deadline:a,sourceRoot:e.sourceRoot,cacheRoot:e.cacheRoot}),{producer:e.producer});return n.set(r,t),t}catch(e){throw S(e)}};return{readyBinary:async(e,t,a)=>n.get(e)||await r.value(e,{start:t=>i(e,t),wait:(e,n)=>T(t,e,a,n),pending:()=>x(`preparing`,`bridge-preparation-pending`)}),close:()=>{n.clear(),r.close()}}}function Ke(e,t){return!n(e)||!n(t)||Math.abs(t.width-t.height)<=1?!1:Math.abs(e.width-t.height)<=1&&Math.abs(e.height-t.width)<=1}const W=Object.freeze({elementType:`XC_kAXXCAttributeElementType`,elementBaseType:`XC_kAXXCAttributeElementBaseType`,label:`XC_kAXXCAttributeLabel`,value:`XC_kAXXCAttributeValue`,identifier:`XC_kAXXCAttributeIdentifier`,frame:`XC_kAXXCAttributeFrame`,automationType:`XC_kAXXCAttributeAutomationType`,traits:`XC_kAXXCAttributeTraits`,children:`XC_kAXXCAttributeChildren`}),G=`Other.Other.Application.Group.Window.Sheet.Drawer.Alert.Dialog.Button.RadioButton.RadioGroup.CheckBox.DisclosureTriangle.PopUpButton.ComboBox.MenuButton.ToolbarButton.Popover.Keyboard.Key.NavigationBar.TabBar.TabGroup.Toolbar.StatusBar.Table.TableRow.TableColumn.Outline.OutlineRow.Browser.CollectionView.Slider.PageIndicator.ProgressIndicator.ActivityIndicator.SegmentedControl.Picker.PickerWheel.Switch.Toggle.Link.Image.Icon.SearchField.ScrollView.ScrollBar.StaticText.TextField.SecureTextField.DatePicker.TextView.Menu.MenuItem.MenuBar.MenuBarItem.Map.WebView.IncrementArrow.DecrementArrow.Timeline.RatingIndicator.ValueIndicator.SplitGroup.Splitter.RelevanceIndicator.ColorWell.HelpTag.Matte.DockItem.Ruler.RulerMarker.Grid.LevelIndicator.Cell.LayoutArea.LayoutItem.Handle.Stepper.Tab.TouchBar.StatusItem`.split(`.`),K={UIApplication:`Application`,UIWindow:`Window`},qe=new Set(Object.values(W)),Je=1n<<8n,Ye={x:0,y:0,width:0,height:0};function Xe(e,t,n){let r=Array.isArray(e)?e:[e];if(r.length===0||r.some(e=>!j(e)))throw x(`malformed-tree`,`guest-tree-root-invalid`);let i=[],a=[],o=0;for(let e of r)c(e,void 0,0,!1);if(i.length>n.maxNodes)throw x(`malformed-tree`,`node-limit-exceeded`,{nodeCount:i.length,maxNodes:n.maxNodes});if(o>n.maxTraversalDepth)throw x(`malformed-tree`,`traversal-depth-exceeded`,{maxTraversalDepth:o,maxAllowedDepth:n.maxTraversalDepth});if(typeof t.truncated!=`boolean`)throw x(`malformed-tree`,`truncated-invalid`);let s=et(i.filter(Y)[0]);return{nodes:i,maxTraversalDepth:o,viewport:s,opaqueRemoteElements:a.filter(e=>$e(e,s)).length,unresolvedCoordinateSpaceWindows:tt(i,s)};function c(e,t,r,s){if(i.length>=n.maxNodes)throw x(`malformed-tree`,`node-limit-exceeded`,{maxNodes:n.maxNodes});for(let t of Object.keys(e))if(!qe.has(t))throw x(`malformed-tree`,`node-contains-unknown-field`,{key:t});let l=e[W.children];if(!Array.isArray(l))throw x(`malformed-tree`,`children-invalid`);let u=i.length,d=Ze(e,u,t,r);i.push(d),o=Math.max(o,r),Qe(d,l.length,s)&&a.push(d.rect);let f=s||d.type===`WebView`;for(let e of l){if(!j(e))throw x(`malformed-tree`,`child-invalid`);c(e,u,r+1,f)}}}function Ze(e,t,n,r){let i=X(e[W.elementType]),a=X(e[W.elementBaseType]),o=it(e[W.automationType]),s=J(e[W.frame]),c=rt(e[W.traits]);return{index:t,...n===void 0?{}:{parentIndex:n},...q(i,o)?{type:q(i,o)}:{},...i?{role:i}:{},...a&&a!==i?{subrole:a}:{},...X(e[W.label])?{label:X(e[W.label])}:{},...Z(e[W.value])?{value:Z(e[W.value])}:{},...X(e[W.identifier])?{identifier:X(e[W.identifier])}:{},...s?{rect:s}:{},...c===void 0?{}:{enabled:c},depth:r}}function q(e,t){if(e!==void 0&&K[e])return K[e];if(e!==void 0&&G.includes(e))return e;if(t!==void 0)return G[t]??`Other`}function Qe(e,t,n){return n&&e.role===`AXRemoteElement`&&t===0}function $e(e,t){return e===void 0?!0:n(e)?t.kind!==`reported`||r(e,t.rect):!1}function J(e){if(e===void 0)return;if(!j(e))throw x(`malformed-tree`,`frame-invalid`);let t=[`X`,`Y`,`Width`,`Height`].map(t=>e[t]);if(!t.every(e=>typeof e==`number`&&Number.isFinite(e)))throw x(`malformed-tree`,`frame-invalid`);let[n,r,i,a]=t;if(i<0||a<0)throw x(`malformed-tree`,`frame-invalid`);return{x:n,y:r,width:i,height:a}}function et(e){return!e||!Y(e)?{kind:`missing`,reason:`not-provided`}:n(e.rect)?{kind:`reported`,rect:e.rect}:{kind:`missing`,reason:e.rect?`invalid`:`not-provided`}}function Y(e){return e.type===`Application`||e.type===`Window`}function tt(e,t){return t.kind===`reported`?e.filter(n=>nt(n,e)&&Ke(n.rect??Ye,t.rect)).length:0}function nt(e,t){return Y(e)?!0:e.parentIndex!==void 0&&Y(t[e.parentIndex]??e)}function X(e){return typeof e==`string`&&e.length>0?e:void 0}function Z(e){if(typeof e==`string`)return e.length>0?e:void 0;if(typeof e==`number`||typeof e==`boolean`)return String(e);if(e!=null)throw x(`malformed-tree`,`scalar-invalid`)}function rt(e){if(e!=null){if(typeof e!=`string`||!/^\d{1,20}$/.test(e))throw x(`malformed-tree`,`traits-invalid`);return(BigInt(e)&Je)===0n}}function it(e){if(e!=null){if(!Number.isSafeInteger(e))throw x(`malformed-tree`,`automation-type-invalid`);return e}}const Q=`simulator-ax-bridge`;function at(e={}){let t=e.host??ge(),n=new Me(t),r=new he,i=Ge({host:t,limits:I(e.limits),producer:Q,sourceRoot:e.sourceRoot,cacheRoot:e.cacheRoot}),a=!1;return{acquire:async o=>{try{if(a)throw x(`unsupported`,`source-closed`);ot(o);let s=I({...e.limits,...o.limits}),c=C(s.maxDurationMs,o.signal),l=ct(o.hint,s.maxTraversalDepth),u=l+1,d=o.hint.rawTraversalDepth!==null;return await t.withDiagnosticTimer(`ios.snapshot-source.acquire`,async()=>{let e=await i.readyBinary(o.target.runtime,c,`bridge-preparation-deadline`),a=r.consume(o.target,u,d),f=await n.request({target:o.target,bridge:e,limits:s,maxDepth:l,nativeLevelsHint:a.nativeLevels,deadline:c});w(c,`snapshot-decode-deadline`);let p=lt(o.hint,o.target,f,s);return st(t,r,o.target,u,d,a,f),{stage:`acquired`,acquisition:p}},{producer:Q})}catch(e){let t=S(e);return{stage:`failed`,failure:{kind:t.failureKind,code:t.failureCode,...t.details?{details:t.details}:{}}}}},close:async()=>{a||(a=!0,i.close(),await n.close())}}}function ot(t){if(!t.target.udid.trim()||!t.target.runtime.trim()||!t.target.generation.trim()||!Number.isSafeInteger(t.target.pid)||t.target.pid<=0)throw new e(`INVALID_ARGS`,`Simulator snapshot source target identity is incomplete`);let n=t.hint;if(n.projection!==`raw`&&n.projection!==`regular`||![`full`,`surface-observation`].includes(n.acquisitionIntent)||typeof n.interactiveOnly!=`boolean`||typeof n.customActions!=`boolean`||!$(n.rawTraversalDepth)||!$(n.regularPresentedDepth))throw new e(`INVALID_ARGS`,`Simulator snapshot source capture hint is invalid`)}function st(e,t,n,r,i,a,o){let s=A(o),c=o.truncated===!0,l=t.learn(n,r,i,s);e.emitDiagnostic({level:`debug`,phase:`ios_snapshot_source_recovery`,data:{producer:Q,...n.targetId?{targetId:n.targetId}:{},generation:n.generation,requestedLevels:r,hint:a.reason,...a.nativeLevels===void 0?{}:{hintedLevels:a.nativeLevels},...s,truncated:c,learning:l}})}function ct(t,n){let r=t.rawTraversalDepth??n;if(r>n)throw new e(`INVALID_ARGS`,`Simulator snapshot source depth exceeds its bound`,{requested:r,maximum:n});return r}function $(e){return e===null||Number.isSafeInteger(e)&&e>=0}function lt(e,t,n,r){if(n.automationEnabled!==!0)throw x(`unsupported`,`automation-mode-unavailable`);let i=n.tree,a=n.truncated;if(typeof a!=`boolean`)throw x(`malformed-tree`,`truncated-invalid`);let o=Xe(i,{truncated:a},r),s=n.generation;if(typeof s!=`string`||!s)throw x(`malformed-tree`,`generation-invalid`);if(o.opaqueRemoteElements>0)throw x(`unsupported`,`remote-content-boundary`,{remoteElements:o.opaqueRemoteElements});if(o.unresolvedCoordinateSpaceWindows>0)throw x(`unsupported`,`window-coordinate-space-unresolved`,{windows:o.unresolvedCoordinateSpaceWindows});let c=Object.freeze(o.nodes.map(e=>Object.freeze({...e,pid:t.pid}))),l=ut(e,a,o.viewport),u=Object.freeze({...t.targetId?{targetId:t.targetId}:{},generation:s}),d={producer:Q,nodes:c,truncated:a,viewport:o.viewport,lineage:u,residue:l};return e.acquisitionIntent===`full`?{...d,intent:`full`,hint:{...e,acquisitionIntent:`full`}}:{...d,intent:`surface-observation`,hint:{...e,acquisitionIntent:`surface-observation`}}}function ut(e,t,n){return Object.freeze([{kind:`unavailable-fact`,fact:`hittability`},...e.interactiveOnly?[{kind:`unavailable-fact`,fact:`interactive-query`}]:[],...t?[{kind:`truncated`}]:[],...n.kind===`missing`?[{kind:`missing-viewport`,reason:n.reason}]:[]])}export{at as createSimulatorSnapshotSource};
|
|
1
|
+
import{D as e,F as t}from"./sdk-contracts.js";import{Ur as n,Wr as r}from"./sdk-batch.js";import{c as i,r as a}from"./diagnostics.js";import{f as o,x as s}from"./owner-identity.js";import{c,l,m as u,r as d}from"./exec.js";import{n as f,t as p}from"./file.js";import"./diagnostics2.js";import"./command.js";import{n as m}from"./retry.js";import{n as ee}from"./version.js";import"./process.js";import{C as te,D as ne,c as re,f as ie,h as ae,n as oe,o as se,w as ce,y as le}from"./host-file.js";import{t as h}from"./apple-runner-platform.js";import{n as ue,r as de,t as fe}from"./snapshot-process.js";import g from"node:path";import{createHash as _,randomUUID as v}from"node:crypto";import pe from"node:net";import{Buffer as y}from"node:buffer";const me={unsupported:`UNSUPPORTED_OPERATION`,"malformed-tree":`COMMAND_FAILED`,"stale-target":`COMMAND_FAILED`,timeout:`COMMAND_FAILED`,cancelled:`COMMAND_FAILED`,"process-crash":`COMMAND_FAILED`,"transport-failure":`COMMAND_FAILED`,preparing:`COMMAND_FAILED`};var b=class extends e{failureKind;failureCode;constructor(e,t,n=`iOS Simulator snapshot source ${e}: ${t}`,r={},i){super(me[e],n,{...r,bridgeFailure:e,bridgeFailureCode:t,...e===`cancelled`?{reason:`request_canceled`}:{}},i),this.name=`SnapshotSourceError`,this.failureKind=e,this.failureCode=t}};function x(e,t,n={},r){return new b(e,t,void 0,n,r)}function S(n){return n instanceof b?n:t(n)?x(`cancelled`,`abort-signal`,{},n):n instanceof e&&typeof n.details?.timeoutMs==`number`?x(`timeout`,`host-operation-timeout`,{timeoutMs:n.details.timeoutMs},n):x(`transport-failure`,`unexpected-host-error`,{error:n instanceof Error?n.message:String(n)},n)}function C(e,t,n=Date.now){if(t?.aborted)throw x(`cancelled`,`abort-signal`);return{clock:m.fromTimeoutMs(e,n()),now:n,signal:t}}function w(e,t){if(e.signal?.aborted)throw x(`cancelled`,`abort-signal`);let n=e.clock.remainingMs(e.now());if(n<=0)throw x(`timeout`,t);return Math.max(1,Math.floor(n))}async function T(e,t,n,r){let i=Math.min(t,w(e,n));await de({waitMs:i,signal:e.signal,stop:r,cancelled:()=>x(`cancelled`,`abort-signal`)})}var he=class{entries=new Map;probeBackAfterUses;constructor(e=8){this.probeBackAfterUses=e}consume(e,t,n){if(n)return{nativeLevels:void 0,reason:`explicit-depth`};let r=this.currentEntry(e);return r===`unidentified`?{nativeLevels:void 0,reason:`unidentified-target`}:!r||r.nativeLevels>=t?{nativeLevels:void 0,reason:`no-hint`}:r.remainingUses<=0?{nativeLevels:void 0,reason:`probe-back`}:(--r.remainingUses,{nativeLevels:r.nativeLevels,reason:`hinted`})}learn(e,t,n,r){return n||!e.targetId?`ignored`:r.rejected>0&&r.acceptedLevels<t?(this.remember(e.targetId,{generation:e.generation,nativeLevels:r.acceptedLevels,remainingUses:this.probeBackAfterUses}),`learned`):r.rejected===0&&r.acceptedLevels>=t?this.entries.delete(e.targetId)?`forgotten`:`ignored`:this.currentEntry(e)?`kept`:`ignored`}currentEntry(e){if(!e.targetId)return`unidentified`;let t=this.entries.get(e.targetId);if(t){if(t.generation!==e.generation){this.entries.delete(e.targetId);return}return t}}remember(e,t){if(this.entries.delete(e),this.entries.size>=32){let e=this.entries.keys().next().value;e!==void 0&&this.entries.delete(e)}this.entries.set(e,t)}};const E=65536;function ge(){return{projectRoot:ee,homeDirectory:ie,run:async(e,t,n)=>await c(e,t,n),start:_e,connect:ve,readText:le,readBinary:ae,writeText:ne,ensureDirectory:se,chmod:oe,exists:re,rename:ce,remove:te,acquireLock:ye,emitDiagnostic:a,withDiagnosticTimer:i,processId:o,readTargetProcessStartTime:fe}}function _e(e,t,n,r={}){if(r.signal?.aborted)throw x(`cancelled`,`abort-signal`);let i=l(`xcrun`,[`simctl`,`spawn`,e,t,`serve`,n,`--idle-timeout`,`60`,`--exit-on-disconnect`,`false`],{allowFailure:!0,captureOutput:!1,detached:!0}),a=i.child.pid??0;if(a<=0)throw x(`transport-failure`,`bridge-process-pid-missing`);let o=``;return i.child.stderr?.setEncoding(`utf8`),i.child.stderr?.on(`data`,e=>{o=be(o,String(e))}),{pid:a,wait:i.wait,isAlive:()=>i.child.exitCode===null&&i.child.signalCode===null,signal:e=>{u(a,e)||i.child.kill(e)},readLog:()=>o}}async function ve(e,t){if(t.signal?.aborted)throw x(`cancelled`,`abort-signal`);let n=Math.max(1,Math.floor(t.timeoutMs));return await new Promise((r,i)=>{let a=pe.createConnection({path:e}),o=!1,s=!1,c=setTimeout(()=>{p(x(`timeout`,`bridge-connect-timeout`)),a.destroy()},n),l=()=>{p(x(`cancelled`,`abort-signal`)),a.destroy()},u=()=>{o=!0,clearTimeout(c),t.signal?.removeEventListener(`abort`,l),a.off(`error`,d),a.off(`close`,f),a.setTimeout(0),r(a)},d=e=>{p(e),a.destroy()},f=()=>{o||p(x(`transport-failure`,`bridge-closed-before-connect`))},p=e=>{s||o||(s=!0,clearTimeout(c),t.signal?.removeEventListener(`abort`,l),a.off(`connect`,u),a.off(`error`,d),a.off(`close`,f),i(e))};a.once(`connect`,u),a.once(`error`,d),a.once(`close`,f),t.signal?.addEventListener(`abort`,l,{once:!0}),t.signal?.aborted&&l()})}async function ye(e,t){let n=o(),r=t.deadline,i=p({lockDirPath:e,owner:{pid:n,startTime:s(n),acquiredAtMs:Date.now()},timeoutMs:w(r,`cache-lock-deadline`),pollMs:100,ownerGraceMs:5e3,description:`iOS Simulator snapshot bridge cache`}),a=r.signal;if(!a)return await i;let c=!1,l,u=new Promise((e,t)=>{l=()=>{c=!0,t(x(`cancelled`,`abort-signal`))},a.addEventListener(`abort`,l,{once:!0}),a.aborted&&l()});try{return await Promise.race([i,u])}catch(e){throw c&&i.then(e=>e().catch(()=>void 0),()=>void 0),r.clock.isExpired()&&!(e instanceof b&&e.failureKind===`cancelled`)?x(`timeout`,`cache-lock-deadline`):e}finally{a.removeEventListener(`abort`,l)}}function be(e,t){let n=e+t;return n.length<=E?n:n.slice(n.length-E)}function xe(e,t,n){let r=_(`sha256`).update(t).digest(`hex`).slice(0,12),i=_(`sha256`).update(n).digest(`hex`).slice(0,12);return g.join(`/tmp`,`agent-device-ax-${r}-${e.processId()}-${i}`,`snapshot.sock`)}const D=new WeakSet;async function O(e,t){let n;try{n=(await t.wait).exitCode}catch{n=void 0}return D.has(t)||(D.add(t),e.emitDiagnostic({level:`error`,phase:`ios.snapshot-source.bridge-process-exit`,data:{pid:t.pid,...n===void 0?{}:{exitCode:n},stderr:Se(t.readLog())}})),x(`process-crash`,`bridge-exited`,{pid:t.pid,...n===void 0?{}:{exitCode:n}})}function Se(e){let t=y.from(e);return t.length<=65536?e:t.subarray(-65536).toString(`utf8`)}const k=`agent-device-simulator-ax-v1.6.0`;Object.freeze([`verb`,`requestId`,`pid`,`generation`,`snapshotTree`,`automationMode`,`maxDepth`,`maxNodes`,`maxDurationMs`,`maxResponseBytes`,`nativeLevelsHint`]),Object.freeze([`protocolVersion`,`sourceVersion`,`requestId`,`generation`,`ok`,`pid`,`tree`,`truncated`,`automationEnabled`,`recovery`,`error_kind`,`error_code`,`error`]),Object.freeze([`XC_kAXXCAttributeElementType`,`XC_kAXXCAttributeElementBaseType`,`XC_kAXXCAttributeLabel`,`XC_kAXXCAttributeValue`,`XC_kAXXCAttributeIdentifier`,`XC_kAXXCAttributeFrame`,`XC_kAXXCAttributeAutomationType`,`XC_kAXXCAttributeTraits`,`XC_kAXXCAttributeChildren`]);const Ce=[`requests`,`rejected`,`continuations`,`acceptedLevels`];function A(e){let t=e.recovery;if(!j(t))throw x(`malformed-tree`,`recovery-invalid`);let n=Ce.map(e=>[e,t[e]]);if(n.some(([,e])=>!Number.isSafeInteger(e)||e<0))throw x(`malformed-tree`,`recovery-invalid`);return Object.freeze(Object.fromEntries(n))}function we(e,t){let n;try{n=y.from(JSON.stringify(e),`utf8`)}catch(e){throw x(`malformed-tree`,`request-not-json`,{},e)}let r=n.length+4;if(r>t.maxRequestBytes)throw x(`transport-failure`,`request-limit-exceeded`,{frameBytes:r,maxRequestBytes:t.maxRequestBytes});let i=y.alloc(4);return i.writeUInt32BE(n.length,0),y.concat([i,n])}var Te=class{header=y.alloc(4);headerBytes=0;chunks=[];payloadBytes=0;expectedBodyBytes;frame;maxFrameBytes;constructor(e){if(!Number.isSafeInteger(e)||e<=0)throw x(`malformed-tree`,`frame-limit-invalid`,{maxFrameBytes:e});this.maxFrameBytes=e}push(e){if(this.frame)return this.acceptTrailingChunk(e);let t=this.readHeader(e);if(t&&(this.appendPayload(e,t.offset,t.bodyBytes),this.payloadBytes===t.bodyBytes))return this.frame=y.concat(this.chunks,t.bodyBytes),this.frame}acceptTrailingChunk(e){if(e.length>0)throw x(`malformed-tree`,`multiple-frames`,{trailingBytes:e.length});return this.frame}readHeader(e){if(this.headerBytes===4)return{offset:0,bodyBytes:this.expectedBodyBytes};let t=Math.min(4-this.headerBytes,e.length);if(e.copy(this.header,this.headerBytes,0,t),this.headerBytes+=t,this.headerBytes<4)return;let n=this.header.readUInt32BE(0);if(n===0||n>this.maxFrameBytes)throw x(`malformed-tree`,`frame-limit-exceeded`,{bodyBytes:n,maxFrameBytes:this.maxFrameBytes});return this.expectedBodyBytes=n,{offset:t,bodyBytes:n}}appendPayload(e,t,n){let r=n-this.payloadBytes,i=e.length-t;if(i>r)throw x(`malformed-tree`,`multiple-frames`,{trailingBytes:i-r});i!==0&&(this.chunks.push(e.subarray(t)),this.payloadBytes+=i)}finish(){if(this.frame)return this.frame;throw x(`transport-failure`,`bridge-frame-incomplete`,{headerBytes:this.headerBytes,payloadBytes:this.payloadBytes,expectedBodyBytes:this.expectedBodyBytes})}};function Ee(e){let t;try{t=JSON.parse(e.toString(`utf8`))}catch(e){throw x(`malformed-tree`,`response-not-json`,{},e)}if(!j(t))throw x(`malformed-tree`,`response-not-object`);return t}function De(e){return Object.freeze({verb:`describe`,requestId:e.requestId,pid:e.pid,generation:e.generation,snapshotTree:!0,automationMode:!0,maxDepth:e.maxDepth,maxNodes:e.maxNodes,maxDurationMs:e.maxDurationMs,maxResponseBytes:e.maxResponseBytes,...e.nativeLevelsHint===void 0?{}:{nativeLevelsHint:e.nativeLevelsHint}})}function Oe(e,t){if(e.protocolVersion!==1)throw x(`transport-failure`,`protocol-version-mismatch`,{expected:1,observed:e.protocolVersion});if(e.sourceVersion!==`agent-device-simulator-ax-v1.6.0`)throw x(`transport-failure`,`source-version-mismatch`,{expected:k,observed:e.sourceVersion});if(e.requestId!==t)throw x(`transport-failure`,`request-id-mismatch`,{expected:t,observed:e.requestId})}function ke(e,t){if(typeof e.pid!=`number`||e.pid!==t.pid)throw x(`stale-target`,`bridge-pid-mismatch`,{expectedPid:t.pid,observedPid:e.pid});if(e.generation!==t.generation)throw x(`stale-target`,`bridge-generation-mismatch`,{expectedGeneration:t.generation,observedGeneration:e.generation})}function Ae(e){let t=e.error_kind,n=typeof e.error_code==`string`?e.error_code:`guest-error`,r=typeof e.error==`string`?e.error:void 0,i=r?{guestMessage:r.slice(0,1024)}:{};throw x(t===`unsupported`?`unsupported`:t===`malformed_tree`?`malformed-tree`:t===`application_not_responding`?`timeout`:t===`application_unavailable`?`transport-failure`:t===`bad_request`?`malformed-tree`:`transport-failure`,n,i)}function j(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}async function je(e){let t=new Te(e.limits.maxResponseBytes-4),n=w(e.deadline,`bridge-request-deadline`);return await new Promise((r,i)=>{let a=!1,o=!1,s=setTimeout(()=>{p(x(`timeout`,`bridge-request-deadline`,{dispatched:o})),e.socket.destroy()},n),c=()=>{p(x(`cancelled`,`abort-signal`,{dispatched:o})),e.socket.destroy()},l=n=>{try{if(!Buffer.isBuffer(n))throw x(`transport-failure`,`bridge-data-invalid`);let r=t.push(n);if(r){let t=Ee(r);if(Oe(t,e.requestId),ke(t,{pid:e.expectedPid,generation:e.expectedGeneration}),t.ok!==!0&&Ae(t),typeof t.truncated!=`boolean`)throw x(`malformed-tree`,`truncated-invalid`);f(t);return}}catch(t){p(t),e.socket.destroy()}},u=e=>p(S(e)),d=()=>{a||(e.process.isAlive()?p(x(`transport-failure`,`bridge-connection-closed`)):O(e.host,e.process).then(p))};e.process.wait.then(()=>{a||O(e.host,e.process).then(p)},e=>{a||p(S(e))});let f=e=>m(()=>r(e)),p=e=>m(()=>i(e)),m=t=>{a||(a=!0,clearTimeout(s),e.deadline.signal?.removeEventListener(`abort`,c),e.socket.off(`data`,l),e.socket.off(`error`,u),e.socket.off(`close`,d),t())};e.socket.on(`data`,l),e.socket.on(`error`,u),e.socket.on(`close`,d),e.deadline.signal?.addEventListener(`abort`,c,{once:!0});try{if(e.deadline.signal?.aborted)throw x(`cancelled`,`abort-signal`);o=!0,e.socket.write(e.frame)}catch(t){p(S(t)),e.socket.destroy()}})}var Me=class{sessions=new Map;requestQueues=new Map;ownerId=v();closed=!1;host;constructor(e){this.host=e}async request(e){if(this.closed)throw x(`unsupported`,`source-closed`);return await this.withSimulatorLock(e.target.udid,e.deadline,()=>this.requestInSimulator(e))}async requestInSimulator(e){if(this.closed)throw x(`unsupported`,`source-closed`);let t=e.deadline;w(t,`bridge-request-deadline`);let n=this.sessions.get(e.target.udid),r=await this.ensureSession(e,t);try{let n=await this.readTargetStartTime(e.target,t),i=await this.exchange(r,e,t);return await this.assertTargetStillCurrent(e.target,n,t),i}catch(e){throw await this.handleRequestFailure(e,r,n)}}async handleRequestFailure(e,t,n){let r=S(e);return Pe(r,t,n)?await this.removeSession(t,!0):r.failureKind===`process-crash`?await this.removeSession(t,!1):r.failureKind===`transport-failure`&&(t.socket?.destroy(),t.socket=void 0),r}async withSimulatorLock(e,t,n){let r=this.requestQueues.get(e)??Promise.resolve(),i,a=new Promise(e=>{i=e}),o=r.then(()=>a);this.requestQueues.set(e,o);try{return await Ne(r,t),await n()}finally{i(),this.requestQueues.get(e)===o&&this.requestQueues.delete(e)}}async close(){if(this.closed)return;this.closed=!0;let e=[...this.sessions.values()];this.sessions.clear(),await Promise.all(e.map(async e=>await this.dispose(e,!0)))}async ensureSession(e,t){let n=e.target.udid,r=this.sessions.get(n);if(r&&r.bridgePath===e.bridge.path&&r.process.isAlive())return(!r.socket||r.socket.destroyed)&&(r.socket=await this.connectUntilReady(r,t)),r;r&&await this.removeSession(r,!0);let i=xe(this.host,e.target.udid,this.ownerId);await this.host.ensureDirectory(g.dirname(i)),await this.host.remove(i);let a=this.host.start(e.target.udid,e.bridge.path,i,{signal:t.signal}),o={udid:e.target.udid,bridgePath:e.bridge.path,socketPath:i,process:a};this.sessions.set(n,o);try{return o.socket=await this.connectUntilReady(o,t),o}catch(e){throw await this.removeSession(o,!0),S(e)}}async connectUntilReady(e,t){let n;for(;;){let r=w(t,`bridge-connect-deadline`);if(!e.process.isAlive())throw await O(this.host,e.process);try{return await this.host.connect(e.socketPath,{signal:t.signal,timeoutMs:Math.min(250,r)})}catch(e){if(n=e,e instanceof b&&e.failureKind===`cancelled`)throw e;let r=Math.min(20,w(t,`bridge-connect-deadline`));try{await T(t,r,`bridge-connect-deadline`)}catch(e){throw S(e)}}if(n instanceof b&&n.failureKind===`timeout`)throw n}}async exchange(e,t,n){(!e.socket||e.socket.destroyed)&&(e.socket=await this.connectUntilReady(e,n));let r=v(),i=we(De({requestId:r,pid:t.target.pid,generation:t.target.generation,maxDepth:Math.min(t.limits.maxTraversalDepth,t.maxDepth),maxNodes:t.limits.maxNodes,maxDurationMs:w(n,`bridge-request-deadline`),maxResponseBytes:t.limits.maxResponseBytes,...t.nativeLevelsHint===void 0?{}:{nativeLevelsHint:t.nativeLevelsHint}}),t.limits);return await je({process:e.process,socket:e.socket,frame:i,requestId:r,deadline:n,limits:t.limits,expectedPid:t.target.pid,expectedGeneration:t.target.generation,host:this.host})}async readTargetStartTime(e,t){let n=await this.host.readTargetProcessStartTime(e.pid,{signal:t.signal,timeoutMs:w(t,`target-identity-deadline`)});if(!n)throw x(`stale-target`,`target-process-unavailable`,{pid:e.pid,generation:e.generation});if(e.processStartTime!==void 0&&e.processStartTime!==n)throw x(`stale-target`,`target-process-changed`,{pid:e.pid,generation:e.generation,expectedStartTime:e.processStartTime,observedStartTime:n});return n}async assertTargetStillCurrent(e,t,n){let r=await this.host.readTargetProcessStartTime(e.pid,{signal:n.signal,timeoutMs:w(n,`target-identity-deadline`)});if(r!==t)throw x(`stale-target`,`target-process-changed`,{pid:e.pid,generation:e.generation,expectedStartTime:t,observedStartTime:r})}async removeSession(e,t){this.sessions.get(e.udid)===e&&this.sessions.delete(e.udid),await this.dispose(e,t)}async dispose(e,t){e.socket?.destroy(),e.socket=void 0,t&&e.process.isAlive()&&(e.process.signal(`SIGTERM`),await M(e.process,500),e.process.isAlive()&&(e.process.signal(`SIGKILL`),await M(e.process,500))),await this.host.remove(e.socketPath)}};async function Ne(e,t){let n=w(t,`bridge-request-deadline`);await Promise.race([e,T(t,n,`bridge-request-deadline`).then(()=>{throw x(`timeout`,`bridge-request-deadline`)})])}function Pe(e,t,n){return(e.failureKind===`cancelled`||e.failureKind===`timeout`)&&(e.details?.dispatched===!0||n!==t)}async function M(e,t){await Promise.race([e.wait.catch(()=>void 0),new Promise(e=>setTimeout(e,t))])}const N=16777216,P=12e4,F=1e4,Fe=Object.freeze({maxRequestBytes:65536,maxResponseBytes:4194304,maxNodes:5e3,maxTraversalDepth:64,maxDurationMs:5e3});function I(t){let n={...Fe,...t??{}};for(let[t,r]of Object.entries(n))if(!Number.isSafeInteger(r)||r<=0)throw new e(`INVALID_ARGS`,`Snapshot source limit ${t} must be a positive integer`,{name:t,value:r});if(n.maxRequestBytes>n.maxResponseBytes)throw new e(`INVALID_ARGS`,`Snapshot source request bytes cannot exceed response bytes`,{maxRequestBytes:n.maxRequestBytes,maxResponseBytes:n.maxResponseBytes});if(n.maxRequestBytes>N||n.maxResponseBytes>N)throw new e(`INVALID_ARGS`,`Snapshot source frame limits exceed the bridge bound`,{maxRequestBytes:n.maxRequestBytes,maxResponseBytes:n.maxResponseBytes,maximumFrameBytes:N});if(n.maxNodes>F||n.maxTraversalDepth>128)throw new e(`INVALID_ARGS`,`Snapshot source tree limits exceed the bridge bound`,{maxNodes:n.maxNodes,maxTraversalDepth:n.maxTraversalDepth,maximumNodes:F,maximumDepth:128});if(n.maxDurationMs>P)throw new e(`INVALID_ARGS`,`Snapshot source duration exceeds the bridge bound`,{maxDurationMs:n.maxDurationMs,maximumDurationMs:P});if(n.maxRequestBytes<=4||n.maxResponseBytes<=4)throw new e(`INVALID_ARGS`,`Snapshot source frame limits must leave room for a body`,{maxRequestBytes:n.maxRequestBytes,maxResponseBytes:n.maxResponseBytes});return Object.freeze(n)}const L=[`SnapshotBridge.m`,`SnapshotBridgeRuntime.m`,`SnapshotBridgeRuntime.h`,`SnapshotBridgeCapture.h`,`SnapshotBridgeCapture.m`],Ie=[`SnapshotBridge.m`,`SnapshotBridgeRuntime.m`,`SnapshotBridgeCapture.m`];async function Le(e,t,n){let r=_(`sha256`);for(let i of L){let a=g.join(t,i);if(w(n,`native-source-fingerprint-deadline`),!e.exists(a))throw x(`unsupported`,`native-source-missing`,{filePath:a});r.update(i),r.update(`\0`),r.update(await e.readBinary(a)),r.update(`\0`)}return r.digest(`hex`)}async function Re(e,t,n){let r=await R(e,`xcodebuild`,[`-version`],n),i=await R(e,`sw_vers`,[`-productVersion`],n),a=await R(e,`sw_vers`,[`-buildVersion`],n),o=await R(e,`uname`,[`-m`],n),s=await R(e,`xcrun`,[`--sdk`,`iphonesimulator`,`--show-sdk-version`],n),c=t.trim();if(!c)throw x(`unsupported`,`simulator-runtime-missing`);if(o!==`arm64`&&o!==`x86_64`)throw x(`unsupported`,`simulator-architecture-unsupported`,{architecture:o});return{xcode:r,macosProductVersion:i,macosBuild:a,architecture:o,simulatorSdk:s,simulatorRuntime:c}}async function R(e,t,n,r){let i=await ze(e,t,n,r);if(i.exitCode!==0)throw x(`unsupported`,`toolchain-probe-failed`,{command:t,exitCode:i.exitCode,stderr:i.stderr.slice(0,1024)});let a=(i.stdout||i.stderr).trim();if(!a)throw x(`unsupported`,`toolchain-probe-empty`,{command:t});return a}async function ze(e,t,n,r){try{return await z(e,t,n,r)}catch(i){if(!d(i))throw i;if(r.signal?.aborted)throw x(`cancelled`,`abort-signal`);if(r.clock.remainingMs(r.now())<=0)throw i;return await z(e,t,n,r)}}function z(e,t,n,r){return e.run(t,n,{allowFailure:!0,signal:r.signal,timeoutMs:Math.min(h,w(r,`toolchain-probe-deadline`))})}const B=`snapshot-bridge`,V=`manifest.json`,H=12e4;async function Be(e){let t=e.deadline,n=e.sourceRoot??Ve(e.host),r=await Le(e.host,n,t),i=await Re(e.host,e.runtime,t),a=Ue({schemaVersion:1,protocolVersion:1,sourceVersion:k,sourceHash:r,toolchain:i}),o=e.cacheRoot??g.join(e.host.homeDirectory(),`.agent-device`,`snapshot-source`),s=g.join(o,a);return await f({acquire:()=>e.host.acquireLock(g.join(o,`${a}.lock`),{deadline:t}),task:async()=>{let c=await He(e.host,s,{sourceHash:r,cacheKey:a,toolchain:i},t);if(c)return c;w(t,`native-build-deadline`),e.host.exists(s)&&await e.host.remove(s),w(t,`native-build-deadline`),await e.host.ensureDirectory(o);let l=g.join(o,`.${a}.${e.host.processId()}.tmp`);w(t,`native-build-deadline`),await e.host.remove(l);try{w(t,`native-build-deadline`),await e.host.ensureDirectory(l);let o=g.join(l,B),c=await e.host.run(`xcrun`,[`--sdk`,`iphonesimulator`,`clang`,`-arch`,i.architecture,`-mios-simulator-version-min=15.0`,`-fobjc-arc`,`-Werror`,`-Wall`,`-Wextra`,`-framework`,`Foundation`,`-framework`,`CoreGraphics`,...Ie.map(e=>g.join(n,e)),`-o`,o],{signal:t.signal,timeoutMs:Math.min(H,w(t,`native-build-deadline`)),allowFailure:!0});if(c.exitCode!==0||!e.host.exists(o))throw x(`unsupported`,`native-build-failed`,{exitCode:c.exitCode,stderr:c.stderr.slice(0,4096)});w(t,`native-build-deadline`),await e.host.chmod(o,493);let u=await U(e.host,o,t),d={schemaVersion:1,protocolVersion:1,sourceVersion:k,sourceHash:r,cacheKey:a,toolchain:i,binarySha256:u};return await e.host.writeText(g.join(l,V),`${JSON.stringify(d,null,2)}\n`),w(t,`native-build-deadline`),await e.host.rename(l,s),{path:g.join(s,B),sourceHash:r,cacheKey:a,protocolVersion:1,sourceVersion:k}}catch(t){throw await e.host.remove(l),t}}})}function Ve(e){let t=e.projectRoot(),n=g.join(t,`apple`,`snapshot-bridge`);if(L.every(t=>e.exists(g.join(n,t))))return n;let r=g.join(t,`dist`,`apple`,`snapshot-bridge`);if(L.every(t=>e.exists(g.join(r,t))))return r;throw x(`unsupported`,`native-source-missing`,{projectRoot:t})}async function He(e,t,n,r){let i=g.join(t,B);if(!(!e.exists(i)||!e.exists(g.join(t,V))))try{let a=JSON.parse(await e.readText(g.join(t,V)));return a.schemaVersion!==1||a.protocolVersion!==1||a.sourceVersion!==`agent-device-simulator-ax-v1.6.0`||a.sourceHash!==n.sourceHash||a.cacheKey!==n.cacheKey||JSON.stringify(a.toolchain)!==JSON.stringify(n.toolchain)||typeof a.binarySha256!=`string`||await U(e,i,r)!==a.binarySha256?void 0:{path:i,sourceHash:n.sourceHash,cacheKey:n.cacheKey,protocolVersion:1,sourceVersion:k}}catch(e){if(e instanceof b&&(e.failureKind===`cancelled`||e.failureKind===`timeout`))throw e;return}}async function U(e,t,n){return w(n,`native-cache-hash-deadline`),_(`sha256`).update(await e.readBinary(t)).digest(`hex`)}function Ue(e){return _(`sha256`).update(JSON.stringify(e)).digest(`hex`).slice(0,32)}const We=h+H;function Ge(e){let t=e.now??Date.now,n=new Map,r=ue({waitMs:2e3,waitGrant:`first-caller`,retryAfterMs:6e4,now:t}),i=async(r,i)=>{let a=C(We,i,t);try{let t=await e.host.withDiagnosticTimer(`ios.snapshot-source.prepare`,async()=>await Be({host:e.host,runtime:r,limits:e.limits,deadline:a,sourceRoot:e.sourceRoot,cacheRoot:e.cacheRoot}),{producer:e.producer});return n.set(r,t),t}catch(e){throw S(e)}};return{readyBinary:async(e,t,a)=>n.get(e)||await r.value(e,{start:t=>i(e,t),wait:(e,n)=>T(t,e,a,n),pending:()=>x(`preparing`,`bridge-preparation-pending`)}),close:()=>{n.clear(),r.close()}}}function Ke(e,t){return!n(e)||!n(t)||Math.abs(t.width-t.height)<=1?!1:Math.abs(e.width-t.height)<=1&&Math.abs(e.height-t.width)<=1}const W=Object.freeze({elementType:`XC_kAXXCAttributeElementType`,elementBaseType:`XC_kAXXCAttributeElementBaseType`,label:`XC_kAXXCAttributeLabel`,value:`XC_kAXXCAttributeValue`,identifier:`XC_kAXXCAttributeIdentifier`,frame:`XC_kAXXCAttributeFrame`,automationType:`XC_kAXXCAttributeAutomationType`,traits:`XC_kAXXCAttributeTraits`,children:`XC_kAXXCAttributeChildren`}),G=`Other.Other.Application.Group.Window.Sheet.Drawer.Alert.Dialog.Button.RadioButton.RadioGroup.CheckBox.DisclosureTriangle.PopUpButton.ComboBox.MenuButton.ToolbarButton.Popover.Keyboard.Key.NavigationBar.TabBar.TabGroup.Toolbar.StatusBar.Table.TableRow.TableColumn.Outline.OutlineRow.Browser.CollectionView.Slider.PageIndicator.ProgressIndicator.ActivityIndicator.SegmentedControl.Picker.PickerWheel.Switch.Toggle.Link.Image.Icon.SearchField.ScrollView.ScrollBar.StaticText.TextField.SecureTextField.DatePicker.TextView.Menu.MenuItem.MenuBar.MenuBarItem.Map.WebView.IncrementArrow.DecrementArrow.Timeline.RatingIndicator.ValueIndicator.SplitGroup.Splitter.RelevanceIndicator.ColorWell.HelpTag.Matte.DockItem.Ruler.RulerMarker.Grid.LevelIndicator.Cell.LayoutArea.LayoutItem.Handle.Stepper.Tab.TouchBar.StatusItem`.split(`.`),K={UIApplication:`Application`,UIWindow:`Window`},qe=new Set(Object.values(W)),Je=1n<<8n,Ye={x:0,y:0,width:0,height:0};function Xe(e,t,n){let r=Array.isArray(e)?e:[e];if(r.length===0||r.some(e=>!j(e)))throw x(`malformed-tree`,`guest-tree-root-invalid`);let i=[],a=[],o=0;for(let e of r)c(e,void 0,0,!1);if(i.length>n.maxNodes)throw x(`malformed-tree`,`node-limit-exceeded`,{nodeCount:i.length,maxNodes:n.maxNodes});if(o>n.maxTraversalDepth)throw x(`malformed-tree`,`traversal-depth-exceeded`,{maxTraversalDepth:o,maxAllowedDepth:n.maxTraversalDepth});if(typeof t.truncated!=`boolean`)throw x(`malformed-tree`,`truncated-invalid`);let s=et(i.filter(Y)[0]);return{nodes:i,maxTraversalDepth:o,viewport:s,opaqueRemoteElements:a.filter(e=>$e(e,s)).length,unresolvedCoordinateSpaceWindows:tt(i,s)};function c(e,t,r,s){if(i.length>=n.maxNodes)throw x(`malformed-tree`,`node-limit-exceeded`,{maxNodes:n.maxNodes});for(let t of Object.keys(e))if(!qe.has(t))throw x(`malformed-tree`,`node-contains-unknown-field`,{key:t});let l=e[W.children];if(!Array.isArray(l))throw x(`malformed-tree`,`children-invalid`);let u=i.length,d=Ze(e,u,t,r);i.push(d),o=Math.max(o,r),Qe(d,l.length,s)&&a.push(d.rect);let f=s||d.type===`WebView`;for(let e of l){if(!j(e))throw x(`malformed-tree`,`child-invalid`);c(e,u,r+1,f)}}}function Ze(e,t,n,r){let i=X(e[W.elementType]),a=X(e[W.elementBaseType]),o=it(e[W.automationType]),s=J(e[W.frame]),c=rt(e[W.traits]);return{index:t,...n===void 0?{}:{parentIndex:n},...q(i,o)?{type:q(i,o)}:{},...i?{role:i}:{},...a&&a!==i?{subrole:a}:{},...X(e[W.label])?{label:X(e[W.label])}:{},...Z(e[W.value])?{value:Z(e[W.value])}:{},...X(e[W.identifier])?{identifier:X(e[W.identifier])}:{},...s?{rect:s}:{},...c===void 0?{}:{enabled:c},depth:r}}function q(e,t){if(e!==void 0&&K[e])return K[e];if(e!==void 0&&G.includes(e))return e;if(t!==void 0)return G[t]??`Other`}function Qe(e,t,n){return n&&e.role===`AXRemoteElement`&&t===0}function $e(e,t){return e===void 0?!0:n(e)?t.kind!==`reported`||r(e,t.rect):!1}function J(e){if(e===void 0)return;if(!j(e))throw x(`malformed-tree`,`frame-invalid`);let t=[`X`,`Y`,`Width`,`Height`].map(t=>e[t]);if(!t.every(e=>typeof e==`number`&&Number.isFinite(e)))throw x(`malformed-tree`,`frame-invalid`);let[n,r,i,a]=t;if(i<0||a<0)throw x(`malformed-tree`,`frame-invalid`);return{x:n,y:r,width:i,height:a}}function et(e){return!e||!Y(e)?{kind:`missing`,reason:`not-provided`}:n(e.rect)?{kind:`reported`,rect:e.rect}:{kind:`missing`,reason:e.rect?`invalid`:`not-provided`}}function Y(e){return e.type===`Application`||e.type===`Window`}function tt(e,t){return t.kind===`reported`?e.filter(n=>nt(n,e)&&Ke(n.rect??Ye,t.rect)).length:0}function nt(e,t){return Y(e)?!0:e.parentIndex!==void 0&&Y(t[e.parentIndex]??e)}function X(e){return typeof e==`string`&&e.length>0?e:void 0}function Z(e){if(typeof e==`string`)return e.length>0?e:void 0;if(typeof e==`number`||typeof e==`boolean`)return String(e);if(e!=null)throw x(`malformed-tree`,`scalar-invalid`)}function rt(e){if(e!=null){if(typeof e!=`string`||!/^\d{1,20}$/.test(e))throw x(`malformed-tree`,`traits-invalid`);return(BigInt(e)&Je)===0n}}function it(e){if(e!=null){if(!Number.isSafeInteger(e))throw x(`malformed-tree`,`automation-type-invalid`);return e}}const Q=`simulator-ax-bridge`;function at(e={}){let t=e.host??ge(),n=new Me(t),r=new he,i=Ge({host:t,limits:I(e.limits),producer:Q,sourceRoot:e.sourceRoot,cacheRoot:e.cacheRoot}),a=!1;return{acquire:async o=>{try{if(a)throw x(`unsupported`,`source-closed`);ot(o);let s=I({...e.limits,...o.limits}),c=C(s.maxDurationMs,o.signal),l=ct(o.hint,s.maxTraversalDepth),u=l+1,d=o.hint.rawTraversalDepth!==null;return await t.withDiagnosticTimer(`ios.snapshot-source.acquire`,async()=>{let e=await i.readyBinary(o.target.runtime,c,`bridge-preparation-deadline`),a=r.consume(o.target,u,d),f=await n.request({target:o.target,bridge:e,limits:s,maxDepth:l,nativeLevelsHint:a.nativeLevels,deadline:c});w(c,`snapshot-decode-deadline`);let p=lt(o.hint,o.target,f,s);return st(t,r,o.target,u,d,a,f),{stage:`acquired`,acquisition:p}},{producer:Q})}catch(e){let t=S(e);return{stage:`failed`,failure:{kind:t.failureKind,code:t.failureCode,...t.details?{details:t.details}:{}}}}},close:async()=>{a||(a=!0,i.close(),await n.close())}}}function ot(t){if(!t.target.udid.trim()||!t.target.runtime.trim()||!t.target.generation.trim()||!Number.isSafeInteger(t.target.pid)||t.target.pid<=0)throw new e(`INVALID_ARGS`,`Simulator snapshot source target identity is incomplete`);let n=t.hint;if(n.projection!==`raw`&&n.projection!==`regular`||![`full`,`surface-observation`].includes(n.acquisitionIntent)||typeof n.interactiveOnly!=`boolean`||typeof n.customActions!=`boolean`||!$(n.rawTraversalDepth)||!$(n.regularPresentedDepth))throw new e(`INVALID_ARGS`,`Simulator snapshot source capture hint is invalid`)}function st(e,t,n,r,i,a,o){let s=A(o),c=o.truncated===!0,l=t.learn(n,r,i,s);e.emitDiagnostic({level:`debug`,phase:`ios_snapshot_source_recovery`,data:{producer:Q,...n.targetId?{targetId:n.targetId}:{},generation:n.generation,requestedLevels:r,hint:a.reason,...a.nativeLevels===void 0?{}:{hintedLevels:a.nativeLevels},...s,truncated:c,learning:l}})}function ct(t,n){let r=t.rawTraversalDepth??n;if(r>n)throw new e(`INVALID_ARGS`,`Simulator snapshot source depth exceeds its bound`,{requested:r,maximum:n});return r}function $(e){return e===null||Number.isSafeInteger(e)&&e>=0}function lt(e,t,n,r){if(n.automationEnabled!==!0)throw x(`unsupported`,`automation-mode-unavailable`);let i=n.tree,a=n.truncated;if(typeof a!=`boolean`)throw x(`malformed-tree`,`truncated-invalid`);let o=Xe(i,{truncated:a},r),s=n.generation;if(typeof s!=`string`||!s)throw x(`malformed-tree`,`generation-invalid`);if(o.opaqueRemoteElements>0)throw x(`unsupported`,`remote-content-boundary`,{remoteElements:o.opaqueRemoteElements});if(o.unresolvedCoordinateSpaceWindows>0)throw x(`unsupported`,`window-coordinate-space-unresolved`,{windows:o.unresolvedCoordinateSpaceWindows});let c=Object.freeze(o.nodes.map(e=>Object.freeze({...e,pid:t.pid}))),l=ut(e,a,o.viewport),u=Object.freeze({...t.targetId?{targetId:t.targetId}:{},generation:s}),d={producer:Q,nodes:c,truncated:a,viewport:o.viewport,lineage:u,residue:l};return e.acquisitionIntent===`full`?{...d,intent:`full`,hint:{...e,acquisitionIntent:`full`}}:{...d,intent:`surface-observation`,hint:{...e,acquisitionIntent:`surface-observation`}}}function ut(e,t,n){return Object.freeze([{kind:`unavailable-fact`,fact:`hittability`},...e.interactiveOnly?[{kind:`unavailable-fact`,fact:`interactive-query`}]:[],...t?[{kind:`truncated`}]:[],...n.kind===`missing`?[{kind:`missing-viewport`,reason:n.reason}]:[]])}export{at as createSimulatorSnapshotSource};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as e}from"./rolldown-runtime.js";import{
|
|
1
|
+
import{r as e}from"./rolldown-runtime.js";import{sr as t}from"./sdk-batch.js";import{r as n}from"./diagnostics.js";import{c as r}from"./owner-identity.js";import"./diagnostics2.js";import{n as i}from"./process.js";import{_ as a,d as o}from"./host-file.js";import"./agent-browser-process-record.js";import s from"node:path";var c=e({DEFAULT_AGENT_BROWSER_IDLE_TIMEOUT_MS:()=>l,cleanupManagedAgentBrowserOrphans:()=>f,cleanupManagedAgentBrowserOrphansForProviderStartup:()=>p,resolveAgentBrowserIdleTimeoutMs:()=>d});const l=3e5,u=new Map;function d(e){return m(e.AGENT_BROWSER_IDLE_TIMEOUT_MS)??m(e.AGENT_DEVICE_WEB_IDLE_TIMEOUT_MS)??3e5}async function f(e,a,o={}){let s=t((o.openWebSessionNames??[]).filter(e=>e.length>0));if(s.length>0)return h(`open-web-session`,{openWebSessionNames:s});let c=d(r()),l=_(e);if(l!==void 0&&Date.now()-l<c)return h(`recent-browser-activity`,{idleTimeoutMs:c,latestActivityMs:l});let u=o.ownedProcessRecords;if(!u)return g();let f=await i(u,{openWebSessionNames:s,purposes:[`managed-web-browser`],termTimeoutMs:1500,killTimeoutMs:1e3}),p=[...f.terminatedPids];return f.inspected>0&&n({level:`warn`,phase:`web_agent_browser_orphan_cleanup`,data:{reason:a,count:f.inspected,pids:[...f.inspectedPids],signalPids:p,ownershipLostPids:[...f.ownershipLostPids],stateDir:e.stateDir,installDir:e.installDir}}),{count:f.inspected,pids:[...f.inspectedPids],processes:[],signalPids:p}}async function p(e,t={}){let n=Date.now(),r=s.resolve(e.stateDir),i=u.get(r);if(!(i!==void 0&&n-i<3e4))return u.set(r,n),await f(e,`provider-startup`,t)}function m(e){if(e===void 0||e.trim()===``)return;let t=Number.parseInt(e,10);return Number.isInteger(t)&&t>0?t:void 0}function h(e,t){return{count:0,pids:[],processes:[],signalPids:[],skipped:{reason:e,...t}}}function g(){return{count:0,pids:[],processes:[],signalPids:[]}}function _(e){let t=v(e.socketDir).map(e=>y(e)).filter(e=>e!==void 0);return t.length>0?Math.max(...t):void 0}function v(e){try{return a(e).map(t=>s.join(e,t))}catch{return[]}}function y(e){try{return o(e).mtimeMs}catch{return}}export{p as n,d as r,c as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as e}from"./rolldown-runtime.js";import{
|
|
1
|
+
import{r as e}from"./rolldown-runtime.js";import{sr as t}from"./sdk-batch.js";import{f as n,g as r,o as i,x as a,y as o}from"./owner-identity.js";import{_ as s}from"./exec.js";import"./command.js";import"./process.js";import c from"node:path";import l from"node:crypto";var u=e({agentBrowserChromeLaunchMarker:()=>d,appendAgentDeviceChromeArgs:()=>f,inspectManagedAgentBrowserProcesses:()=>_,matchAgentBrowserChromeProcess:()=>p,recordManagedAgentBrowserProcesses:()=>v,summarizeAgentBrowserProcesses:()=>m,summarizeManagedAgentBrowserProcesses:()=>g});function d(e){let t=l.createHash(`sha256`);return t.update(c.resolve(e.stateDir)),t.update(`\0`),t.update(c.resolve(e.installDir)),`--agent-device-managed-web=${t.digest(`hex`).slice(0,16)}`}function f(e,t){let n=d(t),r=e?.trim();return r?x(r).includes(n)?r:`${r},${n}`:n}function p(e,t){if(!(e.pid===n()||!S(e.command))){if(e.command.includes(d(t)))return{process:e,reason:`launch-marker`};if(w(t).some(t=>T(e,t)))return{process:e,reason:`managed-browser-home`}}}function m(e,t){return b(e,e=>p(e,t))}function h(e,t){return p(e,t)??C(e,t)}function g(e,t){return b(e,e=>h(e,t))}async function _(e){return m(await y(),e)}async function v(e,t){let n=await y(),r=g(n,e),s=i(r.pids,n),c={count:s.length,pids:s.map(({pid:e})=>e),processes:s.map(t=>({process:t,reason:h(t,e)?.reason??`descendant`}))},l=c.processes.flatMap(({process:e})=>{let t=a(e.pid),n=o(e.pid);return t&&n?[{pid:e.pid,startTime:t,command:n,purpose:`managed-web-browser`}]:[]});return l.length>0&&t.replace({kind:`daemon`},l),c}async function y(){return await s(async()=>await r({timeoutMs:1500}))}function b(e,t){let n=e.flatMap(e=>{let n=t(e);return n?[n]:[]});return{count:n.length,pids:n.map(e=>e.process.pid),processes:n}}function x(e){return e.split(/[,\n]/).map(e=>e.trim()).filter(Boolean)}function S(e){return/\b(?:Google Chrome for Testing|Chrome for Testing|Chromium|chrome|chrome\.exe|chromium|chromium-browser|headless_shell)\b/i.test(e)}function C(e,t){if(e.pid===n()||S(e.command))return;let r=E(e.command),i=E(c.resolve(t.installDir));return r.includes(`${i}/`)?{process:e,reason:`agent-browser-daemon`}:void 0}function w(e){return t([c.join(e.homeDir,`.agent-browser`,`browsers`),c.join(e.runtimeHomeDir,`.agent-browser`,`browsers`)])}function T(e,t){let n=E(e.command),r=`${E(c.resolve(t)).replace(/\/+$/,``)}/`;return n.includes(r)}function E(e){return e.replaceAll(`\\`,`/`)}export{v as i,f as n,_ as r,u as t};
|