agent-device 0.21.6 → 0.21.8
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.6.apk → agent-device-android-ime-helper-0.21.8.apk} +0 -0
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.8.apk.sha256 +1 -0
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.6.manifest.json → agent-device-android-ime-helper-0.21.8.manifest.json} +4 -4
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.21.6.apk → agent-device-android-snapshot-helper-0.21.8.apk} +0 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.8.apk.sha256 +1 -0
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.21.6.manifest.json → agent-device-android-snapshot-helper-0.21.8.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/AgentDeviceMacOSHelper/DeviceHubPose.swift +320 -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/AgentDeviceMacOSInputTests/MouseClickScheduleTests.swift +58 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.h +4 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.m +20 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerScrollViewportPolicy.swift +1 -2
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+AXSnapshotFallback.swift +25 -12
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +56 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandJournal.swift +1 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +36 -108
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Keyboard.swift +241 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Lifecycle.swift +29 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +46 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+PrivateAXPresentation.swift +85 -26
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +134 -117
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotBackendCapabilities.swift +1 -3
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCapturePlan.swift +25 -4
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SystemModal.swift +1 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests.swift +3 -0
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotCoordinateSpace.swift +197 -0
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotModels.swift +30 -4
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotPresentation.swift +0 -81
- package/dist/apple/snapshot-presentation/Sources/AgentDeviceSnapshotPresentation/SnapshotPresentationInvariant.swift +1 -9
- package/dist/src/absence-observation-errors.js +1 -1
- package/dist/src/adapter.js +1 -1
- package/dist/src/adb-executor.js +2 -2
- package/dist/src/adb-failure.js +1 -1
- package/dist/src/adb-transport.js +1 -1
- package/dist/src/adb.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-browser-provider.js +1 -1
- package/dist/src/agent-browser-tool.js +1 -1
- package/dist/src/agent-device-client.js +2 -2
- package/dist/src/ai-sdk.js +1 -1
- package/dist/src/alert-runtime.js +1 -1
- package/dist/src/android-adb.d.ts +29 -2
- 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-catalog.js +1 -1
- package/dist/src/app-deployment-resolution.js +1 -1
- package/dist/src/app-helpers.js +1 -1
- package/dist/src/app-inventory.js +1 -1
- package/dist/src/app-launch.js +2 -2
- package/dist/src/app-lifecycle.js +2 -2
- package/dist/src/app-lifecycle2.js +2 -2
- package/dist/src/app-log-files.js +1 -1
- package/dist/src/app-log-runtime2.js +3 -3
- package/dist/src/app-resolution.js +2 -2
- package/dist/src/app-state.js +1 -1
- package/dist/src/apple-runner-platform.js +1 -1
- package/dist/src/application-lifecycle-interaction.js +1 -1
- package/dist/src/archive.js +1 -1
- package/dist/src/artifact-download.js +1 -1
- package/dist/src/auth-session.js +1 -1
- package/dist/src/auth.js +1 -1
- package/dist/src/back-mode.js +1 -1
- package/dist/src/backend-snapshot-options.js +1 -1
- package/dist/src/boot-diagnostics.js +1 -1
- package/dist/src/capture-disclosure.js +1 -0
- package/dist/src/capture.js +1 -1
- package/dist/src/cli-config.js +1 -1
- package/dist/src/cli-help.js +18 -2
- package/dist/src/cli-output.js +1 -1
- package/dist/src/cli.js +4 -4
- package/dist/src/click-button.js +1 -1
- package/dist/src/client-metro.js +1 -1
- package/dist/src/client-types.d.ts +65 -3
- package/dist/src/clipboard-shell-response.js +1 -0
- package/dist/src/command-schema.js +1 -1
- package/dist/src/command-tools.js +4 -2
- package/dist/src/command.js +1 -1
- package/dist/src/config.js +1 -1
- package/dist/src/connection-runtime.js +1 -1
- package/dist/src/connection.js +1 -1
- package/dist/src/contracts.d.ts +1 -1
- package/dist/src/contracts.js +1 -1
- package/dist/src/daemon-client-lifecycle.js +1 -1
- package/dist/src/daemon.js +1 -1
- package/dist/src/debug-symbols-facade.js +1 -1
- package/dist/src/device-boot.js +1 -1
- package/dist/src/device-claim-inspection.js +1 -1
- package/dist/src/device-claim-rule.js +2 -1
- package/dist/src/device-input-state.d.ts +5 -5
- package/dist/src/device-inventory-context.js +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-shell.js +1 -0
- package/dist/src/device.js +1 -1
- package/dist/src/device2.js +1 -1
- package/dist/src/devicectl.js +1 -0
- package/dist/src/diagnostics.js +1 -1
- package/dist/src/dispatch-resolve.js +1 -1
- package/dist/src/display-inventory.js +1 -0
- package/dist/src/doctor-facade.js +1 -1
- package/dist/src/doctor2.js +1 -1
- package/dist/src/durable-resource.js +1 -1
- package/dist/src/engine-eval-script.js +1 -1
- package/dist/src/error.js +1 -1
- package/dist/src/exec.js +1 -1
- package/dist/src/file.js +1 -1
- package/dist/src/find.js +1 -1
- package/dist/src/finders.js +1 -1
- package/dist/src/format.js +2 -1
- package/dist/src/generic.js +1 -1
- package/dist/src/gesture-admission.js +1 -1
- package/dist/src/gesture-plan.js +1 -1
- package/dist/src/gesture-runtime.js +1 -1
- 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.js +1 -0
- package/dist/src/human-control-contract.js +1 -1
- package/dist/src/human-control.js +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/input-actions.js +1 -1
- package/dist/src/input-actions2.js +1 -1
- package/dist/src/install-artifact-facade.js +1 -1
- package/dist/src/install-source-network-transport.js +1 -1
- package/dist/src/install-source2.js +1 -1
- 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 +9 -1
- package/dist/src/internal/png-worker.js +1 -1
- package/dist/src/internal/run-script-http-child.js +1 -1
- package/dist/src/inventory.js +4 -4
- package/dist/src/inventory2.js +1 -1
- package/dist/src/inventory3.js +2 -2
- package/dist/src/inventory5.js +1 -1
- package/dist/src/ios-snapshot-acquisition.js +1 -1
- package/dist/src/ios-snapshot-runtime.js +1 -1
- package/dist/src/ios-target-activation.js +1 -0
- package/dist/src/lease-context.js +1 -1
- package/dist/src/lease-scope.js +1 -1
- package/dist/src/lease.js +1 -1
- package/dist/src/limrun-download-file.js +1 -0
- package/dist/src/limrun-runtime-dependencies.js +1 -1
- package/dist/src/limrun.d.ts +10 -4
- 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/multitouch-support.js +1 -1
- package/dist/src/observation.js +2 -2
- package/dist/src/output-common.js +5 -2
- package/dist/src/parameterized-recorded-fill.js +1 -1
- package/dist/src/perf-facade.js +2 -2
- package/dist/src/perf-runtime-operation-builder.js +1 -1
- package/dist/src/perf-runtime-plan.js +1 -1
- package/dist/src/perf.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-android-adb-host.js +1 -1
- package/dist/src/platform-runtime-host.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 +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-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 -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-worker-client.js +1 -0
- package/dist/src/png.js +1 -1
- package/dist/src/prepare-kind.js +1 -1
- package/dist/src/provider-session-ownership.js +1 -1
- package/dist/src/provider-webdriver.js +1 -1
- package/dist/src/proxy.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/record-trace.js +1 -1
- package/dist/src/rect-center.js +1 -1
- package/dist/src/register-builtins.js +1 -1
- package/dist/src/registry.js +35 -35
- package/dist/src/remote-config2.js +1 -1
- package/dist/src/replay-divergence.js +1 -1
- package/dist/src/replay.js +1 -1
- package/dist/src/reporting.js +1 -1
- package/dist/src/request-admission.js +1 -1
- package/dist/src/request-cancel.js +1 -1
- package/dist/src/request-runtime-binding.js +1 -1
- package/dist/src/result-serialization.js +1 -1
- package/dist/src/retry.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-transport-hints.js +1 -1
- package/dist/src/runtime.js +3 -3
- package/dist/src/runtime10.js +1 -1
- package/dist/src/runtime2.js +4 -4
- package/dist/src/runtime3.js +1 -1
- 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 -0
- package/dist/src/screen-recording-completion.js +1 -1
- package/dist/src/screen-recording-options.js +1 -1
- package/dist/src/screen-recording-resource-recovery.js +1 -1
- package/dist/src/screen-recording-transport.js +1 -0
- package/dist/src/screenshot-density.js +1 -1
- package/dist/src/screenshot-image.js +1 -0
- package/dist/src/screenshot-runtime.js +1 -1
- package/dist/src/screenshot.js +1 -1
- package/dist/src/screenshot3.js +1 -1
- package/dist/src/script.js +1 -1
- package/dist/src/scroll-command.js +1 -1
- package/dist/src/scroll-gesture.js +1 -1
- package/dist/src/sdk-batch-runner.js +2 -2
- package/dist/src/sdk-batch.js +2 -2
- package/dist/src/sdk-contracts.d.ts +76 -1
- package/dist/src/sdk-contracts.js +2 -2
- package/dist/src/sdk-device.js +1 -1
- package/dist/src/sdk-finders.d.ts +1 -1
- package/dist/src/sdk-finders.js +1 -1
- package/dist/src/sdk-io.js +1 -1
- package/dist/src/sdk-remote-config.js +1 -1
- package/dist/src/sdk-selectors.d.ts +29 -3
- 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/server.js +1 -1
- package/dist/src/session-allocation.js +1 -1
- package/dist/src/session-observation.js +1 -1
- package/dist/src/session-routing.js +1 -1
- package/dist/src/session-runtime-admission.js +1 -1
- package/dist/src/session-snapshot.js +1 -1
- package/dist/src/session-store.js +3 -3
- package/dist/src/session2.js +4 -5
- package/dist/src/settings.js +1 -1
- package/dist/src/simctl-facade.js +1 -1
- 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-capture-annotations.js +1 -1
- package/dist/src/snapshot-diagnostics.js +1 -1
- package/dist/src/snapshot-quality-backend-capabilities.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/snapshot.js +1 -1
- package/dist/src/snapshot2.js +1 -1
- package/dist/src/snapshot3.js +1 -1
- package/dist/src/snapshot4.js +1 -1
- package/dist/src/src.js +1 -1
- package/dist/src/src4.js +1 -1
- package/dist/src/src7.js +1 -1
- package/dist/src/src8.js +2 -2
- package/dist/src/stop-sequence.js +1 -1
- package/dist/src/string-enum.js +1 -1
- package/dist/src/takeover.js +1 -1
- package/dist/src/text-entry-focus.js +1 -1
- package/dist/src/tool-provider.js +1 -1
- package/dist/src/tool-provider2.js +1 -1
- package/dist/src/touch-runtime.js +1 -1
- package/dist/src/transport.js +1 -1
- package/dist/src/tree.js +1 -1
- package/dist/src/tv-remote.js +1 -1
- package/dist/src/type-text-runtime.js +1 -1
- package/dist/src/verified-file.js +1 -1
- package/dist/src/video.js +1 -1
- package/dist/src/viewport.js +1 -1
- package/dist/src/web.js +1 -1
- package/dist/src/web2.js +1 -1
- package/dist/src/webdriver-source.js +1 -1
- package/dist/src/window-state.js +1 -1
- package/package.json +4 -1
- package/server.json +2 -2
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.6.apk.sha256 +0 -1
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.6.apk.sha256 +0 -1
- package/dist/src/session-target-evidence.js +0 -1
- package/dist/src/vars.js +0 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{Ar as e,Er as t,Hr as n,Tr as r,wr as i}from"./sdk-batch.js";import{t as a}from"./scroll-indicator.js";function o(e){if(e.length===0)return{nodes:e,hiddenCount:0,summaryLines:[]};let{visibility:t,visibleNodeIndexes:n,offscreenNodes:r,hintedContainers:i}=c(e),a=n.size===0?e:e.filter(e=>n.has(e.index));return{nodes:a.map(e=>m(e,i.directionsByContainer)),hiddenCount:n.size===0?0:e.length-a.length,summaryLines:h(r.filter(e=>!i.coveredNodeIndexes.has(e.index)&&v(e)),t)}}function s(e){if(e.length===0)return new Map;let{hintedContainers:t}=c(e);return p(t.directionsByContainer)}function c(e){let t=i(e),n=t.nodeByIndex,r=new Set,a=[];for(let i of e){if(t.isVisibleInEffectiveViewport(i)){b(i,r,n);continue}a.push(i)}return{visibility:t,visibleNodeIndexes:r,offscreenNodes:a,hintedContainers:f(e,a,r,n)}}function l(e,n){return e.hittable&&t(e.rect,n)}function u(e,r){if(!e.rect)return null;let i=r.resolveEffectiveViewport(e);if(i&&!n(e.rect,i)){let t=d(e.rect,i);if(t)return t}let a=r.resolveViewport(e.rect);if(a&&!t(e.rect,a)){let t=d(e.rect,a);if(t)return t}return null}function d(e,t){let n=e.x+e.width/2,r=e.y+e.height/2,i=[{direction:`down`,amount:r-(t.y+t.height)},{direction:`up`,amount:t.y-r},{direction:`right`,amount:n-(t.x+t.width)},{direction:`left`,amount:t.x-n}],a=null;for(let e of i)e.amount>0&&(!a||e.amount>a.amount)&&(a=e);return a?.direction??null}function f(e,t,n,r){let i=new Map,a=new Map,o=new Set;for(let e of t){if(!e.rect)continue;let t=x(e,n,r);if(!t?.rect)continue;let s=_(e.rect,t.rect);if(!s)continue;let c=i.get(t.index)??new Set;c.add(s),i.set(t.index,c);let l=a.get(t.index)??new Set;l.add(s),a.set(t.index,l),o.add(e.index)}return S(e,n,r,i,a),{directionsByContainer:i,coveredNodeIndexes:o}}function p(e){let t=new Map;for(let[n,r]of e){let e={};r.has(`above`)&&(e.hiddenContentAbove=!0),r.has(`below`)&&(e.hiddenContentBelow=!0),(e.hiddenContentAbove||e.hiddenContentBelow)&&t.set(n,e)}return t}function m(e,t){let n=t.get(e.index);if(!n||n.size===0)return e;let r=e.hiddenContentAbove===!0||n.has(`above`)?!0:void 0,i=e.hiddenContentBelow===!0||n.has(`below`)?!0:void 0;return{...e,hiddenContentAbove:r,hiddenContentBelow:i}}function h(e,t){let n=new Map;for(let r of e){let e=g(r,t);if(!e)continue;let i=n.get(e)??[];i.push(r),n.set(e,i)}return[`above`,`below`].flatMap(e=>{let t=n.get(e);if(!t||t.length===0)return[];let r=y(t).slice(0,3).map(e=>`"${e}"`),i=t.length===1?`interactive item`:`interactive items`,a=r.length>0?`: ${r.join(`, `)}`:``;return[`[off-screen ${e}] ${t.length} ${i}${a}`]})}function g(e,t){if(!e.rect)return null;let n=t.resolveEffectiveViewport(e);return n?_(e.rect,n):null}function _(e,t){return e.y+e.height<=t.y?`above`:e.y>=t.y+t.height?`below`:null}function v(t){if(t.hittable===!0)return!0;let n=(t.type??``).toLowerCase();return n.includes(`button`)||n.includes(`link`)||n.includes(`textfield`)||n.includes(`edittext`)||n.includes(`searchfield`)||n.includes(`checkbox`)||n.includes(`radio`)||n.includes(`switch`)||n.includes(`menuitem`)||!!e(t)}function y(t){let n=new Set,r=[];for(let i of t){let t=e(i);!t||n.has(t)||(n.add(t),r.push(t))}return r}function b(e,t,n){let r=e,i=new Set;for(;r&&!i.has(r.index);)i.add(r.index),t.add(r.index),r=typeof r.parentIndex==`number`?n.get(r.parentIndex):void 0}function x(e,t,n){return r(e,n,e=>t.has(e.index))}function S(e,t,n,r,i){for(let a of e){let e=C(a);if(!e||e.size===0)continue;let o=x(a,t,n);if(!o)continue;let s=r.get(o.index)??new Set,c=i.get(o.index);for(let t of e)c&&c.size>0&&!c.has(t)||s.add(t);r.set(o.index,s)}}function C(e){let t=a(e.label,e.value);if(!t)return null;let n=new Set;return t.above&&n.add(`above`),t.below&&n.add(`below`),n.size>0?n:null}export{l as i,u as n,s as r,o as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{D as e}from"./sdk-contracts.js";import{C as t,l as n}from"./sdk-device.js";import{n as r}from"./gesture-admission.js";const i={visionos:`visionOS uses spatial input and does not support two-finger touch synthesis.`,tvos:`tvOS has no touch input — this gesture is supported on Android and the iOS simulator only.`,macos:`macOS automation has no multi-touch input — this gesture is supported on Android and the iOS simulator only.`};function a(a,s){if(!n(a.platform))throw o(s,a.platform);let c=t(a);if(c!==`ios`&&c!==`ipados`||a.kind!==`simulator`)throw c===`ios`||c===`ipados`?new e(`UNSUPPORTED_OPERATION`,`gesture ${s} is not supported on physical iOS devices`,{hint:`Two-finger gesture synthesis is iOS-simulator only — not available on physical iOS devices.`}):o(s,r[c],i[c])}function o(t,n,r){return new e(`UNSUPPORTED_OPERATION`,`gesture ${t} is not supported on ${n}`,r===void 0?void 0:{hint:r})}export{a as n,i as t};
|
package/dist/src/observation.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{
|
|
2
|
-
`);for(let e of
|
|
1
|
+
import{D as e}from"./sdk-contracts.js";import{n as t}from"./device-shell.js";const n=`mCurrentFocus=Window{`,r=[n,`mFocusedApp=AppWindowToken{`,`mResumedActivity:`,`ResumedActivity:`],i=[[`dumpsys`,`window`,`windows`],[`dumpsys`,`window`]],a=[[`dumpsys`,`activity`,`activities`],[`dumpsys`,`activity`]],o=RegExp(`(?:${r.map(S).join(`|`)})(.*)$`,`gm`),s=/\bApplication Not Responding:\s*([A-Za-z0-9_.]+)/i,c=/\b([A-Za-z][A-Za-z0-9_]*(?:\.[A-Za-z0-9_]+)+)\b/,l=new Set([`com.android.permissioncontroller`,`com.google.android.permissioncontroller`,`com.android.packageinstaller`,`com.google.android.packageinstaller`]),u=new Map;function d(n){return Object.freeze({readAppState:async e=>await p(n,e),readBlockingDialog:async e=>await m(n,e),async readAppFocus(e,t,r={}){let i=f(n,e);return r.requireNoBlockingDialog&&(await m(n,e,i)).status===`dialog`?!1:(await p(n,e,i)).package===t},readSnapshotNodes:async e=>await n.readSnapshotNodes(e),async tap(e,r,i){return await n.runAdb(e,t(`adb`,`shell`,[`input`,`tap`,String(Math.round(r)),String(Math.round(i))]),{allowFailure:!0})},openApp:async(e,t)=>await n.openApp(e,t),async readScreenSize(r){let i=(await n.runAdb(r,t(`adb`,`shell`,[`wm`,`size`]))).stdout.match(/Physical size:\s*(\d+)x(\d+)/);if(!i)throw new e(`COMMAND_FAILED`,`Unable to read screen size`);return{width:Number(i[1]),height:Number(i[2])}},async isPermissionPackage(e){return l.has(e)}})}function f(e,n){let r=new Map;return i=>{let a=i.join(` `),o=r.get(a)??e.runAdb(n,t(`adb`,`shell`,i),{allowFailure:!0}).then(e=>(g(n,a,e.stdout),e.stdout));return r.set(a,o),o}}async function p(e,t,n=f(e,t)){for(let e of h(t,`foreground`)){let t=v(await n(e));if(t)return t}return{}}async function m(e,t,n=f(e,t)){for(let e of h(t,`blockingDialog`)){let t=y(await n(e));if(t.focus)return{status:`dialog`,focus:t.focus};if(t.focusObserved)return{status:`clear`}}return{status:`unknown`}}function h(e,t){let n=t===`foreground`?[i,a]:[i],r=u.get(e.id);return n.flatMap(e=>{if(!r)return e;let n=e=>r.get(`${t} ${e.join(` `)}`)===!1,i=e.filter(e=>!n(e));return i.length===0||i.length===e.length?e:[...i,...e.filter(n)]})}function g(e,t,i){if(!i)return;let a=u.get(e.id)??new Map;_(a,`foreground ${t}`,x(r).test(i)),_(a,`blockingDialog ${t}`,x([n]).test(i)),u.set(e.id,a)}function _(e,t,n){e.get(t)!==!0&&e.set(t,n)}function v(e){for(let t of e.matchAll(o)){let e=t[1]?.match(/\b([A-Za-z][A-Za-z0-9_]*(?:\.[A-Za-z0-9_]+)+)\/([A-Za-z0-9_.$]+)/);if(e?.[1]&&e[2])return{package:e[1],activity:e[2]}}return null}function y(e){let t=!1,i=e.split(`
|
|
2
|
+
`);for(let e of r)for(let r of i){let i=r.indexOf(e);if(i===-1)continue;e===n&&(t=!0);let a=r.trim(),o=b(r.slice(i+e.length).split(`}`)[0]?.trim()??``,a);if(o)return{focusObserved:t,focus:o}}return{focusObserved:t,focus:null}}function b(e,t){let n=s.exec(e)?.[1];if(n)return{package:n,focusedWindow:`Application Not Responding: ${n}`,raw:t};let r=e.toLowerCase();if(!r.includes(`isn't responding`)&&!r.includes(`is not responding`))return null;let i=e.trim().replaceAll(/\s+/g,` `),a=c.exec(i)?.[1];return{...a?{package:a}:{},focusedWindow:i,raw:t}}function x(e){return new RegExp(e.map(S).join(`|`))}function S(e){return e.replaceAll(/[.*+?^${}()|[\]\\]/g,String.raw`\$&`)}export{d as createAndroidObservationAdapter};
|
|
@@ -1,2 +1,5 @@
|
|
|
1
|
-
import{n as e,t}from"./success-text.js";function n(e){return({result:t})=>e(t)}const r=n(i);function i(e){return{data:e,text:t(e)}}function a(
|
|
2
|
-
`)}function
|
|
1
|
+
import{n as e,t}from"./success-text.js";function n(e){return({result:t})=>e(t)}const r=n(i);function i(e){return{data:e,text:t(e)}}function a(t){return[...typeof t.warning==`string`&&t.warning.trim()!==``?[t.warning]:[],...e(t)].map(e=>c(e)).filter(e=>e.length>0)}function o(e,t){let n=e??``,r=a(t).filter(e=>!n.includes(e)).map(e=>`Warning: ${e}`);return r.length===0?e??null:[...n===``?[]:[n],...r].join(`
|
|
2
|
+
`)}function s(e,t,n){let r=t??{};if(n===`text`)return{...e,text:o(e.text,r)};let i=`${e.text??``}\n${e.stderr??``}`,s=a(r).filter(e=>!i.includes(e)).map(e=>`Warning: ${e}`);if(s.length===0)return e;let c=e.stderr??``;return{...e,stderr:`${c}${c===``||c.endsWith(`
|
|
3
|
+
`)?``:`
|
|
4
|
+
`}${s.join(`
|
|
5
|
+
`)}\n`}}function c(e){return e.replaceAll(/\s*\n\s*/g,` `)}function l(e,t){if(typeof e==`string`&&e.length!==0&&typeof t==`number`)return`@${e.startsWith(`@`)?e.slice(1):e}~s${t}`}export{n as a,l as i,i as n,s as o,r,c as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{D as e}from"./sdk-contracts.js";import{dn as t}from"./sdk-batch.js";import{t as n}from"./script.js";import{t as r}from"./session-paths.js";const i=/^\$\{([A-Z_][A-Z0-9_]*)\}$/;function a(t){if(t!==t.trim()||!n.test(t))throw new e(`INVALID_ARGS`,`Invalid --record-as variable "${t}": use uppercase letters, digits, and underscores (for example PASSWORD).`);if(t.startsWith(`AD_`))throw new e(`INVALID_ARGS`,`Invalid --record-as variable "${t}": the AD_* namespace is reserved for built-in replay variables.`);return t}function o(e){return`\${${e}}`}function ee(e){let t=i.exec(e);if(!(!t?.[1]||t[1].startsWith(`AD_`)))return t[1]}function s(e){let t=e.result?.text;if(typeof t==`string`)return t;let n=e.positionals??[];return n.length===0?``:n[0]?.startsWith(`@`)?n.length>=3?n.slice(2).join(` `):n.slice(1).join(` `):n.length>=3&&!Number.isNaN(Number(n[0]))&&!Number.isNaN(Number(n[1]))?n.slice(2).join(` `):n.slice(1).join(` `)}const c={kind:`none`};function l(e,t){if(t.path===void 0){let n=e??{kind:`default`,force:!1};return t.force?{...n,force:!0}:n}let n=e?.force===!0&&(e.kind==="default"||e.path===t.path);return{kind:`explicit`,path:t.path,force:t.force||n}}function te(e){return e.kind===`repair`?{...e,status:`armed`}:e}function u(e){return e.kind===`none`?void 0:e.target}function d(e){return e.kind===`repair`&&(e.status===`complete`||e.status===`close-succeeded`)}function f(e){return e.kind===`authoring`&&e.status===`aborted`}function p(e){return e.kind===`authoring`?e.status===`armed`:e.kind===`repair`}function m(e){return e.kind===`repair`?e.status===`committed`:e.kind===`authoring`&&e.status===`published`}function h(e){return{kind:`authoring`,status:`armed`,target:l(void 0,e)}}function g(e){return e.kind!==`authoring`||e.status!==`armed`?e:{...e,status:`aborted`}}function _(e,t){return e.kind===`authoring`?{kind:`authoring`,status:`published`,target:{kind:`explicit`,path:t,force:e.target.force}}:e}function v(e,t){let n=e.kind===`repair`?e:void 0,r=n?.sourcePath??t.sourcePath;return{kind:`repair`,status:n?.status??`armed`,target:l(n?.target,t.requested),boundary:n?.boundary??t.boundary,...r===void 0?{}:{sourcePath:r},...n?.closeReceipt===void 0?{}:{closeReceipt:n.closeReceipt}}}function y(e){return e.kind!==`repair`||e.status!==`armed`?e:{...e,status:`complete`}}function b(e,t){return e.kind===`repair`?{...e,status:e.status===`complete`?`close-succeeded`:e.status,closeReceipt:t}:e}function ne(e){if(e.kind!==`repair`)return e;let{closeReceipt:t,...n}=e;return{...n,status:`committed`}}function re(e){if(e.kind!==`repair`)return e;let{closeReceipt:t,...n}=e;return{...n,status:`aborted`}}function ie(e){return e.kind===`repair`?e.boundary:void 0}function x(e){return e.kind===`repair`?e.sourcePath:void 0}function S(e){return e.kind===`repair`&&e.status!==`committed`}function C(e){let t=u(e);return t?.kind===`explicit`?t.path:void 0}function w(e){return u(e)?.force===!0}function T(e){return e?.scriptPublication??c}function E(e){let t=T(e);return t.kind===`authoring`&&t.status===`armed`}function D(e,t){e.scriptPublication=h({path:t.path===void 0?void 0:r(t.path),force:t.force===!0})}function O(e){e.scriptPublication=g(T(e))}function k(e){return p(T(e))}function A(e,t){if(!t.saveScript||f(T(e)))return;let n={path:typeof t.saveScript==`string`?r(t.saveScript):void 0,force:t.force===!0},i=T(e);if(i.kind===`repair`){e.scriptPublication=v(i,{requested:n,boundary:i.boundary,sourcePath:i.sourcePath});return}if(i.kind===`authoring`){e.scriptPublication={...i,target:l(i.target,n)};return}e.scriptPublication=h(n)}function j(e,t){let n=T(e);n.kind===`authoring`&&(e.scriptPublication={...n,target:l(n.target,{path:t.explicitPath===void 0?void 0:r(t.explicitPath),force:t.liveForce===!0})})}function M(e,t){e.scriptPublication=_(T(e),t)}function N(e,t){let n=T(e);n.kind===`authoring`&&(e.scriptPublication=_(n,t))}function P(e,t){return t===!0||w(T(e))}function F(e){return m(T(e))}const ae=new Set(`action.backend.cost.delayMs.evidence.gesture.hint.kind.maestroFallbackReason.maestroNonHittableCoordinateFallbackAllowed.maestroNonHittableCoordinateFallbackUsed.message.platform.ref.referenceHeight.referenceWidth.refLabel.resolution.selector.selectorChain.settle.targetHittable.targetKind.text.warning.x.y`.split(`.`)),I=new Set([`action`,`backend`,`gesture`,`kind`,`platform`,`ref`,`selector`,`targetKind`]),L=new Set([`cost`,`evidence`,`resolution`,`settle`]),R=new Map([[`cost`,new Set([`nodeCount`,`runnerRoundTrips`,`wallClockMs`])],[`evidence`,new Set([`changedFromBefore`,`digest`,`foregroundApp`,`interactiveNodeCount`,`nodeCount`])],[`resolution`,new Set([`alternatives`,`kind`,`matchCount`,`phase`,`source`,`tiebreak`,`winnerDiagnostic`])],[`resolution.alternatives`,new Set([`diagnosticRef`,`label`,`role`])],[`resolution.winnerDiagnostic`,new Set([`diagnosticRef`,`label`,`role`])],[`settle`,new Set([`captures`,`diff`,`hint`,`quietMs`,`refs`,`refsGeneration`,`settled`,`tail`,`tailTruncated`,`timeoutMs`,`waitedMs`])],[`settle.diff`,new Set([`lines`,`summary`,`truncated`])],[`settle.diff.lines`,new Set([`kind`,`ref`,`text`])],[`settle.diff.summary`,new Set([`additions`,`removals`,`unchanged`])],[`settle.refs`,new Set([`ref`])],[`settle.tail`,new Set([`label`,`ref`,`role`])]]),z=new Set([`evidence.digest`,`evidence.foregroundApp`,`resolution.alternatives.diagnosticRef`,`resolution.alternatives.role`,`resolution.kind`,`resolution.phase`,`resolution.source`,`resolution.tiebreak`,`resolution.winnerDiagnostic.diagnosticRef`,`resolution.winnerDiagnostic.role`,`settle.diff.lines.kind`,`settle.diff.lines.ref`,`settle.refs.ref`,`settle.tail.ref`,`settle.tail.role`]);function B(e,t,n){if(!e)return e;let r=le(e.selectorChain),i=e=>q(e,t);return{...J(e,e=>ce(e,t,n),i),...typeof e.text==`string`?{text:n}:{},...r?{selectorChain:r.filter(e=>!i(e))}:{}}}function V(e,t){if(!e)return e;let n=Z(t);return J(e,e=>Q(e,n),e=>G(e,t))}function H(e,t){if(!e)return e;let n=Z(t);return{...e,...e.label===void 0?{}:{label:Q(e.label,n)},ancestry:e.ancestry.map(e=>({...e,...e.label===void 0?{}:{label:Q(e.label,n)}})),...e.scrollRegion?{scrollRegion:{...e.scrollRegion,...e.scrollRegion.label===void 0?{}:{label:Q(e.scrollRegion.label,n)}}}:{}}}function U(e,t){return!!(e.label!==void 0&&W(e.label,t)||e.ancestry.some(e=>e.label&&W(e.label,t))||e.scrollRegion?.label&&W(e.scrollRegion.label,t))}function W(e,t){for(let n of t.keys())if(e.includes(n))return!0;return!1}function G(e,t){for(let n of t.keys())if(q(e,n))return!0;return!1}function K(e,t,n){return!e||!t?e:{...e,...e.label===t?{label:n}:{},ancestry:e.ancestry.map(e=>({...e,...e.label===t?{label:n}:{}})),...e.scrollRegion?{scrollRegion:{...e.scrollRegion,...e.scrollRegion.label===t?{label:n}:{}}}:{}}}function q(e,n){return t(e,n)}function J(e,t,n){return Object.fromEntries(Object.entries(e).map(([e,r])=>[ae.has(e)?e:t(e),oe(r,e,t,n)]))}function oe(e,t,n,r){return typeof e==`string`&&I.has(t)?e:t===`selectorChain`&&$(e)?se(e,r):Y(e,n,r,L.has(t)?t:void 0)}function Y(e,t,n,r){if(typeof e==`string`)return r&&z.has(r)?e:t(e);if(Array.isArray(e))return e.map(e=>Y(e,t,n,r));if(!e||typeof e!=`object`)return e;let i=r?R.get(r):void 0;return Object.fromEntries(Object.entries(e).map(([e,a])=>{let o=i?.has(e)===!0;return[o?e:t(e),Y(a,t,n,o?`${r}.${e}`:void 0)]}))}function se(e,t){return e.filter(e=>!t(e))}function ce(e,t,n){if(!t)return e;let r=n?e.split(n):[e];return r.every(e=>!e.includes(t))?e:t.trim()?r.map(e=>e.replaceAll(t,n)).join(n):n}const X=/\$\{[A-Z_][A-Z0-9_]*\}/y;function Z(e){return[...e].sort(([e],[t])=>t.length-e.length)}function Q(e,t){if(!e||t.length===0)return e;let n=``,r=0;scan:for(;r<e.length;){for(let[i,a]of t)if(e.startsWith(i,r)){n+=a,r+=i.length;continue scan}if(e[r]===`$`){X.lastIndex=r;let t=X.exec(e);if(t){n+=t[0],r+=t[0].length;continue}}n+=e[r],r+=1}return n}function $(e){return Array.isArray(e)&&e.every(e=>typeof e==`string`)}function le(e){return $(e)?e:void 0}export{s as A,S as C,x as D,ie as E,o as M,a as N,w as O,d as S,b as T,re as _,U as a,te as b,D as c,k as d,F as f,c as g,j as h,H as i,ee as j,C as k,P as l,N as m,K as n,O as o,M as p,V as r,A as s,B as t,E as u,v,y as w,p as x,ne as y};
|
package/dist/src/perf-facade.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{C as e}from"./sdk-contracts.js";import{E as t}from"./sdk-batch-runner.js";import{c as n,l as r,u as i,v as a}from"./sdk-device.js";import{rr as o}from"./sdk-batch.js";import{a as s,l as c,n as l}from"./exec.js";import"./command.js";import{t as u}from"./parser.js";import{n as d,t as f}from"./numeric.js";import{C as p,D as ee,g as m,i as te,m as h,o as g,u as _,w as ne,y as v}from"./host-file.js";import{a as y,o as b}from"./tool-provider.js";import{a as re,i as ie,t as ae}from"./physical-device-control.js";import{t as x}from"./simctl.js";import{t as oe}from"./plist.js";import S from"node:path";import{fileURLToPath as C}from"node:url";function w(e,t){for(let n of e){if(t(n))return n;let e=w(n.children,t);if(e)return e}}function T(e,t){let n=[];for(let r of e)t(r)&&n.push(r),n.push(...T(r.children,t));return n}function se(e,t){return e.children.find(e=>e.name===t)?.text??null}function E(e,t){let n=w(e,e=>e.name===`schema`&&e.attributes.name===t);return n?n.children.filter(e=>e.name===`col`).map(e=>se(e,`mnemonic`)??``):[]}function D(e){if(!e||e.children.some(e=>e.name===`sentinel`)||!e.text)return null;let t=Number(e.text);return Number.isFinite(t)?t:null}function O(e,t){return e?e.attributes.ref?t.get(e.attributes.ref)?.numberValue??null:D(e):null}function ce(e){return new Map(T(e,e=>!!e.attributes.id).flatMap(e=>{let t=e.attributes.id;return t?[[t,e]]:[]}))}function k(e,t){if(e)return e.attributes.ref?t.get(e.attributes.ref):e}const A=`xctrace-animation-hitches`;function le(e){let t=ue(e.frameLifetimesXml),n=de(e.displayInfoXml),r=fe(e.hitchesXml).filter(t=>he(t,e.processIds,e.processNames)),i=r.length,a=Math.max(0,Math.round(Date.parse(e.windowEndedAt)-Date.parse(e.windowStartedAt))),s=ge(r,Date.parse(e.windowStartedAt));return{droppedFramePercent:t>0?d(i/t*100):0,droppedFrameCount:i,totalFrameCount:t,sampleWindowMs:a,windowStartedAt:e.windowStartedAt,windowEndedAt:e.windowEndedAt,measuredAt:e.measuredAt,method:A,matchedProcesses:o(r.map(e=>e.processName).filter(e=>typeof e==`string`&&e.length>0)),frameDeadlineMs:n===void 0?void 0:f(1e3/n),refreshRateHz:n,worstWindows:s.length>0?s:void 0}}function ue(e){return ve(e,`hitches-frame-lifetimes`).length}function de(e){if(!e)return;let{rows:t,schema:n}=j(e,`device-display-info`),r=n.indexOf(`max-refresh-rate`);if(r<0)return;let i=new Map;for(let e of t){M(e.children,i);let t=O(e.children[r],i);if(t!==null&&t>0)return t}}function fe(e){let t=u(e),n=pe(t);if(!n)return[];let r=new Map;return T(t,e=>e.name===`row`).map(e=>me(e,n,r)).filter(e=>!!e)}function pe(e){let t=E(e,`hitches`),n={start:t.indexOf(`start`),duration:t.indexOf(`duration`),process:t.indexOf(`process`),isSystem:t.indexOf(`is-system`)};return Object.values(n).every(e=>e>=0)?n:null}function me(e,t,n){if(M(e.children,n),ye(e.children[t.isSystem],n)===!0)return null;let r=O(e.children[t.start],n),i=O(e.children[t.duration],n);if(r===null||i===null)return null;let a=be(e.children[t.process],n);return{startNs:r,durationNs:i,pid:a?.pid,processName:a?.name}}function he(e,t,n){return e.pid!==void 0&&t.includes(e.pid)?!0:e.processName?n.includes(e.processName):!1}function ge(e,t){if(e.length===0)return[];let n=[...e].sort((e,t)=>e.startNs-t.startNs),r=[],i=[];for(let e of n){let t=i.at(-1);if(!t||e.startNs-(t.startNs+t.durationNs)<=5e8){i.push(e);continue}r.push(i),i=[e]}return i.length>0&&r.push(i),r.map(e=>_e(e,t)).sort((e,t)=>t.missedDeadlineFrameCount-e.missedDeadlineFrameCount||t.worstFrameMs-e.worstFrameMs).slice(0,3).sort((e,t)=>e.startOffsetMs-t.startOffsetMs)}function _e(e,t){let n=Math.min(...e.map(e=>e.startNs)),r=Math.max(...e.map(e=>e.startNs+e.durationNs)),i=Math.max(0,Math.round(n/1e6)),a=Math.max(i,Math.round(r/1e6));return{startOffsetMs:i,endOffsetMs:a,startAt:new Date(t+i).toISOString(),endAt:new Date(t+a).toISOString(),missedDeadlineFrameCount:e.length,worstFrameMs:f(Math.max(...e.map(e=>e.durationNs))/1e6)}}function ve(e,t){return j(e,t).rows}function j(e,t){let n=u(e),r=E(n,t);return{rows:r.length===0?[]:T(n,e=>e.name===`row`),schema:r}}function M(e,t){for(let n of e)M(n.children,t),n.attributes.id&&t.set(n.attributes.id,{numberValue:D(n),process:N(n)})}function ye(e,t){let n=O(e,t);return n===null?null:n!==0}function be(e,t){return e?e.attributes.ref?t.get(e.attributes.ref)?.process??null:N(e):null}function N(e){if(!e||e.children.some(e=>e.name===`sentinel`))return null;let t=D(w(e.children,e=>e.name===`pid`)),n=(e.attributes.fmt??``).replace(/\s+\(\d+\)$/,``).trim();return t===null&&n.length===0?null:{pid:t??void 0,name:n.length>0?n:void 0}}const P=`ps-process-snapshot`,F=`xctrace-activity-monitor`,I=`leaks-output-graph`,L=15e3,R=12e4;async function xe(t,n){if(r(t)&&t.kind===`device`)return await Fe(t,n);let i=await G(t,n),a=await q(t,i);if(a.length===0)throw new e(`COMMAND_FAILED`,`No running process found for ${n}`,{appBundleId:n,hint:`Run open <app> for this session again to ensure the Apple app is active, then retry perf.`});let o=new Date().toISOString();return X({residentMemoryKb:a.reduce((e,t)=>e+t.rssKb,0),measuredAt:o,matchedProcesses:[i.executableName],memoryMethod:P})}async function Se(t,n,r){let i=B(t);if(!i.memgraph)return{available:!1,kind:`memgraph`,reason:i.reason,hint:i.hint,support:i};let a=await Ve(t,n,i);if(a.available===!1)return a;let{process:o}=a;await g(S.dirname(r));let s=await Te(r),c;try{c=await Ce(t,r,o.pid)}catch(e){throw await z(r,s),we(t,n,o,r,e)}if(c.exitCode!==0)throw await z(r,s),new e(`COMMAND_FAILED`,`Failed to capture Apple memgraph for ${n}`,l(c,{kind:`memgraph`,appBundleId:n,pid:o.pid,processName:S.basename(J(o.command)),path:r,hint:Y(t,c.stdout,c.stderr)}));let u=await _(r).catch(()=>null);if(!u?.isFile()||u.size<=0)throw await z(r,s),new e(`COMMAND_FAILED`,`Apple memgraph artifact is missing or empty`,{kind:`memgraph`,appBundleId:n,pid:o.pid,path:r,hint:`Retry with a writable --out path. If the file is still empty, run with --debug and inspect leaks output.`});return{available:!0,kind:`memgraph`,path:r,sizeBytes:u.size,measuredAt:new Date().toISOString(),method:I,appBundleId:n,pid:o.pid,processName:S.basename(J(o.command)),support:i}}async function Ce(e,t,n){return i(e)?await y(`leaks`,[`--outputGraph=${t}`,String(n)],{allowFailure:!0,timeoutMs:R}):await b(x(e,[`spawn`,e.id,`leaks`,`--outputGraph=${t}`,String(n)]),{allowFailure:!0,timeoutMs:R})}function we(t,n,r,i,a){if(a instanceof e){let o=a.details??{};return new e(a.code,`Failed to capture Apple memgraph for ${n}`,{...o,kind:`memgraph`,appBundleId:n,pid:r.pid,processName:S.basename(J(r.command)),path:i,hint:Y(t,typeof o.stdout==`string`?o.stdout:``,typeof o.stderr==`string`&&o.stderr.length>0?o.stderr:a.message)},a)}return new e(`COMMAND_FAILED`,`Failed to capture Apple memgraph for ${n}`,{kind:`memgraph`,appBundleId:n,pid:r.pid,processName:S.basename(J(r.command)),path:i,hint:`Retry perf memory snapshot. If it still fails, run with --debug and inspect leaks output.`},a)}async function Te(e){return await _(e).then(e=>e.isFile()).catch(()=>!1)}async function z(e,t){t||await p(e).catch(()=>{})}async function Ee(t,n){if(!r(t)||t.kind!==`device`)throw new e(`COMMAND_FAILED`,`Apple frame-health sampling is currently available only on connected iOS devices.`,{metric:`fps`,platform:a(t),deviceKind:t.kind});let i=await K(t,n),s=await ke(t,n,i);return le({hitchesXml:s.hitchesXml,frameLifetimesXml:s.frameLifetimesXml,displayInfoXml:s.displayInfoXml,processIds:i.map(e=>e.pid),processNames:o(i.map(e=>S.basename(C(e.executable)))),windowStartedAt:s.windowStartedAt,windowEndedAt:s.windowEndedAt,measuredAt:s.windowEndedAt})}function De(e){return r(e)&&e.kind===`device`?{method:A,description:`Rendered-frame hitch health from xctrace Animation Hitches on connected iOS devices. Dropped frames are counted from native hitch rows for the attached app process, with total frames from the same trace frame-lifetime table.`,unit:`percent`,primaryField:`droppedFramePercent`,window:`short 2s xctrace Animation Hitches record of the active app process`,resetsAfterRead:!1}:{method:A,description:`Unavailable on iOS simulators and macOS because local Apple tooling does not expose reliable app frame hitches for these targets.`,unit:`percent`,primaryField:`droppedFramePercent`}}function Oe(e){if(r(e)&&e.kind===`device`)return{method:F,description:`Resident memory snapshot from a short xctrace Activity Monitor sample on the connected iOS device.`,unit:`kB`};let t=i(e)?`host ps for the running macOS app executable resolved from the bundle ID.`:`xcrun simctl spawn ps, with host ps fallback, for the running iOS simulator app executable resolved from the bundle ID.`;return{method:P,description:`Resident memory snapshot from ${t}`,unit:`kB`}}function B(e){return r(e)&&e.kind===`device`?{platform:a(e),deviceKind:e.kind,memgraph:!1,method:I,reason:`Physical iOS device memgraph capture is not exposed through reliable local agent-device tooling.`,hint:`Use perf memory sample for a compact resident-memory reading, or reproduce on an iOS simulator/macOS target for memgraph capture.`}:r(e)&&e.kind===`simulator`?{platform:a(e),deviceKind:e.kind,memgraph:!0,method:I,reason:`iOS simulator processes are host-visible through simctl spawn leaks.`,hint:`Keep the simulator app running in the foreground while the memgraph is captured.`}:i(e)?{platform:a(e),deviceKind:e.kind,memgraph:!0,method:I,reason:`macOS app processes are host-visible to leaks --outputGraph.`,hint:`Grant Terminal/agent process permissions if macOS denies process inspection.`}:{platform:a(e),deviceKind:e.kind,memgraph:!1,method:I,reason:`Apple memgraph capture is available only for iOS simulator and macOS app sessions.`,hint:`Use perf memory sample on supported app sessions, or rerun against iOS simulator/macOS for memgraph capture.`}}async function ke(e,t,n){let r=await h(`agent-device-ios-frame-perf-`),i=S.join(r,`animation-hitches.trace`),a=S.join(r,`hitches.xml`),o=S.join(r,`frame-lifetimes.xml`),s=S.join(r,`display-info.xml`);try{let r=await V({device:e,appBundleId:t,tracePath:i,template:`Animation Hitches`,duration:`2s`,targetPids:n.map(e=>e.pid),validateTraceOutput:!0,failureMessage:`Failed to record iOS frame-health sample for ${t}`});await W(e,t,i,`hitches`,a),await W(e,t,i,`hitches-frame-lifetimes`,o);let c=await Me(e,t,i,`device-display-info`,s);return{windowStartedAt:r.startedAt,windowEndedAt:r.endedAt,hitchesXml:await v(a),frameLifetimesXml:await v(o),displayInfoXml:c?await v(s):void 0}}finally{await p(r).catch(()=>{})}}async function V(t){let{device:n,appBundleId:r,tracePath:i,template:a,duration:o}=t,s=t.allProcesses?[`--all-processes`]:(t.targetPids??[]).flatMap(e=>[`--attach`,String(e)]),c=[`xctrace`,`record`,`--template`,a,`--device`,n.id,...s,`--time-limit`,o,`--output`,i,`--quiet`,`--no-prompt`],u=await Ae(c,t.tracePath);if(u.result.exitCode===0)return t.validateTraceOutput&&await je(t,u.result.stdout,u.result.stderr),{startedAt:u.startedAt,endedAt:u.endedAt,capturedAtMs:u.capturedAtMs};throw new e(`COMMAND_FAILED`,t.failureMessage,l(u.result,{cmd:`xcrun`,args:c,appBundleId:r,deviceId:n.id,hint:Q(u.result.stdout,u.result.stderr)}))}async function Ae(e,t){let n;for(let r=1;r<=3;r+=1){await U(t,r,1500);let i=new Date().toISOString(),a=await b(e,{allowFailure:!0,timeoutMs:6e4});if(n={result:a,startedAt:i,endedAt:new Date().toISOString(),capturedAtMs:Date.now()},a.exitCode===0||!H(a))return n}return n}function H(e){let t=`${e.stdout}\n${e.stderr}`.toLowerCase();return t.includes(`_lockkperf`)||t.includes(`could not lock kperf`)||t.includes(`likely another session just started`)}async function U(e,t,n){t<=1||(await p(e).catch(()=>{}),await new Promise(e=>setTimeout(e,n)))}async function je(t,n,r){let i=await _(t.tracePath).catch(()=>null);if(!(i?.isDirectory()===!0?(await m(t.tracePath).catch(()=>[])).length>0:(i?.size??0)>0))throw new e(`COMMAND_FAILED`,`${t.failureMessage}: xctrace produced no trace data`,{tracePath:t.tracePath,appBundleId:t.appBundleId,deviceId:t.device.id,stdout:n,stderr:r,hint:`Keep the iOS device unlocked and connected by cable, keep the app active, then retry perf.`})}async function W(e,t,n,r,i){let a=[`xctrace`,`export`,`--input`,n,`--xpath`,`/trace-toc/run/data/table[@schema="${r}"]`,`--output`,i];s(await b(a,{allowFailure:!0,timeoutMs:15e3}),`Failed to export iOS device ${r} data`,n=>({cmd:`xcrun`,args:a,appBundleId:t,deviceId:e.id,hint:Q(n.stdout,n.stderr)}))}async function Me(e,t,n,r,i){try{return await W(e,t,n,r,i),!0}catch{return!1}}function Ne(e){let n=[];for(let r of t(e)){let e=r.match(/^(\d+)\s+([0-9]+(?:\.[0-9]+)?)\s+(\d+)\s+(.+)$/);if(!e)continue;let[t,i,a,o]=e.slice(1);if(t===void 0||i===void 0||a===void 0||o===void 0)continue;let s=Number(t),c=Number(i),l=Number(a),u=o.trim();!Number.isFinite(s)||!Number.isFinite(c)||!Number.isFinite(l)||n.push({pid:s,cpuPercent:c,rssKb:l,command:u})}return n}async function Pe(t){let n=u(t),r=E(n,`activity-monitor-process-live`);if(r.length===0)throw new e(`COMMAND_FAILED`,`Failed to parse xctrace activity-monitor-process-live schema`);let i=r.indexOf(`pid`),a=r.indexOf(`process`),o=r.indexOf(`memory-real`);if(i<0||a<0||o<0)throw new e(`COMMAND_FAILED`,`xctrace activity-monitor-process-live export is missing expected columns`);let s=T(n,e=>e.name===`row`),c=[],l=new Map;for(let e of s){let t=e.children;if(t.length===0)continue;for(let e of t){let t=w(e.children,e=>e.name===`pid`&&typeof e.attributes.id==`string`);if(t?.attributes.id){let e=Number(t.text);l.set(t.attributes.id,{numberValue:Number.isFinite(e)?e:null})}e.attributes.id&&l.set(e.attributes.id,{numberValue:D(e),processName:Z(e)})}let n=O(t[i],l),r=We(t[a],l);n===null||!Number.isFinite(n)||!r||c.push({pid:n,processName:r,residentMemoryBytes:O(t[o],l)})}return c}async function G(t,n){let r=i(t)?await Re(n):await ze(t,n),a=i(t)?S.join(r,`Contents`,`Info.plist`):S.join(r,`Info.plist`),o=await oe(a,`CFBundleExecutable`);if(!o)throw new e(`COMMAND_FAILED`,`Failed to resolve executable for ${n}`,{appBundleId:n,appPath:r});return{executableName:o,executablePath:i(t)?S.join(r,`Contents`,`MacOS`,o):S.join(r,o)}}async function Fe(t,n){let r=await K(t,n),i=await Ie(t,n),a=Le(await Pe(i.xml),r,n,t);if(a.residentMemoryBytes===null)throw new e(`COMMAND_FAILED`,`Incomplete Activity Monitor sample for ${n}`,{appBundleId:n,deviceId:t.id,hint:`Keep the app running in the foreground while perf samples the device, then retry.`});return X({residentMemoryKb:a.residentMemoryBytes/1024,measuredAt:new Date(i.capturedAtMs).toISOString(),matchedProcesses:a.matchedProcesses,memoryMethod:F})}async function K(t,n){let{appBundleUrl:r,processes:i}=await ae(t).resolveAppProcesses(t,n),a=C(r);if(i.length===0)throw new e(`COMMAND_FAILED`,`No running process found for ${n}`,{appBundleId:n,deviceId:t.id,appBundlePath:a,hint:`Run open <app> for this session again to ensure the iOS app is active, then retry perf.`});return i}async function Ie(e,t){let n=await h(`agent-device-ios-perf-`),r=S.join(n,`sample.trace`),i=S.join(n,`activity-monitor-process-live.xml`);try{let n=await V({device:e,appBundleId:t,tracePath:r,template:`Activity Monitor`,duration:`1s`,allProcesses:!0,failureMessage:`Failed to record iOS device Activity Monitor sample for ${t}`});return await W(e,t,r,`activity-monitor-process-live`,i),{capturedAtMs:n.capturedAtMs,xml:await v(i)}}finally{await p(n).catch(()=>{})}}function Le(t,n,r,i){let a=new Set(n.map(e=>e.pid)),s=new Set(n.map(e=>S.basename(C(e.executable)))),c=t.filter(e=>a.has(e.pid)||s.has(e.processName));if(c.length===0)throw new e(`COMMAND_FAILED`,`No Activity Monitor sample found for ${r}`,{appBundleId:r,deviceId:i.id,hint:`Keep the app running in the foreground while perf samples the device, then retry.`});let l=new Map;for(let e of c){let t=l.get(e.pid);if(!t){l.set(e.pid,e);continue}l.set(e.pid,{pid:e.pid,processName:e.processName||t.processName,residentMemoryBytes:Ge(t.residentMemoryBytes,e.residentMemoryBytes)})}let u=[...l.values()],d=u.map(e=>e.residentMemoryBytes).filter(e=>e!==null);return{residentMemoryBytes:d.length>0?d.reduce((e,t)=>e+t,0):null,matchedProcesses:o(u.map(e=>e.processName))}}async function Re(t){let n=`kMDItemCFBundleIdentifier == "${t.replaceAll(`"`,String.raw`\"`)}"`,r=s(await y(`mdfind`,[n],{allowFailure:!0,timeoutMs:L}),`Failed to resolve macOS app bundle for ${t}`,{appBundleId:t}).stdout.split(`
|
|
2
|
-
`).map(e=>e.trim()).find(e=>e.endsWith(`.app`));if(!r)throw new e(`APP_NOT_INSTALLED`,`No macOS app found for ${t}`,{appBundleId:t});return r}async function ze(t,n){let r=x(t,[`get_app_container`,t.id,n,`app`]),i=s(await b(r,{allowFailure:!0,timeoutMs:L}),`Failed to resolve iOS simulator app container for ${n}`,{appBundleId:n,hint:`Ensure the iOS simulator app is installed and booted, then retry perf.`}).stdout.trim();if(i.length===0)throw new e(`APP_NOT_INSTALLED`,`No iOS simulator app container found for ${n}`,{appBundleId:n});return i}async function q(e,t){let n=i(e)?[`-axo`,`pid=,%cpu=,rss=,command=`]:x(e,[`spawn`,e.id,`ps`,`-axo`,`pid=,%cpu=,rss=,command=`]),r=i(e)?await y(`ps`,n,{timeoutMs:L}):await Ue(n),{matchesAppleExecutableProcess:a}=await import(`./perf-process-identity.js`);return Ne(r.stdout).filter(e=>a(e.command,t))}function J(e){let[t=``]=e.trim().split(/\s+/,1);return t}async function Be(t,n,r){let i=(await q(t,r)).sort((e,t)=>t.rssKb-e.rssKb)[0];if(i)return i;throw new e(`COMMAND_FAILED`,`No running process found for ${n}`,{kind:`memgraph`,appBundleId:n,hint:`Run open <app> for this session again to ensure the Apple app is active, then retry perf memory snapshot.`})}async function Ve(e,t,n){try{return{available:!0,process:await Be(e,t,await G(e,t))}}catch(t){if(He(e,t))return{available:!1,kind:`memgraph`,reason:`iOS simulator memgraph capture needs process tools inside simctl spawn, but this simulator runtime did not provide ps.`,hint:`Use perf memory sample when available, or retry memgraph on a simulator runtime that includes process tools such as ps and leaks.`,support:{...n,memgraph:!1}};throw t}}function He(t,n){if(!r(t)||t.kind!==`simulator`||!(n instanceof e))return!1;let i=n.details??{},a=Array.isArray(i.args)?i.args.join(` `):``,o=typeof i.stderr==`string`?i.stderr:``,s=`${n.message}\n${o}`.toLowerCase();return a.includes(`simctl spawn`)&&a.includes(` ps `)&&s.includes(`no such file`)}function Y(e,t,n){let r=`${t}\n${n}`.toLowerCase();return r.includes(`timed out`)||r.includes(`timeout`)?`Apple memgraph capture can take longer than metric sampling. Keep the app running and retry; if it times out again, collect a smaller reproduction before capturing leaks --outputGraph.`:r.includes(`not found`)||r.includes(`no such file`)?`Install Xcode command line tools and ensure leaks is available, then retry.`:r.includes(`permission`)||r.includes(`denied`)||r.includes(`not authorized`)?i(e)?`Grant the agent terminal process permission to inspect this macOS app, then retry.`:`Keep the simulator booted and app running; if inspection is denied, retry with a debug simulator build.`:`Keep the app process running and retry perf memory snapshot with --debug if the failure persists.`}async function Ue(e){let t=await b(e,{allowFailure:!0,timeoutMs:L});return t.exitCode===0?t:await y(`ps`,[`-axo`,`pid=,%cpu=,rss=,command=`],{timeoutMs:L})}function X(e){return{residentMemoryKb:Math.round(e.residentMemoryKb),measuredAt:e.measuredAt,method:e.memoryMethod,matchedProcesses:e.matchedProcesses}}function Z(e){let t=e?.attributes.fmt?.trim()??``;return t?t.replace(/\s+\(\d+\)$/,``).trim():null}function We(e,t){return e?e.attributes.ref?t.get(e.attributes.ref)?.processName??null:Z(e):null}function Q(e,t){let n=re(e,t);if(n)return n;let r=`${e}\n${t}`.toLowerCase();return r.includes(`no device matched`)||r.includes(`failed to find device`)?ie:r.includes(`timed out`)?`Keep the iOS device unlocked and connected by cable, keep the app active, then retry perf.`:`Ensure the iOS device is unlocked, trusted, visible to xctrace, and the target app stays active while perf samples it.`}function Ge(e,t){return e===null?t:t===null?e:Math.max(e,t)}function Ke(e,t=10){let n=u(e),r=ce(n),i=new Map,a=0,o=0;for(let e of T(n,e=>e.name===`row`)){let t=qe(e,r),n=Je(e,r);if(t===void 0||!n)continue;let s=n.attributes.name?.trim()||`<unknown>`,c=Ye(n,r),l=`${c??``}\u0000${s}`,u=i.get(l);i.set(l,{symbol:s,binary:c,weightNs:(u?.weightNs??0)+t}),a+=1,o+=t}let s=Math.max(0,Math.floor(t)),c=[...i.values()].sort((e,t)=>t.weightNs-e.weightNs||e.symbol.localeCompare(t.symbol)).slice(0,s).map(({symbol:e,binary:t,weightNs:n})=>({symbol:e,binary:t,selfSampleMs:$(n),selfSamplePercent:o>0?d(n/o*100):0}));return{sampleCount:a,totalSampleWeightMs:$(o),topFunctions:c}}function qe(e,t){let n=k(e.children.find(e=>e.name===`weight`),t);if(!n?.text)return;let r=Number(n.text);return Number.isFinite(r)&&r>0?r:void 0}function Je(e,t){return k(k(e.children.find(e=>e.name===`backtrace`),t)?.children.find(e=>e.name===`frame`),t)}function Ye(e,t){return k(e.children.find(e=>e.name===`binary`),t)?.attributes.name?.trim()||void 0}function $(e){return Math.round(e/1e6*1e3)/1e3}const Xe=15e3;async function Ze(e){let t=await nt(e.device,e.appBundleId);await g(S.dirname(e.outPath));let n=rt({device:e.device,template:e.template,targetPids:t.pids,outPath:e.outPath}),r=new Date().toISOString(),i=await it(n,e.outPath,{device:e.device,appBundleId:e.appBundleId,failureMessage:`Failed to start Apple xctrace ${e.mode} capture for ${e.appBundleId}`});return{kind:`xctrace`,mode:e.mode,template:e.template,outPath:e.outPath,appBundleId:e.appBundleId,deviceId:e.device.id,platform:a(e.device),targetPids:t.pids,targetProcesses:t.processNames,startedAt:r,child:i.child,wait:i.wait}}async function Qe(e,t=e.outPath){t!==e.outPath&&await g(S.dirname(t));let n=s(await ot(e,{failOnForcedKill:!0}),`Failed to stop Apple xctrace ${e.mode} capture`,t=>({tracePath:e.outPath,captureCleanedUp:!0,hint:Q(t.stdout,t.stderr)}));return t!==e.outPath&&await ne(e.outPath,t).catch(async()=>{await te(e.outPath,t),await p(e.outPath)}),await ct(t,{appBundleId:e.appBundleId,deviceId:e.deviceId,stdout:n.stdout,stderr:n.stderr}),{kind:`xctrace`,mode:e.mode,template:e.template,outPath:t,appBundleId:e.appBundleId,deviceId:e.deviceId,platform:e.platform,targetPids:e.targetPids,targetProcesses:e.targetProcesses,startedAt:e.startedAt,endedAt:new Date().toISOString()}}async function $e(e){return await ot(e,{failOnForcedKill:!1})}async function et(t){let n=await h(`agent-device-xctrace-report-`),r=S.join(n,`trace-toc.xml`),i=S.join(n,`time-profile.xml`);try{let n=[`xctrace`,`export`,`--input`,t.tracePath,`--toc`,`--output`,r];s(await b(n,{allowFailure:!0,timeoutMs:Xe}),`Failed to export Apple xctrace report metadata`,e=>({cmd:`xcrun`,args:n,tracePath:t.tracePath,hint:Q(e.stdout,e.stderr)}));let a=await v(r),o=await tt(t.tracePath,i),c=lt({...t,tocXml:a,timeProfileXml:o});if(c.summary.sampleCount===0)throw new e(`COMMAND_FAILED`,`Apple xctrace CPU report contained no samples`,{tracePath:t.tracePath,tableSchemas:c.summary.tableSchemas,hint:`Keep the app active while recording, then retry. Open the raw trace in Instruments if it still contains no Time Profiler samples.`});return await g(S.dirname(t.outPath)),await ee(t.outPath,`${JSON.stringify(c,null,2)}\n`),c}finally{await p(n).catch(()=>{})}}async function tt(e,t){let n=[`xctrace`,`export`,`--input`,e,`--xpath`,`/trace-toc/run/data/table[@schema="time-profile"]`,`--output`,t];return s(await b(n,{allowFailure:!0,timeoutMs:Xe}),`Failed to export Apple xctrace Time Profiler samples`,t=>({cmd:`xcrun`,args:n,tracePath:e,hint:Q(t.stdout,t.stderr)})),await v(t)}async function nt(t,i){if(!n(t.platform))throw new e(`UNSUPPORTED_OPERATION`,`Apple xctrace perf is not supported on Android.`,{platform:t.platform,hint:`Android native profiling belongs to the Android perf rollout and is not implemented under Apple xctrace.`});if(r(t)&&t.kind===`device`){let e=await K(t,i);return{pids:e.map(e=>e.pid),processNames:o(e.map(e=>S.basename(C(e.executable))))}}let a=await G(t,i),s=await q(t,a);if(s.length===0)throw new e(`COMMAND_FAILED`,`No running process found for ${i}`,{appBundleId:i,deviceId:t.id,hint:`Run open <app> for this session again to ensure the Apple app is active, then retry perf.`});return{pids:s.map(e=>e.pid),processNames:[a.executableName]}}function rt(e){return[`xctrace`,`record`,`--template`,e.template,...r(e.device)?[`--device`,e.device.id]:[],...e.targetPids.flatMap(e=>[`--attach`,String(e)]),`--output`,e.outPath,`--quiet`,`--no-prompt`]}async function it(t,n,r){let i;for(let e=1;e<=3;e+=1){await U(n,e,1500);let r=c(`xcrun`,t,{allowFailure:!0}),a=await at(r.wait);if(!a)return r;if(i=a,!H(a))break}let a=i??{stdout:``,stderr:``,exitCode:1};throw new e(`COMMAND_FAILED`,r.failureMessage,l(a,{cmd:`xcrun`,args:t,appBundleId:r.appBundleId,deviceId:r.device.id,hint:Q(a.stdout,a.stderr)}))}async function at(e){return await Promise.race([e,new Promise(e=>setTimeout(e,500))])}async function ot(t,n){t.child.kill(`SIGINT`);let r=await st(t.wait,45e3);if(r)return r;t.child.kill(`SIGKILL`);let i=await st(t.wait,5e3);if(i&&!n.failOnForcedKill)return i;throw i?new e(`COMMAND_FAILED`,`Timed out waiting for Apple xctrace capture to stop`,{exitCode:i.exitCode,stdout:i.stdout,stderr:i.stderr,tracePath:t.outPath,captureCleanedUp:!0,forcedKill:!0,hint:`xctrace did not finish after SIGINT, so it was force-killed. Retry the perf command after confirming no other xctrace session is active.`}):new e(`COMMAND_FAILED`,`Timed out waiting for Apple xctrace capture to stop after SIGKILL`,{tracePath:t.outPath,captureCleanedUp:!1,forcedKill:!0,hint:`xctrace did not exit after SIGKILL. Inspect running xctrace processes before retrying.`})}async function st(e,t){return await Promise.race([e,new Promise(e=>setTimeout(e,t))])}async function ct(t,n){let r=await _(t).catch(()=>null);if(!(r?.isDirectory()===!0?(await m(t).catch(()=>[])).length>0:(r?.size??0)>0))throw new e(`COMMAND_FAILED`,`xctrace produced no trace data`,{tracePath:t,appBundleId:n.appBundleId,deviceId:n.deviceId,stdout:n.stdout,stderr:n.stderr,hint:`Keep the Apple device unlocked and connected, keep the app active, then retry perf.`})}function lt(e){let t=u(e.tocXml),n=T(t,e=>e.name===`run`),r=o(T(t,e=>e.name===`table`).map(e=>e.attributes.schema).filter(e=>typeof e==`string`&&e.length>0)).sort(),i=Ke(e.timeProfileXml);return{kind:`xctrace`,mode:`cpu-profile`,template:e.template,tracePath:e.tracePath,reportPath:e.outPath,appBundleId:e.appBundleId,generatedAt:new Date().toISOString(),summary:{runCount:n.length,tableSchemas:r,...i}}}export{De as buildAppleFrameSamplingMetadata,Oe as buildAppleMemorySamplingMetadata,B as buildAppleMemorySnapshotSupport,Se as captureAppleMemorySnapshot,$e as cleanupAppleXctracePerfCapture,H as isRetryableIosDeviceTraceRecordFailure,q as readAppleProcessSamples,G as resolveAppleExecutable,Q as resolveIosDevicePerfHint,K as resolveIosDevicePerfTarget,Ee as sampleAppleFramePerf,xe as sampleAppleMemoryPerf,Ze as startAppleXctracePerfCapture,Qe as stopAppleXctracePerfCapture,et as writeAppleXctracePerfReport};
|
|
1
|
+
import{D as e}from"./sdk-contracts.js";import{D as t}from"./sdk-batch-runner.js";import{d as n,l as r,u as i,y as a}from"./sdk-device.js";import{ar as o}from"./sdk-batch.js";import{a as s,l as c,n as l}from"./exec.js";import"./command.js";import{t as u}from"./parser.js";import{n as d,t as f}from"./numeric.js";import{C as p,D as ee,g as m,i as te,m as h,o as g,u as _,w as ne,y as v}from"./host-file.js";import{a as y,o as b}from"./tool-provider.js";import{o as re,t as ie}from"./devicectl.js";import{t as x}from"./simctl.js";import{t as ae}from"./physical-device-control.js";import{t as oe}from"./plist.js";import S from"node:path";import{fileURLToPath as C}from"node:url";function w(e,t){for(let n of e){if(t(n))return n;let e=w(n.children,t);if(e)return e}}function T(e,t){let n=[];for(let r of e)t(r)&&n.push(r),n.push(...T(r.children,t));return n}function se(e,t){return e.children.find(e=>e.name===t)?.text??null}function E(e,t){let n=w(e,e=>e.name===`schema`&&e.attributes.name===t);return n?n.children.filter(e=>e.name===`col`).map(e=>se(e,`mnemonic`)??``):[]}function D(e){if(!e||e.children.some(e=>e.name===`sentinel`)||!e.text)return null;let t=Number(e.text);return Number.isFinite(t)?t:null}function O(e,t){return e?e.attributes.ref?t.get(e.attributes.ref)?.numberValue??null:D(e):null}function ce(e){return new Map(T(e,e=>!!e.attributes.id).flatMap(e=>{let t=e.attributes.id;return t?[[t,e]]:[]}))}function k(e,t){if(e)return e.attributes.ref?t.get(e.attributes.ref):e}const A=`xctrace-animation-hitches`;function le(e){let t=ue(e.frameLifetimesXml),n=de(e.displayInfoXml),r=fe(e.hitchesXml).filter(t=>he(t,e.processIds,e.processNames)),i=r.length,a=Math.max(0,Math.round(Date.parse(e.windowEndedAt)-Date.parse(e.windowStartedAt))),s=ge(r,Date.parse(e.windowStartedAt));return{droppedFramePercent:t>0?d(i/t*100):0,droppedFrameCount:i,totalFrameCount:t,sampleWindowMs:a,windowStartedAt:e.windowStartedAt,windowEndedAt:e.windowEndedAt,measuredAt:e.measuredAt,method:A,matchedProcesses:o(r.map(e=>e.processName).filter(e=>typeof e==`string`&&e.length>0)),frameDeadlineMs:n===void 0?void 0:f(1e3/n),refreshRateHz:n,worstWindows:s.length>0?s:void 0}}function ue(e){return ve(e,`hitches-frame-lifetimes`).length}function de(e){if(!e)return;let{rows:t,schema:n}=j(e,`device-display-info`),r=n.indexOf(`max-refresh-rate`);if(r<0)return;let i=new Map;for(let e of t){M(e.children,i);let t=O(e.children[r],i);if(t!==null&&t>0)return t}}function fe(e){let t=u(e),n=pe(t);if(!n)return[];let r=new Map;return T(t,e=>e.name===`row`).map(e=>me(e,n,r)).filter(e=>!!e)}function pe(e){let t=E(e,`hitches`),n={start:t.indexOf(`start`),duration:t.indexOf(`duration`),process:t.indexOf(`process`),isSystem:t.indexOf(`is-system`)};return Object.values(n).every(e=>e>=0)?n:null}function me(e,t,n){if(M(e.children,n),ye(e.children[t.isSystem],n)===!0)return null;let r=O(e.children[t.start],n),i=O(e.children[t.duration],n);if(r===null||i===null)return null;let a=be(e.children[t.process],n);return{startNs:r,durationNs:i,pid:a?.pid,processName:a?.name}}function he(e,t,n){return e.pid!==void 0&&t.includes(e.pid)?!0:e.processName?n.includes(e.processName):!1}function ge(e,t){if(e.length===0)return[];let n=[...e].sort((e,t)=>e.startNs-t.startNs),r=[],i=[];for(let e of n){let t=i.at(-1);if(!t||e.startNs-(t.startNs+t.durationNs)<=5e8){i.push(e);continue}r.push(i),i=[e]}return i.length>0&&r.push(i),r.map(e=>_e(e,t)).sort((e,t)=>t.missedDeadlineFrameCount-e.missedDeadlineFrameCount||t.worstFrameMs-e.worstFrameMs).slice(0,3).sort((e,t)=>e.startOffsetMs-t.startOffsetMs)}function _e(e,t){let n=Math.min(...e.map(e=>e.startNs)),r=Math.max(...e.map(e=>e.startNs+e.durationNs)),i=Math.max(0,Math.round(n/1e6)),a=Math.max(i,Math.round(r/1e6));return{startOffsetMs:i,endOffsetMs:a,startAt:new Date(t+i).toISOString(),endAt:new Date(t+a).toISOString(),missedDeadlineFrameCount:e.length,worstFrameMs:f(Math.max(...e.map(e=>e.durationNs))/1e6)}}function ve(e,t){return j(e,t).rows}function j(e,t){let n=u(e),r=E(n,t);return{rows:r.length===0?[]:T(n,e=>e.name===`row`),schema:r}}function M(e,t){for(let n of e)M(n.children,t),n.attributes.id&&t.set(n.attributes.id,{numberValue:D(n),process:N(n)})}function ye(e,t){let n=O(e,t);return n===null?null:n!==0}function be(e,t){return e?e.attributes.ref?t.get(e.attributes.ref)?.process??null:N(e):null}function N(e){if(!e||e.children.some(e=>e.name===`sentinel`))return null;let t=D(w(e.children,e=>e.name===`pid`)),n=(e.attributes.fmt??``).replace(/\s+\(\d+\)$/,``).trim();return t===null&&n.length===0?null:{pid:t??void 0,name:n.length>0?n:void 0}}const P=`ps-process-snapshot`,F=`xctrace-activity-monitor`,I=`leaks-output-graph`,L=15e3,R=12e4;async function xe(t,n){if(i(t)&&t.kind===`device`)return await Fe(t,n);let r=await G(t,n),a=await q(t,r);if(a.length===0)throw new e(`COMMAND_FAILED`,`No running process found for ${n}`,{appBundleId:n,hint:`Run open <app> for this session again to ensure the Apple app is active, then retry perf.`});let o=new Date().toISOString();return X({residentMemoryKb:a.reduce((e,t)=>e+t.rssKb,0),measuredAt:o,matchedProcesses:[r.executableName],memoryMethod:P})}async function Se(t,n,r){let i=B(t);if(!i.memgraph)return{available:!1,kind:`memgraph`,reason:i.reason,hint:i.hint,support:i};let a=await Ve(t,n,i);if(a.available===!1)return a;let{process:o}=a;await g(S.dirname(r));let s=await Te(r),c;try{c=await Ce(t,r,o.pid)}catch(e){throw await z(r,s),we(t,n,o,r,e)}if(c.exitCode!==0)throw await z(r,s),new e(`COMMAND_FAILED`,`Failed to capture Apple memgraph for ${n}`,l(c,{kind:`memgraph`,appBundleId:n,pid:o.pid,processName:S.basename(J(o.command)),path:r,hint:Y(t,c.stdout,c.stderr)}));let u=await _(r).catch(()=>null);if(!u?.isFile()||u.size<=0)throw await z(r,s),new e(`COMMAND_FAILED`,`Apple memgraph artifact is missing or empty`,{kind:`memgraph`,appBundleId:n,pid:o.pid,path:r,hint:`Retry with a writable --out path. If the file is still empty, run with --debug and inspect leaks output.`});return{available:!0,kind:`memgraph`,path:r,sizeBytes:u.size,measuredAt:new Date().toISOString(),method:I,appBundleId:n,pid:o.pid,processName:S.basename(J(o.command)),support:i}}async function Ce(e,t,r){return n(e)?await y(`leaks`,[`--outputGraph=${t}`,String(r)],{allowFailure:!0,timeoutMs:R}):await b(x(e,[`spawn`,e.id,`leaks`,`--outputGraph=${t}`,String(r)]),{allowFailure:!0,timeoutMs:R})}function we(t,n,r,i,a){if(a instanceof e){let o=a.details??{};return new e(a.code,`Failed to capture Apple memgraph for ${n}`,{...o,kind:`memgraph`,appBundleId:n,pid:r.pid,processName:S.basename(J(r.command)),path:i,hint:Y(t,typeof o.stdout==`string`?o.stdout:``,typeof o.stderr==`string`&&o.stderr.length>0?o.stderr:a.message)},a)}return new e(`COMMAND_FAILED`,`Failed to capture Apple memgraph for ${n}`,{kind:`memgraph`,appBundleId:n,pid:r.pid,processName:S.basename(J(r.command)),path:i,hint:`Retry perf memory snapshot. If it still fails, run with --debug and inspect leaks output.`},a)}async function Te(e){return await _(e).then(e=>e.isFile()).catch(()=>!1)}async function z(e,t){t||await p(e).catch(()=>{})}async function Ee(t,n){if(!i(t)||t.kind!==`device`)throw new e(`COMMAND_FAILED`,`Apple frame-health sampling is currently available only on connected iOS devices.`,{metric:`fps`,platform:a(t),deviceKind:t.kind});let r=await K(t,n),s=await ke(t,n,r);return le({hitchesXml:s.hitchesXml,frameLifetimesXml:s.frameLifetimesXml,displayInfoXml:s.displayInfoXml,processIds:r.map(e=>e.pid),processNames:o(r.map(e=>S.basename(C(e.executable)))),windowStartedAt:s.windowStartedAt,windowEndedAt:s.windowEndedAt,measuredAt:s.windowEndedAt})}function De(e){return i(e)&&e.kind===`device`?{method:A,description:`Rendered-frame hitch health from xctrace Animation Hitches on connected iOS devices. Dropped frames are counted from native hitch rows for the attached app process, with total frames from the same trace frame-lifetime table.`,unit:`percent`,primaryField:`droppedFramePercent`,window:`short 2s xctrace Animation Hitches record of the active app process`,resetsAfterRead:!1}:{method:A,description:`Unavailable on iOS simulators and macOS because local Apple tooling does not expose reliable app frame hitches for these targets.`,unit:`percent`,primaryField:`droppedFramePercent`}}function Oe(e){if(i(e)&&e.kind===`device`)return{method:F,description:`Resident memory snapshot from a short xctrace Activity Monitor sample on the connected iOS device.`,unit:`kB`};let t=n(e)?`host ps for the running macOS app executable resolved from the bundle ID.`:`xcrun simctl spawn ps, with host ps fallback, for the running iOS simulator app executable resolved from the bundle ID.`;return{method:P,description:`Resident memory snapshot from ${t}`,unit:`kB`}}function B(e){return i(e)&&e.kind===`device`?{platform:a(e),deviceKind:e.kind,memgraph:!1,method:I,reason:`Physical iOS device memgraph capture is not exposed through reliable local agent-device tooling.`,hint:`Use perf memory sample for a compact resident-memory reading, or reproduce on an iOS simulator/macOS target for memgraph capture.`}:i(e)&&e.kind===`simulator`?{platform:a(e),deviceKind:e.kind,memgraph:!0,method:I,reason:`iOS simulator processes are host-visible through simctl spawn leaks.`,hint:`Keep the simulator app running in the foreground while the memgraph is captured.`}:n(e)?{platform:a(e),deviceKind:e.kind,memgraph:!0,method:I,reason:`macOS app processes are host-visible to leaks --outputGraph.`,hint:`Grant Terminal/agent process permissions if macOS denies process inspection.`}:{platform:a(e),deviceKind:e.kind,memgraph:!1,method:I,reason:`Apple memgraph capture is available only for iOS simulator and macOS app sessions.`,hint:`Use perf memory sample on supported app sessions, or rerun against iOS simulator/macOS for memgraph capture.`}}async function ke(e,t,n){let r=await h(`agent-device-ios-frame-perf-`),i=S.join(r,`animation-hitches.trace`),a=S.join(r,`hitches.xml`),o=S.join(r,`frame-lifetimes.xml`),s=S.join(r,`display-info.xml`);try{let r=await V({device:e,appBundleId:t,tracePath:i,template:`Animation Hitches`,duration:`2s`,targetPids:n.map(e=>e.pid),validateTraceOutput:!0,failureMessage:`Failed to record iOS frame-health sample for ${t}`});await W(e,t,i,`hitches`,a),await W(e,t,i,`hitches-frame-lifetimes`,o);let c=await Me(e,t,i,`device-display-info`,s);return{windowStartedAt:r.startedAt,windowEndedAt:r.endedAt,hitchesXml:await v(a),frameLifetimesXml:await v(o),displayInfoXml:c?await v(s):void 0}}finally{await p(r).catch(()=>{})}}async function V(t){let{device:n,appBundleId:r,tracePath:i,template:a,duration:o}=t,s=t.allProcesses?[`--all-processes`]:(t.targetPids??[]).flatMap(e=>[`--attach`,String(e)]),c=[`xctrace`,`record`,`--template`,a,`--device`,n.id,...s,`--time-limit`,o,`--output`,i,`--quiet`,`--no-prompt`],u=await Ae(c,t.tracePath);if(u.result.exitCode===0)return t.validateTraceOutput&&await je(t,u.result.stdout,u.result.stderr),{startedAt:u.startedAt,endedAt:u.endedAt,capturedAtMs:u.capturedAtMs};throw new e(`COMMAND_FAILED`,t.failureMessage,l(u.result,{cmd:`xcrun`,args:c,appBundleId:r,deviceId:n.id,hint:Q(u.result.stdout,u.result.stderr)}))}async function Ae(e,t){let n;for(let r=1;r<=3;r+=1){await U(t,r,1500);let i=new Date().toISOString(),a=await b(e,{allowFailure:!0,timeoutMs:6e4});if(n={result:a,startedAt:i,endedAt:new Date().toISOString(),capturedAtMs:Date.now()},a.exitCode===0||!H(a))return n}return n}function H(e){let t=`${e.stdout}\n${e.stderr}`.toLowerCase();return t.includes(`_lockkperf`)||t.includes(`could not lock kperf`)||t.includes(`likely another session just started`)}async function U(e,t,n){t<=1||(await p(e).catch(()=>{}),await new Promise(e=>setTimeout(e,n)))}async function je(t,n,r){let i=await _(t.tracePath).catch(()=>null);if(!(i?.isDirectory()===!0?(await m(t.tracePath).catch(()=>[])).length>0:(i?.size??0)>0))throw new e(`COMMAND_FAILED`,`${t.failureMessage}: xctrace produced no trace data`,{tracePath:t.tracePath,appBundleId:t.appBundleId,deviceId:t.device.id,stdout:n,stderr:r,hint:`Keep the iOS device unlocked and connected by cable, keep the app active, then retry perf.`})}async function W(e,t,n,r,i){let a=[`xctrace`,`export`,`--input`,n,`--xpath`,`/trace-toc/run/data/table[@schema="${r}"]`,`--output`,i];s(await b(a,{allowFailure:!0,timeoutMs:15e3}),`Failed to export iOS device ${r} data`,n=>({cmd:`xcrun`,args:a,appBundleId:t,deviceId:e.id,hint:Q(n.stdout,n.stderr)}))}async function Me(e,t,n,r,i){try{return await W(e,t,n,r,i),!0}catch{return!1}}function Ne(e){let n=[];for(let r of t(e)){let e=r.match(/^(\d+)\s+([0-9]+(?:\.[0-9]+)?)\s+(\d+)\s+(.+)$/);if(!e)continue;let[t,i,a,o]=e.slice(1);if(t===void 0||i===void 0||a===void 0||o===void 0)continue;let s=Number(t),c=Number(i),l=Number(a),u=o.trim();!Number.isFinite(s)||!Number.isFinite(c)||!Number.isFinite(l)||n.push({pid:s,cpuPercent:c,rssKb:l,command:u})}return n}async function Pe(t){let n=u(t),r=E(n,`activity-monitor-process-live`);if(r.length===0)throw new e(`COMMAND_FAILED`,`Failed to parse xctrace activity-monitor-process-live schema`);let i=r.indexOf(`pid`),a=r.indexOf(`process`),o=r.indexOf(`memory-real`);if(i<0||a<0||o<0)throw new e(`COMMAND_FAILED`,`xctrace activity-monitor-process-live export is missing expected columns`);let s=T(n,e=>e.name===`row`),c=[],l=new Map;for(let e of s){let t=e.children;if(t.length===0)continue;for(let e of t){let t=w(e.children,e=>e.name===`pid`&&typeof e.attributes.id==`string`);if(t?.attributes.id){let e=Number(t.text);l.set(t.attributes.id,{numberValue:Number.isFinite(e)?e:null})}e.attributes.id&&l.set(e.attributes.id,{numberValue:D(e),processName:Z(e)})}let n=O(t[i],l),r=We(t[a],l);n===null||!Number.isFinite(n)||!r||c.push({pid:n,processName:r,residentMemoryBytes:O(t[o],l)})}return c}async function G(t,r){let i=n(t)?await Re(r):await ze(t,r),a=n(t)?S.join(i,`Contents`,`Info.plist`):S.join(i,`Info.plist`),o=await oe(a,`CFBundleExecutable`);if(!o)throw new e(`COMMAND_FAILED`,`Failed to resolve executable for ${r}`,{appBundleId:r,appPath:i});return{executableName:o,executablePath:n(t)?S.join(i,`Contents`,`MacOS`,o):S.join(i,o)}}async function Fe(t,n){let r=await K(t,n),i=await Ie(t,n),a=Le(await Pe(i.xml),r,n,t);if(a.residentMemoryBytes===null)throw new e(`COMMAND_FAILED`,`Incomplete Activity Monitor sample for ${n}`,{appBundleId:n,deviceId:t.id,hint:`Keep the app running in the foreground while perf samples the device, then retry.`});return X({residentMemoryKb:a.residentMemoryBytes/1024,measuredAt:new Date(i.capturedAtMs).toISOString(),matchedProcesses:a.matchedProcesses,memoryMethod:F})}async function K(t,n){let{appBundleUrl:r,processes:i}=await ae(t).resolveAppProcesses(t,n),a=C(r);if(i.length===0)throw new e(`COMMAND_FAILED`,`No running process found for ${n}`,{appBundleId:n,deviceId:t.id,appBundlePath:a,hint:`Run open <app> for this session again to ensure the iOS app is active, then retry perf.`});return i}async function Ie(e,t){let n=await h(`agent-device-ios-perf-`),r=S.join(n,`sample.trace`),i=S.join(n,`activity-monitor-process-live.xml`);try{let n=await V({device:e,appBundleId:t,tracePath:r,template:`Activity Monitor`,duration:`1s`,allProcesses:!0,failureMessage:`Failed to record iOS device Activity Monitor sample for ${t}`});return await W(e,t,r,`activity-monitor-process-live`,i),{capturedAtMs:n.capturedAtMs,xml:await v(i)}}finally{await p(n).catch(()=>{})}}function Le(t,n,r,i){let a=new Set(n.map(e=>e.pid)),s=new Set(n.map(e=>S.basename(C(e.executable)))),c=t.filter(e=>a.has(e.pid)||s.has(e.processName));if(c.length===0)throw new e(`COMMAND_FAILED`,`No Activity Monitor sample found for ${r}`,{appBundleId:r,deviceId:i.id,hint:`Keep the app running in the foreground while perf samples the device, then retry.`});let l=new Map;for(let e of c){let t=l.get(e.pid);if(!t){l.set(e.pid,e);continue}l.set(e.pid,{pid:e.pid,processName:e.processName||t.processName,residentMemoryBytes:Ge(t.residentMemoryBytes,e.residentMemoryBytes)})}let u=[...l.values()],d=u.map(e=>e.residentMemoryBytes).filter(e=>e!==null);return{residentMemoryBytes:d.length>0?d.reduce((e,t)=>e+t,0):null,matchedProcesses:o(u.map(e=>e.processName))}}async function Re(t){let n=`kMDItemCFBundleIdentifier == "${t.replaceAll(`"`,String.raw`\"`)}"`,r=s(await y(`mdfind`,[n],{allowFailure:!0,timeoutMs:L}),`Failed to resolve macOS app bundle for ${t}`,{appBundleId:t}).stdout.split(`
|
|
2
|
+
`).map(e=>e.trim()).find(e=>e.endsWith(`.app`));if(!r)throw new e(`APP_NOT_INSTALLED`,`No macOS app found for ${t}`,{appBundleId:t});return r}async function ze(t,n){let r=x(t,[`get_app_container`,t.id,n,`app`]),i=s(await b(r,{allowFailure:!0,timeoutMs:L}),`Failed to resolve iOS simulator app container for ${n}`,{appBundleId:n,hint:`Ensure the iOS simulator app is installed and booted, then retry perf.`}).stdout.trim();if(i.length===0)throw new e(`APP_NOT_INSTALLED`,`No iOS simulator app container found for ${n}`,{appBundleId:n});return i}async function q(e,t){let r=n(e)?[`-axo`,`pid=,%cpu=,rss=,command=`]:x(e,[`spawn`,e.id,`ps`,`-axo`,`pid=,%cpu=,rss=,command=`]),i=n(e)?await y(`ps`,r,{timeoutMs:L}):await Ue(r),{matchesAppleExecutableProcess:a}=await import(`./perf-process-identity.js`);return Ne(i.stdout).filter(e=>a(e.command,t))}function J(e){let[t=``]=e.trim().split(/\s+/,1);return t}async function Be(t,n,r){let i=(await q(t,r)).sort((e,t)=>t.rssKb-e.rssKb)[0];if(i)return i;throw new e(`COMMAND_FAILED`,`No running process found for ${n}`,{kind:`memgraph`,appBundleId:n,hint:`Run open <app> for this session again to ensure the Apple app is active, then retry perf memory snapshot.`})}async function Ve(e,t,n){try{return{available:!0,process:await Be(e,t,await G(e,t))}}catch(t){if(He(e,t))return{available:!1,kind:`memgraph`,reason:`iOS simulator memgraph capture needs process tools inside simctl spawn, but this simulator runtime did not provide ps.`,hint:`Use perf memory sample when available, or retry memgraph on a simulator runtime that includes process tools such as ps and leaks.`,support:{...n,memgraph:!1}};throw t}}function He(t,n){if(!i(t)||t.kind!==`simulator`||!(n instanceof e))return!1;let r=n.details??{},a=Array.isArray(r.args)?r.args.join(` `):``,o=typeof r.stderr==`string`?r.stderr:``,s=`${n.message}\n${o}`.toLowerCase();return a.includes(`simctl spawn`)&&a.includes(` ps `)&&s.includes(`no such file`)}function Y(e,t,r){let i=`${t}\n${r}`.toLowerCase();return i.includes(`timed out`)||i.includes(`timeout`)?`Apple memgraph capture can take longer than metric sampling. Keep the app running and retry; if it times out again, collect a smaller reproduction before capturing leaks --outputGraph.`:i.includes(`not found`)||i.includes(`no such file`)?`Install Xcode command line tools and ensure leaks is available, then retry.`:i.includes(`permission`)||i.includes(`denied`)||i.includes(`not authorized`)?n(e)?`Grant the agent terminal process permission to inspect this macOS app, then retry.`:`Keep the simulator booted and app running; if inspection is denied, retry with a debug simulator build.`:`Keep the app process running and retry perf memory snapshot with --debug if the failure persists.`}async function Ue(e){let t=await b(e,{allowFailure:!0,timeoutMs:L});return t.exitCode===0?t:await y(`ps`,[`-axo`,`pid=,%cpu=,rss=,command=`],{timeoutMs:L})}function X(e){return{residentMemoryKb:Math.round(e.residentMemoryKb),measuredAt:e.measuredAt,method:e.memoryMethod,matchedProcesses:e.matchedProcesses}}function Z(e){let t=e?.attributes.fmt?.trim()??``;return t?t.replace(/\s+\(\d+\)$/,``).trim():null}function We(e,t){return e?e.attributes.ref?t.get(e.attributes.ref)?.processName??null:Z(e):null}function Q(e,t){let n=re(e,t);if(n)return n;let r=`${e}\n${t}`.toLowerCase();return r.includes(`no device matched`)||r.includes(`failed to find device`)?ie:r.includes(`timed out`)?`Keep the iOS device unlocked and connected by cable, keep the app active, then retry perf.`:`Ensure the iOS device is unlocked, trusted, visible to xctrace, and the target app stays active while perf samples it.`}function Ge(e,t){return e===null?t:t===null?e:Math.max(e,t)}function Ke(e,t=10){let n=u(e),r=ce(n),i=new Map,a=0,o=0;for(let e of T(n,e=>e.name===`row`)){let t=qe(e,r),n=Je(e,r);if(t===void 0||!n)continue;let s=n.attributes.name?.trim()||`<unknown>`,c=Ye(n,r),l=`${c??``}\u0000${s}`,u=i.get(l);i.set(l,{symbol:s,binary:c,weightNs:(u?.weightNs??0)+t}),a+=1,o+=t}let s=Math.max(0,Math.floor(t)),c=[...i.values()].sort((e,t)=>t.weightNs-e.weightNs||e.symbol.localeCompare(t.symbol)).slice(0,s).map(({symbol:e,binary:t,weightNs:n})=>({symbol:e,binary:t,selfSampleMs:$(n),selfSamplePercent:o>0?d(n/o*100):0}));return{sampleCount:a,totalSampleWeightMs:$(o),topFunctions:c}}function qe(e,t){let n=k(e.children.find(e=>e.name===`weight`),t);if(!n?.text)return;let r=Number(n.text);return Number.isFinite(r)&&r>0?r:void 0}function Je(e,t){return k(k(e.children.find(e=>e.name===`backtrace`),t)?.children.find(e=>e.name===`frame`),t)}function Ye(e,t){return k(e.children.find(e=>e.name===`binary`),t)?.attributes.name?.trim()||void 0}function $(e){return Math.round(e/1e6*1e3)/1e3}const Xe=15e3;async function Ze(e){let t=await nt(e.device,e.appBundleId);await g(S.dirname(e.outPath));let n=rt({device:e.device,template:e.template,targetPids:t.pids,outPath:e.outPath}),r=new Date().toISOString(),i=await it(n,e.outPath,{device:e.device,appBundleId:e.appBundleId,failureMessage:`Failed to start Apple xctrace ${e.mode} capture for ${e.appBundleId}`});return{kind:`xctrace`,mode:e.mode,template:e.template,outPath:e.outPath,appBundleId:e.appBundleId,deviceId:e.device.id,platform:a(e.device),targetPids:t.pids,targetProcesses:t.processNames,startedAt:r,child:i.child,wait:i.wait}}async function Qe(e,t=e.outPath){t!==e.outPath&&await g(S.dirname(t));let n=s(await ot(e,{failOnForcedKill:!0}),`Failed to stop Apple xctrace ${e.mode} capture`,t=>({tracePath:e.outPath,captureCleanedUp:!0,hint:Q(t.stdout,t.stderr)}));return t!==e.outPath&&await ne(e.outPath,t).catch(async()=>{await te(e.outPath,t),await p(e.outPath)}),await ct(t,{appBundleId:e.appBundleId,deviceId:e.deviceId,stdout:n.stdout,stderr:n.stderr}),{kind:`xctrace`,mode:e.mode,template:e.template,outPath:t,appBundleId:e.appBundleId,deviceId:e.deviceId,platform:e.platform,targetPids:e.targetPids,targetProcesses:e.targetProcesses,startedAt:e.startedAt,endedAt:new Date().toISOString()}}async function $e(e){return await ot(e,{failOnForcedKill:!1})}async function et(t){let n=await h(`agent-device-xctrace-report-`),r=S.join(n,`trace-toc.xml`),i=S.join(n,`time-profile.xml`);try{let n=[`xctrace`,`export`,`--input`,t.tracePath,`--toc`,`--output`,r];s(await b(n,{allowFailure:!0,timeoutMs:Xe}),`Failed to export Apple xctrace report metadata`,e=>({cmd:`xcrun`,args:n,tracePath:t.tracePath,hint:Q(e.stdout,e.stderr)}));let a=await v(r),o=await tt(t.tracePath,i),c=lt({...t,tocXml:a,timeProfileXml:o});if(c.summary.sampleCount===0)throw new e(`COMMAND_FAILED`,`Apple xctrace CPU report contained no samples`,{tracePath:t.tracePath,tableSchemas:c.summary.tableSchemas,hint:`Keep the app active while recording, then retry. Open the raw trace in Instruments if it still contains no Time Profiler samples.`});return await g(S.dirname(t.outPath)),await ee(t.outPath,`${JSON.stringify(c,null,2)}\n`),c}finally{await p(n).catch(()=>{})}}async function tt(e,t){let n=[`xctrace`,`export`,`--input`,e,`--xpath`,`/trace-toc/run/data/table[@schema="time-profile"]`,`--output`,t];return s(await b(n,{allowFailure:!0,timeoutMs:Xe}),`Failed to export Apple xctrace Time Profiler samples`,t=>({cmd:`xcrun`,args:n,tracePath:e,hint:Q(t.stdout,t.stderr)})),await v(t)}async function nt(t,n){if(!r(t.platform))throw new e(`UNSUPPORTED_OPERATION`,`Apple xctrace perf is not supported on Android.`,{platform:t.platform,hint:`Android native profiling belongs to the Android perf rollout and is not implemented under Apple xctrace.`});if(i(t)&&t.kind===`device`){let e=await K(t,n);return{pids:e.map(e=>e.pid),processNames:o(e.map(e=>S.basename(C(e.executable))))}}let a=await G(t,n),s=await q(t,a);if(s.length===0)throw new e(`COMMAND_FAILED`,`No running process found for ${n}`,{appBundleId:n,deviceId:t.id,hint:`Run open <app> for this session again to ensure the Apple app is active, then retry perf.`});return{pids:s.map(e=>e.pid),processNames:[a.executableName]}}function rt(e){return[`xctrace`,`record`,`--template`,e.template,...i(e.device)?[`--device`,e.device.id]:[],...e.targetPids.flatMap(e=>[`--attach`,String(e)]),`--output`,e.outPath,`--quiet`,`--no-prompt`]}async function it(t,n,r){let i;for(let e=1;e<=3;e+=1){await U(n,e,1500);let r=c(`xcrun`,t,{allowFailure:!0}),a=await at(r.wait);if(!a)return r;if(i=a,!H(a))break}let a=i??{stdout:``,stderr:``,exitCode:1};throw new e(`COMMAND_FAILED`,r.failureMessage,l(a,{cmd:`xcrun`,args:t,appBundleId:r.appBundleId,deviceId:r.device.id,hint:Q(a.stdout,a.stderr)}))}async function at(e){return await Promise.race([e,new Promise(e=>setTimeout(e,500))])}async function ot(t,n){t.child.kill(`SIGINT`);let r=await st(t.wait,45e3);if(r)return r;t.child.kill(`SIGKILL`);let i=await st(t.wait,5e3);if(i&&!n.failOnForcedKill)return i;throw i?new e(`COMMAND_FAILED`,`Timed out waiting for Apple xctrace capture to stop`,{exitCode:i.exitCode,stdout:i.stdout,stderr:i.stderr,tracePath:t.outPath,captureCleanedUp:!0,forcedKill:!0,hint:`xctrace did not finish after SIGINT, so it was force-killed. Retry the perf command after confirming no other xctrace session is active.`}):new e(`COMMAND_FAILED`,`Timed out waiting for Apple xctrace capture to stop after SIGKILL`,{tracePath:t.outPath,captureCleanedUp:!1,forcedKill:!0,hint:`xctrace did not exit after SIGKILL. Inspect running xctrace processes before retrying.`})}async function st(e,t){return await Promise.race([e,new Promise(e=>setTimeout(e,t))])}async function ct(t,n){let r=await _(t).catch(()=>null);if(!(r?.isDirectory()===!0?(await m(t).catch(()=>[])).length>0:(r?.size??0)>0))throw new e(`COMMAND_FAILED`,`xctrace produced no trace data`,{tracePath:t,appBundleId:n.appBundleId,deviceId:n.deviceId,stdout:n.stdout,stderr:n.stderr,hint:`Keep the Apple device unlocked and connected, keep the app active, then retry perf.`})}function lt(e){let t=u(e.tocXml),n=T(t,e=>e.name===`run`),r=o(T(t,e=>e.name===`table`).map(e=>e.attributes.schema).filter(e=>typeof e==`string`&&e.length>0)).sort(),i=Ke(e.timeProfileXml);return{kind:`xctrace`,mode:`cpu-profile`,template:e.template,tracePath:e.tracePath,reportPath:e.outPath,appBundleId:e.appBundleId,generatedAt:new Date().toISOString(),summary:{runCount:n.length,tableSchemas:r,...i}}}export{De as buildAppleFrameSamplingMetadata,Oe as buildAppleMemorySamplingMetadata,B as buildAppleMemorySnapshotSupport,Se as captureAppleMemorySnapshot,$e as cleanupAppleXctracePerfCapture,H as isRetryableIosDeviceTraceRecordFailure,q as readAppleProcessSamples,G as resolveAppleExecutable,Q as resolveIosDevicePerfHint,K as resolveIosDevicePerfTarget,Ee as sampleAppleFramePerf,xe as sampleAppleMemoryPerf,Ze as startAppleXctracePerfCapture,Qe as stopAppleXctracePerfCapture,et as writeAppleXctracePerfReport};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{D as e,L as t}from"./sdk-contracts.js";async function n(e){try{return{available:!0,...await e}}catch(e){let n=t(e);return{available:!1,reason:n.message,error:n}}}function r(e,t){return{available:!1,reason:`No ${e} app ${t} is associated with this session. Run open <app> first.`}}function i(e,t,n,r){return{artifact:{available:!1,kind:t,reason:`${e} perf memory snapshot does not support ${t}.`,hint:r,support:n},support:n}}function a(){return new e(`INVALID_ARGS`,`perf memory snapshot requires an active app session`,{hint:`Run open <app> first so perf memory snapshot can resolve the app process.`})}function o(t){return Object.freeze({perfNativeCaptureStart:t.start,perfNativeCaptureReattach:t.reattach,perfNativeCaptureCleanup:t.cleanup,perfProfileReport:async n=>{if(n.kind!==t.expectedProfileKind)throw new e(`INVALID_ARGS`,`${t.platform} native perf requires --kind ${t.expectedProfileKind}, not ${n.kind}`);return await t.writeProfileReport(n)}})}export{i as a,n as i,r as n,a as r,o as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{C as e,N as t}from"./sdk-contracts.js";import{S as n,c as r,w as i}from"./sdk-device.js";import{At as a,Dt as o,Et as s,Tt as c,kt as l}from"./sdk-batch.js";import{m as u}from"./observability.js";import{r as d}from"./diagnostics.js";import{D as ee,a as f,i as p}from"./owner-identity.js";import{n as te,t as m}from"./file.js";import"./diagnostics2.js";import"./process.js";import{c as h,i as ne,l as g,r as _,s as v,t as y,u as b}from"./device-claim-inspection.js";import{l as x,u as S}from"./screen-recording-resource-recovery.js";import C from"node:path";import w from"node:fs";import re from"node:crypto";async function T(e){let t=await e.observeDeviceBoot?.observeBootTimeMs(e.device);if(t?.observed!==!0||t.bootedAtMs<=e.claim.updatedAtMs)return;let{session:n,workspace:r,stateDir:i}=e.claim;return{session:n,workspace:r,stateDir:i,bootedAtMs:t.bootedAtMs}}function E(e){d({level:`info`,phase:`device_claim_reboot_released`,data:{deviceKey:e.deviceKey,ownerSession:e.claim.session,ownerStateDir:e.claim.stateDir,ownerWorkspace:e.claim.workspace,claimUpdatedAtMs:e.claim.updatedAtMs,deviceBootedAtMs:e.bootedAtMs}})}function D(e){let t=g(e.deviceKey);w.mkdirSync(C.dirname(t),{recursive:!0,mode:448}),ee({destination:t,contents:`${JSON.stringify(e)}\n`,mode:384})}async function O(e,t){let n=f();return await te({acquire:()=>m({lockDirPath:`${g(e)}.lock`,owner:{pid:n.pid,startTime:n.startTime,acquiredAtMs:Date.now()},timeoutMs:3e4,description:`device claim for ${e}`}),task:t})}async function ie(e){let t=_(g(e.deviceKey));return t?t.claim&&M(t.claim,e.stateDir,e.owner)?(I(e.deviceKey,t.claim),{status:`available`}):t.claim&&N(t.claim,e,e.owner)?{status:`held`,ownership:ae(t.claim)}:await oe(t,e):{status:`available`}}function ae(e){if(e.updatedAtMs>=Date.now())return v(e);let t={...e,updatedAtMs:Date.now()};return D(t),v(t)}async function oe(e,t){let n=e.claim;if(!n)return P(t.deviceKey,e),{status:`conflict`,conflict:e};let r=await se({classification:e.classification,claim:n,device:t.device,observeDeviceBoot:t.observeDeviceBoot});if(!r.settles)return P(t.deviceKey,e),{status:`conflict`,conflict:e};let i=await k(n,t.reconcileOrphanedDeviceClaim);return i.status===`retained`?(P(t.deviceKey,e,i.reason),{status:`conflict`,conflict:e}):r.tookOver?(E({deviceKey:t.deviceKey,claim:n,bootedAtMs:r.tookOver.bootedAtMs}),{status:`available`,tookOver:r.tookOver}):{status:`available`}}async function se(e){if(y(e.classification))return{settles:!0};let t=await T(e);return t?{settles:!0,tookOver:t}:{settles:!1}}async function k(e,t){let n=await t(e);if(n.status===`retained`)return n;try{w.unlinkSync(g(e.deviceKey))}catch(e){if(e.code!==`ENOENT`)throw e}return{status:`reconciled`}}function A(e,t,n){return e.stateDir===t&&p({pid:e.ownerPid,startTime:e.ownerStartTime},n)}function j(e){return e.abandonedAtMs!==void 0}function M(e,t,n){return j(e)&&A(e,t,n)}function N(e,t,n){return e.session===t.session&&e.workspace===t.workspace&&A(e,t.stateDir,n)}function P(e,t,n){d({level:`warn`,phase:`device_claim_conflict`,data:{deviceKey:e,classification:t.classification,...F(t),...n?{reconciliationReason:n}:{}}})}function F(e){return e.allocatorClaim?{ownerStateDir:e.allocatorClaim.stateDir,allocatorInstanceId:e.allocatorClaim.allocator.instanceId,identityIncarnationId:e.allocatorClaim.allocator.identityIncarnationId}:{ownerSession:e.claim?.session,ownerStateDir:e.claim?.stateDir}}function I(e,t){d({level:`info`,phase:`device_claim_abandoned_superseded`,data:{deviceKey:e,abandonedSession:t.session,abandonedAtMs:t.abandonedAtMs}})}function L(e){return`transient:${e}`}async function R(e){let t=H(e.device),n=h(t);return await O(n,async()=>await B({...e,deviceKey:n,identity:t}))}async function z(e){let t=H(e.device),n=h(t);return await O(n,async()=>{let r=_(g(n));return r?.claim&&!j(r.claim)&&A(r.claim,e.stateDir,f())?{status:`covered-by-owned-claim`}:await B({device:e.device,deviceKey:n,identity:t,session:L(e.command),workspace:e.workspace,stateDir:e.stateDir,reconcileOrphanedDeviceClaim:e.reconcileOrphanedDeviceClaim})})}async function B(e){let{deviceKey:t,identity:n}=e,r=f(),i=await ie({...e,owner:r});if(i.status===`conflict`)return i;if(i.status===`held`)return{status:`acquired`,ownership:i.ownership};let a=Date.now(),o={schemaVersion:2,deviceKey:t,device:{...n,name:e.device.name},session:e.session,workspace:e.workspace,stateDir:e.stateDir,ownerPid:r.pid,ownerStartTime:r.startTime,ownerToken:re.randomUUID(),createdAtMs:a,updatedAtMs:a};return D(o),{status:`acquired`,ownership:v(o),...i.tookOver?{tookOver:i.tookOver}:{}}}function V(e){let t=h(H(e)),n=_(g(t))?.claim;return n!==void 0&&n.deviceKey===t&&!j(n)&&p({pid:n.ownerPid,startTime:n.ownerStartTime},f())}function H(e){return i({...e,...r(e.platform)?{appleOs:n(e)}:{}})}async function U(e){let t=[];for(let n of ne(e.selectors))t.push(await W(n,e.reconcile));return t}async function W(e,t){let n=e.claim,r={fileName:e.fileName,classification:e.classification,...e.deviceKey?{deviceKey:e.deviceKey}:{},...n?{device:n.device,session:n.session,workspace:n.workspace,stateDir:n.stateDir}:{},...e.allocatorClaim?{device:e.allocatorClaim.device,stateDir:e.allocatorClaim.stateDir,allocator:e.allocatorClaim.allocator}:{}};if(!n||!y(e.classification))return{...r,status:`refused`,reason:K(e.classification)};if(g(n.deviceKey)!==C.join(b(),e.fileName))return{...r,status:`refused`,reason:`claim-file-name-mismatch`};let{deviceKey:i,ownerToken:a}=n;return await O(i,async()=>{let e=_(g(i));if(!e?.claim||e.claim.ownerToken!==a||!y(e.classification))return{...r,status:`changed`,reason:`claim-changed-during-release`};let o=await k(e.claim,t);return o.status===`retained`?{...r,status:`retained`,reason:o.reason}:(d({level:`info`,phase:`device_claim_stale_released`,data:{deviceKey:i,ownerSession:n.session,ownerStateDir:n.stateDir}}),{...r,status:`released`})})}const G=Object.freeze({live:`live-owner`,"owner-process-reused":`owner-pid-reused`,"owner-state-dir-gone":`owner-process-still-running`,unknown:`owner-liveness-unknown`,inconsistent:`claim-record-inconsistent`,"allocator-inconsistent":`allocator-claim-record-inconsistent`,"allocator-held":`allocator-held-owner`,"owner-process-dead":`claim-record-unreadable`,"owner-daemon-superseded":`claim-record-unreadable`});function K(e){return G[e]}async function ce(e){return e?await q(e,(e,t)=>{try{w.unlinkSync(t)}catch(e){if(e.code!==`ENOENT`)throw e;return`absent`}return`deleted`},e=>e?`ownership-changed`:`absent`):`absent`}async function le(e){return e?await q(e,e=>{let t=Date.now();return D({...e,abandonedAtMs:t,updatedAtMs:t}),`abandoned`},e=>e?`ownership-changed`:`absent`):`absent`}async function ue(e){return e?await q(e,e=>(D({...e,updatedAtMs:Date.now()}),{status:`renewed`}),e=>({status:`lost`,conflict:e})):{status:`lost`,conflict:void 0}}async function q(e,t,n){return await O(e.deviceKey,async()=>{let r=g(e.deviceKey),i=_(r);if(!i)return n(void 0);let a=i.claim;return!a||!de(a,e)?n(i):t(a,r)})}function de(e,t){return e.ownerToken===t.ownerToken&&p({pid:e.ownerPid,startTime:e.ownerStartTime},{pid:t.ownerPid,startTime:t.ownerStartTime})}async function fe(e,t){let n=b(),r;try{r=w.readdirSync(n,{withFileTypes:!0})}catch{return{examined:0,reconciled:0,retained:0,changed:0}}let i=0,a=0,o=0,s=0;for(let c of r){if(!c.isFile()||!c.name.endsWith(`.json`))continue;let r=C.join(n,c.name),l=_(r);if(!l?.claim||!J(l.classification,l.claim.stateDir,t))continue;i+=1;let{deviceKey:u,ownerToken:d}=l.claim;if(g(u)!==r){o+=1;continue}await O(u,async()=>{let n=_(r);if(!n?.claim||!J(n.classification,n.claim.stateDir,t)||n.claim.ownerToken!==d){s+=1;return}if((await k(n.claim,e)).status===`retained`){o+=1;return}a+=1})}return{examined:i,reconciled:a,retained:o,changed:s}}function J(e,t,n){return y(e)?e!==`owner-daemon-superseded`||C.resolve(t)===C.resolve(n):!1}const Y=S({resourceKind:`app-log`,fileName:`app-log.resource.json`,displayName:`App-log`}),X=x({resourceKind:`app-log`,displayName:`app-log`,store:Y,sessionSlot:{read:e=>e.appLog,replace:(e,t)=>({...e,appLog:t,appLogFailure:void 0})},completionMetadata:e=>({backend:e.backend,outputPath:e.outputPath,completedAt:e.completedAt}),failedFinishPolicy:`dispose-on-failed-finish`,messages:{noActive:`no app log stream active`,cleanupPendingHint:`Keep app-log.resource.json and retry cleanup through its exact runtime owner.`}});function pe(e){if(e.appLog){let t=e.appLog.handle.inspect();return{active:t.state===`active`||t.state===`recovering`,...t}}return e.appLogFailure?{active:!1,state:`failed`,backend:e.appLogFailure.backend,failureCode:e.appLogFailure.code,failureMessage:e.appLogFailure.message,hint:e.appLogFailure.hint}:{active:!1,state:`inactive`}}function me(e){return X.adoptStarted(e)}function he(e){return X.finishLive(e)}function ge(e){return X.forceCleanupLive(e)}function _e(e){let n=t(e.error);return e.sessionStore.set(e.sessionName,{...e.session,appLog:void 0,appLogFailure:{backend:e.backend,code:n.code,message:n.message,hint:n.hint}}),n}function ve(e){e.sessionStore.set(e.sessionName,{...e.session,appLogFailure:void 0})}const ye=S({resourceKind:`audio-probe`,fileName:`audio-probe.resource.json`,displayName:`Audio probe`}),Z=x({resourceKind:`audio-probe`,displayName:`audio probe`,store:ye,sessionSlot:{read:e=>e.audioProbe,replace:(e,t)=>({...e,audioProbe:t})},completionMetadata:e=>({backend:e.backend??`unknown`,source:e.source,durationMs:e.durationMs,elapsedMs:e.elapsedMs,bucketMs:e.bucketMs,sampleCount:e.sampleCount,heard:e.heard}),failedFinishPolicy:`dispose-on-failed-finish`,messages:{noActive:`no active audio probe`,cleanupPendingHint:`Keep audio-probe.resource.json and retry stop through its exact runtime owner.`}});function be(e){return Z.adoptStarted(e)}function xe(e){return Z.finishLive(e)}const Q=S({resourceKind:`perf-capture`,fileName:`perf-capture.resource.json`,displayName:`Perf capture`}),$=x({resourceKind:`perf-capture`,displayName:`perf capture`,store:Q,sessionSlot:{read:e=>e.perfCapture,replace:(e,t)=>({...e,perfCapture:t})},completionMetadata:e=>({kind:typeof e.kind==`string`?e.kind:`unknown`,mode:typeof e.mode==`string`?e.mode:`unknown`,...typeof e.outPath==`string`?{outPath:e.outPath}:{}}),failedFinishPolicy:`preserve-retry-material`,messages:{noActive:`no active native perf capture`,cleanupPendingHint:`Keep perf-capture.resource.json and retry stop through its exact runtime owner.`}});function Se(e){return $.adoptStarted(e)}function Ce(e){return $.finishLive(e)}function we(e){if(e.area===`frames`)return Object.freeze({kind:`frames`,request:e,use:c});if(e.area===`memory`)return e.action===`snapshot`?Object.freeze({kind:`memory-snapshot`,request:e,use:o}):Object.freeze({kind:`memory-sample`,request:e,use:s});if(e.area===`trace`)return e.action===`start`?Object.freeze({kind:`capture-start`,request:e,use:l}):Object.freeze({kind:`capture-stop`,request:e});switch(e.action){case`start`:return Object.freeze({kind:`capture-start`,request:e,use:l});case`stop`:return Object.freeze({kind:`capture-stop`,request:e});case`report`:return Object.freeze({kind:`profile-report`,request:e,use:a})}}function Te(t){let n=t.positionals??[],r=n[0]?.toLowerCase();if(r===`frames`){let i=n[1]?.toLowerCase();if(i!==void 0&&i!==`sample`||n.length>2||t.kind!==void 0)throw new e(`INVALID_ARGS`,`perf action must be frames, memory sample|snapshot, cpu profile start|stop|report, or trace start|stop`);return Object.freeze({area:r,action:`sample`})}if(r===`memory`)return Ee(n,t);if(r===`cpu`)return De(n,t.outPath);if(r===`trace`)return Oe(n,t.outPath);throw new e(`INVALID_ARGS`,`perf requires frames, memory, cpu, or trace`)}function Ee(t,n){let r=(t[1]??`sample`).toLowerCase();if(r!==`sample`&&r!==`snapshot`)throw new e(`INVALID_ARGS`,`perf memory requires sample or snapshot`);if(n.kind!==void 0&&r!==`snapshot`)throw new e(`INVALID_ARGS`,`--kind is only supported with perf memory snapshot`);if(r===`sample`&&t.length>2)throw new e(`INVALID_ARGS`,`perf memory sample does not accept additional positionals`);if(r===`snapshot`&&t.length>3)throw new e(`INVALID_ARGS`,`perf memory snapshot accepts at most one positional kind`);let i=n.kind??t[2];if(i!==void 0&&!u(i))throw new e(`INVALID_ARGS`,`perf memory snapshot --kind must be android-hprof or memgraph`);return Object.freeze({area:`memory`,action:r,...i===void 0?{}:{kind:i},...n.outPath===void 0?{}:{outPath:n.outPath}})}function De(t,n){if(t[1]?.toLowerCase()!==`profile`)throw new e(`INVALID_ARGS`,`perf cpu requires profile`);let r=t[2]?.toLowerCase();if(r!==`start`&&r!==`stop`&&r!==`report`)throw new e(`INVALID_ARGS`,`perf cpu profile action must be start, stop, or report`);let i=t[3]?.toLowerCase();if(i!==`xctrace`&&i!==`simpleperf`)throw new e(`INVALID_ARGS`,`perf cpu profile requires --kind xctrace or simpleperf`);let a=n??t[5];return Object.freeze({area:`cpu`,subject:`profile`,action:r,kind:i,...t[4]?{template:t[4]}:{},...a?{outPath:a}:{},...t[6]?{tracePath:t[6]}:{}})}function Oe(t,n){let r=t[1]?.toLowerCase();if(r!==`start`&&r!==`stop`)throw new e(`INVALID_ARGS`,`perf trace action must be start or stop`);let i=t[2]?.toLowerCase();if(i!==`xctrace`&&i!==`perfetto`)throw new e(`INVALID_ARGS`,`perf trace requires --kind xctrace or perfetto`);let a=n??t[4];return Object.freeze({area:`trace`,action:r,kind:i,...t[3]?{template:t[3]}:{},...a?{outPath:a}:{}})}export{fe as C,V as S,ue as T,le as _,$ as a,ce as b,xe as c,ve as d,he as f,Y as g,_e as h,Ce as i,me as l,pe as m,we as n,be as o,ge as p,Se as r,Z as s,Te as t,X as u,R as v,U as w,H as x,z as y};
|
|
1
|
+
import{D as e,L as t}from"./sdk-contracts.js";import{C as n,T as r,l as i}from"./sdk-device.js";import{Dt as a,Mt as o,Ot as s,jt as c,kt as l}from"./sdk-batch.js";import{m as u}from"./observability.js";import{r as d}from"./diagnostics.js";import{D as ee,a as f,i as p}from"./owner-identity.js";import{n as te,t as m}from"./file.js";import"./diagnostics2.js";import"./process.js";import{c as h,i as ne,l as g,r as _,s as v,t as y,u as b}from"./device-claim-inspection.js";import{l as x,u as S}from"./screen-recording-resource-recovery.js";import C from"node:path";import w from"node:fs";import re from"node:crypto";async function T(e){let t=await e.observeDeviceBoot?.observeBootTimeMs(e.device);if(t?.observed!==!0||t.bootedAtMs<=e.claim.updatedAtMs)return;let{session:n,workspace:r,stateDir:i}=e.claim;return{session:n,workspace:r,stateDir:i,bootedAtMs:t.bootedAtMs}}function E(e){d({level:`info`,phase:`device_claim_reboot_released`,data:{deviceKey:e.deviceKey,ownerSession:e.claim.session,ownerStateDir:e.claim.stateDir,ownerWorkspace:e.claim.workspace,claimUpdatedAtMs:e.claim.updatedAtMs,deviceBootedAtMs:e.bootedAtMs}})}function D(e){let t=g(e.deviceKey);w.mkdirSync(C.dirname(t),{recursive:!0,mode:448}),ee({destination:t,contents:`${JSON.stringify(e)}\n`,mode:384})}async function O(e,t){let n=f();return await te({acquire:()=>m({lockDirPath:`${g(e)}.lock`,owner:{pid:n.pid,startTime:n.startTime,acquiredAtMs:Date.now()},timeoutMs:3e4,description:`device claim for ${e}`}),task:t})}async function ie(e){let t=_(g(e.deviceKey));return t?t.claim&&M(t.claim,e.stateDir,e.owner)?(I(e.deviceKey,t.claim),{status:`available`}):t.claim&&N(t.claim,e,e.owner)?{status:`held`,ownership:ae(t.claim)}:await oe(t,e):{status:`available`}}function ae(e){if(e.updatedAtMs>=Date.now())return v(e);let t={...e,updatedAtMs:Date.now()};return D(t),v(t)}async function oe(e,t){let n=e.claim;if(!n)return P(t.deviceKey,e),{status:`conflict`,conflict:e};let r=await se({classification:e.classification,claim:n,device:t.device,observeDeviceBoot:t.observeDeviceBoot});if(!r.settles)return P(t.deviceKey,e),{status:`conflict`,conflict:e};let i=await k(n,t.reconcileOrphanedDeviceClaim);return i.status===`retained`?(P(t.deviceKey,e,i.reason),{status:`conflict`,conflict:e}):r.tookOver?(E({deviceKey:t.deviceKey,claim:n,bootedAtMs:r.tookOver.bootedAtMs}),{status:`available`,tookOver:r.tookOver}):{status:`available`}}async function se(e){if(y(e.classification))return{settles:!0};let t=await T(e);return t?{settles:!0,tookOver:t}:{settles:!1}}async function k(e,t){let n=await t(e);if(n.status===`retained`)return n;try{w.unlinkSync(g(e.deviceKey))}catch(e){if(e.code!==`ENOENT`)throw e}return{status:`reconciled`}}function A(e,t,n){return e.stateDir===t&&p({pid:e.ownerPid,startTime:e.ownerStartTime},n)}function j(e){return e.abandonedAtMs!==void 0}function M(e,t,n){return j(e)&&A(e,t,n)}function N(e,t,n){return e.session===t.session&&e.workspace===t.workspace&&A(e,t.stateDir,n)}function P(e,t,n){d({level:`warn`,phase:`device_claim_conflict`,data:{deviceKey:e,classification:t.classification,...F(t),...n?{reconciliationReason:n}:{}}})}function F(e){return e.allocatorClaim?{ownerStateDir:e.allocatorClaim.stateDir,allocatorInstanceId:e.allocatorClaim.allocator.instanceId,identityIncarnationId:e.allocatorClaim.allocator.identityIncarnationId}:{ownerSession:e.claim?.session,ownerStateDir:e.claim?.stateDir}}function I(e,t){d({level:`info`,phase:`device_claim_abandoned_superseded`,data:{deviceKey:e,abandonedSession:t.session,abandonedAtMs:t.abandonedAtMs}})}function L(e){return`transient:${e}`}async function R(e){let t=H(e.device),n=h(t);return await O(n,async()=>await B({...e,deviceKey:n,identity:t}))}async function z(e){let t=H(e.device),n=h(t);return await O(n,async()=>{let r=_(g(n));return r?.claim&&!j(r.claim)&&A(r.claim,e.stateDir,f())?{status:`covered-by-owned-claim`}:await B({device:e.device,deviceKey:n,identity:t,session:L(e.command),workspace:e.workspace,stateDir:e.stateDir,reconcileOrphanedDeviceClaim:e.reconcileOrphanedDeviceClaim})})}async function B(e){let{deviceKey:t,identity:n}=e,r=f(),i=await ie({...e,owner:r});if(i.status===`conflict`)return i;if(i.status===`held`)return{status:`acquired`,ownership:i.ownership};let a=Date.now(),o={schemaVersion:2,deviceKey:t,device:{...n,name:e.device.name},session:e.session,workspace:e.workspace,stateDir:e.stateDir,ownerPid:r.pid,ownerStartTime:r.startTime,ownerToken:re.randomUUID(),createdAtMs:a,updatedAtMs:a};return D(o),{status:`acquired`,ownership:v(o),...i.tookOver?{tookOver:i.tookOver}:{}}}function V(e){let t=h(H(e)),n=_(g(t))?.claim;return n!==void 0&&n.deviceKey===t&&!j(n)&&p({pid:n.ownerPid,startTime:n.ownerStartTime},f())}function H(e){return r({...e,...i(e.platform)?{appleOs:n(e)}:{}})}async function U(e){let t=[];for(let n of ne(e.selectors))t.push(await W(n,e.reconcile));return t}async function W(e,t){let n=e.claim,r={fileName:e.fileName,classification:e.classification,...e.deviceKey?{deviceKey:e.deviceKey}:{},...n?{device:n.device,session:n.session,workspace:n.workspace,stateDir:n.stateDir}:{},...e.allocatorClaim?{device:e.allocatorClaim.device,stateDir:e.allocatorClaim.stateDir,allocator:e.allocatorClaim.allocator}:{}};if(!n||!y(e.classification))return{...r,status:`refused`,reason:K(e.classification)};if(g(n.deviceKey)!==C.join(b(),e.fileName))return{...r,status:`refused`,reason:`claim-file-name-mismatch`};let{deviceKey:i,ownerToken:a}=n;return await O(i,async()=>{let e=_(g(i));if(!e?.claim||e.claim.ownerToken!==a||!y(e.classification))return{...r,status:`changed`,reason:`claim-changed-during-release`};let o=await k(e.claim,t);return o.status===`retained`?{...r,status:`retained`,reason:o.reason}:(d({level:`info`,phase:`device_claim_stale_released`,data:{deviceKey:i,ownerSession:n.session,ownerStateDir:n.stateDir}}),{...r,status:`released`})})}const G=Object.freeze({live:`live-owner`,"owner-process-reused":`owner-pid-reused`,"owner-state-dir-gone":`owner-process-still-running`,unknown:`owner-liveness-unknown`,inconsistent:`claim-record-inconsistent`,"allocator-inconsistent":`allocator-claim-record-inconsistent`,"allocator-held":`allocator-held-owner`,"owner-process-dead":`claim-record-unreadable`,"owner-daemon-superseded":`claim-record-unreadable`});function K(e){return G[e]}async function ce(e){return e?await q(e,(e,t)=>{try{w.unlinkSync(t)}catch(e){if(e.code!==`ENOENT`)throw e;return`absent`}return`deleted`},e=>e?`ownership-changed`:`absent`):`absent`}async function le(e){return e?await q(e,e=>{let t=Date.now();return D({...e,abandonedAtMs:t,updatedAtMs:t}),`abandoned`},e=>e?`ownership-changed`:`absent`):`absent`}async function ue(e){return e?await q(e,e=>(D({...e,updatedAtMs:Date.now()}),{status:`renewed`}),e=>({status:`lost`,conflict:e})):{status:`lost`,conflict:void 0}}async function q(e,t,n){return await O(e.deviceKey,async()=>{let r=g(e.deviceKey),i=_(r);if(!i)return n(void 0);let a=i.claim;return!a||!de(a,e)?n(i):t(a,r)})}function de(e,t){return e.ownerToken===t.ownerToken&&p({pid:e.ownerPid,startTime:e.ownerStartTime},{pid:t.ownerPid,startTime:t.ownerStartTime})}async function fe(e,t){let n=b(),r;try{r=w.readdirSync(n,{withFileTypes:!0})}catch{return{examined:0,reconciled:0,retained:0,changed:0}}let i=0,a=0,o=0,s=0;for(let c of r){if(!c.isFile()||!c.name.endsWith(`.json`))continue;let r=C.join(n,c.name),l=_(r);if(!l?.claim||!J(l.classification,l.claim.stateDir,t))continue;i+=1;let{deviceKey:u,ownerToken:d}=l.claim;if(g(u)!==r){o+=1;continue}await O(u,async()=>{let n=_(r);if(!n?.claim||!J(n.classification,n.claim.stateDir,t)||n.claim.ownerToken!==d){s+=1;return}if((await k(n.claim,e)).status===`retained`){o+=1;return}a+=1})}return{examined:i,reconciled:a,retained:o,changed:s}}function J(e,t,n){return y(e)?e!==`owner-daemon-superseded`||C.resolve(t)===C.resolve(n):!1}const Y=S({resourceKind:`app-log`,fileName:`app-log.resource.json`,displayName:`App-log`}),X=x({resourceKind:`app-log`,displayName:`app-log`,store:Y,sessionSlot:{read:e=>e.appLog,replace:(e,t)=>({...e,appLog:t,appLogFailure:void 0})},completionMetadata:e=>({backend:e.backend,outputPath:e.outputPath,completedAt:e.completedAt}),failedFinishPolicy:`dispose-on-failed-finish`,messages:{noActive:`no app log stream active`,cleanupPendingHint:`Keep app-log.resource.json and retry cleanup through its exact runtime owner.`}});function pe(e){if(e.appLog){let t=e.appLog.handle.inspect();return{active:t.state===`active`||t.state===`recovering`,...t}}return e.appLogFailure?{active:!1,state:`failed`,backend:e.appLogFailure.backend,failureCode:e.appLogFailure.code,failureMessage:e.appLogFailure.message,hint:e.appLogFailure.hint}:{active:!1,state:`inactive`}}function me(e){return X.adoptStarted(e)}function he(e){return X.finishLive(e)}function ge(e){return X.forceCleanupLive(e)}function _e(e){let n=t(e.error);return e.sessionStore.set(e.sessionName,{...e.session,appLog:void 0,appLogFailure:{backend:e.backend,code:n.code,message:n.message,hint:n.hint}}),n}function ve(e){e.sessionStore.set(e.sessionName,{...e.session,appLogFailure:void 0})}const ye=S({resourceKind:`audio-probe`,fileName:`audio-probe.resource.json`,displayName:`Audio probe`}),Z=x({resourceKind:`audio-probe`,displayName:`audio probe`,store:ye,sessionSlot:{read:e=>e.audioProbe,replace:(e,t)=>({...e,audioProbe:t})},completionMetadata:e=>({backend:e.backend??`unknown`,source:e.source,durationMs:e.durationMs,elapsedMs:e.elapsedMs,bucketMs:e.bucketMs,sampleCount:e.sampleCount,heard:e.heard}),failedFinishPolicy:`dispose-on-failed-finish`,messages:{noActive:`no active audio probe`,cleanupPendingHint:`Keep audio-probe.resource.json and retry stop through its exact runtime owner.`}});function be(e){return Z.adoptStarted(e)}function xe(e){return Z.finishLive(e)}const Q=S({resourceKind:`perf-capture`,fileName:`perf-capture.resource.json`,displayName:`Perf capture`}),$=x({resourceKind:`perf-capture`,displayName:`perf capture`,store:Q,sessionSlot:{read:e=>e.perfCapture,replace:(e,t)=>({...e,perfCapture:t})},completionMetadata:e=>({kind:typeof e.kind==`string`?e.kind:`unknown`,mode:typeof e.mode==`string`?e.mode:`unknown`,...typeof e.outPath==`string`?{outPath:e.outPath}:{}}),failedFinishPolicy:`preserve-retry-material`,messages:{noActive:`no active native perf capture`,cleanupPendingHint:`Keep perf-capture.resource.json and retry stop through its exact runtime owner.`}});function Se(e){return $.adoptStarted(e)}function Ce(e){return $.finishLive(e)}function we(e){if(e.area===`frames`)return Object.freeze({kind:`frames`,request:e,use:a});if(e.area===`memory`)return e.action===`snapshot`?Object.freeze({kind:`memory-snapshot`,request:e,use:l}):Object.freeze({kind:`memory-sample`,request:e,use:s});if(e.area===`trace`)return e.action===`start`?Object.freeze({kind:`capture-start`,request:e,use:c}):Object.freeze({kind:`capture-stop`,request:e});switch(e.action){case`start`:return Object.freeze({kind:`capture-start`,request:e,use:c});case`stop`:return Object.freeze({kind:`capture-stop`,request:e});case`report`:return Object.freeze({kind:`profile-report`,request:e,use:o})}}function Te(t){let n=t.positionals??[],r=n[0]?.toLowerCase();if(r===`frames`){let i=n[1]?.toLowerCase();if(i!==void 0&&i!==`sample`||n.length>2||t.kind!==void 0)throw new e(`INVALID_ARGS`,`perf action must be frames, memory sample|snapshot, cpu profile start|stop|report, or trace start|stop`);return Object.freeze({area:r,action:`sample`})}if(r===`memory`)return Ee(n,t);if(r===`cpu`)return De(n,t.outPath);if(r===`trace`)return Oe(n,t.outPath);throw new e(`INVALID_ARGS`,`perf requires frames, memory, cpu, or trace`)}function Ee(t,n){let r=(t[1]??`sample`).toLowerCase();if(r!==`sample`&&r!==`snapshot`)throw new e(`INVALID_ARGS`,`perf memory requires sample or snapshot`);if(n.kind!==void 0&&r!==`snapshot`)throw new e(`INVALID_ARGS`,`--kind is only supported with perf memory snapshot`);if(r===`sample`&&t.length>2)throw new e(`INVALID_ARGS`,`perf memory sample does not accept additional positionals`);if(r===`snapshot`&&t.length>3)throw new e(`INVALID_ARGS`,`perf memory snapshot accepts at most one positional kind`);let i=n.kind??t[2];if(i!==void 0&&!u(i))throw new e(`INVALID_ARGS`,`perf memory snapshot --kind must be android-hprof or memgraph`);return Object.freeze({area:`memory`,action:r,...i===void 0?{}:{kind:i},...n.outPath===void 0?{}:{outPath:n.outPath}})}function De(t,n){if(t[1]?.toLowerCase()!==`profile`)throw new e(`INVALID_ARGS`,`perf cpu requires profile`);let r=t[2]?.toLowerCase();if(r!==`start`&&r!==`stop`&&r!==`report`)throw new e(`INVALID_ARGS`,`perf cpu profile action must be start, stop, or report`);let i=t[3]?.toLowerCase();if(i!==`xctrace`&&i!==`simpleperf`)throw new e(`INVALID_ARGS`,`perf cpu profile requires --kind xctrace or simpleperf`);let a=n??t[5];return Object.freeze({area:`cpu`,subject:`profile`,action:r,kind:i,...t[4]?{template:t[4]}:{},...a?{outPath:a}:{},...t[6]?{tracePath:t[6]}:{}})}function Oe(t,n){let r=t[1]?.toLowerCase();if(r!==`start`&&r!==`stop`)throw new e(`INVALID_ARGS`,`perf trace action must be start or stop`);let i=t[2]?.toLowerCase();if(i!==`xctrace`&&i!==`perfetto`)throw new e(`INVALID_ARGS`,`perf trace requires --kind xctrace or perfetto`);let a=n??t[4];return Object.freeze({area:`trace`,action:r,kind:i,...t[3]?{template:t[3]}:{},...a?{outPath:a}:{}})}export{fe as C,V as S,ue as T,le as _,$ as a,ce as b,xe as c,ve as d,he as f,Y as g,_e as h,Ce as i,me as l,pe as m,we as n,be as o,ge as p,Se as r,Z as s,Te as t,X as u,R as v,U as w,H as x,z as y};
|
package/dist/src/perf.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{D as e}from"./sdk-contracts.js";import{runHarmonyShell as t}from"./hdc.js";function n(e){let t=e.trim().split(/\s+/)[0];if(!t||!/^\d+$/.test(t))return;let n=Number.parseInt(t,10);return n>0?n:void 0}function r(e){let t=o(e,`VmRSS`);if(t===void 0)return;let n=o(e,`VmHWM`);return{totalRssKb:t,...n===void 0?{}:{peakRssKb:n}}}async function i(n,i){let o=await a(n,i),s=r((await t(n,[`cat`,`/proc/${o}/status`],{timeoutMs:15e3})).stdout);if(!s)throw new e(`COMMAND_FAILED`,`Could not read resident memory for ${i}`,{hint:`Verify the app is still running, then retry perf memory sample.`,details:{bundleName:i,pid:o}});return{...s,measuredAt:new Date().toISOString(),method:`hdc-shell-proc-status`,pid:o}}async function a(r,i){let a=await t(r,[`pidof`,i],{allowFailure:!0,timeoutMs:15e3}),o=a.exitCode===0?n(a.stdout):void 0;if(o!==void 0)return o;throw new e(`COMMAND_FAILED`,`Could not find a running process for ${i}`,{hint:`Open the app in this session, then retry perf memory sample.`,details:{bundleName:i}})}function o(e,t){let n=e.match(RegExp(`^${t}:\\s+(\\d+)\\s+kB$`,`m`));if(!n?.[1])return;let r=Number.parseInt(n[1],10);return Number.isFinite(r)?r:void 0}export{i as sampleHarmonyMemoryPerf};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{C as e}from"./sdk-contracts.js";import{r as t}from"./diagnostics.js";import{f as n}from"./owner-identity.js";import{n as r}from"./exec.js";import"./diagnostics2.js";import"./command.js";import{n as i}from"./retry.js";import"./process.js";import{C as a,E as o,T as s,p as c,y as l}from"./host-file.js";import{a as u,i as d,r as ee}from"./config.js";import{c as te,o as f}from"./tool-provider.js";import{t as p}from"./apps-simctl.js";import"./runner.js";import{t as m}from"./runner-cache-metadata.js";import h from"node:path";async function g(t,n,i={}){let a=[`devicectl`,...t],o=await f(a,{allowFailure:!0,signal:i.signal,timeoutMs:i.timeoutMs??2e4});if(o.exitCode===0)return;let{stdout:s,stderr:c}=o;if(!i.tolerateOutput?.(s,c))throw new e(`COMMAND_FAILED`,`Failed to ${n.action}`,r(o,{cmd:`xcrun`,args:a,stdout:s,stderr:c,deviceId:n.deviceId,hint:D(s,c)??`Ensure the iOS device is unlocked, trusted, and available in Xcode > Devices, then retry.`}))}async function _(e,t){return ae(re(await x(e,{jsonPrefix:`agent-device-ios-apps`,args:[`devicectl`,`device`,`info`,`apps`,`--device`,e.id,`--include-all-apps`],failureMessage:`Failed to list iOS apps`,parseFailureMessage:`Failed to parse iOS apps list`})),t)}async function v(t){let n=await x(t,{jsonPrefix:`agent-device-ios-processes`,args:[`devicectl`,`device`,`info`,`processes`,`--device`,t.id],failureMessage:`Failed to list iOS processes`,parseFailureMessage:`Failed to parse iOS process list`,fallbackHint:E});if(!ne(n))throw new e(`COMMAND_FAILED`,`Unsupported iOS process list response`,{deviceId:t.id,hint:E});return ie(n)}async function y(e,t){let{appBundleUrl:n,processes:r}=await b(e,t),i=r.sort((e,t)=>C(e,n)-C(t,n))[0];i&&await x(e,{jsonPrefix:`agent-device-ios-process-terminate`,args:[`devicectl`,`device`,`process`,`terminate`,`--device`,e.id,`--pid`,String(i.pid),`--kill`],failureMessage:`Failed to terminate iOS app`,parseFailureMessage:`Failed to parse iOS process termination response`,tolerateFailurePayload:w})}async function b(t,n){let r=(await _(t,`all`)).find(e=>e.bundleId===n);if(!r)throw new e(`APP_NOT_INSTALLED`,`No iOS device app found for ${n}`,{appBundleId:n,deviceId:t.id});if(!r.url)throw new e(`COMMAND_FAILED`,`Missing app bundle URL for ${n}`,{appBundleId:n,deviceId:t.id,hint:`Installed-app metadata from devicectl did not include the bundle URL required to match running processes. Use an Xcode/CoreDevice toolchain that reports app URLs.`});let i=r.url.replace(/\/+$/,``);return{appBundleUrl:i,processes:(await v(t)).filter(e=>e.executable.startsWith(`${i}/`))}}async function x(t,i){let a=h.join(c(),`${i.jsonPrefix}-${n()}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`),o=[...i.args,`--json-output`,a],l=await f(o,{allowFailure:!0,timeoutMs:ee});try{if(l.exitCode!==0){let{stdout:n,stderr:s}=l;if(i.tolerateFailurePayload){let e=await S(a).catch(()=>void 0);if(e!==void 0&&i.tolerateFailurePayload(e))return e}throw new e(`COMMAND_FAILED`,i.failureMessage,r(l,{cmd:`xcrun`,args:o,stdout:n,stderr:s,deviceId:t.id,hint:D(n,s)??i.fallbackHint??`Ensure the iOS device is unlocked, trusted, and available in Xcode > Devices, then retry.`}))}return await S(a)}catch(n){throw n instanceof e?n:new e(`COMMAND_FAILED`,i.parseFailureMessage,{deviceId:t.id,cause:String(n)})}finally{await s(a).catch(()=>{})}}async function S(e){return JSON.parse(await l(e))}function C(e,t){return e.executable.slice(t.length+1).split(`/`).length}function ne(e){return Array.isArray(e?.result?.runningProcesses)}function w(e){let t=e?.error?.userInfo?.NSUnderlyingError?.error;return t?.domain===`NSPOSIXErrorDomain`&&t.code===3}function re(e){let t=e?.result?.apps;if(!Array.isArray(t))return[];let n=[];for(let e of t){if(!e||typeof e!=`object`)continue;let t=typeof e.bundleIdentifier==`string`?e.bundleIdentifier.trim():``;if(!t)continue;let r=typeof e.name==`string`&&e.name.trim().length>0?e.name.trim():t,i=typeof e.url==`string`&&e.url.trim().length>0?e.url.trim():void 0;n.push({bundleId:t,name:r,url:i})}return n}function ie(e){let t=e?.result?.runningProcesses;if(!Array.isArray(t))return[];let n=[];for(let e of t){if(!e||typeof e!=`object`)continue;let t=typeof e.executable==`string`?e.executable.trim():``,r=typeof e.processIdentifier==`number`&&Number.isFinite(e.processIdentifier)?e.processIdentifier:NaN;!t||!Number.isFinite(r)||n.push({executable:t,pid:r})}return n}function ae(e,t){return te(e,t)}const T=`Ensure the iOS device is unlocked, trusted, and available in Xcode > Devices, then retry.`,E=`This Xcode/CoreDevice toolchain must support 'devicectl device info processes' with JSON runningProcesses so agent-device can resolve app process IDs. Inspect diagnostics for the exact devicectl API failure.`;function D(e,t){let n=`${e}\n${t}`.toLowerCase();return n.includes(`device is busy`)&&n.includes(`connecting`)?`iOS device is still connecting. Keep it unlocked and connected by cable until it is fully available in Xcode Devices, then retry.`:n.includes(`coredeviceservice`)&&n.includes(`timed out`)?`CoreDevice service timed out. Reconnect the device and retry; if it persists restart Xcode and the iOS device.`:n.includes(`developer disk image`)||n.includes(`developer mode is disabled`)?`Enable Developer Mode on the iOS device (Settings > Privacy & Security > Developer Mode), restart it when prompted, unlock it, then retry.`:n.includes(`must be paired`)?`Pair the iOS device with this Mac: connect it by cable, unlock it, accept the Trust prompt, and enter the device passcode, then retry.`:null}async function O(e,t){return await _(e,t)}async function k(e,t,n){await g([`device`,`install`,`app`,`--device`,e.id,t],{action:`install iOS app`,deviceId:e.id},{signal:n,timeoutMs:d})}async function A(e,t,n){await g([`device`,`uninstall`,`app`,`--device`,e.id,t],{action:`uninstall iOS app ${t}`,deviceId:e.id},{signal:n,tolerateOutput:(e,t)=>p(`${e}\n${t}`.toLowerCase())})}async function j(e,t){await y(e,t)}async function M(e,t){return await b(e,t)}const N=1e4;async function P(e,t,n={}){let r=[`device`,`process`,`launch`,`--device`,e.id,t];n.payloadUrl&&r.push(`--payload-url`,n.payloadUrl),n.launchArgs&&n.launchArgs.length>0&&r.push(`--`,...n.launchArgs),await g(r,{action:`launch iOS app`,deviceId:e.id})}async function F(t,n){try{let{result:i,parsed:a}=await B(t.id,15e3,3e3,n);if(i.exitCode===0){if(!a.parsed)throw new e(`COMMAND_FAILED`,`iOS device readiness probe failed`,{kind:`probe_inconclusive`,deviceId:t.id,stdout:i.stdout,stderr:i.stderr,hint:`CoreDevice returned success but readiness JSON output was missing or invalid. Retry; if it persists restart Xcode and the iOS device.`});let n=a.tunnelState?.toLowerCase();if(n===`connecting`)throw new e(`COMMAND_FAILED`,`iOS device is not ready for automation`,{kind:`not_ready`,deviceId:t.id,tunnelState:n,hint:`Device tunnel is still connecting. Keep the device unlocked and connected by cable until it is fully available in Xcode Devices, then retry.`});return}throw new e(`COMMAND_FAILED`,`iOS device is not ready for automation`,r(i,{kind:`not_ready`,deviceId:t.id,tunnelState:a.tunnelState,hint:W(i.stdout,i.stderr)}))}catch(e){throw I(t.id,e)}}function I(t,n){return!(n instanceof e)||n.code!==`COMMAND_FAILED`?R(t,n):(typeof n.details?.kind==`string`?n.details.kind:``)===`not_ready`?n:L(t,n)}function L(t,n){let r=n.details??{},i=String(r.stdout??``),a=String(r.stderr??``),o=Number(r.timeoutMs??15e3),s=`CoreDevice did not respond within ${o}ms. Keep the device unlocked and trusted, then retry; if it persists restart Xcode and the iOS device.`;return new e(`COMMAND_FAILED`,`iOS device readiness probe failed`,{deviceId:t,cause:n.message,timeoutMs:o,stdout:i,stderr:a,hint:i||a?W(i,a):s},n)}function R(t,n){return new e(`COMMAND_FAILED`,`iOS device readiness probe failed`,{deviceId:t,hint:`Reconnect the device, keep it unlocked, and retry.`},n instanceof Error?n:void 0)}async function z(e,t){if(typeof t==`number`&&t<=0)return null;let n=typeof t==`number`?Math.max(1,Math.min(N,t)):N;try{let t=await B(e.id,n);return t.result.exitCode!==0||!t.parsed.parsed||t.parsed.outcome&&t.parsed.outcome!==`success`?null:t.parsed.tunnelIp??null}catch{return null}}async function B(e,t,r=0,i){let o=h.join(c(),`agent-device-coredevice-info-${n()}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`),s=Math.max(1,Math.ceil(t/1e3));try{return{result:await f([`devicectl`,`device`,`info`,`details`,`--device`,e,`--json-output`,o,`--timeout`,String(s)],{allowFailure:!0,signal:i,timeoutMs:t+r}),parsed:await V(o)}}finally{await a(o).catch(()=>{})}}async function V(e){try{return{parsed:!0,...H(JSON.parse(await l(e)))}}catch{return{parsed:!1}}}function H(e){let t=e?.result;if(!t||typeof t!=`object`)return{};let n=t.connectionProperties,r=t.device?.connectionProperties,i=U(n?.tunnelState)??U(r?.tunnelState),a=U(n?.tunnelIPAddress)??U(r?.tunnelIPAddress),o=U(e?.info?.outcome);return{...o?{outcome:o}:{},...i?{tunnelState:i}:{},...a?{tunnelIp:a}:{}}}function U(e){return typeof e==`string`&&e.trim()?e.trim():void 0}function W(e,t){return D(e,t)||(`${e}\n${t}`.toLowerCase().includes(`timed out waiting for all destinations`)?`Xcode destination did not become available in time. Keep device unlocked and retry.`:T)}async function G(t,n,r,a=u){let o=i.fromTimeoutMs(a),s={exitCode:1,stdout:``,stderr:``};for(let e of m)if(s=await f([`devicectl`,`device`,`copy`,`from`,`--device`,t.id,`--source`,n,`--destination`,r,`--domain-type`,`appDataContainer`,`--domain-identifier`,e],{allowFailure:!0,timeoutMs:K(o,a)}),s.exitCode===0)return;let c=s.stderr.trim()||s.stdout.trim()||`devicectl exited with code ${s.exitCode}`;throw new e(`COMMAND_FAILED`,`Failed to copy runner file from iOS device: ${c}`)}function K(t,n){let r=t.remainingMs();if(r>0)return r;throw new e(`COMMAND_FAILED`,`iOS runner file copy timed out after ${n}ms`,{timeoutMs:n,step:`runner file copy`})}function q(t){if(!(t instanceof e))return{reason:t instanceof Error?t.message:String(t)};let n=t.details??{},r=Array.isArray(n.args)?n.args.filter(e=>typeof e==`string`).join(` `):void 0;return{errorCode:t.code,reason:t.message,timeoutMs:typeof n.timeoutMs==`number`?n.timeoutMs:void 0,exitCode:typeof n.exitCode==`number`?n.exitCode:void 0,stderr:typeof n.stderr==`string`&&n.stderr.trim()?n.stderr:void 0,stdout:typeof n.stdout==`string`&&n.stdout.trim()?n.stdout:void 0,commandArgs:r}}function J(e){let t=e.details??{},n=typeof t.stdout==`string`?t.stdout:``,r=typeof t.stderr==`string`?t.stderr:``,i=Array.isArray(t.args)?t.args.filter(e=>typeof e==`string`).join(` `):``;return`${e.message}\n${n}\n${r}\n${i}`.toLowerCase()}async function oe(e,t,n){if(!n.preferRunner)try{await g([`device`,`capture`,`screenshot`,`--device`,e.id,`--destination`,t],{action:`capture iOS screenshot`,deviceId:e.id});return}catch(t){if(!ue(t))throw t;le(e,t)}let r=await Y(e,n,!1);await X(r,t)||await G(e,ce(r),t)}async function se(t,n,r){if(!await X(await Y(t,r,!0),n))throw new e(`COMMAND_FAILED`,`Failed to capture iOS screenshot: XCTest runner returned no inline image`,{deviceId:t.id,backend:`xctest`})}async function Y(e,t,n){return await t.runRunnerCommand(e,{command:`screenshot`,appBundleId:t.appBundleId,fullscreen:t.fullscreen,inlineScreenshot:n},t.runnerOptions??{})}async function X(e,t){let n=e.imageBase64;return typeof n!=`string`||n.length===0?!1:(await o(t,Buffer.from(n,`base64`)),!0)}function ce(t){let n=t.message;if(typeof n==`string`&&n.length>0)return n;throw new e(`COMMAND_FAILED`,`Failed to capture iOS screenshot: runner returned no file path`)}function le(e,n){t({level:`warn`,phase:`ios_screenshot_fallback`,data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,from:`devicectl_screenshot`,to:`runner`,...q(n)}})}function ue(t){if(!(t instanceof e)||t.code!==`COMMAND_FAILED`)return!1;let n=J(t);return n.includes(`unknown option '--device'`)||n.includes(`unknown subcommand`)&&n.includes(`screenshot`)||n.includes(`unrecognized subcommand`)&&n.includes(`screenshot`)}const de={coredevice:{backend:`coredevice`,assertAppInstallationSupported:()=>{},ensureReady:F,listApps:O,installApp:k,uninstallApp:A,launchApp:P,terminateApp:async(e,t)=>await j(e,t),resolveAppProcesses:M,captureScreenshot:oe,copyRunnerFile:G,resolveTunnel:async(e,t)=>({tunnelIp:await z(e,t)})},xctest:{backend:`xctest`,assertAppInstallationSupported:Z,ensureReady:ge,listApps:pe,installApp:Q,uninstallApp:Q,launchApp:_e,terminateApp:ve,resolveAppProcesses:$,captureScreenshot:se,copyRunnerFile:he,resolveTunnel:me}};function fe(e){return de[e.iosPhysicalDeviceBackend===`xctest`?`xctest`:`coredevice`]}function Z(t){throw new e(`UNSUPPORTED_OPERATION`,`Installing apps is unavailable on this XCTest-backed physical iOS device.`,{deviceId:t.id,backend:`xctest`,hint:`Install the app with Xcode, then open it in agent-device by bundle ID.`})}async function Q(e){return Z(e)}async function pe(t){throw new e(`UNSUPPORTED_OPERATION`,`App inventory is unavailable on this XCTest-backed physical iOS device.`,{deviceId:t.id,backend:`xctest`,hint:`Use an installed app bundle ID when opening the device.`})}async function $(t){throw new e(`UNSUPPORTED_OPERATION`,`Process lookup is unavailable on this XCTest-backed physical iOS device.`,{deviceId:t.id,backend:`xctest`,hint:`Use a CoreDevice-backed iOS device for performance sampling.`})}async function me(t){throw new e(`UNSUPPORTED_OPERATION`,`XCTest-backed physical iOS devices have no CoreDevice tunnel.`,{deviceId:t.id,backend:`xctest`,hint:`Connect the device by cable so it is reachable through usbmux.`})}async function he(t){throw new e(`UNSUPPORTED_OPERATION`,`Runner file copy is unavailable on this XCTest-backed physical iOS device.`,{deviceId:t.id,backend:`xctest`})}async function ge(t,n){let i=[`xcdevice`,`wait`,`--both`,`--timeout=15`,t.id],a=await f(i,{allowFailure:!0,signal:n,timeoutMs:18e3});if(a.exitCode!==0)throw new e(`COMMAND_FAILED`,`iOS device is not ready for XCTest automation`,r(a,{cmd:`xcrun`,args:i,deviceId:t.id,backend:`xctest`,hint:"Keep the device unlocked, trusted, connected, and visible in `xcrun xcdevice list`, then retry."}))}async function _e(t,n,r){if(r.payloadUrl||r.launchArgs&&r.launchArgs.length>0)throw new e(`UNSUPPORTED_OPERATION`,`XCTest-backed physical iOS devices do not support deep links or launch arguments during open.`,{deviceId:t.id,backend:`xctest`,hint:`Open the installed app by bundle ID without a URL or --launch-args.`});await r.runRunnerCommand(t,{command:`activate`,appBundleId:n},r.runnerOptions??{})}async function ve(e,t,n){await n.runRunnerCommand(e,{command:`terminate`,appBundleId:t},n.runnerOptions??{})}export{D as a,T as i,J as n,q as r,fe as t};
|
|
1
|
+
import{D as e}from"./sdk-contracts.js";import{r as t}from"./diagnostics.js";import{f as n}from"./owner-identity.js";import{n as r}from"./exec.js";import"./diagnostics2.js";import"./command.js";import{n as i}from"./retry.js";import"./process.js";import{C as a,E as o,p as s,y as c}from"./host-file.js";import{a as l,c as u}from"./config.js";import{o as d}from"./tool-provider.js";import{a as f,i as p,l as m,n as h,o as g,r as _,s as v,t as ee}from"./devicectl.js";import{t as y}from"./apps-simctl.js";import"./runner.js";import{t as b}from"./runner-cache-metadata.js";import te from"node:path";async function ne(e,t){return await p(e,t)}async function re(e,t,n){await v([`device`,`install`,`app`,`--device`,e.id,t],{action:`install iOS app`,deviceId:e.id},{signal:n,timeoutMs:l})}async function ie(e,t,n){await v([`device`,`uninstall`,`app`,`--device`,e.id,t],{action:`uninstall iOS app ${t}`,deviceId:e.id},{signal:n,tolerateOutput:(e,t)=>y(`${e}\n${t}`.toLowerCase())})}async function ae(e,t){await m(e,t)}async function oe(e,t){return await f(e,t)}const x=1e4;async function S(e,t,n={}){let r=[`device`,`process`,`launch`,`--device`,e.id,t];n.payloadUrl&&r.push(`--payload-url`,n.payloadUrl),n.launchArgs&&n.launchArgs.length>0&&r.push(`--`,...n.launchArgs),await v(r,{action:`launch iOS app`,deviceId:e.id})}async function C(t,n){try{let{result:i,parsed:a}=await k(t.id,15e3,3e3,n);if(i.exitCode===0){if(!a.parsed)throw new e(`COMMAND_FAILED`,`iOS device readiness probe failed`,{kind:`probe_inconclusive`,deviceId:t.id,stdout:i.stdout,stderr:i.stderr,hint:`CoreDevice returned success but readiness JSON output was missing or invalid. Retry; if it persists restart Xcode and the iOS device.`});let n=a.tunnelState?.toLowerCase();if(n===`connecting`)throw new e(`COMMAND_FAILED`,`iOS device is not ready for automation`,{kind:`not_ready`,deviceId:t.id,tunnelState:n,hint:`Device tunnel is still connecting. Keep the device unlocked and connected by cable until it is fully available in Xcode Devices, then retry.`});return}throw new e(`COMMAND_FAILED`,`iOS device is not ready for automation`,r(i,{kind:`not_ready`,deviceId:t.id,tunnelState:a.tunnelState,hint:W(i.stdout,i.stderr)}))}catch(e){throw w(t.id,e)}}function w(t,n){return!(n instanceof e)||n.code!==`COMMAND_FAILED`?E(t,n):(typeof n.details?.kind==`string`?n.details.kind:``)===`not_ready`?n:T(t,n)}function T(t,n){let r=n.details??{},i=String(r.stdout??``),a=String(r.stderr??``),o=Number(r.timeoutMs??15e3),s=`CoreDevice did not respond within ${o}ms. Keep the device unlocked and trusted, then retry; if it persists restart Xcode and the iOS device.`;return new e(`COMMAND_FAILED`,`iOS device readiness probe failed`,{deviceId:t,cause:n.message,timeoutMs:o,stdout:i,stderr:a,hint:i||a?W(i,a):s},n)}function E(t,n){return new e(`COMMAND_FAILED`,`iOS device readiness probe failed`,{deviceId:t,hint:`Reconnect the device, keep it unlocked, and retry.`},n instanceof Error?n:void 0)}async function D(e,t){return(await O(e,t??x))?.tunnelIp??null}async function O(e,t,n){if(!(t>0))return null;let r=Math.max(1,Math.min(x,t));try{let t=await k(e.id,r,0,n);if(t.result.exitCode!==0||!t.parsed.parsed||t.parsed.outcome&&t.parsed.outcome!==`success`)return null;let{parsed:i}=t,{parsed:a,...o}=i;return o}catch{return null}}async function k(e,t,r=0,i){let o=te.join(s(),`agent-device-coredevice-info-${n()}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`),c=Math.max(1,Math.ceil(t/1e3));try{return{result:await d([`devicectl`,`device`,`info`,`details`,`--device`,e,`--json-output`,o,`--timeout`,String(c)],{allowFailure:!0,signal:i,timeoutMs:t+r}),parsed:await A(o)}}finally{await a(o).catch(()=>{})}}async function A(e){try{return{parsed:!0,...P(JSON.parse(await c(e)))}}catch{return{parsed:!1}}}function j(e){let t=e,n=N(t.device);return{connectionProperties:M(N(t.connectionProperties),N(n?.connectionProperties)),deviceProperties:M(N(t.deviceProperties),N(n?.deviceProperties))}}function M(e,t){if(!e)return t;if(!t)return e;let n={...t};for(let[t,r]of Object.entries(e))r!==void 0&&(n[t]=r);return n}function N(e){return e&&typeof e==`object`?e:void 0}function P(e){let t=N(e?.result);if(!t)return{};let{connectionProperties:n,deviceProperties:r}=j(t);return{...F(`outcome`,I(e?.info?.outcome)),...F(`tunnelState`,I(n?.tunnelState)),...F(`tunnelIp`,I(n?.tunnelIPAddress)),...F(`developerModeStatus`,I(r?.developerModeStatus)),...F(`developerDiskImageServicesAvailable`,L(r?.ddiServicesAvailable)),...F(`bootState`,I(r?.bootState))}}function F(e,t){return t===void 0?{}:{[e]:t}}function I(e){return typeof e==`string`&&e.trim()?e.trim():void 0}function L(e){return typeof e==`boolean`?e:void 0}const R={developerModeOff:_,developerDiskImageUnavailable:h};function z(e){return e.tunnelState===`connected`&&e.bootState===`booted`}function B(e){return`The device reported its developer disk image as unavailable while it was not observable (tunnelState=${e.tunnelState??`unknown`}, bootState=${e.bootState??`unknown`}). Unlock it, keep it connected by cable until \`xcrun devicectl device info details\` reports tunnelState=connected and bootState=booted, then retry.`}async function V(e,t=1e4,n){let r=await O(e,t,n);if(!r)return{available:!1,reason:`device_readiness_unreadable`,hint:"Read the device state directly with `xcrun devicectl device info details --device <id> --json-output -`, keeping the device unlocked and connected by cable, then retry."};let i=H(r.developerModeStatus),a=U(r.developerDiskImageServicesAvailable);return a===`unavailable`&&i!==`disabled`&&!z(r)?{available:!1,reason:`device_readiness_unreadable`,hint:B(r)}:{available:!0,developerMode:i,developerDiskImage:a,remedies:R}}function H(e){let t=e?.toLowerCase();return t===`enabled`?`enabled`:t===`disabled`?`disabled`:`unknown`}function U(e){return e===!0?`available`:e===!1?`unavailable`:`unknown`}function W(e,t){return g(e,t)||(`${e}\n${t}`.toLowerCase().includes(`timed out waiting for all destinations`)?`Xcode destination did not become available in time. Keep device unlocked and retry.`:ee)}async function G(t,n,r,a=u){let o=i.fromTimeoutMs(a),s={exitCode:1,stdout:``,stderr:``};for(let e of b)if(s=await d([`devicectl`,`device`,`copy`,`from`,`--device`,t.id,`--source`,n,`--destination`,r,`--domain-type`,`appDataContainer`,`--domain-identifier`,e],{allowFailure:!0,timeoutMs:K(o,a)}),s.exitCode===0)return;let c=s.stderr.trim()||s.stdout.trim()||`devicectl exited with code ${s.exitCode}`;throw new e(`COMMAND_FAILED`,`Failed to copy runner file from iOS device: ${c}`)}function K(t,n){let r=t.remainingMs();if(r>0)return r;throw new e(`COMMAND_FAILED`,`iOS runner file copy timed out after ${n}ms`,{timeoutMs:n,step:`runner file copy`})}function q(t){if(!(t instanceof e))return{reason:t instanceof Error?t.message:String(t)};let n=t.details??{},r=Array.isArray(n.args)?n.args.filter(e=>typeof e==`string`).join(` `):void 0;return{errorCode:t.code,reason:t.message,timeoutMs:typeof n.timeoutMs==`number`?n.timeoutMs:void 0,exitCode:typeof n.exitCode==`number`?n.exitCode:void 0,stderr:typeof n.stderr==`string`&&n.stderr.trim()?n.stderr:void 0,stdout:typeof n.stdout==`string`&&n.stdout.trim()?n.stdout:void 0,commandArgs:r}}function J(e){let t=e.details??{},n=typeof t.stdout==`string`?t.stdout:``,r=typeof t.stderr==`string`?t.stderr:``,i=Array.isArray(t.args)?t.args.filter(e=>typeof e==`string`).join(` `):``;return`${e.message}\n${n}\n${r}\n${i}`.toLowerCase()}async function se(e,t,n){if(!n.preferRunner)try{await v([`device`,`capture`,`screenshot`,`--device`,e.id,`--destination`,t],{action:`capture iOS screenshot`,deviceId:e.id});return}catch(t){if(!de(t))throw t;ue(e,t)}let r=await Y(e,n,!1);await X(r,t)||await G(e,le(r),t)}async function ce(t,n,r){if(!await X(await Y(t,r,!0),n))throw new e(`COMMAND_FAILED`,`Failed to capture iOS screenshot: XCTest runner returned no inline image`,{deviceId:t.id,backend:`xctest`})}async function Y(e,t,n){return await t.runRunnerCommand(e,{command:`screenshot`,appBundleId:t.appBundleId,fullscreen:t.fullscreen,inlineScreenshot:n},t.runnerOptions??{})}async function X(e,t){let n=e.imageBase64;return typeof n!=`string`||n.length===0?!1:(await o(t,Buffer.from(n,`base64`)),!0)}function le(t){let n=t.message;if(typeof n==`string`&&n.length>0)return n;throw new e(`COMMAND_FAILED`,`Failed to capture iOS screenshot: runner returned no file path`)}function ue(e,n){t({level:`warn`,phase:`ios_screenshot_fallback`,data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,from:`devicectl_screenshot`,to:`runner`,...q(n)}})}function de(t){if(!(t instanceof e)||t.code!==`COMMAND_FAILED`)return!1;let n=J(t);return n.includes(`unknown option '--device'`)||n.includes(`unknown subcommand`)&&n.includes(`screenshot`)||n.includes(`unrecognized subcommand`)&&n.includes(`screenshot`)}const fe={coredevice:{backend:`coredevice`,assertAppInstallationSupported:()=>{},ensureReady:C,listApps:ne,installApp:re,uninstallApp:ie,launchApp:S,terminateApp:async(e,t)=>await ae(e,t),resolveAppProcesses:oe,captureScreenshot:se,copyRunnerFile:G,resolveTunnel:async(e,t)=>({tunnelIp:await D(e,t)}),readDeviceReadiness:V},xctest:{backend:`xctest`,assertAppInstallationSupported:Z,ensureReady:ve,listApps:me,installApp:Q,uninstallApp:Q,launchApp:ye,terminateApp:be,resolveAppProcesses:he,captureScreenshot:ce,copyRunnerFile:$,resolveTunnel:ge,readDeviceReadiness:_e}};function pe(e){return fe[e.iosPhysicalDeviceBackend===`xctest`?`xctest`:`coredevice`]}function Z(t){throw new e(`UNSUPPORTED_OPERATION`,`Installing apps is unavailable on this XCTest-backed physical iOS device.`,{deviceId:t.id,backend:`xctest`,hint:`Install the app with Xcode, then open it in agent-device by bundle ID.`})}async function Q(e){return Z(e)}async function me(t){throw new e(`UNSUPPORTED_OPERATION`,`App inventory is unavailable on this XCTest-backed physical iOS device.`,{deviceId:t.id,backend:`xctest`,hint:`Use an installed app bundle ID when opening the device.`})}async function he(t){throw new e(`UNSUPPORTED_OPERATION`,`Process lookup is unavailable on this XCTest-backed physical iOS device.`,{deviceId:t.id,backend:`xctest`,hint:`Use a CoreDevice-backed iOS device for performance sampling.`})}async function ge(t){throw new e(`UNSUPPORTED_OPERATION`,`XCTest-backed physical iOS devices have no CoreDevice tunnel.`,{deviceId:t.id,backend:`xctest`,hint:`Connect the device by cable so it is reachable through usbmux.`})}async function _e(e){return{available:!1,reason:`device_readiness_unreadable`,hint:`This device is driven through XCTest (device ${e.id}), which does not report Developer Mode or developer disk image state. Check the device's own Settings if development tooling fails to start on it.`}}async function $(t){throw new e(`UNSUPPORTED_OPERATION`,`Runner file copy is unavailable on this XCTest-backed physical iOS device.`,{deviceId:t.id,backend:`xctest`})}async function ve(t,n){let i=[`xcdevice`,`wait`,`--both`,`--timeout=15`,t.id],a=await d(i,{allowFailure:!0,signal:n,timeoutMs:18e3});if(a.exitCode!==0)throw new e(`COMMAND_FAILED`,`iOS device is not ready for XCTest automation`,r(a,{cmd:`xcrun`,args:i,deviceId:t.id,backend:`xctest`,hint:"Keep the device unlocked, trusted, connected, and visible in `xcrun xcdevice list`, then retry."}))}async function ye(t,n,r){if(r.payloadUrl||r.launchArgs&&r.launchArgs.length>0)throw new e(`UNSUPPORTED_OPERATION`,`XCTest-backed physical iOS devices do not support deep links or launch arguments during open.`,{deviceId:t.id,backend:`xctest`,hint:`Open the installed app by bundle ID without a URL or --launch-args.`});await r.runRunnerCommand(t,{command:`activate`,appBundleId:n},r.runnerOptions??{})}async function be(e,t,n){await n.runRunnerCommand(e,{command:`terminate`,appBundleId:t},n.runnerOptions??{})}export{J as n,q as r,pe as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{O as e}from"./sdk-device.js";import{At as t,M as n,Yt as r,mt as i}from"./sdk-batch.js";import{t as a}from"./session-store.js";import{r as o}from"./diagnostics.js";import"./diagnostics2.js";import{t as s}from"./daemon-resolution.js";import{t as c}from"./process.js";import{r as l}from"./session-paths.js";import{r as u}from"./request-cancel.js";import{t as d}from"./request.js";import{r as f}from"./platform-runtime.js";import{a as p,s as m,u as h}from"./perf-runtime-plan.js";import{c as g,n as _,r as v}from"./screen-recording-resource-recovery.js";import y from"node:path";const b=i({required:[`appLogReattach`,`appLogCleanup`]});function x(e){return h.recoverAll({sessionsDir:e.sessionsDir,...C(e)})}function S(e){return h.recoverOne({sessionsDir:e.sessionsDir,...C(e)},e.resourcePath)}function C(e){return{scope:e.scope,perRecordDeadlineMs:e.perRecordDeadlineMs,onDiagnostic:e.onDiagnostic,acquireControl:async(t,n)=>await w(e.gateway,t,n)}}async function w(e,t,n){return await v({gateway:e,envelope:t,scope:n,create:e=>{let t=r(e,b);return Object.freeze({reattach:async e=>await t.operations.appLogReattach({envelope:e}),cleanup:async e=>await t.operations.appLogCleanup({envelope:e}),[Symbol.asyncDispose]:async()=>await e[Symbol.asyncDispose]()})}})}function T(e){return m.recoverOne({sessionsDir:e.sessionsDir,scope:e.scope,perRecordDeadlineMs:e.perRecordDeadlineMs,onDiagnostic:e.onDiagnostic,acquireControl:async(t,n)=>await E(e.gateway,t,n)},e.resourcePath)}async function E(e,t,i){return await v({gateway:e,envelope:t,scope:i,create:e=>D({runtime:r(e,n),dispose:async()=>await e[Symbol.asyncDispose]()})})}function D(e){return Object.freeze({reattach:async t=>await e.runtime.operations.audioProbeReattach({envelope:t}),cleanup:async t=>await e.runtime.operations.audioProbeCleanup({envelope:t}),[Symbol.asyncDispose]:e.dispose})}function O(e){return p.recoverOne({sessionsDir:e.sessionsDir,scope:e.scope,perRecordDeadlineMs:e.perRecordDeadlineMs,onDiagnostic:e.onDiagnostic,acquireControl:async(t,n)=>await k(e.gateway,t,n)},e.resourcePath)}async function k(e,n,i){return await v({gateway:e,envelope:n,scope:i,create:e=>A({runtime:r(e,t),dispose:async()=>await e[Symbol.asyncDispose]()})})}function A(e){return Object.freeze({reattach:async t=>await e.runtime.operations.perfNativeCaptureReattach({envelope:t}),cleanup:async t=>await e.runtime.operations.perfNativeCaptureCleanup({envelope:t}),[Symbol.asyncDispose]:e.dispose})}function j(e){return async t=>{let n=s(t.stateDir).sessionsDir,r=y.join(n,l(t.session));try{for(let i of Object.values(M)){let a=N(i,t,r);if(a.status===`retained`)return{status:`retained`,reason:a.reason};if(a.status===`owned`&&await i.recover(e,n,a.resourcePath)===`retained`)return{status:`retained`,reason:`${i.resourceKind}-cleanup-pending`}}return{status:`reconciled`}}catch(e){return o({level:`warn`,phase:`device_claim_orphan_reconciliation_failed`,data:{deviceKey:t.deviceKey,ownerSession:t.session,error:e instanceof Error?e.message:String(e)}}),{status:`retained`,reason:`durable-resource-reconciliation-failed`}}}}const M={"app-log":{resourceKind:`app-log`,store:h.store,recover:async(e,t,n)=>await S({sessionsDir:t,resourcePath:n,gateway:e.gateway,scope:e.scope})},"screen-recording":{resourceKind:`screen-recording`,store:g.store,recover:async(e,t,n)=>await _({sessionsDir:t,resourcePath:n,gateway:e.gateway,scope:e.scope})},"audio-probe":{resourceKind:`audio-probe`,store:m.store,recover:async(e,t,n)=>await T({sessionsDir:t,resourcePath:n,gateway:e.gateway,scope:e.scope})},"perf-capture":{resourceKind:`perf-capture`,store:p.store,recover:async(e,t,n)=>await O({sessionsDir:t,resourcePath:n,gateway:e.gateway,scope:e.scope})}};function N(t,n,r){let i=t.store.resolvePath(r),a=t.store.read(i);return a.status===`missing`?{status:`missing`}:a.status===`unreattachable`?{status:`retained`,reason:`${t.resourceKind}-${a.reason}`}:a.envelope.sessionId!==n.session||!e(a.envelope.device,n.device)?{status:`retained`,reason:`${t.resourceKind}-owner-mismatch`}:{status:`owned`,resourcePath:i}}function P(e,t){let n=t??(t=>F(t,e));return async e=>{let t=n(e.stateDir);try{return await t.reconcile(e)}finally{await t.dispose()}}}function F(e,t){let n=s(e),r=new a(n.sessionsDir),i=f({sessionsDir:n.sessionsDir,ownedProcesses:c({stateDir:n.baseDir,sessionsDir:n.sessionsDir,resolveSessionDir:e=>r.resolveSessionDir(e)}),resolveSessionArtifacts:e=>({outputPath:r.resolveAppLogPath(e),pidPath:r.resolveAppLogPidPath(e)})});return{reconcile:j({gateway:i,scope:t}),dispose:async()=>{await i.shutdown()}}}const I=new AbortController().signal;function L(e){return Object.freeze({signal:u(e.meta?.requestId)??I,diagnostics:Object.freeze({emit:e=>o(e)}),progress:Object.freeze({report:e=>d({type:`command`,status:`progress`,message:e.message})})})}function R(){return Object.freeze({signal:I,diagnostics:Object.freeze({emit:e=>o(e)}),progress:Object.freeze({report:()=>{}})})}export{x as i,L as n,P as r,R as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as e}from"./rolldown-runtime.js";import{r as t}from"./diagnostics.js";import{_ as n,c as r,g as i,l as a,n as o,t as s}from"./exec.js";import"./diagnostics2.js";import"./command.js";import{
|
|
1
|
+
import{r as e}from"./rolldown-runtime.js";import{r as t}from"./diagnostics.js";import{_ as n,c as r,g as i,l as a,n as o,t as s}from"./exec.js";import"./diagnostics2.js";import"./command.js";import{t as c}from"./device-shell.js";import{m as l}from"./adb-executor.js";import{c as u}from"./adb-transport.js";import"./mechanics.js";import d from"node:path";import{constants as f}from"node:fs";import{createHash as p,randomUUID as m}from"node:crypto";import h from"node:os";import{access as g,mkdir as _,mkdtemp as v,open as y,readFile as b,readdir as x,rename as S,rm as C,stat as w,writeFile as T}from"node:fs/promises";var E=e({});const D=process.env;function O(e){c(e,`adb`)}l({environment:D,files:{access:async e=>await g(e),ensureDirectory:async e=>{await _(e,{recursive:!0})},isExecutable:async e=>{try{return await g(e,f.X_OK),!0}catch{return!1}},makeTempDirectory:async e=>await v(d.join(h.tmpdir(),e)),readBytes:async e=>await b(e),readDirectory:async e=>await x(e),readText:async e=>await b(e,`utf8`),remove:async(e,t)=>await C(e,t),stat:async e=>{let t=await w(e);return{isFile:t.isFile(),size:t.size}},sha256:e=>p(`sha256`).update(e).digest(`hex`),writeAtomicText:async(e,t,n=384)=>{let r=d.dirname(e),i=d.join(r,`.${d.basename(e)}.${m()}.tmp`),a,o=!1;try{a=await y(i,`wx`,n),await a.writeFile(t,`utf8`),await a.sync(),await a.close(),a=void 0,await S(i,e),o=!0;let s;try{s=await y(r,`r`),await s.sync()}catch{}finally{s&&await s.close().catch(()=>{})}}finally{a&&await a.close().catch(()=>{}),o||await C(i,{force:!0}).catch(()=>{})}},writeBytes:async(e,t)=>await T(e,t)},execAdb:async(e,t)=>{O(e.command);let n=u(e,t,D);return await r(`adb`,n.args,{...n.options,detached:process.platform!==`win32`})},spawnAdb:(e,t)=>{O(e.command);let n=u(e,t,D),r=a(`adb`,n.args,{...n.options,allowFailure:!0,captureOutput:!1});return r.wait.catch(()=>{}),r.child},withAdbCommandExecutorOverride:i,withoutAdbCommandExecutorOverride:n,coerceAdbResult:s,execFailureDetails:o,emitDiagnostic:t,imeRecoveryMarkers:{write:async(e,t)=>{let{writeAndroidTestImeRecoveryMarker:n}=await import(`./mechanics.js`).then(e=>e.r);return await n(e,t)},clear:async(e,t)=>{let{clearAndroidTestImeRecoveryMarker:n}=await import(`./mechanics.js`).then(e=>e.r);await n(e,t)},read:async e=>{let{readAndroidTestImeRecoveryMarkers:t}=await import(`./mechanics.js`).then(e=>e.r);return await t(e)}},resolveHelperArtifact:async e=>{let{resolveAndroidHelperArtifact:t}=await import(`./mechanics.js`).then(e=>e.r);return await t(e)},ensureHelperInstalled:async(e,t)=>{let{makeEnsureAndroidHelperInstalled:n}=await import(`./mechanics.js`).then(e=>e.r);return await n(e)(t)}});export{E as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{c as e,h as t}from"./exec.js";import"./command.js";import{t as
|
|
1
|
+
import{c as e,h as t}from"./exec.js";import"./command.js";import{r as n,t as r}from"./device-shell.js";import{t as i}from"./platform-runtime-android-mechanics.js";import a from"node:path";import{constants as o}from"node:fs";import s from"node:os";import{access as c,mkdtemp as l,readFile as u,rm as d,writeFile as f}from"node:fs/promises";function p(){return Object.freeze({isXcrunAvailable:async e=>{let{resolveAppleToolProvider:t}=await m(async()=>await import(`./tool-provider-facade.js`),e),n=t();return await m(async()=>await n.whichCommand(`xcrun`),e)},run:async(e,t)=>{let{runXcrun:n}=await m(async()=>await import(`./tool-provider-facade.js`),t),r=await m(async()=>await n([e.tool,...e.args],{allowFailure:e.allowFailure,signal:t,timeoutMs:e.timeoutMs}),t);return{stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode}}})}async function m(e,t){t?.throwIfAborted();try{let n=await e();return t?.throwIfAborted(),n}catch(e){throw t?.throwIfAborted(),e}}function h(){return Object.freeze({prepare:async e=>{if(e===`android`){let{ensureAndroidSdkPathConfigured:e}=await i();await e(process.env);return}if(e===`harmonyos`){let{ensureHarmonyToolchainPathConfigured:e}=await import(`./src4.js`).then(e=>e.b);await e()}}})}function g(e){let t=n(e.executable);return t&&r(e.args,t),e.args}function _(){return Object.freeze({commands:Object.freeze({which:async e=>await t(e)?e:void 0,run:async(t,n)=>{let r=await e(t.executable,g(t),{allowFailure:t.allowFailure,cwd:t.cwd,env:t.env?{...process.env,...t.env}:void 0,signal:n,timeoutMs:t.timeoutMs});return{stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode}}}),appleTools:p(),toolchains:h(),files:Object.freeze({isExecutable:async e=>await y(e),createTemporaryTextFile:async e=>await b(e)}),hostOs:v(process.platform),hostName:s.hostname(),homeDirectory:s.homedir(),observations:Object.freeze({deviceBooted:async e=>{let{markSimulatorBooted:t}=await import(`./simulator-facade.js`);t(e)}})})}function v(e){return e===`darwin`||e===`linux`||e===`win32`?e:`other`}async function y(e){try{return await c(e,o.X_OK),!0}catch{return!1}}async function b(e){let t=await l(a.join(s.tmpdir(),e.prefix)),n=a.join(t,`value${e.suffix}`),r=!1;return{path:n,readText:async()=>await u(n,`utf8`),writeText:async e=>await f(n,e,`utf8`),[Symbol.asyncDispose]:async()=>{r||(r=!0,await d(t,{recursive:!0,force:!0}))}}}export{_ as createDeviceInventoryHost,b as createTemporaryTextFile,h as n,p as r,g as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{D as e}from"./sdk-contracts.js";import{Qt as t}from"./sdk-batch.js";import{n}from"./scoped-provider.js";import{r,t as i}from"./platform-runtime-unavailable.js";import{a,t as o}from"./managed-device-scope.js";const s={ensureReady:`both`,deployApp:`both`,materializeAppSource:`both`,deployMaterializedApp:`both`,sendPushNotification:`both`,setSetting:`both`,readClipboard:`both`,writeClipboard:`both`,captureScreenshot:`android`},c=Object.freeze({available:!1,reason:`owner-capability-missing`,hint:`This operation has no verified managed-device automation path.`});function l(s){return Object.freeze({owner:s.owner,ownsDevice:()=>!1,inspectFacts:async e=>r(e,s.owner,i(c)),bind:async r=>{if(r.intent.kind!==`exact-owner`||!t(r.intent.owner,s.owner))throw new e(`COMMAND_FAILED`,`A managed local owner binds only under an exact-owner intent naming it`,{reason:`runtime-contract-invalid`});let i=r.scope.managedDevice;if(!i||!t(i.owner,s.owner)||i.fence.token!==r.intent.fence.token||i.fence.generation!==r.intent.fence.generation)throw new e(`COMMAND_FAILED`,`Managed automation requires its exact request authority.`,{reason:`runtime-contract-invalid`});o(i,r.device);let c=e=>i.run(()=>a(i,e)),l=await s.loadLocal(r.device.platform),f=await c(()=>l.bind({device:r.device,intent:{kind:`ordinary`},scope:r.scope})),p=u(f.facts);return Object.freeze({device:f.device,owner:s.owner,facts:p,operations:d(n({...f.operations},e=>c(async()=>(r.scope.signal.throwIfAborted(),await i.admit(async()=>(r.scope.signal.throwIfAborted(),await e()))))),p),[Symbol.asyncDispose]:async()=>await c(async()=>await f[Symbol.asyncDispose]())})},shutdown:async()=>void 0})}function u(e){let t=Object.fromEntries(Object.entries(e.operations).map(([t,n])=>{let r=s[t];return[t,(e.device.family===`android`||e.device.family===`apple`&&e.device.appleOs===`ios`)&&(r===`both`||r===e.device.family)?n:c]}));return Object.freeze({device:e.device,operations:Object.freeze(t)})}function d(e,t){let n={};for(let[r,i]of Object.entries(e))t.operations[r]?.available===!0&&(n[r]=i);return Object.freeze(n)}export{l as createManagedLocalRuntimeOwner};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as e}from"./rolldown-runtime.js";import{
|
|
1
|
+
import{r as e}from"./rolldown-runtime.js";import{D as t}from"./sdk-contracts.js";import{a as n,i as r,r as i}from"./sdk-batch-runner.js";import{d as a,l as o}from"./sdk-device.js";import{n as s}from"./session.js";import{t as c}from"./platform-runtime-android-mechanics.js";var l=e({resolveRequestedOpenSurface:()=>d,resolveSessionAppBundleIdForTarget:()=>S,validateOpenRelaunchTarget:()=>g});const u=new Set([`app`,`desktop`,`frontmost-app`]);function d(e){let{device:t,surfaceFlag:n,openTarget:r,existingSurface:i}=e;return t.platform===`linux`?f(n,r,i):a(t)?p(n,r,i):m(n)}function f(e,n,r){if(!e)return r??`app`;let i=s(e);if(!u.has(i))throw new t(`INVALID_ARGS`,`Linux supports --surface app, desktop, and frontmost-app (got "${e}")`);return h(i,n),i}function p(e,t,n){if(!e)return n??`app`;let r=s(e);return r!==`app`&&r!==`menubar`&&h(r,t),r}function m(e){if(e)throw new t(`INVALID_ARGS`,`surface is only supported on macOS and Linux`);return`app`}function h(e,n){if(e!==`app`&&e!==`menubar`&&n)throw new t(`INVALID_ARGS`,`open --surface ${e} does not accept an app target`)}async function g(e){let{target:t,platform:n,surface:r}=e;if(t&&i(t))return`open --relaunch does not support URL targets.`;if(r!==void 0&&r!==`app`)return`open --relaunch is supported only for app surfaces.`;if(n===`android`&&t){let{classifyAndroidAppTarget:e,formatAndroidInstalledPackageRequiredMessage:n}=await c();if(e(t)===`binary`)return n(t)}}async function _(e,t,s){if(!(!o(e.platform)||!t))return i(t)?a(e)?void 0:e.kind===`device`?n(s,t):r(t)?void 0:s??await v(e,t):await y(e,t)}async function v(e,t){try{let{resolveIosSimulatorDeepLinkBundleId:n}=await import(`./app-resolution-facade.js`);return await n(e,t)}catch{return}}async function y(e,t){try{let{resolveIosApp:n}=await import(`./app-resolution-facade.js`);return await n(e,t)}catch{return}}function b(e,t){return e.platform===`android`&&!!(t&&i(t))}function x(e){let t=e?.trim();if(!(!t||i(t)||!t.includes(`.`)))return t}async function S(e,t,n){return e.platform===`harmonyos`?x(t)??n:await _(e,t,n)??await C(e,t)??(b(e,t)?n:void 0)}async function C(e,t){if(!(e.platform!==`android`||!t))try{let{resolveAndroidPackageForOpen:n}=await c();return await n(e,t)}catch{return}}export{g as i,d as n,S as r,l as t};
|