agent-device 0.20.10 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.20.10.apk → agent-device-android-ime-helper-0.21.0.apk} +0 -0
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.0.apk.sha256 +1 -0
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.20.10.manifest.json → agent-device-android-ime-helper-0.21.0.manifest.json} +4 -4
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.0.apk +0 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.0.apk.sha256 +1 -0
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.20.10.manifest.json → agent-device-android-snapshot-helper-0.21.0.manifest.json} +6 -6
- package/apple/macos-helper/Sources/AgentDeviceMacOSHelper/AudioProbe.swift +35 -33
- package/apple/macos-helper/Sources/AgentDeviceMacOSHelper/main.swift +6 -1
- package/apple/snapshot-bridge/LICENSE.idb +23 -0
- package/apple/snapshot-bridge/README.md +49 -0
- package/apple/snapshot-bridge/SnapshotBridge.m +280 -0
- package/apple/snapshot-bridge/SnapshotBridgeRuntime.h +33 -0
- package/apple/snapshot-bridge/SnapshotBridgeRuntime.m +382 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunner/AgentDeviceRunnerApp.m +58 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunner.xcodeproj/project.pbxproj +19 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAlertVerification.swift +36 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerStringNormalization.swift +8 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedGesture.h +12 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedGesture.m +100 -6
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTapPointPolicy.swift +2 -2
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+AXSnapshotFallback.swift +16 -8
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Alert.swift +21 -88
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+AlertObservation.swift +124 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +106 -103
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandJournal.swift +6 -14
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +63 -91
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Lifecycle.swift +13 -6
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +72 -155
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+PrivateAXElementTypes.swift +12 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+PrivateAXPresentation.swift +74 -78
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScreenRecorder.swift +17 -9
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScrollGesture.swift +42 -11
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +185 -461
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotBackendCapabilities.swift +98 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCapturePlan.swift +224 -164
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotPresentationInvariant.swift +19 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotTiming.swift +110 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedCommitDeadline.swift +206 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedTextEntry.swift +147 -25
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SystemModal.swift +1 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntry.swift +24 -307
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntryFocus.swift +206 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntryReadiness.swift +158 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextTyping.swift +49 -16
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Transport.swift +2 -11
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TvRemote.swift +4 -19
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests.swift +16 -20
- package/dist/apple/runner/AgentDeviceRunner/RecordingScripts/RecordingExportSupport.swift +111 -0
- package/dist/apple/runner/AgentDeviceRunner/RecordingScripts/recording-overlay.swift +42 -81
- package/dist/apple/runner/AgentDeviceRunner/RecordingScripts/recording-trim.swift +35 -82
- package/dist/apple/snapshot-presentation/Package.swift +21 -0
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotGeometry.swift +56 -0
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotModels.swift +259 -0
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotPresentation.swift +153 -0
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotPresentationFailure.swift +27 -0
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotPresentationInvariant.swift +91 -0
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotPresentationProjection.swift +161 -0
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotScopePolicy.swift +53 -0
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotVisibilityFold.swift +242 -0
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotVisibilityFoldProjection.swift +97 -0
- package/dist/src/adapter.js +1 -0
- package/dist/src/adb-executor.js +2 -0
- package/dist/src/adb-failure.js +1 -0
- package/dist/src/adb-host.js +1 -0
- package/dist/src/adb.js +1 -0
- package/dist/src/agent-browser-lifecycle.js +1 -0
- package/dist/src/agent-browser-process-record.js +1 -0
- package/dist/src/agent-browser-provider.js +1 -0
- package/dist/src/agent-browser-tool.js +1 -1
- package/dist/src/agent-device-client.js +2 -2
- package/dist/src/ai-sdk.d.ts +2 -2
- package/dist/src/ai-sdk.js +1 -1
- package/dist/src/alert-contract.js +1 -0
- package/dist/src/alert-runtime.js +1 -0
- package/dist/src/android-adb.d.ts +27 -19
- package/dist/src/android-adb.js +1 -1
- package/dist/src/android-input-ownership.js +1 -0
- package/dist/src/android-system-chrome.js +1 -0
- package/dist/src/android.js +1 -1
- package/dist/src/api.js +11 -0
- package/dist/src/app-catalog.js +1 -0
- package/dist/src/app-deployment-resolution.js +2 -0
- package/dist/src/app-helpers.js +1 -1
- package/dist/src/app-inventory-contract.js +1 -0
- package/dist/src/app-inventory.js +1 -0
- package/dist/src/app-launch.js +2 -0
- package/dist/src/app-lifecycle-facade.js +1 -0
- package/dist/src/app-lifecycle.js +3 -6
- package/dist/src/app-lifecycle2.js +2 -2
- package/dist/src/app-lifecycle3.js +1 -0
- package/dist/src/app-log-files.js +1 -1
- package/dist/src/app-log-reconnect.js +1 -1
- package/dist/src/app-log-runtime.js +1 -4
- package/dist/src/app-log-runtime2.js +4 -0
- package/dist/src/app-parsers.js +4 -0
- package/dist/src/app-resolution-cache.js +1 -0
- package/dist/src/app-resolution-facade.js +1 -0
- package/dist/src/app-resolution.js +2 -2
- package/dist/src/app-state.js +1 -2
- package/dist/src/application-lifecycle-interaction.js +1 -0
- package/dist/src/application-lifecycle-runtime.js +1 -0
- package/dist/src/apps-simctl.js +1 -0
- package/dist/src/archive.js +4 -0
- package/dist/src/artifact-download.js +1 -0
- package/dist/src/artifacts.d.ts +6 -2
- package/dist/src/artifacts.js +1 -1
- package/dist/src/async-lifecycle.js +1 -0
- package/dist/src/audio-probe-result.js +1 -0
- package/dist/src/audio-probe-runtime.js +1 -0
- package/dist/src/audio-probe-support.js +1 -0
- package/dist/src/auth-session.js +1 -1
- package/dist/src/auth.js +1 -1
- package/dist/src/back-mode.js +1 -0
- package/dist/src/{url.js → base-url.js} +1 -1
- package/dist/src/boot-diagnostics.js +2 -2
- package/dist/src/byte-limit-stream.js +1 -1
- package/dist/src/capabilities.js +1 -0
- package/dist/src/capture.js +1 -0
- package/dist/src/catalog.js +1 -0
- package/dist/src/cli-command-aliases.js +1 -0
- package/dist/src/cli-config.js +1 -1
- package/dist/src/cli-help.js +69 -50
- package/dist/src/cli-output.js +1 -1
- package/dist/src/cli-runner.js +1 -1
- package/dist/src/cli.js +4 -6
- package/dist/src/click-button.js +1 -0
- package/dist/src/client-metro-companion.js +1 -0
- package/dist/src/client-metro.js +1 -1
- package/dist/src/client-types.d.ts +255 -231
- package/dist/src/clipboard.js +1 -0
- package/dist/src/code-signature-cache.js +1 -0
- package/dist/src/code-signature.js +1 -0
- package/dist/src/color.js +1 -0
- package/dist/src/command-metadata.js +1 -1
- package/dist/src/command-schema.js +3 -3
- package/dist/src/command-surface.js +1 -1
- package/dist/src/command-tools.js +2 -2
- package/dist/src/command.js +1 -0
- package/dist/src/compatibility-policy.js +1 -0
- package/dist/src/config.js +1 -1
- package/dist/src/config2.js +1 -0
- package/dist/src/connection-runtime.js +1 -1
- package/dist/src/connection.js +5 -5
- package/dist/src/contracts.d.ts +1 -1
- package/dist/src/contracts.js +1 -1
- package/dist/src/daemon-client-lifecycle.js +1 -0
- package/dist/src/daemon-process.js +1 -0
- package/dist/src/daemon-registration.js +1 -0
- package/dist/src/daemon-shutdown-report.js +1 -1
- package/dist/src/daemon.js +2 -2
- package/dist/src/debug-symbols-facade.js +5 -0
- package/dist/src/deploy-result-target.js +1 -0
- package/dist/src/device-claim-inspection.js +1 -1
- package/dist/src/device-claim-rule.js +1 -0
- package/dist/src/device-input-state.d.ts +190 -3
- package/dist/src/device-inventory-context.js +1 -0
- package/dist/src/device-isolation.js +1 -0
- package/dist/src/device-release.js +1 -0
- package/dist/src/device-rotation.js +1 -0
- package/dist/src/device-selection-resolver.js +1 -0
- package/dist/src/device-session.js +1 -0
- package/dist/src/device.js +1 -1
- package/dist/src/device2.js +3 -2
- package/dist/src/diagnostics.js +3 -0
- package/dist/src/diagnostics2.js +1 -0
- package/dist/src/dispatch-resolve.js +1 -0
- package/dist/src/doctor-facade.js +1 -0
- package/dist/src/doctor-output.js +1 -0
- package/dist/src/doctor.js +1 -0
- package/dist/src/doctor2.js +1 -0
- package/dist/src/doctor3.js +1 -0
- package/dist/src/durable-resource.js +1 -0
- package/dist/src/entities.js +1 -1
- package/dist/src/error.js +2 -0
- package/dist/src/exec.js +1 -0
- package/dist/src/file.js +1 -0
- package/dist/src/find.js +1 -1
- package/dist/src/finders.js +1 -1
- package/dist/src/format.js +2 -0
- package/dist/src/generic-settle.js +1 -1
- package/dist/src/generic.js +1 -1
- package/dist/src/gesture-admission.js +1 -0
- package/dist/src/gesture-plan-types.js +1 -0
- package/dist/src/gesture-plan.js +1 -0
- package/dist/src/gesture-runtime.js +1 -0
- package/dist/src/harmonyos.js +1 -1
- package/dist/src/hdc.js +1 -1
- package/dist/src/helper.js +2 -2
- package/dist/src/host-file.js +1 -0
- package/dist/src/human-control-contract.js +1 -0
- package/dist/src/human-control.js +1 -0
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/input-actions.js +1 -4
- package/dist/src/input-actions2.js +2 -1
- package/dist/src/install-artifact-facade.js +1 -0
- package/dist/src/install-source-network-transport.js +1 -0
- package/dist/src/install-source.d.ts +3 -10
- package/dist/src/install-source2.js +1 -1
- package/dist/src/interaction-positionals.js +1 -0
- package/dist/src/interaction-ref-policy.js +1 -0
- package/dist/src/interaction.js +1 -1
- package/dist/src/interaction2.js +1 -1
- package/dist/src/interactor-operation-catalog.js +1 -0
- package/dist/src/interactor-types.js +1 -0
- package/dist/src/interactor.js +6 -2
- package/dist/src/interactor2.js +1 -1
- package/dist/src/interactors.js +1 -1
- package/dist/src/internal/bin.d.ts +1 -1
- package/dist/src/internal/bin.js +1 -2
- package/dist/src/internal/companion-tunnel.d.ts +1 -1
- package/dist/src/internal/companion-tunnel.js +1 -1
- package/dist/src/internal/daemon.d.ts +1 -1
- package/dist/src/internal/daemon.js +2 -4
- package/dist/src/internal/png-worker.d.ts +4 -4
- package/dist/src/internal/png-worker.js +1 -1
- package/dist/src/internal/run-script-http-child.d.ts +4 -0
- package/dist/src/internal/run-script-http-child.js +1 -0
- package/dist/src/internal/update-check-entry.d.ts +1 -1
- package/dist/src/inventory.js +4 -4
- package/dist/src/inventory2.js +1 -1
- package/dist/src/inventory3.js +1 -1
- package/dist/src/inventory5.js +1 -1
- package/dist/src/inventory6.js +1 -1
- package/dist/src/ios-client.js +16 -0
- package/dist/src/ios-snapshot-acquisition.js +1 -0
- package/dist/src/ios-snapshot-adapter.js +1 -0
- package/dist/src/ios-snapshot-planning.js +1 -0
- package/dist/src/ios-snapshot-runtime.js +1 -0
- package/dist/src/json.js +1 -0
- package/dist/src/keyboard-actions.js +1 -0
- package/dist/src/launch-console.js +1 -0
- package/dist/src/lease-context.js +1 -1
- package/dist/src/lease-scope.js +1 -0
- package/dist/src/lease.js +1 -1
- package/dist/src/limrun-runtime-dependencies.js +1 -1
- package/dist/src/limrun.d.ts +1610 -7
- package/dist/src/limrun.js +1 -1
- package/dist/src/linux.js +1 -1
- package/dist/src/local-interactor-operation-set.js +1 -0
- package/dist/src/location-coordinates.js +1 -1
- package/dist/src/logcat.js +1 -1
- package/dist/src/macos-facade.js +1 -0
- package/dist/src/managed-device-scope.js +1 -0
- package/dist/src/mechanics.js +19 -0
- package/dist/src/metro.d.ts +4 -2
- package/dist/src/metro.js +1 -1
- package/dist/src/metro2.js +1 -1
- package/dist/src/mobile-snapshot-semantics.js +1 -1
- package/dist/src/multitouch-support.js +1 -0
- package/dist/src/numeric.js +1 -0
- package/dist/src/observability.js +1 -1
- package/dist/src/observation.js +2 -0
- package/dist/src/output-path.js +1 -1
- package/dist/src/owner-identity.js +3 -1
- package/dist/src/parameterized-recorded-fill.js +1 -0
- package/dist/src/parser.js +1 -1
- package/dist/src/perf-facade.js +2 -0
- package/dist/src/perf-runtime-operation-builder.js +1 -0
- package/dist/src/perf-runtime-plan.js +1 -0
- package/dist/src/perf-runtime.js +1 -0
- package/dist/src/perf.js +1 -4
- package/dist/src/physical-device-control.js +1 -1
- package/dist/src/physical-device-facade.js +1 -0
- package/dist/src/platform-request-scope.js +1 -0
- package/dist/src/platform-runtime-android-adb-host.js +1 -0
- package/dist/src/platform-runtime-android-mechanics.js +1 -0
- package/dist/src/platform-runtime-app-log-android-transport.js +1 -1
- package/dist/src/platform-runtime-app-log-process.js +1 -1
- package/dist/src/platform-runtime-apple-resources.js +1 -0
- package/dist/src/platform-runtime-host.js +1 -1
- package/dist/src/platform-runtime-managed-owner.js +1 -0
- package/dist/src/platform-runtime-network-web-transport.js +1 -1
- package/dist/src/platform-runtime-open-target.js +1 -1
- package/dist/src/platform-runtime-operation-host.js +4 -4
- package/dist/src/platform-runtime-runtime-hints.js +2 -2
- package/dist/src/platform-runtime-screen-recording-android-host.js +1 -1
- package/dist/src/platform-runtime-screen-recording-apple-runner-host.js +1 -1
- package/dist/src/platform-runtime-screen-recording-apple-runner-transport.js +1 -1
- package/dist/src/platform-runtime-screen-recording-apple-simulator-host.js +1 -1
- package/dist/src/platform-runtime-screen-recording-apple-transport.js +1 -1
- package/dist/src/platform-runtime-screen-recording-finalizer-host.js +1 -1
- package/dist/src/platform-runtime-screen-recording-harmony-host.js +1 -1
- package/dist/src/platform-runtime-screen-recording-process-host.js +1 -0
- package/dist/src/platform-runtime-screen-recording-web-host.js +1 -1
- package/dist/src/platform-runtime-unavailable.js +1 -0
- package/dist/src/platform-runtime.js +1 -1
- package/dist/src/platform-runtime2.js +1 -1
- package/dist/src/plist.js +1 -1
- package/dist/src/png-worker-contract.js +1 -1
- package/dist/src/prepare-kind.js +1 -0
- package/dist/src/process-exit.js +1 -1
- package/dist/src/process.js +1 -0
- package/dist/src/provider-device-runtime.js +1 -0
- package/dist/src/provider-session-ownership.js +2 -0
- package/dist/src/provider-webdriver.js +1 -1
- package/dist/src/provider.js +1 -1
- package/dist/src/providers.js +1 -0
- package/dist/src/proxy.js +2 -2
- package/dist/src/react-native-overlay.js +1 -0
- package/dist/src/react-native.js +1 -1
- package/dist/src/record-runtime.js +1 -1
- package/dist/src/record-trace.js +1 -1
- package/dist/src/rect-center.js +1 -0
- package/dist/src/register-builtins.js +1 -0
- package/dist/src/registry.js +39 -28
- package/dist/src/remote-config2.js +1 -1
- package/dist/src/replay-divergence.js +2 -0
- package/dist/src/replay.js +2 -2
- package/dist/src/reporting.js +8 -8
- package/dist/src/request-admission.js +1 -0
- package/dist/src/request-cancel.js +1 -0
- package/dist/src/request-cancellation.js +1 -0
- package/dist/src/request-progress-protocol.js +1 -0
- package/dist/src/request-providers.js +1 -0
- package/dist/src/request-runtime-binding.js +1 -0
- package/dist/src/request.js +1 -0
- package/dist/src/result-serialization.js +1 -0
- package/dist/src/retry.js +1 -0
- package/dist/src/rolldown-runtime.js +1 -1
- package/dist/src/runner-cache-metadata.js +2 -0
- package/dist/src/runner-client.js +1 -1
- package/dist/src/runner-disposal.js +1 -1
- package/dist/src/runner-operations-facade.js +1 -0
- package/dist/src/runner-owner-facade.js +1 -0
- package/dist/src/runner-owner-state.js +1 -0
- package/dist/src/runner-presentation.js +1 -0
- package/dist/src/runner-selector-query.js +1 -0
- package/dist/src/runner.js +1 -0
- package/dist/src/{runtime-transport.js → runtime-transport-hints.js} +1 -1
- package/dist/src/runtime.js +3 -3
- package/dist/src/runtime2.js +4 -4
- package/dist/src/runtime3.js +1 -1
- package/dist/src/runtime4.js +4 -3
- 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/scoped-provider.js +1 -1
- package/dist/src/screen-recording-completion.js +1 -0
- package/dist/src/screen-recording-live-handle.js +1 -0
- package/dist/src/screen-recording-options.js +1 -0
- package/dist/src/screen-recording-resource-recovery.js +1 -0
- package/dist/src/screen-recording-runtime.js +1 -0
- package/dist/src/screenshot-density.js +1 -1
- package/dist/src/screenshot-result.js +1 -6
- package/dist/src/screenshot-runtime.js +1 -0
- package/dist/src/screenshot.js +1 -1
- package/dist/src/screenshot2.js +1 -0
- package/dist/src/screenshot3.js +5 -0
- package/dist/src/script.js +1 -0
- package/dist/src/scroll-command.js +1 -0
- package/dist/src/scroll-gesture.js +1 -0
- package/dist/src/scroll-indicator.js +1 -0
- package/dist/src/sdk-batch-runner.d.ts +23 -6
- package/dist/src/sdk-batch-runner.js +2 -3
- package/dist/src/sdk-batch.js +2 -0
- package/dist/src/sdk-contracts.d.ts +127 -41
- 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-io.js +1 -1
- package/dist/src/sdk-remote-config.d.ts +1 -1
- package/dist/src/sdk-remote-config.js +1 -1
- package/dist/src/sdk-selectors.d.ts +472 -144
- package/dist/src/sdk-selectors.js +1 -1
- package/dist/src/selection.js +1 -0
- package/dist/src/selector-runtime.js +1 -1
- package/dist/src/selectors.js +1 -1
- package/dist/src/semantic-index.js +1 -0
- package/dist/src/server.js +4 -4
- package/dist/src/session-allocation.js +1 -0
- package/dist/src/session-artifact-paths.js +1 -0
- package/dist/src/session-paths.js +1 -0
- package/dist/src/session-repair-tombstone.js +1 -0
- package/dist/src/session-routing.js +1 -0
- package/dist/src/session-runtime-admission.js +1 -0
- package/dist/src/session-snapshot.js +1 -0
- package/dist/src/session-store.js +4 -0
- package/dist/src/session-target-evidence.js +1 -1
- package/dist/src/session2.js +5 -27
- package/dist/src/settings.js +1 -0
- package/dist/src/shared.js +2 -2
- package/dist/src/simctl-facade.js +1 -0
- package/dist/src/simctl.js +1 -1
- package/dist/src/simulator-facade.js +1 -0
- package/dist/src/simulator.js +1 -1
- package/dist/src/snapshot-capture-annotations.js +1 -0
- package/dist/src/snapshot-desktop-projection.js +1 -0
- package/dist/src/snapshot-diagnostics.js +1 -0
- package/dist/src/snapshot-process.js +1 -0
- package/dist/src/snapshot-quality-backend-capabilities.js +1 -0
- package/dist/src/snapshot-quality-verdict.js +1 -0
- package/dist/src/snapshot-runtime-binding.js +1 -0
- package/dist/src/snapshot-runtime.js +1 -1
- package/dist/src/snapshot-scope.js +1 -1
- package/dist/src/snapshot-state.js +1 -0
- package/dist/src/snapshot.js +1 -8
- package/dist/src/snapshot2.js +1 -1
- package/dist/src/snapshot3.js +1 -1
- package/dist/src/snapshot4.js +1 -0
- package/dist/src/src.js +1 -1
- package/dist/src/src2.js +1 -1
- package/dist/src/src3.js +1 -2
- package/dist/src/src4.js +1 -1
- package/dist/src/src5.js +1 -0
- package/dist/src/src6.js +1 -0
- package/dist/src/src7.js +2 -0
- package/dist/src/src8.js +115 -0
- package/dist/src/startup-recovery-fence.js +1 -0
- package/dist/src/status-markers.js +1 -0
- package/dist/src/string-enum.js +1 -1
- package/dist/src/success-text.js +1 -0
- package/dist/src/surface-snapshot.js +1 -0
- package/dist/src/surface-snapshot2.js +1 -0
- package/dist/src/takeover.js +5 -0
- package/dist/src/tool-provider-facade.js +1 -0
- package/dist/src/tool-provider.js +4 -3
- package/dist/src/tool-provider2.js +1 -1
- package/dist/src/tool-provider3.js +1 -1
- package/dist/src/toolchain-probe.js +2 -0
- package/dist/src/touch-runtime.js +1 -0
- package/dist/src/transport.js +3 -0
- package/dist/src/tree.js +1 -0
- package/dist/src/ttl-memo.js +1 -0
- package/dist/src/tv-remote.js +1 -0
- package/dist/src/type-text-runtime.js +1 -0
- package/dist/src/undici.js +99 -0
- package/dist/src/update-check.js +1 -1
- package/dist/src/verified-file.js +1 -1
- package/dist/src/version.js +1 -1
- package/dist/src/video.js +2 -2
- package/dist/src/web.js +2 -1
- package/dist/src/web2.js +1 -0
- package/dist/src/webdriver-ios-snapshot.js +1 -0
- package/dist/src/webdriver-source.js +1 -0
- package/linux/atspi-dump.py +54 -9
- package/package.json +56 -34
- package/server.json +9 -3
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.10.apk.sha256 +0 -1
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.10.apk +0 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.10.apk.sha256 +0 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CoordinateTextEntryTests.swift +0 -4
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+FlatSnapshotFiltering.swift +0 -168
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+LifecycleCacheTests.swift +0 -6
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+RecordingTests.swift +0 -4
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SelectorMatchPolicyTests.swift +0 -4
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotPresentation.swift +0 -183
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotPresentationTests.swift +0 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotTraversalIdentityTests.swift +0 -4
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntryPolicyTests.swift +0 -4
- package/dist/src/appearance.js +0 -1
- package/dist/src/apps.js +0 -5
- package/dist/src/audio-probe.js +0 -1
- package/dist/src/cli-grammar.js +0 -1
- package/dist/src/command-catalog.js +0 -1
- package/dist/src/debug-symbols.js +0 -5
- package/dist/src/device-input-state.js +0 -2
- package/dist/src/device-ready.js +0 -1
- package/dist/src/dispatch.js +0 -1
- package/dist/src/handler-utils.js +0 -1
- package/dist/src/helper-package-install.js +0 -1
- package/dist/src/host-process.js +0 -3
- package/dist/src/ime-lifecycle.js +0 -2
- package/dist/src/ime-recovery-marker.js +0 -1
- package/dist/src/input-actions3.js +0 -1
- package/dist/src/install-artifact.js +0 -1
- package/dist/src/install-artifact2.js +0 -1
- package/dist/src/interaction-common.js +0 -1
- package/dist/src/interaction-runtime.js +0 -1
- package/dist/src/interaction-snapshot.js +0 -1
- package/dist/src/manifest.js +0 -1
- package/dist/src/method-scope.js +0 -1
- package/dist/src/png-resize.js +0 -1
- package/dist/src/process-lock.js +0 -1
- package/dist/src/runner-lease.js +0 -1
- package/dist/src/runner-sequence.js +0 -1
- package/dist/src/script-source-bundle.js +0 -16
- package/dist/src/sdk-android-adb.d.ts +0 -245
- package/dist/src/sdk-android-adb.js +0 -4
- package/dist/src/sdk.js +0 -1
- package/dist/src/setting-state.js +0 -1
- package/dist/src/shell-quote.js +0 -1
- package/dist/src/snapshot-session.js +0 -1
- package/dist/src/timing-safe-equal.js +0 -1
- package/dist/src/unsupported-interactor.js +0 -1
- package/dist/src/verdict.js +0 -1
- /package/dist/src/{recording-telemetry.js → telemetry.js} +0 -0
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import XCTest
|
|
2
|
+
|
|
3
|
+
// Text-entry readiness: whether the target is actually able to receive text yet. The waits, the
|
|
4
|
+
// keyboard signals they read, and the focus corroboration that ends the hardware-keyboard window.
|
|
5
|
+
// RunnerTests+TextEntryFocus.swift is the only caller of the two non-private entries here; nothing
|
|
6
|
+
// in this file reaches back into it.
|
|
7
|
+
extension RunnerTests {
|
|
8
|
+
func focusedTextInput(app: XCUIApplication) -> XCUIElement? {
|
|
9
|
+
#if os(iOS)
|
|
10
|
+
// iOS focus predicates can return stale or misleading text-input matches
|
|
11
|
+
// under XCUITest, so text entry readiness is driven by tap/keyboard state.
|
|
12
|
+
return nil
|
|
13
|
+
#else
|
|
14
|
+
return safely("FOCUSED_INPUT_QUERY") {
|
|
15
|
+
let candidates = app
|
|
16
|
+
.descendants(matching: .any)
|
|
17
|
+
.matching(NSPredicate(format: "hasKeyboardFocus == 1"))
|
|
18
|
+
.allElementsBoundByIndex
|
|
19
|
+
for candidate in candidates where candidate.exists {
|
|
20
|
+
switch candidate.elementType {
|
|
21
|
+
case .textField, .secureTextField, .searchField, .textView:
|
|
22
|
+
return candidate
|
|
23
|
+
default:
|
|
24
|
+
continue
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return nil
|
|
28
|
+
}
|
|
29
|
+
#endif
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
func waitForTextEntryReadiness(
|
|
33
|
+
app: XCUIApplication,
|
|
34
|
+
target: TextEntryTarget,
|
|
35
|
+
timeout: TimeInterval = TextEntryTiming.readinessTimeout
|
|
36
|
+
) -> XCUIElement? {
|
|
37
|
+
#if os(iOS)
|
|
38
|
+
var latest = resolveTextEntryElement(app: app, target: target)
|
|
39
|
+
let keyboardVisibleAtEntry = isKeyboardVisible(app: app)
|
|
40
|
+
let deadline = Date().addingTimeInterval(timeout)
|
|
41
|
+
var hardwareKeyboardFallback = Date().addingTimeInterval(
|
|
42
|
+
min(TextEntryTiming.hardwareKeyboardFallbackTimeout, timeout)
|
|
43
|
+
)
|
|
44
|
+
var sawSoftwareKeyboard = false
|
|
45
|
+
while Date() < deadline {
|
|
46
|
+
if let focused = focusedTextInput(app: app) {
|
|
47
|
+
latest = focused
|
|
48
|
+
if isKeyboardVisible(app: app) {
|
|
49
|
+
return focused
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
// Fast-path on a keyboard hidden->visible transition: our tapped field gained focus, so
|
|
53
|
+
// return immediately instead of burning the full readinessTimeout (warmup-first-char echo
|
|
54
|
+
// + post-type verify/repair remain as drop safety nets). When the keyboard was ALREADY up
|
|
55
|
+
// (back-to-back fills), this isn't a focus signal — fall through to the settle/timeout so
|
|
56
|
+
// text isn't sent to the previously-focused field.
|
|
57
|
+
if keyboardBecameVisible(app: app, wasVisibleAtEntry: keyboardVisibleAtEntry) {
|
|
58
|
+
return latest
|
|
59
|
+
}
|
|
60
|
+
sawSoftwareKeyboard = sawSoftwareKeyboard || keyboardElementExists(app: app)
|
|
61
|
+
// A responder that takes no software keyboard (hardware keyboard connected, or a custom
|
|
62
|
+
// `inputView`) would otherwise burn the whole readinessTimeout waiting for one that is never
|
|
63
|
+
// coming. Leaving that window a bare wall-clock guess made readiness a function of ambient
|
|
64
|
+
// simulator state (#1874): on a loaded host the keyboard is merely late, and returning here
|
|
65
|
+
// handed the caller an element that had not taken focus yet. Ask the target itself instead,
|
|
66
|
+
// and re-arm rather than re-asking every poll — the query is cheap, not free.
|
|
67
|
+
if !sawSoftwareKeyboard, Date() >= hardwareKeyboardFallback, let candidate = latest {
|
|
68
|
+
if keyboardFocusConfirmed(app: app, element: candidate) {
|
|
69
|
+
return candidate
|
|
70
|
+
}
|
|
71
|
+
hardwareKeyboardFallback = Date().addingTimeInterval(
|
|
72
|
+
TextEntryTiming.hardwareKeyboardFallbackTimeout
|
|
73
|
+
)
|
|
74
|
+
}
|
|
75
|
+
sleepFor(TextEntryTiming.pollInterval)
|
|
76
|
+
}
|
|
77
|
+
return focusedTextInput(app: app) ?? latest
|
|
78
|
+
#else
|
|
79
|
+
return resolveTextEntryElement(app: app, target: target)
|
|
80
|
+
#endif
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
func waitForTextEntryReadinessAfterTap(app: XCUIApplication, element: XCUIElement) {
|
|
84
|
+
#if os(iOS)
|
|
85
|
+
switch element.elementType {
|
|
86
|
+
case .textField, .secureTextField, .searchField, .textView:
|
|
87
|
+
if waitForFocusedTextInput(app: app, timeout: TextEntryTiming.readinessTimeout) != nil {
|
|
88
|
+
return
|
|
89
|
+
}
|
|
90
|
+
let frame = element.frame
|
|
91
|
+
if !frame.isEmpty {
|
|
92
|
+
_ = tapAt(app: app, x: frame.midX, y: frame.midY)
|
|
93
|
+
_ = waitForFocusedTextInput(app: app, timeout: TextEntryTiming.readinessTimeout)
|
|
94
|
+
}
|
|
95
|
+
default:
|
|
96
|
+
return
|
|
97
|
+
}
|
|
98
|
+
#endif
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
private func waitForFocusedTextInput(app: XCUIApplication, timeout: TimeInterval) -> XCUIElement? {
|
|
102
|
+
let deadline = Date().addingTimeInterval(timeout)
|
|
103
|
+
while Date() < deadline {
|
|
104
|
+
if let focused = focusedTextInput(app: app) {
|
|
105
|
+
return focused
|
|
106
|
+
}
|
|
107
|
+
sleepFor(TextEntryTiming.pollInterval)
|
|
108
|
+
}
|
|
109
|
+
return focusedTextInput(app: app)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
func keyboardBecameVisible(app: XCUIApplication, wasVisibleAtEntry: Bool) -> Bool {
|
|
113
|
+
return !wasVisibleAtEntry && isKeyboardVisible(app: app)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/// Positive evidence that this element — the one readiness is about to hand its caller — holds
|
|
117
|
+
/// keyboard focus. Readable even with no software keyboard on screen, which is what lets the
|
|
118
|
+
/// hardware-keyboard fallback stop guessing from a wall clock.
|
|
119
|
+
///
|
|
120
|
+
/// This is the same app-wide predicate `focusedTextInput` refuses to trust on iOS, used the
|
|
121
|
+
/// other way round. There, the query PICKS the target, so a stale or unrelated match becomes
|
|
122
|
+
/// the field that gets typed into. Here the target is already chosen and the query only
|
|
123
|
+
/// corroborates it: at most one element holds keyboard focus, so an answer that is not this
|
|
124
|
+
/// element is a refusal, not a substitution. Every way of being wrong therefore ends as `false`
|
|
125
|
+
/// and costs the remaining readiness timeout — exactly what the wait would spend with no
|
|
126
|
+
/// fallback at all.
|
|
127
|
+
func keyboardFocusConfirmed(app: XCUIApplication, element: XCUIElement) -> Bool {
|
|
128
|
+
#if os(iOS)
|
|
129
|
+
return safely("TEXT_ENTRY_FOCUS_CONFIRMED", false) {
|
|
130
|
+
// An element that no longer resolves reads as identifier "" and frame `.zero`, which would
|
|
131
|
+
// match any focused element that also reports an empty frame. Require a real frame first,
|
|
132
|
+
// so a dead handle cannot corroborate anything.
|
|
133
|
+
let frame = element.frame
|
|
134
|
+
guard !frame.isEmpty else {
|
|
135
|
+
return false
|
|
136
|
+
}
|
|
137
|
+
let focused = app
|
|
138
|
+
.descendants(matching: .any)
|
|
139
|
+
.matching(NSPredicate(format: "hasKeyboardFocus == 1"))
|
|
140
|
+
.firstMatch
|
|
141
|
+
guard focused.exists else {
|
|
142
|
+
return false
|
|
143
|
+
}
|
|
144
|
+
return focused.identifier == element.identifier && focused.frame == frame
|
|
145
|
+
}
|
|
146
|
+
#else
|
|
147
|
+
return false
|
|
148
|
+
#endif
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
private func keyboardElementExists(app: XCUIApplication) -> Bool {
|
|
152
|
+
#if os(iOS)
|
|
153
|
+
return safely("KEYBOARD_EXISTS", false) { app.keyboards.firstMatch.exists }
|
|
154
|
+
#else
|
|
155
|
+
return false
|
|
156
|
+
#endif
|
|
157
|
+
}
|
|
158
|
+
}
|
package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextTyping.swift
CHANGED
|
@@ -15,6 +15,36 @@ extension RunnerTests {
|
|
|
15
15
|
) -> TextEntryResult {
|
|
16
16
|
let totalStartedAt = Date()
|
|
17
17
|
guard !text.isEmpty else {
|
|
18
|
+
// Replacing a field WITH the empty string is the clear-field primitive (#2063): the typing
|
|
19
|
+
// is vacuous but the clear is not. Returning here unconditionally left the old value in
|
|
20
|
+
// place while the response reported "typed". Append (`type`) and unrepaired entry stay
|
|
21
|
+
// no-ops, which is what an empty payload means for them.
|
|
22
|
+
if repairMode == .replacement {
|
|
23
|
+
guard let clearTarget = resolveTextEntryElement(app: app, target: target) else {
|
|
24
|
+
// No resolvable input means no clear happened — including the synthesized
|
|
25
|
+
// first-responder route, whose target carries no element. Success here would claim a
|
|
26
|
+
// clear the runner never performed.
|
|
27
|
+
logTextEntryPhase(commandId: commandId, phase: "total", startedAt: totalStartedAt, chars: 0, mode: repairMode)
|
|
28
|
+
return TextEntryResult(
|
|
29
|
+
verified: nil,
|
|
30
|
+
repaired: false,
|
|
31
|
+
expectedText: "",
|
|
32
|
+
observedText: nil,
|
|
33
|
+
failure: .notFocused
|
|
34
|
+
)
|
|
35
|
+
}
|
|
36
|
+
clearTextInput(clearTarget)
|
|
37
|
+
// nil means the value is unreadable (secure fields), not "not empty": leave `verified`
|
|
38
|
+
// nil there rather than reporting a mismatch the runner cannot actually observe.
|
|
39
|
+
let observed = editableTextValue(for: clearTarget, treatingPlaceholderAsEmpty: true)
|
|
40
|
+
logTextEntryPhase(commandId: commandId, phase: "total", startedAt: totalStartedAt, chars: 0, mode: repairMode)
|
|
41
|
+
return TextEntryResult(
|
|
42
|
+
verified: observed.map { $0.isEmpty },
|
|
43
|
+
repaired: false,
|
|
44
|
+
expectedText: "",
|
|
45
|
+
observedText: observed
|
|
46
|
+
)
|
|
47
|
+
}
|
|
18
48
|
logTextEntryPhase(commandId: commandId, phase: "total", startedAt: totalStartedAt, chars: 0, mode: repairMode)
|
|
19
49
|
return TextEntryResult(verified: true, repaired: false, expectedText: "", observedText: "")
|
|
20
50
|
}
|
|
@@ -104,11 +134,11 @@ extension RunnerTests {
|
|
|
104
134
|
}
|
|
105
135
|
}
|
|
106
136
|
|
|
107
|
-
func typeIntoCurrentTarget(_ value: String) -> (element: XCUIElement?,
|
|
137
|
+
func typeIntoCurrentTarget(_ value: String) -> (element: XCUIElement?, failure: TextEntryFailure?) {
|
|
108
138
|
#if os(iOS)
|
|
109
139
|
if shouldUseSynthesizedFirstResponderType {
|
|
110
140
|
guard let currentTarget = resolveTextEntryElement(app: app, target: activeTarget) else {
|
|
111
|
-
return (nil,
|
|
141
|
+
return (nil, .notFocused)
|
|
112
142
|
}
|
|
113
143
|
textEntryRoute = "synthesized-first-responder"
|
|
114
144
|
NSLog("AGENT_DEVICE_RUNNER_TEXT_ENTRY_ROUTE route=synthesized-first-responder")
|
|
@@ -117,7 +147,7 @@ extension RunnerTests {
|
|
|
117
147
|
case .continueTyping:
|
|
118
148
|
// No refresh point: like the tap-witness target itself, the commit wait must observe
|
|
119
149
|
// only the element the tap selected, never rediscover a different field.
|
|
120
|
-
awaitSynthesizedFirstResponderCommit(
|
|
150
|
+
let commit = awaitSynthesizedFirstResponderCommit(
|
|
121
151
|
app: app,
|
|
122
152
|
target: TextEntryTarget(
|
|
123
153
|
element: currentTarget,
|
|
@@ -128,9 +158,12 @@ extension RunnerTests {
|
|
|
128
158
|
textBefore: textBefore,
|
|
129
159
|
typedText: value
|
|
130
160
|
)
|
|
131
|
-
|
|
161
|
+
// The characters were posted, so the element stays on the tuple for the caller's
|
|
162
|
+
// bookkeeping; the failure is what makes the command refuse. Reporting ok here is the
|
|
163
|
+
// defect this route had — the deadline was indistinguishable from a commit.
|
|
164
|
+
return (currentTarget, Self.textEntryFailure(forCommitOutcome: commit))
|
|
132
165
|
case .fallback:
|
|
133
|
-
return (nil,
|
|
166
|
+
return (nil, .synthesisUnavailable)
|
|
134
167
|
case .raise(let message):
|
|
135
168
|
NSException(
|
|
136
169
|
name: NSExceptionName.internalInconsistencyException,
|
|
@@ -142,7 +175,7 @@ extension RunnerTests {
|
|
|
142
175
|
if let currentTarget = resolveTextEntryElement(app: app, target: activeTarget) {
|
|
143
176
|
textEntryRoute = "xctest-element"
|
|
144
177
|
currentTarget.typeText(value)
|
|
145
|
-
return (currentTarget,
|
|
178
|
+
return (currentTarget, nil)
|
|
146
179
|
} else if activeTarget.prefersFocusedElement && isKeyboardVisible(app: app) {
|
|
147
180
|
#if os(iOS)
|
|
148
181
|
textEntryRoute = "synthesized-first-responder"
|
|
@@ -167,9 +200,9 @@ extension RunnerTests {
|
|
|
167
200
|
#else
|
|
168
201
|
app.typeText(value)
|
|
169
202
|
#endif
|
|
170
|
-
return (resolveTextEntryElement(app: app, target: activeTarget),
|
|
203
|
+
return (resolveTextEntryElement(app: app, target: activeTarget), nil)
|
|
171
204
|
}
|
|
172
|
-
return (nil,
|
|
205
|
+
return (nil, .notFocused)
|
|
173
206
|
}
|
|
174
207
|
|
|
175
208
|
func dispatchFailureResult(_ failure: TextEntryFailure) -> TextEntryResult {
|
|
@@ -203,8 +236,8 @@ extension RunnerTests {
|
|
|
203
236
|
let delayedTypeStartedAt = Date()
|
|
204
237
|
for (index, character) in characters.enumerated() {
|
|
205
238
|
let dispatch = typeIntoCurrentTarget(String(character))
|
|
206
|
-
|
|
207
|
-
return dispatchFailureResult(
|
|
239
|
+
if let failure = dispatch.failure {
|
|
240
|
+
return dispatchFailureResult(failure)
|
|
208
241
|
}
|
|
209
242
|
typedTarget = dispatch.element ?? typedTarget
|
|
210
243
|
if index + 1 < characters.count {
|
|
@@ -252,8 +285,8 @@ extension RunnerTests {
|
|
|
252
285
|
let firstCharacter = String(characters[0])
|
|
253
286
|
let firstStartedAt = Date()
|
|
254
287
|
let firstDispatch = typeIntoCurrentTarget(firstCharacter)
|
|
255
|
-
|
|
256
|
-
return dispatchFailureResult(
|
|
288
|
+
if let failure = firstDispatch.failure {
|
|
289
|
+
return dispatchFailureResult(failure)
|
|
257
290
|
}
|
|
258
291
|
var firstTypedTarget = firstDispatch.element
|
|
259
292
|
logTextEntryPhase(
|
|
@@ -281,8 +314,8 @@ extension RunnerTests {
|
|
|
281
314
|
let remainingText = String(characters.dropFirst())
|
|
282
315
|
let remainingStartedAt = Date()
|
|
283
316
|
let remainingDispatch = typeIntoCurrentTarget(remainingText)
|
|
284
|
-
|
|
285
|
-
return dispatchFailureResult(
|
|
317
|
+
if let failure = remainingDispatch.failure {
|
|
318
|
+
return dispatchFailureResult(failure)
|
|
286
319
|
}
|
|
287
320
|
firstTypedTarget = remainingDispatch.element ?? firstTypedTarget
|
|
288
321
|
logTextEntryPhase(
|
|
@@ -296,8 +329,8 @@ extension RunnerTests {
|
|
|
296
329
|
} else {
|
|
297
330
|
let typeStartedAt = Date()
|
|
298
331
|
let dispatch = typeIntoCurrentTarget(text)
|
|
299
|
-
|
|
300
|
-
return dispatchFailureResult(
|
|
332
|
+
if let failure = dispatch.failure {
|
|
333
|
+
return dispatchFailureResult(failure)
|
|
301
334
|
}
|
|
302
335
|
typedTarget = dispatch.element
|
|
303
336
|
logTextEntryPhase(
|
package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Transport.swift
CHANGED
|
@@ -190,7 +190,7 @@ extension RunnerTests {
|
|
|
190
190
|
command: Command,
|
|
191
191
|
completion: @escaping ((data: Data, shouldFinish: Bool)) -> Void
|
|
192
192
|
) -> Bool {
|
|
193
|
-
guard let commandId =
|
|
193
|
+
guard let commandId = command.commandId?.trimmedNonEmpty else { return false }
|
|
194
194
|
inFlightCommandLock.lock()
|
|
195
195
|
if inFlightCommandIds.contains(commandId) {
|
|
196
196
|
inFlightCommandWaiters[commandId, default: []].append(completion)
|
|
@@ -213,7 +213,7 @@ extension RunnerTests {
|
|
|
213
213
|
completion: ((data: Data, shouldFinish: Bool)) -> Void
|
|
214
214
|
) {
|
|
215
215
|
var waiters: [((data: Data, shouldFinish: Bool)) -> Void] = []
|
|
216
|
-
if let commandId =
|
|
216
|
+
if let commandId = command.commandId?.trimmedNonEmpty {
|
|
217
217
|
inFlightCommandLock.lock()
|
|
218
218
|
inFlightCommandIds.remove(commandId)
|
|
219
219
|
waiters = inFlightCommandWaiters.removeValue(forKey: commandId) ?? []
|
|
@@ -225,15 +225,6 @@ extension RunnerTests {
|
|
|
225
225
|
}
|
|
226
226
|
}
|
|
227
227
|
|
|
228
|
-
private func normalizedInFlightCommandId(_ commandId: String?) -> String? {
|
|
229
|
-
guard let trimmed = commandId?.trimmingCharacters(in: .whitespacesAndNewlines),
|
|
230
|
-
!trimmed.isEmpty
|
|
231
|
-
else {
|
|
232
|
-
return nil
|
|
233
|
-
}
|
|
234
|
-
return trimmed
|
|
235
|
-
}
|
|
236
|
-
|
|
237
228
|
|
|
238
229
|
// MARK: - Response Encoding
|
|
239
230
|
|
package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TvRemote.swift
CHANGED
|
@@ -7,7 +7,7 @@ enum RunnerInteractionOutcome {
|
|
|
7
7
|
case unsupported(message: String, hint: String?)
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
enum TvRemoteButton {
|
|
10
|
+
enum TvRemoteButton: String {
|
|
11
11
|
case select
|
|
12
12
|
case menu
|
|
13
13
|
case home
|
|
@@ -18,6 +18,7 @@ enum TvRemoteButton {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
extension RunnerTests {
|
|
21
|
+
|
|
21
22
|
func resolveTvRemoteDoublePressDelay() -> TimeInterval {
|
|
22
23
|
guard
|
|
23
24
|
let raw = ProcessInfo.processInfo.environment["AGENT_DEVICE_TV_REMOTE_DOUBLE_PRESS_DELAY_MS"],
|
|
@@ -47,24 +48,8 @@ extension RunnerTests {
|
|
|
47
48
|
}
|
|
48
49
|
|
|
49
50
|
func tvRemoteButton(from raw: String?) -> TvRemoteButton? {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
return .select
|
|
53
|
-
case "menu":
|
|
54
|
-
return .menu
|
|
55
|
-
case "home":
|
|
56
|
-
return .home
|
|
57
|
-
case "up":
|
|
58
|
-
return .up
|
|
59
|
-
case "down":
|
|
60
|
-
return .down
|
|
61
|
-
case "left":
|
|
62
|
-
return .left
|
|
63
|
-
case "right":
|
|
64
|
-
return .right
|
|
65
|
-
default:
|
|
66
|
-
return nil
|
|
67
|
-
}
|
|
51
|
+
guard let raw else { return nil }
|
|
52
|
+
return TvRemoteButton(rawValue: raw.lowercased())
|
|
68
53
|
}
|
|
69
54
|
|
|
70
55
|
func elementHasFocus(_ element: XCUIElement) -> Bool {
|
|
@@ -66,7 +66,11 @@ final class RunnerTests: XCTestCase {
|
|
|
66
66
|
let minRecordingFps = 1
|
|
67
67
|
let maxRecordingFps = 120
|
|
68
68
|
var needsPostSnapshotInteractionDelay = false
|
|
69
|
-
|
|
69
|
+
/// When the first interaction after an activation may run, on the monotonic uptime clock.
|
|
70
|
+
/// The guarantee is a minimum gap *since the activation*, not a pause at the interaction:
|
|
71
|
+
/// a caller that already spent that gap elsewhere (an agent's round trip is 190-260 ms)
|
|
72
|
+
/// has satisfied it and waits for nothing. `nil` = no activation is pending stabilization.
|
|
73
|
+
var firstInteractionReadyUptime: TimeInterval?
|
|
70
74
|
var runnerAccessibilityHealth: RunnerAccessibilityHealth = .unknown
|
|
71
75
|
var activeRecording: ScreenRecorder?
|
|
72
76
|
let commandJournal = RunnerCommandJournal()
|
|
@@ -119,29 +123,21 @@ final class RunnerTests: XCTestCase {
|
|
|
119
123
|
// Bounds the pre-plan SpringBoard system-modal probe, which can otherwise grind for tens of
|
|
120
124
|
// seconds on remote-hosted consent dialogs and bypass the plan budget (#1244).
|
|
121
125
|
let systemModalProbeBudget: TimeInterval = 4
|
|
126
|
+
// In-bundle unit tests (every `func test…` except `testCommand` below) compile only under
|
|
127
|
+
// `-D AGENT_DEVICE_RUNNER_UNIT_TESTS` and are classified by their `#if` guard (#1781 A7):
|
|
128
|
+
// - `#if AGENT_DEVICE_RUNNER_UNIT_TESTS` alone: a pure runner decision (rule table,
|
|
129
|
+
// geometry, parser, policy, journal, dispatch bookkeeping) that needs no launched app.
|
|
130
|
+
// Runs on the macOS host lane on every PR (ci.yml, no simulator) and on the iOS lanes.
|
|
131
|
+
// - `… && os(iOS)` (or a nested `#if os(iOS)`): runner/XCTest semantics — launches the
|
|
132
|
+
// host app, routes through SpringBoard, swizzles XCUIApplication, or asserts an
|
|
133
|
+
// iOS-only branch. Simulator lanes only (ios.yml PR list, xctest-nightly.yml).
|
|
134
|
+
// `pnpm check:xctest-selection` derives each lane's reachable set from these guards and
|
|
135
|
+
// fails when a declared test is reachable by no lane, so a test gated to a platform nothing
|
|
136
|
+
// runs (the old tvOS-only pair) cannot go dark silently.
|
|
122
137
|
// Observability for the record(_:) suppression below: how many AX-broken-screen snapshot
|
|
123
138
|
// issues this session muted, so wedge investigations see the volume without grepping logs.
|
|
124
139
|
let suppressedIssueLock = NSLock()
|
|
125
140
|
var suppressedAxSnapshotIssueCount = 0
|
|
126
|
-
let interactiveTypes: Set<XCUIElement.ElementType> = [
|
|
127
|
-
.button,
|
|
128
|
-
.cell,
|
|
129
|
-
.checkBox,
|
|
130
|
-
.collectionView,
|
|
131
|
-
.link,
|
|
132
|
-
.menuItem,
|
|
133
|
-
.picker,
|
|
134
|
-
.searchField,
|
|
135
|
-
.segmentedControl,
|
|
136
|
-
.slider,
|
|
137
|
-
.stepper,
|
|
138
|
-
.switch,
|
|
139
|
-
.tabBar,
|
|
140
|
-
.textField,
|
|
141
|
-
.secureTextField,
|
|
142
|
-
.textView,
|
|
143
|
-
.webView
|
|
144
|
-
]
|
|
145
141
|
// Keep blocker actions narrow to avoid false positives from generic hittable containers.
|
|
146
142
|
let actionableTypes: Set<XCUIElement.ElementType> = [
|
|
147
143
|
.button,
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import AVFoundation
|
|
2
|
+
import Foundation
|
|
3
|
+
|
|
4
|
+
/// Shared mechanics for the recording post-processing scripts (overlay burn-in, start trim).
|
|
5
|
+
/// Each script keeps its own argument grammar and export-quality policy; this file owns the
|
|
6
|
+
/// error vocabulary, flag-value reading, composition assembly, and the bounded export wait.
|
|
7
|
+
|
|
8
|
+
enum RecordingScriptError: Error, CustomStringConvertible {
|
|
9
|
+
case invalidArgs(String)
|
|
10
|
+
case invalidTrimRange
|
|
11
|
+
case missingVideoTrack
|
|
12
|
+
case exportFailed(String)
|
|
13
|
+
|
|
14
|
+
var description: String {
|
|
15
|
+
switch self {
|
|
16
|
+
case .invalidArgs(let message):
|
|
17
|
+
return message
|
|
18
|
+
case .invalidTrimRange:
|
|
19
|
+
return "Trim start must be before the end of the recording."
|
|
20
|
+
case .missingVideoTrack:
|
|
21
|
+
return "Input video does not contain a video track."
|
|
22
|
+
case .exportFailed(let message):
|
|
23
|
+
return message
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
func recordingOptionValue(_ arguments: [String], _ nextIndex: Int, _ flag: String) throws -> String {
|
|
29
|
+
guard nextIndex < arguments.count else {
|
|
30
|
+
throw RecordingScriptError.invalidArgs("\(flag) requires a value")
|
|
31
|
+
}
|
|
32
|
+
return arguments[nextIndex]
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
func removeStaleOutput(_ outputURL: URL) throws {
|
|
36
|
+
if FileManager.default.fileExists(atPath: outputURL.path) {
|
|
37
|
+
try FileManager.default.removeItem(at: outputURL)
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
func sourceVideoTrack(of asset: AVURLAsset) throws -> AVAssetTrack {
|
|
42
|
+
guard let track = asset.tracks(withMediaType: .video).first else {
|
|
43
|
+
throw RecordingScriptError.missingVideoTrack
|
|
44
|
+
}
|
|
45
|
+
return track
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/// Copies `videoTrack` for `timeRange` into a fresh composition, carrying the optional audio track
|
|
49
|
+
/// along when present. The caller owns any `preferredTransform` policy: trim propagates the source
|
|
50
|
+
/// transform directly, while overlay re-applies it through a video-composition layer instruction
|
|
51
|
+
/// instead.
|
|
52
|
+
func makeRecordingComposition(
|
|
53
|
+
asset: AVURLAsset,
|
|
54
|
+
videoTrack: AVAssetTrack,
|
|
55
|
+
timeRange: CMTimeRange
|
|
56
|
+
) throws -> AVMutableComposition {
|
|
57
|
+
let composition = AVMutableComposition()
|
|
58
|
+
guard let compositionVideoTrack = composition.addMutableTrack(
|
|
59
|
+
withMediaType: .video,
|
|
60
|
+
preferredTrackID: kCMPersistentTrackID_Invalid
|
|
61
|
+
) else {
|
|
62
|
+
throw RecordingScriptError.exportFailed("Failed to create composition video track.")
|
|
63
|
+
}
|
|
64
|
+
try compositionVideoTrack.insertTimeRange(timeRange, of: videoTrack, at: .zero)
|
|
65
|
+
|
|
66
|
+
if let sourceAudioTrack = asset.tracks(withMediaType: .audio).first,
|
|
67
|
+
let compositionAudioTrack = composition.addMutableTrack(
|
|
68
|
+
withMediaType: .audio,
|
|
69
|
+
preferredTrackID: kCMPersistentTrackID_Invalid
|
|
70
|
+
) {
|
|
71
|
+
try? compositionAudioTrack.insertTimeRange(timeRange, of: sourceAudioTrack, at: .zero)
|
|
72
|
+
}
|
|
73
|
+
return composition
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
func makeRecordingExporter(
|
|
77
|
+
_ composition: AVAsset,
|
|
78
|
+
presetName: String,
|
|
79
|
+
outputURL: URL,
|
|
80
|
+
videoComposition: AVMutableVideoComposition? = nil
|
|
81
|
+
) throws -> AVAssetExportSession {
|
|
82
|
+
guard let exporter = AVAssetExportSession(asset: composition, presetName: presetName) else {
|
|
83
|
+
throw RecordingScriptError.exportFailed("Failed to create export session.")
|
|
84
|
+
}
|
|
85
|
+
exporter.outputURL = outputURL
|
|
86
|
+
exporter.outputFileType = .mp4
|
|
87
|
+
exporter.videoComposition = videoComposition
|
|
88
|
+
exporter.shouldOptimizeForNetworkUse = true
|
|
89
|
+
return exporter
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/// Bounded asynchronous export: signals completion through a semaphore and cancels after 120s so a
|
|
93
|
+
/// wedged encoder cannot hang the recording pipeline past the caller's own timeout budget.
|
|
94
|
+
func runRecordingExport(
|
|
95
|
+
_ exporter: AVAssetExportSession,
|
|
96
|
+
timeoutMessage: String,
|
|
97
|
+
failureMessage: String
|
|
98
|
+
) throws {
|
|
99
|
+
let semaphore = DispatchSemaphore(value: 0)
|
|
100
|
+
exporter.exportAsynchronously {
|
|
101
|
+
semaphore.signal()
|
|
102
|
+
}
|
|
103
|
+
if semaphore.wait(timeout: .now() + 120) == .timedOut {
|
|
104
|
+
exporter.cancelExport()
|
|
105
|
+
throw RecordingScriptError.exportFailed(timeoutMessage)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if exporter.status != .completed {
|
|
109
|
+
throw RecordingScriptError.exportFailed(exporter.error?.localizedDescription ?? failureMessage)
|
|
110
|
+
}
|
|
111
|
+
}
|