agent-device 0.20.7 → 0.20.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +94 -31
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.20.7.apk → agent-device-android-ime-helper-0.20.9.apk} +0 -0
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.9.apk.sha256 +1 -0
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.20.7.manifest.json → agent-device-android-ime-helper-0.20.9.manifest.json} +4 -4
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.20.7.apk → agent-device-android-snapshot-helper-0.20.9.apk} +0 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.9.apk.sha256 +1 -0
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.20.7.manifest.json → agent-device-android-snapshot-helper-0.20.9.manifest.json} +6 -6
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.h +3 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.m +13 -7
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+AXSnapshotFallback.swift +4 -112
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +5 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+FlatSnapshotFiltering.swift +9 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+PrivateAXPresentation.swift +90 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+RecordingTests.swift +4 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +46 -10
- package/dist/src/agent-browser-tool.js +1 -1
- package/dist/src/agent-device-client.js +2 -2
- package/dist/src/android-adb.d.ts +5 -5
- package/dist/src/android-adb.js +1 -1
- package/dist/src/android.js +1 -1
- package/dist/src/app-helpers.js +1 -1
- package/dist/src/app-lifecycle.js +6 -7
- package/dist/src/app-lifecycle2.js +2 -2
- package/dist/src/app-log-reconnect.js +1 -1
- package/dist/src/app-log-runtime.js +3 -3
- package/dist/src/app-resolution.js +2 -2
- package/dist/src/app-state.js +2 -0
- package/dist/src/appearance.js +1 -0
- package/dist/src/apps.js +5 -5
- package/dist/src/artifacts.d.ts +1 -1
- package/dist/src/audio-probe.js +1 -1
- package/dist/src/backend-snapshot-options.js +1 -0
- package/dist/src/boot-diagnostics.js +2 -2
- package/dist/src/bounds.js +1 -0
- package/dist/src/byte-limit-stream.js +1 -0
- package/dist/src/cancel.js +1 -0
- package/dist/src/cli-config.js +1 -1
- package/dist/src/cli-help.js +25 -20
- package/dist/src/cli.js +6 -6
- package/dist/src/client-metro.js +1 -1
- package/dist/src/command-catalog.js +1 -0
- package/dist/src/command-metadata.js +1 -1
- package/dist/src/command-schema.js +1 -1
- package/dist/src/command-surface.js +1 -1
- package/dist/src/config.js +1 -0
- package/dist/src/connection-runtime.js +1 -1
- package/dist/src/connection.js +3 -3
- package/dist/src/contracts.js +1 -1
- package/dist/src/debug-symbols.js +1 -1
- package/dist/src/device-claim-inspection.js +1 -1
- package/dist/src/device-input-state.js +1 -1
- package/dist/src/device-ready.js +1 -0
- package/dist/src/device2.js +2 -2
- package/dist/src/dispatch.js +1 -0
- package/dist/src/entities.js +1 -1
- package/dist/src/find.js +1 -1
- package/dist/src/finders.js +1 -1
- package/dist/src/generic-settle.js +1 -1
- package/dist/src/generic.js +1 -1
- package/dist/src/handler-utils.js +1 -0
- package/dist/src/harmonyos.js +1 -1
- package/dist/src/hdc.js +1 -0
- package/dist/src/helper-package-install.js +1 -0
- package/dist/src/helper.js +2 -2
- package/dist/src/host-process.js +3 -2
- package/dist/src/ime-lifecycle.js +2 -9
- package/dist/src/ime-recovery-marker.js +1 -0
- package/dist/src/index.d.ts +35 -26
- package/dist/src/index.js +1 -1
- package/dist/src/input-actions.js +3 -3
- package/dist/src/input-actions2.js +1 -1
- package/dist/src/input-actions3.js +1 -1
- package/dist/src/install-artifact.js +1 -1
- package/dist/src/install-artifact2.js +1 -1
- package/dist/src/install-source2.js +1 -1
- package/dist/src/interaction-common.js +1 -0
- package/dist/src/interaction-runtime.js +1 -1
- package/dist/src/interaction-snapshot.js +1 -1
- package/dist/src/interaction.js +1 -1
- package/dist/src/interaction2.js +1 -0
- package/dist/src/interactor.js +2 -2
- package/dist/src/interactor2.js +1 -1
- package/dist/src/interactors.js +1 -0
- package/dist/src/internal/bin.js +1 -1
- package/dist/src/internal/daemon.js +4 -29
- package/dist/src/internal/png-worker.js +1 -1
- package/dist/src/inventory.js +1 -1
- package/dist/src/inventory2.js +1 -1
- package/dist/src/keyed-lock.js +1 -0
- package/dist/src/lease-context.js +1 -1
- package/dist/src/lease.js +1 -1
- package/dist/src/limrun-runtime-dependencies.js +1 -1
- package/dist/src/limrun.d.ts +3 -1
- package/dist/src/limrun.js +1 -1
- package/dist/src/linux.js +1 -1
- package/dist/src/location-coordinates.js +1 -0
- package/dist/src/logcat.js +1 -1
- package/dist/src/manifest.js +1 -1
- package/dist/src/observability.js +1 -0
- package/dist/src/output-path.js +1 -0
- package/dist/src/owner-identity.js +1 -1
- package/dist/src/perf.js +4 -0
- package/dist/src/physical-device-control.js +1 -1
- package/dist/src/platform-runtime-app-log-process.js +1 -1
- package/dist/src/platform-runtime-host.js +1 -1
- package/dist/src/platform-runtime-open-target.js +1 -0
- package/dist/src/platform-runtime-operation-host.js +4 -4
- package/dist/src/platform-runtime-runtime-hints.js +2 -0
- package/dist/src/platform-runtime-screen-recording-android-host.js +1 -0
- package/dist/src/platform-runtime-screen-recording-apple-host.js +1 -0
- package/dist/src/platform-runtime-screen-recording-apple-runner-host.js +1 -0
- package/dist/src/platform-runtime-screen-recording-apple-runner-transport.js +1 -0
- package/dist/src/platform-runtime-screen-recording-apple-simulator-host.js +1 -0
- package/dist/src/platform-runtime-screen-recording-apple-transport.js +1 -0
- package/dist/src/platform-runtime-screen-recording-finalizer-host.js +1 -0
- package/dist/src/platform-runtime-screen-recording-harmony-host.js +1 -0
- package/dist/src/platform-runtime-screen-recording-output-host.js +1 -0
- package/dist/src/platform-runtime-screen-recording-web-host.js +1 -0
- package/dist/src/platform-runtime.js +1 -1
- package/dist/src/platform-runtime2.js +1 -0
- package/dist/src/plist.js +1 -1
- package/dist/src/png-resize.js +1 -0
- package/dist/src/png-worker-contract.js +1 -1
- package/dist/src/prepare-kind.js +13 -13
- package/dist/src/process-lock.js +1 -1
- package/dist/src/project-runtime.js +1 -0
- package/dist/src/provider-webdriver.js +1 -1
- package/dist/src/provider.js +1 -1
- package/dist/src/proxy.js +1 -1
- package/dist/src/react-native.js +1 -1
- package/dist/src/record-runtime.js +1 -0
- package/dist/src/record-trace.js +1 -1
- package/dist/src/recording-export-quality.js +1 -0
- package/dist/src/recording-telemetry.js +1 -0
- package/dist/src/registry.js +29 -26
- package/dist/src/replay.js +2 -2
- package/dist/src/reporting.js +3 -3
- package/dist/src/rolldown-runtime.js +1 -0
- package/dist/src/runner-client.js +1 -1
- package/dist/src/runner-disposal.js +1 -1
- package/dist/src/runner-lease.js +1 -1
- package/dist/src/runner-sequence.js +1 -1
- package/dist/src/runtime-transport.js +1 -1
- package/dist/src/runtime.js +3 -3
- package/dist/src/runtime2.js +4 -3
- package/dist/src/runtime3.js +1 -3
- package/dist/src/runtime4.js +3 -1
- 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 -0
- package/dist/src/runtime9.js +1 -0
- package/dist/src/scoped-provider.js +1 -0
- package/dist/src/screenshot-density.js +1 -0
- package/dist/src/screenshot-geometry.js +1 -0
- package/dist/src/screenshot-result.js +4 -4
- package/dist/src/screenshot.js +1 -1
- package/dist/src/sdk-android-adb.d.ts +20 -2
- package/dist/src/sdk-android-adb.js +4 -4
- package/dist/src/sdk-batch-runner.js +3 -3
- package/dist/src/sdk-contracts.d.ts +3 -3
- package/dist/src/sdk-contracts.js +2 -2
- package/dist/src/sdk-device.js +1 -1
- package/dist/src/sdk-finders.js +1 -1
- package/dist/src/sdk-io.js +1 -1
- package/dist/src/sdk-selectors.d.ts +24 -20
- package/dist/src/sdk-selectors.js +1 -1
- package/dist/src/sdk.js +1 -0
- package/dist/src/selector-runtime.js +1 -1
- package/dist/src/selectors.d.ts +1 -1
- package/dist/src/selectors.js +1 -1
- package/dist/src/server.js +2 -2
- package/dist/src/session-target-evidence.js +1 -1
- package/dist/src/session.js +1 -30
- package/dist/src/session2.js +28 -0
- package/dist/src/setting-state.js +1 -1
- package/dist/src/shared.js +1 -1
- package/dist/src/simctl.js +1 -0
- package/dist/src/simulator-state.js +1 -0
- package/dist/src/simulator.js +1 -1
- package/dist/src/snapshot-runtime.js +1 -1
- package/dist/src/snapshot-session.js +1 -1
- package/dist/src/snapshot.js +8 -1
- package/dist/src/snapshot2.js +1 -1
- package/dist/src/snapshot3.js +1 -0
- package/dist/src/src.js +1 -1
- package/dist/src/src2.js +1 -2
- package/dist/src/src3.js +2 -1
- package/dist/src/string-enum.js +1 -0
- package/dist/src/tool-provider.js +3 -3
- package/dist/src/tool-provider2.js +1 -1
- package/dist/src/update-check.js +1 -1
- package/dist/src/verdict.js +1 -0
- package/dist/src/verified-file.js +1 -0
- package/dist/src/version.js +1 -1
- package/dist/src/video.js +23 -0
- package/package.json +8 -6
- package/server.json +3 -3
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.7.apk.sha256 +0 -1
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.7.apk.sha256 +0 -1
- package/dist/src/context.js +0 -1
- package/dist/src/interaction-touch-reference-frame.js +0 -1
- package/dist/src/notifications.js +0 -1
- package/dist/src/platform-runtime-toolchain-host.js +0 -1
- package/dist/src/runner-provider.js +0 -1
- package/dist/src/text-surface.js +0 -1
- package/dist/src/tool-provider3.js +0 -1
- package/skills/agent-device/SKILL.md +0 -20
- package/skills/dogfood/SKILL.md +0 -27
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{
|
|
2
|
-
`).map(e=>e.trim()).filter(e=>/^([a-zA-Z0-9_]+\.)+[a-zA-Z0-9_]+$/.test(e))}function
|
|
1
|
+
import{_ as e}from"./sdk-contracts.js";import"./sdk-android-adb.js";import{n as t}from"./hdc.js";function n(e){return e.split(`
|
|
2
|
+
`).map(e=>e.trim()).filter(e=>/^([a-zA-Z0-9_]+\.)+[a-zA-Z0-9_]+$/.test(e))}function r(e){let t=a(e);if(!t)return;let n=t.hapModuleInfos?.find(e=>e.mainElementName);if(n?.mainElementName)return{ability:n.mainElementName,module:n.moduleName}}function i(e){let t=a(e),n=t?.applicationInfo?.isSystemApp??t?.appInfo?.isSystemApp;return typeof n==`boolean`?n:void 0}function a(e){let t=e.indexOf(`{`);if(t!==-1)try{return JSON.parse(e.slice(t))}catch{return}}async function o(r,i,a={}){if(i===`all`)return s(n((await t(r,[`shell`,`bm`,`dump`,`-a`],{timeoutMs:15e3,signal:a.signal})).stdout));let o=new AbortController,u=setTimeout(()=>o.abort(),6e4),d=l(a.signal,o.signal);try{return s(await c(r,n((await t(r,[`shell`,`bm`,`dump`,`-a`],{timeoutMs:15e3,signal:d})).stdout),d))}catch(t){throw o.signal.aborted?new e(`COMMAND_FAILED`,`Timed out while classifying HarmonyOS application inventory`,{hint:`Use apps --all to list bundles without per-bundle classification, then retry after the device is responsive.`}):t}finally{clearTimeout(u)}}function s(e){return e.map(e=>({package:e,name:e.split(`.`).at(-1)??e}))}async function c(n,r,a){let o=Array(r.length),s=new AbortController,c=l(a,s.signal),u=0,d,f=Math.min(4,r.length),p=Array.from({length:f},async()=>{try{for(;;){c?.throwIfAborted();let a=u++;if(a>=r.length)return;let s=r[a];if(!s)return;let l=i((await t(n,[`shell`,`bm`,`dump`,`-n`,s],{timeoutMs:15e3,signal:c})).stdout);if(l===void 0)throw new e(`COMMAND_FAILED`,`Could not determine whether ${s} is a system application`,{hint:`Use apps --all to list all bundles when Bundle Manager does not expose applicationInfo.isSystemApp.`});o[a]=l}}catch(e){throw!c?.aborted&&d===void 0&&(d=e),s.abort(),e}}),m=await Promise.allSettled(p);if(d!==void 0)throw d;let h=m.find(e=>e.status===`rejected`);if(h)throw h.reason;return r.filter((e,t)=>!o[t])}function l(...e){let t=e.filter(e=>!!e);if(t.length!==0)return t.length===1?t[0]:AbortSignal.any(t)}async function u(n,i,a){let o=a?.activity?{ability:a.activity}:r((await t(n,[`shell`,`bm`,`dump`,`-n`,i],{signal:a?.signal,timeoutMs:15e3})).stdout);if(!o)throw new e(`COMMAND_FAILED`,`Could not determine a launchable ability for ${i}`,{hint:`Pass --activity with the HarmonyOS ability name, or check that the bundle is installed.`});let s=[`shell`,`aa`,`start`,`-a`,o.ability,`-b`,i];o.module&&s.push(`-m`,o.module);let c=await t(n,s,{signal:a?.signal});if(!c.stdout.includes(`start ability successfully`))throw new e(`COMMAND_FAILED`,`Failed to start ${i}`,{details:{output:c.stdout.trim()}})}async function d(e,n){await t(e,[`shell`,`aa`,`force-stop`,n])}export{d as closeHarmonyApp,o as listHarmonyApps,u as openHarmonyApp};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{ut as e}from"./sdk-batch-runner.js";import{NotFoundError as t}from"@limrun/api";import{createInstanceClient as n}from"@limrun/api/instance-client";import{createInstanceClient as r}from"@limrun/api/ios-client";async function i(e){try{return e.descriptor.platform===`ios`?await a(e):await o(e)}catch(e){if(e instanceof t)return{status:`missing`};throw e}}async function a(e){let t=await s(async()=>await e.limrun.iosInstances.get(e.descriptor.instanceId,{timeout:5e3,maxRetries:0,signal:e.signal}),e.descriptor);if(t.status!==`active`)return t;let{instance:n}=t,i=await r({apiUrl:t.apiUrl,token:n.status.token,logLevel:`warn`});return{status:`opened`,reader:{platform:`ios`,leaseId:e.descriptor.leaseId,instanceId:e.descriptor.instanceId,readLogs:async(e,t)=>await i.appLogTail(e,t),[Symbol.asyncDispose]:async()=>i.disconnect()}}}async function o(t){let r=await s(async()=>await t.limrun.androidInstances.get(t.descriptor.instanceId,{timeout:5e3,maxRetries:0,signal:t.signal}),t.descriptor);if(r.status!==`active`)return r;let{instance:i}=r;if(!i.status.adbWebSocketUrl)return{status:`missing`};let a=await n({apiUrl:r.apiUrl,adbUrl:i.status.adbWebSocketUrl,token:i.status.token,logLevel:`warn`}),o=new e,c=!1;o.defer(async()=>{c||a.disconnect()});try{let e=await a.startAdbTunnel();o.defer(async()=>{c||e.close()});let n=`${e.address.address}:${e.address.port}`,r=async(e,r)=>await t.dependencies.host.runAdb([`-s`,n,...e],r),i={platform:`android`,leaseId:t.descriptor.leaseId,instanceId:t.descriptor.instanceId,readLogs:async(e,n)=>await t.dependencies.android.readLogs(r,n),[Symbol.asyncDispose]:async()=>{await t.dependencies.host.runAdb([`disconnect`,n],{allowFailure:!0,timeoutMs:1e4}).catch(()=>void 0);let r=(await Promise.allSettled([Promise.resolve().then(()=>e.close()),Promise.resolve().then(()=>a.disconnect())])).flatMap(e=>e.status===`rejected`?[e.reason]:[]);if(r.length===1)throw r[0];if(r.length>1)throw AggregateError(r,`Limrun Android app-log reader cleanup failed`)}};return c=!0,{status:`opened`,reader:i}}finally{await o[Symbol.asyncDispose]()}}async function s(e,t){let n=await e();return c(n.metadata.labels,t)?n.status.state===`terminated`||!n.status.apiUrl?{status:`missing`}:{status:`active`,instance:n,apiUrl:n.status.apiUrl}:{status:`ownership-lost`}}function c(e,t){return e?.provider===`limrun`&&e.leaseId===t.leaseId}export{i as reconnectLimrunAppLogReader};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{_ as e}from"./sdk-contracts.js";import{
|
|
2
|
-
`)?r:`${r}\n`),a=`active`}catch{if(o)return;a=`recovering`}await e.host.clock.sleep(1e3)}})(),l;return
|
|
1
|
+
import{_ as e}from"./sdk-contracts.js";import{B as t,R as n,St as r,at as i,it as a,ot as o,tt as s,ut as c,wt as l}from"./sdk-batch-runner.js";import{a as u,i as d,s as f}from"./src.js";import{c as p,g as m,h,m as g,n as _,s as v,v as y,x as b}from"./src3.js";const x=Object.freeze({resourceKind:s,version:1,encode:e=>({...e}),decode:e=>e.transport!==`limrun-log-poller`||e.platform!==`ios`&&e.platform!==`android`||!C(e.leaseId)||!C(e.instanceId)||!C(e.appBundleId)||!C(e.outputPath)?{status:`invalid`,message:`Invalid Limrun app-log descriptor`}:{status:`decoded`,descriptor:Object.freeze({transport:`limrun-log-poller`,platform:e.platform,leaseId:e.leaseId,instanceId:e.instanceId,appBundleId:e.appBundleId,outputPath:e.outputPath})}});function S(e){if(e.device.platform===`apple`&&!e.device.appleOs)throw TypeError(`Limrun Apple app-log persistence requires an explicit appleOs identity`);return y({resourceKind:s,sessionId:e.sessionId,device:{id:e.device.id,family:e.device.platform,...e.device.appleOs===void 0?{}:{appleOs:e.device.appleOs},kind:e.device.kind,...e.device.target===void 0?{}:{target:e.device.target},...e.device.iosPhysicalDeviceBackend===void 0?{}:{iosPhysicalDeviceBackend:e.device.iosPhysicalDeviceBackend}},owner:e.owner,fence:e.fence,lifecycle:`open`,descriptor:b(x,e.descriptor)})}function C(e){return typeof e==`string`&&e.trim().length>0}async function w(e){let t=new c,n=!1;t.defer(async()=>{n||await e.reader[Symbol.asyncDispose]()});try{let r=await e.host.outputs.readTail(e.outputPath,256*1024),i=await e.host.outputs.openAppend(e.outputPath);t.defer(async()=>{n||await i[Symbol.asyncDispose]()});let a=T(e,i,ie(r));return n=!0,a}finally{await t[Symbol.asyncDispose]()}}function T(e,t,n){let r=D(e.reader),i=e.host.clock.now(),a=`active`,o=!1,s=n,c=(async()=>{for(;!o;){try{let n=await ee(e);if(n.status===`timeout`){a=`failed`;return}if(o)return;let r=te(s,n.text);s=n.text,r&&await t.write(r.endsWith(`
|
|
2
|
+
`)?r:`${r}\n`),a=`active`}catch{if(o)return;a=`recovering`}await e.host.clock.sleep(1e3)}})(),l;return g({inspect:()=>({backend:r,state:a,startedAt:i}),finish:async()=>l??=(async()=>(o=!0,await c,(await E([e.reader,t])).length>0?(a=`failed`,{status:`cleanup-pending`,reason:`transport-failed`,message:`Limrun app-log cleanup did not settle every owned resource`}):(a=`ended`,{status:`completed`,result:{backend:r,outputPath:e.outputPath,completedAt:e.host.clock.now()}})))()})}async function ee(e){let t=new AbortController,n=d(e.reader.readLogs(e.appBundleId,1e3),t.signal,`App-log provider read aborted`).then(e=>({status:`read`,text:e}));try{let r=await Promise.race([n,e.host.clock.sleep(5e3,t.signal).then(()=>({status:`timeout`}))]);return r.status===`timeout`&&(t.abort(),await n.catch(()=>void 0)),r}finally{t.abort()}}function te(e,t){if(!e||!t)return t;let n=ne(t),r=Math.min(e.length,t.length),i=e.slice(e.length-r);return t.slice(re(i,t,n))}function ne(e){let t=new Uint32Array(e.length),n=0;for(let r=1;r<e.length;r+=1){for(;n>0&&e[r]!==e[n];)n=t[n-1];e[r]===e[n]&&(n+=1),t[r]=n}return t}function re(e,t,n){let r=0;for(let i=0;i<e.length;i+=1){for(;r>0&&e[i]!==t[r];)r=n[r-1];e[i]===t[r]&&(r+=1),r===t.length&&i<e.length-1&&(r=n[r-1])}return r}function ie(e){return e.split(`
|
|
3
3
|
`).filter(e=>!e.startsWith(`[agent-device][mark]`)).join(`
|
|
4
|
-
`)}async function
|
|
4
|
+
`)}async function E(e){return(await Promise.allSettled(e.map(async e=>await e[Symbol.asyncDispose]()))).flatMap(e=>e.status===`rejected`?[e.reason]:[])}function D(e){return e.platform===`ios`?`ios-simulator`:`android`}function O(e){return n({owner:`Limrun`,openTargetIdentity:`bundle-id`,closeBeforeRelaunch:!0,configureProviderPortReverse:async t=>await e.configurePortReverse(t),binding:t({device:e.device,signal:e.signal,resolveInteractor:t=>e.getInteractor(e.device,t)})})}function k(e){let t=f(e.id);return!t||e.target!==`mobile`?!1:t.platform===`ios`?e.platform===`apple`&&e.appleOs===`ios`&&e.kind===`simulator`&&e.iosPhysicalDeviceBackend===void 0:e.platform===`android`&&e.appleOs===void 0&&e.kind===`emulator`&&e.iosPhysicalDeviceBackend===void 0}const A=Object.freeze({available:!0}),j=Object.freeze({available:!1,reason:`owner-capability-missing`,hint:`The Limrun provider session is no longer active for this device.`}),M=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Push notifications are unavailable for Limrun provider-owned devices.`});function N(e,t){let n=F(e,t);return Object.freeze({deployApp:n,materializeAppSource:n,deployMaterializedApp:n,sendPushNotification:I(e,t)?M:j})}function P(e,t,n,r){let i=e.deployApp,a=e.deployMaterializedApp;return!N(e,t).deployApp.available||!i||!a?Object.freeze({}):Object.freeze({deployApp:async e=>R(await i(t,e,n,r)),materializeAppSource:async r=>await L(e.host,t,r,n),deployMaterializedApp:async e=>R(await a(t,e,n,r))})}function F(e,t){return k(t)&&I(e,t)&&e.deployApp&&e.deployMaterializedApp?A:j}function I(e,t){return e.isSessionActive?.(t)??e.ownsDevice(t)}async function L(e,t,n,r){return await(t.platform===`apple`?e.appleDeployment:e.androidDeployment).prepareArtifact(n,{signal:r})}function R(t){if(!t)throw new e(`UNSUPPORTED_OPERATION`,`The Limrun provider session is no longer active.`);return t}function z(e){return{...e,isSessionActive:e.hasLiveSession}}const B=Object.freeze({available:!0}),V=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun does not expose an exact-owner screen-recording runtime.`}),ae=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Headless boot is unavailable for provider-owned devices.`}),H=Object.freeze({available:!1,reason:`owner-capability-missing`,hint:`Limrun requires a matching live provider session for this device.`}),U=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Apple runner preparation is unavailable for Limrun-owned devices.`}),W=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun open requires a Limrun-owned iOS simulator or Android emulator.`}),G=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun close requires a Limrun-owned iOS simulator or Android emulator.`}),K=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Runtime hints are not applied to provider-owned devices.`}),q=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun port reverse requires an active Android Limrun session.`});function J(e,t){let n=oe(e,t),r=se(e,t),a=ce(e,t);return i({resolveOpenTarget:n,prepareApplicationOpen:n,openApplication:n,applyRuntimeHints:K,clearRuntimeHints:K,closeApplication:r,finalizeApplicationClose:r,prepareAppleRunner:U,configureProviderPortReverse:a})}function oe(e,t){return $(e)?t?B:H:W}function se(e,t){return $(e)?t?B:H:G}function ce(e,t){return t?e.platform===`android`?B:q:H}function le(t){let n=r(`limrun`,t.runtimeInstance),i=e=>$(e)&&t.ownsDevice(e),o=e=>i(e)&&t.hasLiveSession(e);return Object.freeze({owner:n,ownsDevice:i,inspectFacts:async e=>o(e)?X(t,e):a(e,n,{appLog:H,appState:H,appDeployment:H,network:H,readiness:H,shutdown:H,lifecycle:J(e,!1)}),bind:async r=>{if(r.intent.kind===`exact-owner`&&!l(r.intent.owner,n))throw new e(`UNSUPPORTED_OPERATION`,`Limrun app-log owner identity does not match`);if(!$(r.device))throw new e(`UNSUPPORTED_PLATFORM`,`Limrun app logs require an iOS simulator or Android emulator device identity`);let i=o(r.device);if(r.intent.kind!==`exact-owner`&&!i)throw new e(`UNSUPPORTED_OPERATION`,`Limrun provider session is no longer live for the selected device`,{reason:`provider-session-unavailable`});return ue(t,n,r.device,r.scope.signal,!i)},shutdown:async()=>void 0})}function ue(t,n,r,i,a){let s=a?de(t,r):X(t,r),c=u(),l=h({codec:x,reattach:async(e,n)=>{if(!Q(e,r)||!v(t.host,n.sessionId,e))return{status:`unreattachable`,reason:`descriptor-invalid`,message:`Limrun app-log descriptor does not match the bound device or owning session`};let a=await t.reconnect(e,i);return a.status===`missing`?{status:`missing`}:a.status===`ownership-lost`?{status:`unreattachable`,reason:`ownership-fence-lost`}:{status:`active`,handle:await w({host:t.host,reader:a.reader,appBundleId:e.appBundleId,outputPath:e.outputPath})}},cleanup:async(e,n)=>Q(e,r)&&v(t.host,n.sessionId,e)?{status:`cleaned`}:{status:`cleanup-pending`,reason:`ownership-fence-lost`,message:`Limrun app-log descriptor does not match the bound device or owning session`}}),d={appLogInspect:async()=>({backend:Z(r)}),appLogDoctor:async()=>({backend:Z(r),checks:{limrunSessionAvailable:await Y(t,r,i)},notes:[]}),appLogStart:async a=>{p(t.host,a),i.throwIfAborted();let o=await t.openCurrent(r);if(!o)throw new e(`UNSUPPORTED_OPERATION`,`Limrun app logs require an active instance`);let s={transport:`limrun-log-poller`,platform:o.platform,leaseId:o.leaseId,instanceId:o.instanceId,appBundleId:a.appBundleId,outputPath:a.outputPath},c=!1;try{i.throwIfAborted();let e=S({sessionId:a.sessionId,device:r,owner:n,fence:a.fence,descriptor:s});return c=!0,m(await w({host:t.host,reader:o,appBundleId:a.appBundleId,outputPath:a.outputPath}),e)}catch(e){throw c||await o[Symbol.asyncDispose](),e}},...l,networkDump:async e=>{let n=await t.host.appLogs.readRecent(e.sessionId,e.maxScanLines),i=Z(r),a=_(n.text,{...e,path:n.path,exists:n.exists,lineNumberOffset:n.skippedLines,backend:i}),o=a.entries.length===0?[`No HTTP(s) entries were found in recent session app logs.`]:[];return Object.freeze({source:`app-log`,backend:i,dump:a,notes:o})},ensureReady:async()=>({...r,booted:!0}),bootTarget:async()=>({...r,booted:!0}),listApps:async e=>await t.listApps(e.device,e.filter,i),...r.platform===`android`?{appState:async()=>await t.getAppState(r,i)}:{},...o(O({device:r,signal:i,getInteractor:t.getInteractor,configurePortReverse:t.configurePortReverse}),s.operations),...P(z(t),r,i,c)};return Object.freeze({device:r,owner:n,facts:s,operations:Object.freeze(a?{appLogReattach:l.appLogReattach,appLogCleanup:l.appLogCleanup}:d),[Symbol.asyncDispose]:async()=>await c[Symbol.asyncDispose]()})}async function Y(e,t,n){n.throwIfAborted();let r=await e.openCurrent(t);if(!r)return!1;try{n.throwIfAborted()}finally{await r[Symbol.asyncDispose]()}return!0}function X(e,t){let n=N(z(e),t);return Object.freeze({device:{family:t.platform,...t.appleOs===void 0?{}:{appleOs:t.appleOs},kind:t.kind,...t.target===void 0?{}:{target:t.target},...t.iosPhysicalDeviceBackend===void 0?{}:{iosPhysicalDeviceBackend:t.iosPhysicalDeviceBackend},providerMode:`provider-runtime`},operations:{appLogInspect:B,appLogDoctor:B,appLogStart:B,appLogReattach:B,appLogCleanup:B,...n,appState:t.platform===`android`?B:{available:!1,reason:`unsupported-provider-mode`,hint:`Limrun iOS appstate is session-owned; no sessionless provider foreground probe is exposed.`},networkDump:B,screenRecordingStart:V,screenRecordingReattach:V,screenRecordingCleanup:V,ensureReady:B,bootTarget:B,bootTargetHeadless:ae,listApps:B,shutdownTarget:{available:!1,reason:`unsupported-provider-mode`,hint:`Limrun owns the target lifecycle for provider-owned devices.`},...J(t,!0)}})}function de(e,t){let n=X(e,t);return Object.freeze({device:n.device,operations:{...n.operations,appLogInspect:H,appLogDoctor:H,appLogStart:H,appLogReattach:B,appLogCleanup:B,appState:H,networkDump:H,screenRecordingStart:H,screenRecordingReattach:H,screenRecordingCleanup:H,ensureReady:H,bootTarget:H,bootTargetHeadless:H,listApps:H,deployApp:H,materializeAppSource:H,deployMaterializedApp:H,sendPushNotification:H,shutdownTarget:H,...J(t,!1)}})}function Z(e){return e.platform===`apple`?`ios-simulator`:`android`}function Q(e,t){if(!$(t))return!1;let n=f(t.id);return n!==void 0&&n.leaseId===e.leaseId&&n.platform===e.platform&&(t.platform===`apple`?e.platform===`ios`:e.platform===`android`)}function $(e){let t=f(e.id);return!t||e.target!==`mobile`?!1:t.platform===`ios`?fe(e):pe(e)}function fe(e){return e.platform===`apple`&&e.appleOs===`ios`&&e.kind===`simulator`&&e.iosPhysicalDeviceBackend===void 0}function pe(e){return e.platform===`android`&&e.appleOs===void 0&&e.kind===`emulator`&&e.iosPhysicalDeviceBackend===void 0}export{le as createLimrunPlatformRuntimeOwner};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{
|
|
2
|
-
`)){let t=z.exec(e);t?.[1]&&n.push(t[1])}return n}async function H(e,t){if(!r(e)||e.kind!==`simulator`)return;let n=U(t);if(!n)return;let i=await K(e),a=[];for(let e of i)e.bundleId.startsWith(`com.callstack.agentdevice.runner`)||e.path&&(await J(p.join(e.path,`Info.plist`))).has(n)&&a.push(e);let o=a.filter(e=>e.applicationType===`User`);if(o.length===1)return o[0]?.bundleId;if(!(o.length>1))return a.length===1?a[0]?.bundleId:void 0}function U(e){return/^([A-Za-z][A-Za-z0-9+.-]*):/.exec(e.trim())?.[1]?.toLowerCase()}async function W(e,t){return i(e)?await D(t):e.kind===`simulator`?
|
|
1
|
+
import{n as e}from"./rolldown-runtime.js";import{_ as t}from"./sdk-contracts.js";import{K as n}from"./sdk-batch-runner.js";import{c as r,l as i}from"./sdk-device.js";import{_ as a}from"./app-lifecycle.js";import{t as o}from"./appearance.js";import{i as s,r as c,s as l}from"./tool-provider.js";import{n as u}from"./helper.js";import{a as d,n as f}from"./physical-device-control.js";import p from"node:path";import{fileURLToPath as m}from"node:url";const h={settings:`com.apple.systempreferences`},g=/^[a-z0-9-]+(?:\.[a-z0-9-]+)+$/,_={platform:`macos`,deviceId:`host`,variant:`all`},v=a();function y(e){return g.test(e)}async function b(e){let n=e.trim(),r=h[n.toLowerCase()];if(r)return r;if(y(n))return n;let i=v.get(_,n);if(i)return i;let a=(await D(`all`)).filter(e=>e.name.toLowerCase()===n.toLowerCase()),o=a[0];if(o!==void 0&&a.length===1)return v.set(_,n,o.bundleId);throw a.length>1?new t(`INVALID_ARGS`,`Multiple apps matched "${e}"`,{matches:a}):new t(`APP_NOT_INSTALLED`,`No app found matching "${e}"`)}async function x(e,r,i){let a=i?.url?.trim();if(a){if(!n(a))throw new t(`INVALID_ARGS`,`open <app> <url> requires a valid URL target`);let e=i?.appBundleId??await b(r);await O().openBundle(e,a);return}let o=r.trim();if(n(o)){await O().openTarget(o);return}let s=i?.appBundleId??await b(o);await O().openBundle(s)}async function S(e,n){let r=await b(n),i=await u(r);if(!(!i.running||i.terminated||i.forceTerminated))throw new t(`COMMAND_FAILED`,`Failed to close macOS app ${n}`,{bundleId:r,running:i.running,terminated:i.terminated,forceTerminated:i.forceTerminated})}async function C(){return await O().readClipboard()}async function w(e){await O().writeClipboard(e)}async function T(){return await O().readDarkMode()}async function E(e){let t=o(e),n=t===`toggle`?!await T():t===`dark`;await O().setDarkMode(n)}async function D(e){return await O().listApps(e)}function O(){let e=c().macosHost;if(!e)throw new t(`UNSUPPORTED_OPERATION`,`macOS host provider is not available`);return e}var k=e({buildAppNotInstalledError:()=>F,detectSoleRunningIosSimulatorApp:()=>B,findIosSimulatorInstalledApp:()=>I,invalidateIosAppResolutionCache:()=>N,listIosApps:()=>W,resolveIosApp:()=>P,resolveIosAppAlias:()=>L,resolveIosSimulatorDeepLinkBundleId:()=>H});const A={settings:`com.apple.Preferences`},j=a();function M(e){return{platform:`ios`,deviceId:e.id,variant:e.kind}}async function N(e,t){return await j.invalidateWhile(M(e),t)}async function P(e,n){if(i(e))return await b(n);let r=n.trim();if(r.includes(`.`))return r;let a=L(r);if(a!==r)return a;let o=M(e),s=j.get(o,r);if(s)return s;let c=(e.kind===`simulator`?await G(e):await f(e).listApps(e,`all`)).filter(e=>e.name.toLowerCase()===r.toLowerCase()),l=c[0];if(l!==void 0&&c.length===1)return j.set(o,r,l.bundleId);throw c.length>1?new t(`INVALID_ARGS`,`Multiple apps matched "${n}"`,{matches:c}):F(n)}function F(e){return new t(`APP_NOT_INSTALLED`,`No app found matching "${e}"`)}async function I(e,t){if(!r(e)||e.kind!==`simulator`||e.booted!==!0)return;let n=L(t.trim());if(!n)return;let i=await G(e);if(n.includes(`.`))return i.find(e=>e.bundleId===n)?.bundleId;let a=i.filter(e=>e.name.toLowerCase()===n.toLowerCase());return a.length===1?a[0]?.bundleId:void 0}function L(e){let t=e.trim();return A[t.toLowerCase()]??e}const R=3e3,z=/UIKitApplication:([^[\s]+)\[/;async function B(e){if(!(!r(e)||e.kind!==`simulator`||e.booted!==!0))try{let[t,n]=await Promise.all([V(e),G(e,{timeoutMs:R})]);if(t.length===0)return;let r=new Map(n.map(e=>[e.bundleId,e])),i=new Map;for(let e of t){let t=r.get(e);t&&i.set(t.bundleId,t)}return i.size===1?[...i.values()][0]:void 0}catch{return}}async function V(e){let t=await d(e,[`spawn`,e.id,`launchctl`,`list`],{allowFailure:!0,timeoutMs:R});if(t.exitCode!==0)return[];let n=[];for(let e of t.stdout.split(`
|
|
2
|
+
`)){let t=z.exec(e);t?.[1]&&n.push(t[1])}return n}async function H(e,t){if(!r(e)||e.kind!==`simulator`)return;let n=U(t);if(!n)return;let i=await K(e),a=[];for(let e of i)e.bundleId.startsWith(`com.callstack.agentdevice.runner`)||e.path&&(await J(p.join(e.path,`Info.plist`))).has(n)&&a.push(e);let o=a.filter(e=>e.applicationType===`User`);if(o.length===1)return o[0]?.bundleId;if(!(o.length>1))return a.length===1?a[0]?.bundleId:void 0}function U(e){return/^([A-Za-z][A-Za-z0-9+.-]*):/.exec(e.trim())?.[1]?.toLowerCase()}async function W(e,t){return i(e)?await D(t):e.kind===`simulator`?l(await G(e),t):await f(e).listApps(e,t)}async function G(e,t){return(await K(e,t)).map(e=>({bundleId:e.bundleId,name:e.name}))}async function K(e,t){let n=(await d(e,[`listapps`,e.id],{allowFailure:!0,timeoutMs:t?.timeoutMs})).stdout.trim();if(!n)return[];let r=null;if(n.startsWith(`{`))try{r=JSON.parse(n)}catch{r=null}if(!r&&n.startsWith(`{`))try{let e=await s(`plutil`,[`-convert`,`json`,`-o`,`-`,`-`],{allowFailure:!0,stdin:n,timeoutMs:t?.timeoutMs});e.exitCode===0&&e.stdout.trim().startsWith(`{`)&&(r=JSON.parse(e.stdout))}catch{r=null}return r?Object.entries(r).map(([e,t])=>{let n=q(t);return{bundleId:e,name:t.CFBundleDisplayName??t.CFBundleName??e,...n?{path:n}:{},...t.ApplicationType?{applicationType:t.ApplicationType}:{}}}):[]}function q(e){if(e.Path)return e.Path;if(e.Bundle)try{return m(e.Bundle)}catch{return}}async function J(e){let t=await s(`plutil`,[`-convert`,`json`,`-o`,`-`,e],{allowFailure:!0});if(t.exitCode!==0)return new Set;try{let e=JSON.parse(t.stdout),n=new Set;for(let t of e.CFBundleURLTypes??[])if(Array.isArray(t.CFBundleURLSchemes))for(let e of t.CFBundleURLSchemes)typeof e==`string`&&e.trim()&&n.add(e.trim().toLowerCase());return n}catch{return new Set}}export{H as a,C as c,P as i,E as l,I as n,S as o,W as r,x as s,k as t,w as u};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=[[`shell`,`dumpsys`,`window`,`windows`],[`shell`,`dumpsys`,`window`]],t=[[`shell`,`dumpsys`,`activity`,`activities`],[`shell`,`dumpsys`,`activity`]],n=[`mCurrentFocus=Window{`,`mFocusedApp=AppWindowToken{`,`mResumedActivity:`,`ResumedActivity:`];async function r(n,r,i){return await a(n,r,e,i)||await a(n,r,t,i)||{}}function i(e){let t=e.split(`
|
|
2
|
+
`);for(let e of n)for(let n of t){let t=n.indexOf(e);if(t===-1)continue;let r=o(n.slice(t+e.length));if(r)return r}return null}async function a(e,t,n,r){for(let a of n){r.throwIfAborted();let n=await e.run(t,{args:a,allowFailure:!0},r);r.throwIfAborted();let o=i(n.stdout);if(o)return o}return null}function o(e){let t=e.match(/\b([A-Za-z][A-Za-z0-9_]*(?:\.[A-Za-z0-9_]+)+)\/([A-Za-z0-9_.$]+)/);return t?.[1]&&t[2]?{package:t[1],activity:t[2]}:null}export{i as parseAndroidForegroundApp,r as readAndroidAppState};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{_ as e}from"./sdk-contracts.js";function t(t){let n=t.trim().toLowerCase();if(n===`light`)return`light`;if(n===`dark`)return`dark`;if(n===`toggle`)return`toggle`;throw new e(`INVALID_ARGS`,`Invalid appearance state: ${t}. Use light|dark|toggle.`)}export{t};
|
package/dist/src/apps.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import{
|
|
2
|
-
`).map(e=>e.trim()).filter(e=>e.length>0&&e!==`Current Status Bar Overrides:`&&!/^=+$/.test(e));for(let e of r){let r=/^DataNetworkType:\s+(\d+)$/.exec(e);if(r){let e=Number(r[1]),i=Oe[e];if(!i)throw new t(`COMMAND_FAILED`,`Unsupported simulator data network type: ${e}`);n.dataNetwork=i;continue}let i=/^WiFi Mode:\s+(\d+),\s+WiFi Bars:\s+(\d+)$/.exec(e);if(i){let e=ke[Number(i[1])];e&&(n.wifiMode=e),n.wifiBars=i[2];continue}let a=/^Cell Mode:\s+(\d+),\s+Cell Bars:\s+(\d+)$/.exec(e);if(a){let e=Number(a[1]),r=Ae[e];if(!r)throw new t(`COMMAND_FAILED`,`Unsupported simulator cellular mode: ${e}`);n.cellularMode=r,n.cellularBars=a[2];continue}let o=/^Operator Name:\s*(.*)$/.exec(e);if(o){n.operatorName=o[1]??``;continue}}return Object.keys(n).length===0?null:n}function Re(e){let t=[];return e.dataNetwork&&t.push(`--dataNetwork`,e.dataNetwork),e.wifiMode&&t.push(`--wifiMode`,e.wifiMode),e.wifiBars!==void 0&&(e.dataNetwork===`wifi`||e.wifiMode)&&t.push(`--wifiBars`,e.wifiBars),e.cellularMode&&t.push(`--cellularMode`,e.cellularMode),e.cellularBars!==void 0&&(e.cellularMode||ze(e.dataNetwork)||e.operatorName!==void 0)&&t.push(`--cellularBars`,e.cellularBars),e.operatorName!==void 0&&t.push(`--operatorName`,e.operatorName),t}function ze(e){return!!(e&&e!==`hide`&&e!==`wifi`)}function B(e,t,n){p({level:`warn`,phase:`ios_screenshot_status_bar_${t}`,data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,...w(n)}})}function V(e,t,n){return y(e,t,n)}const Be={ensureBooted:A,prepareStatusBarForScreenshot:je,captureWithRetry:Ue,normalizeDensity:Ye,captureWithRunner:W,shouldFallbackToRunner:q},H=new Map,U=new Map;async function Ve(e,t,n={}){if(u(e)){await W(e,t,n.appBundleId,n.fullscreen,n.runnerOptions);return}if(e.kind===`simulator`){await He(e,t,n);return}await T(e).captureScreenshot(e,t,{appBundleId:n.appBundleId,fullscreen:n.fullscreen,runnerOptions:n.runnerOptions,runRunnerCommand:O})}async function He(e,n,r={}){if(e.kind!==`simulator`)throw new t(`UNSUPPORTED_OPERATION`,`Simulator screenshot fallback flow supports only iOS simulators`);let i={...Be,...r.deps??{}};r.skipIosSimulatorBootCheck||await i.ensureBooted(e);let a=async()=>{};if(r.normalizeStatusBar===!0)try{a=await i.prepareStatusBarForScreenshot(e)}catch(t){K(e,`prepare_failed`,t)}try{try{await i.captureWithRetry(e,n),await i.normalizeDensity(e,n,r.pixelDensity);return}catch(t){let a=t;if(r.skipIosSimulatorBootCheck&&Je(t)){await i.ensureBooted(e);try{await i.captureWithRetry(e,n),await i.normalizeDensity(e,n,r.pixelDensity);return}catch(e){a=e}}if(!i.shouldFallbackToRunner(a))throw a;Ke(e,`simctl_screenshot`,a)}await i.captureWithRunner(e,n,r.appBundleId,r.fullscreen,r.runnerOptions),await i.normalizeDensity(e,n,r.pixelDensity)}finally{await a().catch(t=>K(e,`restore_failed`,t))}}async function Ue(e,t){let n=g.fromTimeoutMs(ae);await _(async({deadline:n})=>{await V(e,[`io`,e.id,`screenshot`,t],{timeoutMs:Math.max(1e3,n?.remainingMs()??2e4)})},{maxAttempts:5,baseDelayMs:ue,maxDelayMs:ce,jitter:.2,shouldRetry:e=>q(e)},{deadline:n,phase:`ios_simulator_screenshot`})}async function W(e,n,r,i,a){if(e.kind===`device`&&!u(e)){await T(e).captureScreenshot(e,n,{appBundleId:r,fullscreen:i,runnerOptions:a,preferRunner:!0,runRunnerCommand:O});return}let o=(await O(e,{command:`screenshot`,appBundleId:r,fullscreen:i,inlineScreenshot:!1},a)).message;if(!o)throw new t(`COMMAND_FAILED`,`Failed to capture iOS screenshot: runner returned no file path`);if(u(e)){await P.copyFile(o,n);return}if(e.kind===`simulator`){await We(e,o,n);return}throw new t(`COMMAND_FAILED`,`Unsupported Apple screenshot target`)}async function We(e,n,r){let i=g.fromTimeoutMs(oe),a=`Unable to locate runner container for simulator screenshot`,o=U.get(e.id);if(o){let t=await G(o,n,r);if(t.copied)return;a=t.error,U.delete(e.id)}for(let t of fe){let o=await V(e,[`get_app_container`,e.id,t,`data`],{allowFailure:!0,timeoutMs:Ge(i,oe,`runner screenshot container lookup`)});if(o.exitCode!==0){let e=o.stderr.trim();e&&(a=e);continue}let s=o.stdout.trim();if(!s){a=`simctl get_app_container returned empty output`;continue}let c=await G(s,n,r);if(c.copied){U.set(e.id,s);return}a=c.error}throw new t(`COMMAND_FAILED`,`Failed to capture iOS screenshot: ${a}`)}async function G(e,t,n){let r=`Runner screenshot was not found in the simulator container`;for(let i of qe(e,t))try{return await P.copyFile(i,n),{copied:!0}}catch(e){r=e instanceof Error?e.message:String(e)}return{copied:!1,error:r}}function Ge(e,n,r){let i=e.remainingMs();if(i>0)return i;throw new t(`COMMAND_FAILED`,`iOS ${r} timed out after ${n}ms`,{timeoutMs:n,step:r})}function Ke(e,t,n){let r=w(n);p({level:`warn`,phase:`ios_screenshot_fallback`,data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,from:t,to:`runner`,...r}})}function K(e,t,n){p({level:`warn`,phase:`ios_screenshot_status_bar_${t}`,data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,...w(n)}})}function qe(e,t){let n=N.resolve(e),r=t.trim();if(!r)return[];let i=[],a=new Set,o=e=>{let t=N.normalize(e);a.has(t)||(a.add(t),i.push(t))},s=r.replace(/^\/+/,``),c=s.replace(/\\/g,`/`);if(s&&o(N.join(n,s)),N.isAbsolute(r)&&o(N.normalize(r)),c.startsWith(`tmp/`))o(N.join(n,c));else{let e=c.lastIndexOf(`/tmp/`);if(e>=0){let t=c.slice(e+1);o(N.join(n,t))}}let l=N.basename(r);return l&&o(N.join(n,`tmp`,l)),i}function q(e){if(!(e instanceof t)||e.code!==`COMMAND_FAILED`)return!1;let n=S(e);return n.includes(`timeout waiting for screen surfaces`)||n.includes(`nsposixerrordomain`)&&n.includes(`code=60`)&&n.includes(`screenshot`)||n.includes(`timed out`)&&n.includes(`screenshot`)}function Je(e){if(!(e instanceof t)||e.code!==`COMMAND_FAILED`)return!1;let n=S(e);return n.includes(`not booted`)||n.includes(`current state: shutdown`)||n.includes(`current state is shutdown`)||n.includes(`current state=shutdown`)||n.includes(`state: shutdown`)||n.includes(`state=shutdown`)}async function Ye(e,t,n){let r=await Xe(e),i=me(await he(t),r,n);i&&await f(t,i.width,i.height)}async function Xe(e){let n=H.get(e.id);if(n!==void 0)return n;let r=await V(e,[`getenv`,e.id,`SIMULATOR_MAINSCREEN_SCALE`],{timeoutMs:se}),i=Number(r.stdout.trim());if(!Number.isFinite(i)||i<=0)throw new t(`COMMAND_FAILED`,`Failed to read iOS simulator screenshot scale from SIMULATOR_MAINSCREEN_SCALE`);return H.set(e.id,i),i}function J(e){if(!(e instanceof t)||e.code!==`COMMAND_FAILED`)return!1;let n=e.details??{};if(n.exitCode!==4)return!1;let r=String(n.stderr??``).toLowerCase();return r.includes(`fbsopenapplicationserviceerrordomain`)&&r.includes(`the request to open`)}async function Ze(e,t){let n=await E(re(e,[`get_app_container`,e.id,t]),{allowFailure:!0});if(n.exitCode!==0)return{installed:!1};let r=n.stdout.trim();if(!r)return{installed:!1};let i=await D(`plutil`,[`-extract`,`CFBundleExecutable`,`raw`,`-o`,`-`,`${r}/Info.plist`],{allowFailure:!0});if(i.exitCode!==0||!i.stdout.trim())return{installed:!0};let a=await D(`otool`,[`-l`,`${r}/${i.stdout.trim()}`],{allowFailure:!0});if(a.exitCode!==0)return{installed:!0};let o=a.stdout.toLowerCase();return{installed:!0,simulatorCompatible:o.includes(`iossimulator`)||o.includes(`platform 7`)}}function Qe(e){return e.installed?e.simulatorCompatible===!1?`ARCH_MISMATCH`:`PERSISTENT_LAUNCH_FAIL`:`APP_NOT_INSTALLED`}function $e(e){switch(e){case`ARCH_MISMATCH`:return`The app binary was not built for the simulator platform. Rebuild with a simulator destination or use a physical device.`;case`APP_NOT_INSTALLED`:return`The app bundle is not installed on this simulator. Run install before open.`;case`PERSISTENT_LAUNCH_FAIL`:return`The simulator repeatedly refused to launch the app. Inspect crash logs in Console.app or ~/Library/Logs/DiagnosticReports/ and consider reinstalling the app.`;default:return`The simulator failed to launch the app. Retry with --debug and inspect diagnostics log for details.`}}const Y=25e3;async function et(e,n,r){let i=r?.launchConsole?.trim(),a=r?.launchArgs;if(i&&(!l(e)||e.kind!==`simulator`))throw new t(`UNSUPPORTED_OPERATION`,ee);if(u(e)){if(a&&a.length>0)throw new t(`UNSUPPORTED_OPERATION`,`--launch-args is not supported on macOS; launch arguments are currently iOS-only.`);await xe(e,n,r);return}let f=r?.url?.trim();if(f){if(i)throw new t(`INVALID_ARGS`,d);if(!c(f))throw new t(`INVALID_ARGS`,`open <app> <url> requires a valid URL target`);if(e.kind===`simulator`){let t=!!a||o(f);if(r?.terminateRunningApp||t){let i=r?.appBundleId??await M(e,n);t?await rt(e,i,{...a?{launchArgs:a}:{},...r?.terminateRunningApp?{terminateRunningApp:!0}:{}}):await nt(e,i)}await X(e,f,void 0);return}let l=s(r?.appBundleId??await M(e,n),f);if(!l)throw new t(`INVALID_ARGS`,`Deep link open on iOS devices requires an active app bundle ID. Open the app first, then open the URL.`);await Q(e,l,{payloadUrl:f,launchArgs:a,runnerOptions:r?.runnerOptions});return}let p=n.trim();if(c(p)){if(i)throw new t(`INVALID_ARGS`,d);if(e.kind===`simulator`){await X(e,p,a);return}let n=s(r?.appBundleId,p);if(!n)throw new t(`INVALID_ARGS`,`Deep link open on iOS devices requires an active app bundle ID. Open the app first, then open the URL.`);await Q(e,n,{payloadUrl:p,launchArgs:a,runnerOptions:r?.runnerOptions});return}let m=r?.appBundleId??await M(e,n);if(e.kind===`simulator`){await rt(e,m,{...i?{launchConsole:i}:{},...a?{launchArgs:a}:{},...r?.terminateRunningApp?{terminateRunningApp:!0}:{}});return}await Q(e,m,{launchArgs:a,runnerOptions:r?.runnerOptions})}async function X(e,n,r){if(r&&r.length>0)throw new t(`INVALID_ARGS`,`--launch-args is not supported with iOS simulator URL opens (simctl openurl ignores launch args). Launch the app first with --launch-args, then issue the URL open in a separate call.`);await A(e),await b(e,[`openurl`,e.id,n])}async function tt(e){u(e)||e.kind===`simulator`&&await ge(e)!==`Booted`&&await A(e)}async function Z(e,t,n){if(u(e)){await ve(e,t);return}let r=await M(e,t);if(e.kind===`simulator`){await nt(e,r);return}await T(e).terminateApp(e,r,{runnerOptions:n,runRunnerCommand:O})}async function nt(e,n){await A(e);let r=C(e,[`terminate`,e.id,n]),i=await E(r,{allowFailure:!0,timeoutMs:de});if(i.exitCode!==0&&!i.stderr.toLowerCase().includes(`found nothing to terminate`))throw new t(`COMMAND_FAILED`,`xcrun exited with code ${i.exitCode}`,m(i,{cmd:`xcrun`,args:r}))}async function rt(e,n,r){await A(e);let i=0,a=g.fromTimeoutMs(x);try{await _(async({deadline:i})=>{if(i?.isExpired())throw new t(`COMMAND_FAILED`,`App launch deadline exceeded`,{timeoutMs:x});let a=C(e,it(e.id,n,r)),o=r?.launchConsole?await at(a,r.launchConsole):await E(a,{allowFailure:!0});if(o.exitCode!==0)throw new t(`COMMAND_FAILED`,`xcrun exited with code ${o.exitCode}`,m(o,{cmd:`xcrun`,args:a}))},{maxAttempts:10,baseDelayMs:1e3,maxDelayMs:5e3,jitter:.2,shouldRetry(e){return J(e)?(i+=1,i<3):!1}},{deadline:a})}catch(t){if(J(t)){let r=t,i=Qe(await Ze(e,n));r.details={...r.details,hint:$e(i)}}throw t}}function it(e,t,n){let r=[`launch`];return n?.launchConsole&&r.push(`--console-pty`),n?.terminateRunningApp&&r.push(`--terminate-running-process`),r.push(e,t),n?.launchArgs&&n.launchArgs.length>0&&r.push(...n.launchArgs),r}async function at(e,n){await P.mkdir(N.dirname(n),{recursive:!0});try{let t=await E(e,{allowFailure:!0,timeoutMs:Y});return await ot(n,t.stdout,t.stderr),t}catch(e){let r=(e instanceof t?e:void 0)?.details;if(r?.timeoutMs===Y){let e=typeof r.stdout==`string`?r.stdout:``,t=typeof r.stderr==`string`?r.stderr:``;return await ot(n,e,t),p({level:`warn`,phase:`ios_simulator_launch_console_capture_timeout`,data:{timeoutMs:Y,logPath:n,stdoutBytes:Buffer.byteLength(e),stderrBytes:Buffer.byteLength(t)}}),{stdout:e,stderr:t,exitCode:0}}throw e}}async function ot(e,t,n){await P.writeFile(e,st(t,n),`utf8`)}function st(e,t){return!e||!t||e.endsWith(`
|
|
3
|
-
`)||e.endsWith(`\r`)?`${e}${t}`:`${e}\n${t}`}async function Q(e,t,n){await
|
|
4
|
-
`).replace(/\n$/,``))}async function
|
|
5
|
-
`)){let e=r.trim();if(!e)continue;if(e===`service`){n=!0;continue}if(!n)continue;if(e.startsWith(`bundle identifier`))break;let i=/^([a-z-]+)\s+-\s+/.exec(e)?.[1];i!==void 0&&t.add(i)}return t}function
|
|
1
|
+
import{n as e}from"./rolldown-runtime.js";import{_ as t}from"./sdk-contracts.js";import{a as n,c as r,n as i,s as a}from"./location-coordinates.js";import{G as o,J as s,K as c,W as l,q as ee}from"./sdk-batch-runner.js";import{c as u,l as d}from"./sdk-device.js";import"./observability.js";import{A as f,f as p,h as m}from"./sdk-android-adb.js";import{i as h,o as te}from"./boot-diagnostics.js";import{n as ne,t as g}from"./setting-state.js";import{t as re}from"./appearance.js";import{n as ie,r as _,s as ae}from"./simctl.js";import{a as v,i as oe}from"./tool-provider.js";import{i as se}from"./helper.js";import{t as ce}from"./png-resize.js";import{i as le,n as ue}from"./screenshot-density.js";import{a as y,i as b,l as de,n as x,o as S,r as C}from"./physical-device-control.js";import{a as w,c as fe,d as pe,f as me,l as he,t as T,u as ge}from"./config.js";import{n as E}from"./runner-client.js";import{n as _e,r as D,t as O}from"./simulator.js";import{a as ve,c as ye,i as k,l as be,n as xe,o as Se,r as Ce,s as we,u as Te}from"./app-resolution.js";import A from"node:path";import{promises as j}from"node:fs";import"node:os";const Ee=[`--time`,`9:41`,`--dataNetwork`,`wifi`,`--wifiMode`,`active`,`--wifiBars`,`3`,`--batteryState`,`charged`,`--batteryLevel`,`100`],De={0:`hide`,1:`wifi`,6:`3g`,7:`4g`,8:`lte`,9:`lte-a`,10:`lte+`,11:`5g`,12:`5g+`,13:`5g-uwb`,14:`5g-uc`},Oe={1:`searching`,2:`failed`,3:`active`},ke={0:`notSupported`,1:`searching`,2:`failed`,3:`active`};function M(e,t,n){return _(e,t,n)}const N=new Set;async function Ae(e){let t=null,n=!1;if(Me(e))n=!0;else try{t=await Ne(e),n=!0}catch(t){R(e,`snapshot_failed`,t)}try{(!n||t)&&await Pe(e),await L(e,Ee)}catch(t){R(e,`prepare_failed`,t)}return async()=>{await je(e,n?t:null)}}async function je(e,t){if(await Pe(e),!t){F(e);return}await L(e,Ie(t)),P(e)}function P(e){N.delete(I(e))}function F(e){N.add(I(e))}function Me(e){return N.has(I(e))}function I(e){return`${e.platform}:${e.kind}:${e.id}`}async function Ne(e){return Fe(m(await M(e,[`status_bar`,e.id,`list`],{allowFailure:!0}),`Failed to read simulator status bar overrides`).stdout)}async function Pe(e){await M(e,[`status_bar`,e.id,`clear`])}async function L(e,t){t.length!==0&&await M(e,[`status_bar`,e.id,`override`,...t])}function Fe(e){let n={},r=e.split(`
|
|
2
|
+
`).map(e=>e.trim()).filter(e=>e.length>0&&e!==`Current Status Bar Overrides:`&&!/^=+$/.test(e));for(let e of r){let r=/^DataNetworkType:\s+(\d+)$/.exec(e);if(r){let e=Number(r[1]),i=De[e];if(!i)throw new t(`COMMAND_FAILED`,`Unsupported simulator data network type: ${e}`);n.dataNetwork=i;continue}let i=/^WiFi Mode:\s+(\d+),\s+WiFi Bars:\s+(\d+)$/.exec(e);if(i){let e=Oe[Number(i[1])];e&&(n.wifiMode=e),n.wifiBars=i[2];continue}let a=/^Cell Mode:\s+(\d+),\s+Cell Bars:\s+(\d+)$/.exec(e);if(a){let e=Number(a[1]),r=ke[e];if(!r)throw new t(`COMMAND_FAILED`,`Unsupported simulator cellular mode: ${e}`);n.cellularMode=r,n.cellularBars=a[2];continue}let o=/^Operator Name:\s*(.*)$/.exec(e);if(o){n.operatorName=o[1]??``;continue}}return Object.keys(n).length===0?null:n}function Ie(e){let t=[];return e.dataNetwork&&t.push(`--dataNetwork`,e.dataNetwork),e.wifiMode&&t.push(`--wifiMode`,e.wifiMode),e.wifiBars!==void 0&&(e.dataNetwork===`wifi`||e.wifiMode)&&t.push(`--wifiBars`,e.wifiBars),e.cellularMode&&t.push(`--cellularMode`,e.cellularMode),e.cellularBars!==void 0&&(e.cellularMode||Le(e.dataNetwork)||e.operatorName!==void 0)&&t.push(`--cellularBars`,e.cellularBars),e.operatorName!==void 0&&t.push(`--operatorName`,e.operatorName),t}function Le(e){return!!(e&&e!==`hide`&&e!==`wifi`)}function R(e,t,n){f({level:`warn`,phase:`ios_screenshot_status_bar_${t}`,data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,...b(n)}})}function z(e,t,n){return _(e,t,n)}const Re={ensureBooted:O,prepareStatusBarForScreenshot:Ae,captureWithRetry:Ve,normalizeDensity:qe,captureWithRunner:H,shouldFallbackToRunner:G},B=new Map,V=new Map;async function ze(e,t,n={}){if(d(e)){await H(e,t,n.appBundleId,n.fullscreen,n.runnerOptions);return}if(e.kind===`simulator`){await Be(e,t,n);return}await x(e).captureScreenshot(e,t,{appBundleId:n.appBundleId,fullscreen:n.fullscreen,runnerOptions:n.runnerOptions,runRunnerCommand:E})}async function Be(e,n,r={}){if(e.kind!==`simulator`)throw new t(`UNSUPPORTED_OPERATION`,`Simulator screenshot fallback flow supports only iOS simulators`);let i={...Re,...r.deps??{}};r.skipIosSimulatorBootCheck||await i.ensureBooted(e);let a=async()=>{};if(r.normalizeStatusBar===!0)try{a=await i.prepareStatusBarForScreenshot(e)}catch(t){W(e,`prepare_failed`,t)}try{try{await i.captureWithRetry(e,n),await i.normalizeDensity(e,n,r.pixelDensity);return}catch(t){let a=t;if(r.skipIosSimulatorBootCheck&&Ke(t)){await i.ensureBooted(e);try{await i.captureWithRetry(e,n),await i.normalizeDensity(e,n,r.pixelDensity);return}catch(e){a=e}}if(!i.shouldFallbackToRunner(a))throw a;We(e,`simctl_screenshot`,a)}await i.captureWithRunner(e,n,r.appBundleId,r.fullscreen,r.runnerOptions),await i.normalizeDensity(e,n,r.pixelDensity)}finally{await a().catch(t=>W(e,`restore_failed`,t))}}async function Ve(e,t){let n=h.fromTimeoutMs(pe);await te(async({deadline:n})=>{await z(e,[`io`,e.id,`screenshot`,t],{timeoutMs:Math.max(1e3,n?.remainingMs()??2e4)})},{maxAttempts:5,baseDelayMs:fe,maxDelayMs:he,jitter:.2,shouldRetry:e=>G(e)},{deadline:n,phase:`ios_simulator_screenshot`})}async function H(e,n,r,i,a){if(e.kind===`device`&&!d(e)){await x(e).captureScreenshot(e,n,{appBundleId:r,fullscreen:i,runnerOptions:a,preferRunner:!0,runRunnerCommand:E});return}let o=(await E(e,{command:`screenshot`,appBundleId:r,fullscreen:i,inlineScreenshot:!1},a)).message;if(!o)throw new t(`COMMAND_FAILED`,`Failed to capture iOS screenshot: runner returned no file path`);if(d(e)){await j.copyFile(o,n);return}if(e.kind===`simulator`){await He(e,o,n);return}throw new t(`COMMAND_FAILED`,`Unsupported Apple screenshot target`)}async function He(e,n,r){let i=h.fromTimeoutMs(w),a=`Unable to locate runner container for simulator screenshot`,o=V.get(e.id);if(o){let t=await U(o,n,r);if(t.copied)return;a=t.error,V.delete(e.id)}for(let t of de){let o=await z(e,[`get_app_container`,e.id,t,`data`],{allowFailure:!0,timeoutMs:Ue(i,w,`runner screenshot container lookup`)});if(o.exitCode!==0){let e=o.stderr.trim();e&&(a=e);continue}let s=o.stdout.trim();if(!s){a=`simctl get_app_container returned empty output`;continue}let c=await U(s,n,r);if(c.copied){V.set(e.id,s);return}a=c.error}throw new t(`COMMAND_FAILED`,`Failed to capture iOS screenshot: ${a}`)}async function U(e,t,n){let r=`Runner screenshot was not found in the simulator container`;for(let i of Ge(e,t))try{return await j.copyFile(i,n),{copied:!0}}catch(e){r=e instanceof Error?e.message:String(e)}return{copied:!1,error:r}}function Ue(e,n,r){let i=e.remainingMs();if(i>0)return i;throw new t(`COMMAND_FAILED`,`iOS ${r} timed out after ${n}ms`,{timeoutMs:n,step:r})}function We(e,t,n){let r=b(n);f({level:`warn`,phase:`ios_screenshot_fallback`,data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,from:t,to:`runner`,...r}})}function W(e,t,n){f({level:`warn`,phase:`ios_screenshot_status_bar_${t}`,data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,...b(n)}})}function Ge(e,t){let n=A.resolve(e),r=t.trim();if(!r)return[];let i=[],a=new Set,o=e=>{let t=A.normalize(e);a.has(t)||(a.add(t),i.push(t))},s=r.replace(/^\/+/,``),c=s.replace(/\\/g,`/`);if(s&&o(A.join(n,s)),A.isAbsolute(r)&&o(A.normalize(r)),c.startsWith(`tmp/`))o(A.join(n,c));else{let e=c.lastIndexOf(`/tmp/`);if(e>=0){let t=c.slice(e+1);o(A.join(n,t))}}let l=A.basename(r);return l&&o(A.join(n,`tmp`,l)),i}function G(e){if(!(e instanceof t)||e.code!==`COMMAND_FAILED`)return!1;let n=C(e);return n.includes(`timeout waiting for screen surfaces`)||n.includes(`nsposixerrordomain`)&&n.includes(`code=60`)&&n.includes(`screenshot`)||n.includes(`timed out`)&&n.includes(`screenshot`)}function Ke(e){if(!(e instanceof t)||e.code!==`COMMAND_FAILED`)return!1;let n=C(e);return n.includes(`not booted`)||n.includes(`current state: shutdown`)||n.includes(`current state is shutdown`)||n.includes(`current state=shutdown`)||n.includes(`state: shutdown`)||n.includes(`state=shutdown`)}async function qe(e,t,n){let r=await Je(e),i=ue(await le(t),r,n);i&&await ce(t,i.width,i.height)}async function Je(e){let n=B.get(e.id);if(n!==void 0)return n;let r=await z(e,[`getenv`,e.id,`SIMULATOR_MAINSCREEN_SCALE`],{timeoutMs:ge}),i=Number(r.stdout.trim());if(!Number.isFinite(i)||i<=0)throw new t(`COMMAND_FAILED`,`Failed to read iOS simulator screenshot scale from SIMULATOR_MAINSCREEN_SCALE`);return B.set(e.id,i),i}function K(e){if(!(e instanceof t)||e.code!==`COMMAND_FAILED`)return!1;let n=e.details??{};if(n.exitCode!==4)return!1;let r=String(n.stderr??``).toLowerCase();return r.includes(`fbsopenapplicationserviceerrordomain`)&&r.includes(`the request to open`)}async function Ye(e,t){let n=await v(ie(e,[`get_app_container`,e.id,t]),{allowFailure:!0});if(n.exitCode!==0)return{installed:!1};let r=n.stdout.trim();if(!r)return{installed:!1};let i=await oe(`plutil`,[`-extract`,`CFBundleExecutable`,`raw`,`-o`,`-`,`${r}/Info.plist`],{allowFailure:!0});if(i.exitCode!==0||!i.stdout.trim())return{installed:!0};let a=await oe(`otool`,[`-l`,`${r}/${i.stdout.trim()}`],{allowFailure:!0});if(a.exitCode!==0)return{installed:!0};let o=a.stdout.toLowerCase();return{installed:!0,simulatorCompatible:o.includes(`iossimulator`)||o.includes(`platform 7`)}}function Xe(e){return e.installed?e.simulatorCompatible===!1?`ARCH_MISMATCH`:`PERSISTENT_LAUNCH_FAIL`:`APP_NOT_INSTALLED`}function Ze(e){switch(e){case`ARCH_MISMATCH`:return`The app binary was not built for the simulator platform. Rebuild with a simulator destination or use a physical device.`;case`APP_NOT_INSTALLED`:return`The app bundle is not installed on this simulator. Run install before open.`;case`PERSISTENT_LAUNCH_FAIL`:return`The simulator repeatedly refused to launch the app. Inspect crash logs in Console.app or ~/Library/Logs/DiagnosticReports/ and consider reinstalling the app.`;default:return`The simulator failed to launch the app. Retry with --debug and inspect diagnostics log for details.`}}const q=25e3;async function Qe(e,n,r){let i=r?.launchConsole?.trim(),a=r?.launchArgs;if(i&&(!u(e)||e.kind!==`simulator`))throw new t(`UNSUPPORTED_OPERATION`,o);if(d(e)){if(a&&a.length>0)throw new t(`UNSUPPORTED_OPERATION`,`--launch-args is not supported on macOS; launch arguments are currently iOS-only.`);await we(e,n,r);return}let f=r?.url?.trim();if(f){if(i)throw new t(`INVALID_ARGS`,l);if(!c(f))throw new t(`INVALID_ARGS`,`open <app> <url> requires a valid URL target`);if(e.kind===`simulator`){let t=!!a||ee(f);if(r?.terminateRunningApp||t){let i=r?.appBundleId??await k(e,n);t?await Z(e,i,{...a?{launchArgs:a}:{},...r?.terminateRunningApp?{terminateRunningApp:!0}:{}}):await X(e,i)}await J(e,f,void 0);return}let o=s(r?.appBundleId??await k(e,n),f);if(!o)throw new t(`INVALID_ARGS`,`Deep link open on iOS devices requires an active app bundle ID. Open the app first, then open the URL.`);await Q(e,o,{payloadUrl:f,launchArgs:a,runnerOptions:r?.runnerOptions});return}let p=n.trim();if(c(p)){if(i)throw new t(`INVALID_ARGS`,l);if(e.kind===`simulator`){await J(e,p,a);return}let n=s(r?.appBundleId,p);if(!n)throw new t(`INVALID_ARGS`,`Deep link open on iOS devices requires an active app bundle ID. Open the app first, then open the URL.`);await Q(e,n,{payloadUrl:p,launchArgs:a,runnerOptions:r?.runnerOptions});return}let m=r?.appBundleId??await k(e,n);if(e.kind===`simulator`){await Z(e,m,{...i?{launchConsole:i}:{},...a?{launchArgs:a}:{},...r?.terminateRunningApp?{terminateRunningApp:!0}:{}});return}await Q(e,m,{launchArgs:a,runnerOptions:r?.runnerOptions})}async function J(e,n,r){if(r&&r.length>0)throw new t(`INVALID_ARGS`,`--launch-args is not supported with iOS simulator URL opens (simctl openurl ignores launch args). Launch the app first with --launch-args, then issue the URL open in a separate call.`);await O(e),await y(e,[`openurl`,e.id,n])}async function $e(e){d(e)||e.kind===`simulator`&&await _e(e)!==`Booted`&&await O(e)}async function Y(e,t,n){if(d(e)){await Se(e,t);return}let r=await k(e,t);if(e.kind===`simulator`){await X(e,r);return}await x(e).terminateApp(e,r,{runnerOptions:n,runRunnerCommand:E})}async function X(e,n){await O(e);let r=S(e,[`terminate`,e.id,n]),i=await v(r,{allowFailure:!0,timeoutMs:me});if(i.exitCode!==0&&!i.stderr.toLowerCase().includes(`found nothing to terminate`))throw new t(`COMMAND_FAILED`,`xcrun exited with code ${i.exitCode}`,p(i,{cmd:`xcrun`,args:r}))}async function Z(e,n,r){await O(e);let i=0,a=h.fromTimeoutMs(T);try{await te(async({deadline:i})=>{if(i?.isExpired())throw new t(`COMMAND_FAILED`,`App launch deadline exceeded`,{timeoutMs:T});let a=S(e,et(e.id,n,r)),o=r?.launchConsole?await tt(a,r.launchConsole):await v(a,{allowFailure:!0});if(o.exitCode!==0)throw new t(`COMMAND_FAILED`,`xcrun exited with code ${o.exitCode}`,p(o,{cmd:`xcrun`,args:a}))},{maxAttempts:10,baseDelayMs:1e3,maxDelayMs:5e3,jitter:.2,shouldRetry(e){return K(e)?(i+=1,i<3):!1}},{deadline:a})}catch(t){if(K(t)){let r=t,i=Xe(await Ye(e,n));r.details={...r.details,hint:Ze(i)}}throw t}}function et(e,t,n){let r=[`launch`];return n?.launchConsole&&r.push(`--console-pty`),n?.terminateRunningApp&&r.push(`--terminate-running-process`),r.push(e,t),n?.launchArgs&&n.launchArgs.length>0&&r.push(...n.launchArgs),r}async function tt(e,n){await j.mkdir(A.dirname(n),{recursive:!0});try{let t=await v(e,{allowFailure:!0,timeoutMs:q});return await nt(n,t.stdout,t.stderr),t}catch(e){let r=(e instanceof t?e:void 0)?.details;if(r?.timeoutMs===q){let e=typeof r.stdout==`string`?r.stdout:``,t=typeof r.stderr==`string`?r.stderr:``;return await nt(n,e,t),f({level:`warn`,phase:`ios_simulator_launch_console_capture_timeout`,data:{timeoutMs:q,logPath:n,stdoutBytes:Buffer.byteLength(e),stderrBytes:Buffer.byteLength(t)}}),{stdout:e,stderr:t,exitCode:0}}throw e}}async function nt(e,t,n){await j.writeFile(e,rt(t,n),`utf8`)}function rt(e,t){return!e||!t||e.endsWith(`
|
|
3
|
+
`)||e.endsWith(`\r`)?`${e}${t}`:`${e}\n${t}`}async function Q(e,t,n){await x(e).launchApp(e,t,{...n,runRunnerCommand:E})}async function it(e){return d(e)?await ye():(D(e,`clipboard`),await O(e),m(await y(e,[`pbpaste`,e.id],{allowFailure:!0}),`Failed to read iOS simulator clipboard`).stdout.replace(/\r\n/g,`
|
|
4
|
+
`).replace(/\n$/,``))}async function at(e,t){if(d(e)){await Te(t);return}D(e,`clipboard`),await O(e),m(await y(e,[`pbcopy`,e.id],{allowFailure:!0,stdin:t}),`Failed to write iOS simulator clipboard`)}let $=null,ot;async function st(e,r,o,s,c){if(d(e)){let e=r.toLowerCase();if(e===`appearance`){await be(o);return}if(e===`permission`){let e=a(o);if(e===`deny`)throw new t(`INVALID_ARGS`,n(`permission`));return await se(e,lt(c?.permissionTarget))}throw new t(`INVALID_ARGS`,n(r))}D(e,`settings`),await O(e);let l=r.toLowerCase();switch(l){case`clear-app-state`:{if(o.toLowerCase()!==`clear`)throw new t(`INVALID_ARGS`,`settings clear-app-state only supports clear.`);if(!s)throw new t(`INVALID_ARGS`,`settings clear-app-state requires an app id or an active app session.`);let n=await ct(e,s);return{bundleId:n.bundleId,containerPath:n.containerPath,cleared:!0}}case`wifi`:{let t=g(o)?`active`:`failed`;await y(e,[`status_bar`,e.id,`override`,`--wifiMode`,t]),P(e);return}case`airplane`:g(o)?(await y(e,[`status_bar`,e.id,`override`,`--dataNetwork`,`hide`,`--wifiMode`,`failed`,`--wifiBars`,`0`,`--cellularMode`,`failed`,`--cellularBars`,`0`,`--operatorName`,``]),P(e)):(await y(e,[`status_bar`,e.id,`clear`]),F(e));return;case`location`:{if(o.toLowerCase()===`set`){let{latitude:t,longitude:n}=i(c);return await y(e,[`location`,e.id,`set`,`${t},${n}`]),{latitude:t,longitude:n}}let n=g(o);if(!s)throw new t(`INVALID_ARGS`,`location setting requires an active app in session`);let r=n?`grant`:`revoke`;await y(e,[`privacy`,e.id,r,`location`,s]);return}case`faceid`:case`touchid`:{let t=l,n=ft[t];await bt(e,yt(o,t),{settingName:t,label:n.label,modalityAliases:n.modalityAliases});return}case`appearance`:{let t=await ut(e,o);await y(e,[`ui`,e.id,`appearance`,t]);return}case`permission`:if(!s)throw new t(`INVALID_ARGS`,`permission setting requires an active app in session`);await mt(e,pt(a(o)),vt(c?.permissionTarget,c?.permissionMode),s);return;default:throw new t(`INVALID_ARGS`,`Unsupported setting: ${r}`)}}async function ct(e,n){if(!u(e)||e.kind!==`simulator`)throw new t(`UNSUPPORTED_OPERATION`,`Clearing app state is currently supported only on iOS simulators.`);let r=await k(e,n);await O(e),await Y(e,r);let i=m(await y(e,[`get_app_container`,e.id,r,`data`],{allowFailure:!0}),`simctl get_app_container failed for ${r}`).stdout.trim();if(!i)throw new t(`COMMAND_FAILED`,`simctl get_app_container returned an empty data container path for ${r}`);let a=await j.readdir(i);return await Promise.all(a.map(e=>j.rm(A.join(i,e),{recursive:!0,force:!0}))),{bundleId:r,containerPath:i}}function lt(e){let n=e?.trim().toLowerCase();if(n===`accessibility`||n===`screen-recording`||n===`input-monitoring`)return n;throw new t(`INVALID_ARGS`,`Unsupported macOS permission target. Use accessibility|screen-recording|input-monitoring.`)}async function ut(e,n){let r=re(n);if(r!==`toggle`)return r;let i=m(await y(e,[`ui`,e.id,`appearance`],{allowFailure:!0}),`Failed to read current iOS appearance`),a=dt(i.stdout,i.stderr);if(!a)throw new t(`COMMAND_FAILED`,`Unable to determine current iOS appearance for toggle`,{stdout:i.stdout,stderr:i.stderr});return a===`dark`?`light`:`dark`}function dt(e,t){let n=/\b(light|dark|unsupported|unknown)\b/i.exec(`${e}\n${t}`);if(!n)return null;let r=n[1]?.toLowerCase();return r===`dark`?`dark`:r===`light`?`light`:null}const ft={faceid:{label:`Face ID`,modalityAliases:[`face`]},touchid:{label:`Touch ID`,modalityAliases:[`finger`,`touch`]}};function pt(e){return e===`deny`?`revoke`:e}async function mt(e,n,r,i){let a=await gt(e);if(!a.has(r))throw new t(`UNSUPPORTED_OPERATION`,`iOS simctl privacy does not support service "${r}" on this runtime.`,{deviceId:e.id,appBundleId:i,hint:`Supported services: ${Array.from(a).sort().join(`, `)}`});let o=[`privacy`,e.id,n,r,i],s=r===`notifications`;if(!(n===`reset`&&s))try{await y(e,o);return}catch(n){throw s&&ht(n)?new t(`UNSUPPORTED_OPERATION`,`iOS simulator does not support setting notifications permission via simctl privacy on this runtime.`,{deviceId:e.id,appBundleId:i,hint:`Use reset notifications for reprompt behavior, or toggle notifications manually in Settings.`}):n}try{await y(e,o);return}catch(e){if(!ht(e))throw e}try{await y(e,[`privacy`,e.id,`reset`,`all`,i])}catch(n){throw new t(`COMMAND_FAILED`,`iOS simulator blocked direct notifications reset. Fallback reset-all also failed.`,{deviceId:e.id,appBundleId:i,hint:`Use reinstall to force a fresh notifications prompt, or reset simulator content and settings.`},n instanceof Error?n:void 0)}}function ht(e){if(!(e instanceof t)||e.code!==`COMMAND_FAILED`)return!1;let n=String(e.details?.stderr??``).toLowerCase();return(n.includes(`failed to grant access`)||n.includes(`failed to revoke access`)||n.includes(`failed to reset access`))&&n.includes(`operation not permitted`)}async function gt(e){let n=ae(e.simulatorSetPath),r=`${process.env.PATH??``}::${n??``}`;if($&&ot===r)return $;let i=await y(e,[`privacy`,`help`],{allowFailure:!0}),a=_t(`${i.stdout}\n${i.stderr}`);if(a.size===0)throw new t(`COMMAND_FAILED`,`Unable to determine supported simctl privacy services`,{stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode,hint:"Run `xcrun simctl privacy help` manually to verify available services for this runtime."});return $=a,ot=r,a}function _t(e){let t=new Set,n=!1;for(let r of e.split(`
|
|
5
|
+
`)){let e=r.trim();if(!e)continue;if(e===`service`){n=!0;continue}if(!n)continue;if(e.startsWith(`bundle identifier`))break;let i=/^([a-z-]+)\s+-\s+/.exec(e)?.[1];i!==void 0&&t.add(i)}return t}function vt(e,n){let i=r(e);if(i!==`photos`&&n?.trim())throw new t(`INVALID_ARGS`,`Permission mode is only supported for photos. Received: ${n}.`);if(i===`camera`)return`camera`;if(i===`microphone`)return`microphone`;if(i===`contacts`)return`contacts`;if(i===`contacts-limited`)return`contacts-limited`;if(i===`notifications`)return`notifications`;if(i===`calendar`)return`calendar`;if(i===`location`)return`location`;if(i===`location-always`)return`location-always`;if(i===`media-library`)return`media-library`;if(i===`motion`)return`motion`;if(i===`reminders`)return`reminders`;if(i===`siri`)return`siri`;if(i===`photos`){let e=n?.trim().toLowerCase();if(!e||e===`full`)return`photos`;if(e===`limited`)return`photos-add`;throw new t(`INVALID_ARGS`,`Invalid photos mode: ${n}. Use full|limited.`)}throw new t(`INVALID_ARGS`,`Unsupported permission target: ${e}. Use camera|microphone|photos|contacts|contacts-limited|notifications|calendar|location|location-always|media-library|motion|reminders|siri.`)}function yt(e,n){let r=e.trim().toLowerCase();if(r===`match`)return`match`;if(r===`nonmatch`)return`nonmatch`;if(r===`enroll`)return`enroll`;if(r===`unenroll`)return`unenroll`;throw new t(`INVALID_ARGS`,`Invalid ${n} state: ${e}. Use match|nonmatch|enroll|unenroll.`)}async function bt(e,n,r){let i=xt(e.id,n,r.modalityAliases),a=[];for(let t of i){let n=S(e,t),r=await v(n,{allowFailure:!0});if(r.exitCode===0)return;a.push({args:n,stderr:r.stderr,stdout:r.stdout,exitCode:r.exitCode})}let o=ne(a);throw a.length>0&&a.every(e=>St(e.stdout,e.stderr))?new t(`UNSUPPORTED_OPERATION`,`${r.label} simulation is not supported on this simulator runtime.`,{deviceId:e.id,action:n,setting:r.settingName,attempts:o}):new t(`COMMAND_FAILED`,`Failed to simulate ${r.settingName}.`,{deviceId:e.id,action:n,setting:r.settingName,attempts:o})}function xt(e,t,n){let r=n.length>0?n:[`face`];switch(t){case`match`:return r.flatMap(t=>[[`biometric`,e,`match`,t],[`biometric`,`match`,e,t]]);case`nonmatch`:return r.flatMap(t=>[[`biometric`,e,`nonmatch`,t],[`biometric`,e,`nomatch`,t],[`biometric`,`nonmatch`,e,t],[`biometric`,`nomatch`,e,t]]);case`enroll`:return[[`biometric`,e,`enroll`,`yes`],[`biometric`,e,`enroll`,`1`],[`biometric`,`enroll`,e,`yes`],[`biometric`,`enroll`,e,`1`]];case`unenroll`:return[[`biometric`,e,`enroll`,`no`],[`biometric`,e,`enroll`,`0`],[`biometric`,`enroll`,e,`no`],[`biometric`,`enroll`,e,`0`]]}}function St(e,t){let n=`${e}\n${t}`.toLowerCase();return n.includes(`unrecognized subcommand`)||n.includes(`unknown subcommand`)||n.includes(`not supported`)||n.includes(`unavailable`)||n.includes(`biometric`)&&n.includes(`invalid`)}var Ct=e({findIosSimulatorInstalledApp:()=>xe,listIosApps:()=>Ce,resolveIosApp:()=>k,resolveIosSimulatorDeepLinkBundleId:()=>ve});export{Y as a,H as c,at as i,ze as l,st as n,Qe as o,it as r,$e as s,Ct as t};
|
package/dist/src/artifacts.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
//#region src/platforms/android/manifest.d.ts
|
|
2
|
-
declare function resolveAndroidArchivePackageName(archivePath: string): Promise<string | undefined>;
|
|
2
|
+
declare function resolveAndroidArchivePackageName(archivePath: string, signal?: AbortSignal): Promise<string | undefined>;
|
|
3
3
|
//#endregion
|
|
4
4
|
export { resolveAndroidArchivePackageName };
|
package/dist/src/audio-probe.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{c as e}from"./sdk-device.js";import{
|
|
1
|
+
import{c as e}from"./sdk-device.js";import{s as t}from"./helper.js";const n={platform:`host-system-audio`,source:`system-audio`,backend:`macos-screencapturekit`,sourceCount:1,start:t,notes:r};function r(t){return[`Audio probe samples host system audio through ScreenCaptureKit for this ${e(t)?`iOS simulator`:t.platform===`android`?`Android emulator`:`macOS session`}; it is not app-instrumented audio.`,`Screen Recording permission is required for host system audio capture.`,`Other audible host apps can contribute to the measured buckets.`]}export{n as macOsScreenCaptureKitAudioProbeBackend};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const e={interactiveOnly:`snapshotInteractiveOnly`,scope:`snapshotScope`,depth:`snapshotDepth`,raw:`snapshotRaw`,customActions:`snapshotCustomActions`,includeHiddenContentHints:`snapshotIncludeHiddenContentHints`,preferredBackend:`snapshotPreferredBackend`};function t(t){return t?Object.fromEntries(Object.entries(e).flatMap(([e,n])=>{let r=t[e];return r===void 0?[]:[[n,r]]})):{}}export{t};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{_ as
|
|
2
|
-
`).toLowerCase();return r===`ios`&&d.includes(`0xe8008012`)?`IOS_RUNNER_DEVICE_NOT_PROVISIONED`:r===`ios`&&(d.includes(`provisioning profile`)||d.includes(`embedded profile`))?`BOOT_COMMAND_FAILED`:r===`ios`&&(d.includes(`runner did not accept connection`)||i===`connect`&&(d.includes(`timed out`)||d.includes(`timeout`)||d.includes(`econnrefused`)||d.includes(`connection refused`)||d.includes(`fetch failed`)||d.includes(`socket hang up`)))?`IOS_RUNNER_CONNECT_TIMEOUT`:r===`ios`&&i===`boot`&&(d.includes(`timed out`)||d.includes(`timeout`))?`IOS_BOOT_TIMEOUT`:r===`android`&&i===`boot`&&(d.includes(`timed out`)||d.includes(`timeout`))?`ANDROID_BOOT_TIMEOUT`:d.includes(`resource temporarily unavailable`)||d.includes(`killed: 9`)||d.includes(`cannot allocate memory`)||d.includes(`system is low on memory`)?`CI_RESOURCE_STARVATION_SUSPECTED`:r===`android`&&(d.includes(`device not found`)||d.includes(`no devices`)||d.includes(`device offline`)||d.includes(`offline`)||d.includes(`unauthorized`)||d.includes(`not authorized`)||d.includes(`unable to locate device`)||d.includes(`invalid device`))?`ADB_TRANSPORT_UNAVAILABLE`:
|
|
1
|
+
import{n as e}from"./rolldown-runtime.js";import{_ as t,v as n}from"./sdk-contracts.js";import{A as r}from"./sdk-android-adb.js";var i=e({Deadline:()=>s,isEnvTruthy:()=>a,retryWithPolicy:()=>c});function a(e){return[`1`,`true`,`yes`,`on`].includes((e??``).trim().toLowerCase())}const o={maxAttempts:3,baseDelayMs:200,maxDelayMs:2e3,jitter:.2};var s=class e{startedAtMs;expiresAtMs;constructor(e,t){this.startedAtMs=e,this.expiresAtMs=e+Math.max(0,t)}static fromTimeoutMs(t,n=Date.now()){return new e(n,t)}remainingMs(e=Date.now()){return Math.max(0,this.expiresAtMs-e)}elapsedMs(e=Date.now()){return Math.max(0,e-this.startedAtMs)}isExpired(e=Date.now()){return this.remainingMs(e)<=0}};async function c(e,n={},r={}){let i={maxAttempts:n.maxAttempts??o.maxAttempts,baseDelayMs:n.baseDelayMs??o.baseDelayMs,maxDelayMs:n.maxDelayMs??o.maxDelayMs,jitter:n.jitter??o.jitter,shouldRetry:n.shouldRetry},a;for(let n=1;n<=i.maxAttempts;n+=1){if(r.signal?.aborted)throw new t(`COMMAND_FAILED`,`request canceled`,{reason:`request_canceled`});if(r.deadline?.isExpired()&&n>1)break;try{let t=await e({attempt:n,maxAttempts:i.maxAttempts,deadline:r.deadline});return r.onEvent?.({phase:r.phase,event:`succeeded`,attempt:n,maxAttempts:i.maxAttempts,elapsedMs:r.deadline?.elapsedMs(),remainingMs:r.deadline?.remainingMs()}),d({phase:r.phase,event:`succeeded`,attempt:n,maxAttempts:i.maxAttempts,elapsedMs:r.deadline?.elapsedMs(),remainingMs:r.deadline?.remainingMs()}),t}catch(e){a=e;let t=r.classifyReason?.(e),o={phase:r.phase,event:`attempt_failed`,attempt:n,maxAttempts:i.maxAttempts,elapsedMs:r.deadline?.elapsedMs(),remainingMs:r.deadline?.remainingMs(),reason:t};if(r.onEvent?.(o),d(o),n>=i.maxAttempts||i.shouldRetry&&!i.shouldRetry(e,n))break;let s=l(i.baseDelayMs,i.maxDelayMs,i.jitter,n),c=r.deadline?Math.min(s,r.deadline.remainingMs()):s;if(c<=0)break;let f={phase:r.phase,event:`retry_scheduled`,attempt:n,maxAttempts:i.maxAttempts,delayMs:c,elapsedMs:r.deadline?.elapsedMs(),remainingMs:r.deadline?.remainingMs(),reason:t};r.onEvent?.(f),d(f),await u(c,r.signal)}}let s={phase:r.phase,event:`exhausted`,attempt:i.maxAttempts,maxAttempts:i.maxAttempts,elapsedMs:r.deadline?.elapsedMs(),remainingMs:r.deadline?.remainingMs(),reason:r.classifyReason?.(a)};throw r.onEvent?.(s),d(s),a||new t(`COMMAND_FAILED`,`retry failed`)}function l(e,t,n,r){let i=Math.min(t,e*2**(r-1)),a=i*n;return Math.max(0,i+(Math.random()*2-1)*a)}function u(e,t){return new Promise(n=>{if(t?.aborted){n();return}let r=!1,i=()=>{r||(r=!0,t&&t.removeEventListener(`abort`,o),n())},a=setTimeout(i,e);function o(){clearTimeout(a),i()}t&&t.addEventListener(`abort`,o,{once:!0})})}function d(e){r({level:e.event===`attempt_failed`||e.event===`exhausted`?`warn`:`debug`,phase:`retry`,data:{...e}})}const f=new Set([`IOS_BOOT_TIMEOUT`,`IOS_RUNNER_CONNECT_TIMEOUT`,`IOS_TOOL_MISSING`,`ANDROID_BOOT_TIMEOUT`,`ADB_TRANSPORT_UNAVAILABLE`,`CI_RESOURCE_STARVATION_SUSPECTED`]);function p(e){return f.has(e.toUpperCase())}function m(e){let t=e.error?n(e.error):null,r=e.context?.platform,i=e.context?.phase;if(t?.code===`TOOL_MISSING`)return r===`android`?`ADB_TRANSPORT_UNAVAILABLE`:`IOS_TOOL_MISSING`;let a=t?.details??{},o=typeof a.message==`string`?a.message:void 0,s=typeof a.stdout==`string`?a.stdout:void 0,c=typeof a.stderr==`string`?a.stderr:void 0,l=a.boot&&typeof a.boot==`object`?a.boot:null,u=a.bootstatus&&typeof a.bootstatus==`object`?a.bootstatus:null,d=[e.message,t?.message,e.stdout,e.stderr,o,s,c,typeof l?.stdout==`string`?l.stdout:void 0,typeof l?.stderr==`string`?l.stderr:void 0,typeof u?.stdout==`string`?u.stdout:void 0,typeof u?.stderr==`string`?u.stderr:void 0].filter(Boolean).join(`
|
|
2
|
+
`).toLowerCase();return r===`ios`&&d.includes(`0xe8008012`)?`IOS_RUNNER_DEVICE_NOT_PROVISIONED`:r===`ios`&&(d.includes(`provisioning profile`)||d.includes(`embedded profile`))?`BOOT_COMMAND_FAILED`:r===`ios`&&(d.includes(`runner did not accept connection`)||i===`connect`&&(d.includes(`timed out`)||d.includes(`timeout`)||d.includes(`econnrefused`)||d.includes(`connection refused`)||d.includes(`fetch failed`)||d.includes(`socket hang up`)))?`IOS_RUNNER_CONNECT_TIMEOUT`:r===`ios`&&i===`boot`&&(d.includes(`timed out`)||d.includes(`timeout`))?`IOS_BOOT_TIMEOUT`:r===`android`&&i===`boot`&&(d.includes(`timed out`)||d.includes(`timeout`))?`ANDROID_BOOT_TIMEOUT`:d.includes(`resource temporarily unavailable`)||d.includes(`killed: 9`)||d.includes(`cannot allocate memory`)||d.includes(`system is low on memory`)?`CI_RESOURCE_STARVATION_SUSPECTED`:r===`android`&&(d.includes(`device not found`)||d.includes(`no devices`)||d.includes(`device offline`)||d.includes(`offline`)||d.includes(`unauthorized`)||d.includes(`not authorized`)||d.includes(`unable to locate device`)||d.includes(`invalid device`))?`ADB_TRANSPORT_UNAVAILABLE`:t?.code===`COMMAND_FAILED`||d.length>0?`BOOT_COMMAND_FAILED`:`UNKNOWN`}function h(e){switch(e){case`IOS_BOOT_TIMEOUT`:return`Retry simulator boot and inspect simctl bootstatus logs; in CI reduce parallel jobs or use a larger runner.`;case`IOS_RUNNER_CONNECT_TIMEOUT`:return`Retry runner startup, inspect xcodebuild logs, and verify simulator responsiveness before command execution.`;case`IOS_RUNNER_DEVICE_NOT_PROVISIONED`:return`The XCTest runner cannot be installed on this device: its provisioning profile does not cover it. Register the device with the signing team (Xcode > Settings > Accounts, or add its UDID to the provisioning profile) and retry. Retrying without that will keep failing.`;case`ANDROID_BOOT_TIMEOUT`:return`Retry emulator startup and verify sys.boot_completed reaches 1; consider increasing startup budget in CI.`;case`ADB_TRANSPORT_UNAVAILABLE`:return`Check adb server/device transport (adb devices -l), restart adb, and ensure the target device is online and authorized.`;case`CI_RESOURCE_STARVATION_SUSPECTED`:return`CI machine may be resource constrained; reduce parallel jobs or use a larger runner.`;case`IOS_TOOL_MISSING`:return`Xcode command-line tools are missing or not in PATH; run xcode-select --install and verify xcrun works.`;case`BOOT_COMMAND_FAILED`:return`Inspect command stderr/stdout for the failing boot phase and retry after environment validation.`;default:return`Retry once and inspect verbose logs for the failing phase.`}}export{a,s as i,m as n,c as o,p as r,i as s,h as t};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function e(e){if(!e)return;let t=/\[(-?\d+),(-?\d+)\]\[(-?\d+),(-?\d+)\]/.exec(e);if(!t)return;let n=Number(t[1]),r=Number(t[2]),i=Number(t[3]),a=Number(t[4]);return{x:n,y:r,width:Math.max(0,i-n),height:Math.max(0,a-r)}}export{e as t};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{_ as e}from"./sdk-contracts.js";import t from"node:path";import{createReadStream as n,createWriteStream as r,promises as i}from"node:fs";import{pipeline as a}from"node:stream/promises";import{Transform as o}from"node:stream";import{createGunzip as s}from"node:zlib";import*as c from"tar-stream";import*as l from"yauzl";const u=2*1024*1024*1024;var d=class{maxBytes;maxEntries;maxDepth;#e=0;#t=0;constructor(e={}){this.maxBytes=v(e.maxBytes??4294967296,`maxBytes`),this.maxEntries=v(e.maxEntries??1e5,`maxEntries`),this.maxDepth=v(e.maxDepth??3,`maxDepth`)}get bytes(){return this.#e}get entries(){return this.#t}preflightArchive(e){let t=v(e.depth,`depth`),n=v(e.entryCount,`entryCount`),r=v(e.declaredBytes,`declaredBytes`);if(t<1||t>this.maxDepth)throw _(`ARCHIVE_NESTING_LIMIT`,`Archive nesting depth exceeds the limit`);if(n>this.maxEntries-this.#t)throw _(`ARCHIVE_ENTRY_LIMIT`,`Archive contains too many entries`);if(r>this.maxBytes-this.#e)throw _(`ARCHIVE_EXPANDED_BYTES_LIMIT`,`Archive expands beyond the byte limit`);return new f(e=>this.#n(e),()=>this.#r(),e.entryCount,e.declaredBytes)}#n(e){let t=v(e,`bytes`);if(t>this.maxBytes-this.#e)throw _(`ARCHIVE_EXPANDED_BYTES_LIMIT`,`Archive expands beyond the byte limit`);this.#e+=t}#r(){if(this.#t>=this.maxEntries)throw _(`ARCHIVE_ENTRY_LIMIT`,`Archive contains too many entries`);this.#t+=1}},f=class{#e;#t;#n;#r;#i=0;#a=0;constructor(e,t,n,r){this.#e=e,this.#t=t,this.#n=n,this.#r=r}chargeBytes(e){let t=v(e,`bytes`);if(t>this.#r-this.#a)throw _(`ARCHIVE_MANIFEST_MISMATCH`,`Archive contents changed after inspection`);this.#e(t),this.#a+=t}commitEntry(){if(this.#i>=this.#n)throw _(`ARCHIVE_MANIFEST_MISMATCH`,`Archive contents changed after inspection`);this.#t(),this.#i+=1}finish(){if(this.#i!==this.#n||this.#a!==this.#r)throw _(`ARCHIVE_MANIFEST_MISMATCH`,`Archive contents changed after inspection`)}};function p(e,t,n){return e.preflightArchive({depth:t,entryCount:n.length,declaredBytes:n.reduce((e,t)=>e+t.size,0)})}function m(e,t){return e.name===t.name&&e.kind===t.kind&&e.size===t.size&&e.mode===t.mode}function h(e){if(!e||e.includes(`\0`)||e.includes(`\\`)||t.posix.isAbsolute(e)||/^[a-zA-Z]:/.test(e)||e.startsWith(`//`))throw _(`ARCHIVE_UNSAFE_PATH`,`Archive contains an unsafe entry path`);let n=t.posix.normalize(e).replace(/^(\.\/)+/,``).replace(/\/$/,``);if(!n||n===`.`||n===`..`||n.startsWith(`../`))throw _(`ARCHIVE_UNSAFE_PATH`,`Archive contains an unsafe entry path`);return n}function g(e,n){let r=h(n),i=t.resolve(e),a=t.resolve(i,...r.split(`/`));if(!a.startsWith(`${i}${t.sep}`))throw _(`ARCHIVE_UNSAFE_PATH`,`Archive entry escapes the extraction root`);return a}function _(t,n,r){return new e(`INVALID_ARGS`,n,{reason:t},r)}function v(e,t){if(!Number.isSafeInteger(e)||e<0)throw RangeError(`${t} must be a non-negative safe integer`);return e}async function y(e){e.signal?.throwIfAborted();let t=e.budget??new d,n=e.depth??1,r=await b(e,t,n);await e.validateManifest?.(r);let i=p(t,n,r),a=c.extract(),o=x(e.archivePath,e.gzip,a,e.signal);try{for await(let t of a){e.signal?.throwIfAborted();let n=w(t.header);if(!n){await E(t);continue}let a=r.shift();if(!a||!m(a,n))throw _(`ARCHIVE_MANIFEST_MISMATCH`,`Archive contents changed after inspection`);await T(t,a,e.outputRoot,i),i.commitEntry()}await o}catch(e){throw a.destroy(),await o.catch(()=>{}),e}if(r.length!==0)throw _(`ARCHIVE_MANIFEST_MISMATCH`,`Archive contents changed after inspection`);i.finish()}async function b(e,t,n){let r=[],i=0,a=c.extract(),o=x(e.archivePath,e.gzip,a,e.signal);try{for await(let o of a){e.signal?.throwIfAborted();let a=w(o.header);if(!a){await E(o);continue}i+=a.size,t.preflightArchive({depth:n,entryCount:r.length+1,declaredBytes:i}),r.push(a),await E(o)}await o}catch(e){throw a.destroy(),await o.catch(()=>{}),e}return r}function x(e,t,r,i){return t?a(n(e),s(),r,{signal:i}):a(n(e),r,{signal:i})}function S(e){if(e===`directory`)return`directory`;if(e===`file`||e===`contiguous-file`||e==null)return`file`;throw e===`link`||e===`symlink`?_(`ARCHIVE_UNSAFE_ENTRY`,`Uploaded app bundle archive cannot contain symlinks or hard links`):_(`ARCHIVE_UNSAFE_ENTRY`,`Archive contains a link or special entry`)}function C(e,t){return(e??(t===`directory`?493:420))&511}function w(e){if(D(e.name,e.type))return;let t=h(e.name),n=S(e.type),r=n===`directory`?0:e.size??0;if(!Number.isSafeInteger(r)||r<0)throw _(`ARCHIVE_INVALID_ENTRY`,`Archive entry has an invalid size`);return{name:t,kind:n,size:r,mode:C(e.mode,n)}}async function T(e,n,o,s){let c=g(o,n.name);if(n.kind===`directory`){await i.mkdir(c,{recursive:!0,mode:n.mode}),await E(e);return}await i.mkdir(t.dirname(c),{recursive:!0}),await a(e,async function*(e){for await(let t of e)s.chargeBytes(Buffer.byteLength(t)),yield t},r(c,{flags:`wx`,mode:n.mode}))}async function E(e){for await(let t of e);}function D(e,t){return t===`directory`&&(e===`.`||e===`./`||e===``)}async function O(e){e.signal?.throwIfAborted();let n=e.budget??new d,o=e.depth??1,s=[],c=0;await k(e.archivePath,e.signal,e=>{n.preflightArchive({depth:o,entryCount:s.length+1,declaredBytes:c});let t=M(e);c+=t.size,n.preflightArchive({depth:o,entryCount:s.length+1,declaredBytes:c}),s.push(t)}),await e.validateManifest?.(s);let l=p(n,o,s),u=await k(e.archivePath,e.signal,(e,t)=>{t>=s.length&&F()});u.length!==s.length&&F();let f=await A(e.archivePath);try{for(let n=0;n<u.length;n+=1){e.signal?.throwIfAborted();let o=u[n],c=s[n];(!o||!c||!m(M(o),c))&&F();let d=g(e.outputRoot,c.name);c.kind===`directory`?await i.mkdir(d,{recursive:!0,mode:c.mode}):(await i.mkdir(t.dirname(d),{recursive:!0}),await a(await j(f,o),async function*(e){for await(let t of e)l.chargeBytes(Buffer.byteLength(t)),yield t},r(d,{flags:`wx`,mode:c.mode}),{signal:e.signal})),l.commitEntry()}l.finish()}finally{f.close()}}async function k(e,t,n){let r=await A(e);return await new Promise((e,i)=>{let a=[],o=()=>{r.off(`entry`,s),r.off(`end`,c),r.off(`error`,l),t?.removeEventListener(`abort`,u)},s=e=>{try{n?.(e,a.length),a.push(e),r.readEntry()}catch(e){o(),i(e)}},c=()=>{o(),e(a)},l=e=>{o(),i(e)},u=()=>{o(),r.close(),i(t?.reason??new DOMException(`The operation was aborted`,`AbortError`))};if(r.on(`entry`,s),r.once(`end`,c),r.once(`error`,l),t?.addEventListener(`abort`,u,{once:!0}),t?.aborted)return u();r.readEntry()}).finally(()=>r.close())}function A(e){return new Promise((t,n)=>{l.open(e,{lazyEntries:!0,autoClose:!1,validateEntrySizes:!0,strictFileNames:!0},(e,r)=>e?n(e):t(r))})}function j(e,t){return new Promise((n,r)=>{e.openReadStream(t,(e,t)=>e?r(e):n(t))})}function M(e){N(e);let t=h(e.fileName),n=e.externalFileAttributes>>>16&65535,r=P(e.fileName,n),i=r?493:420;return{name:t,kind:r?`directory`:`file`,size:r?0:e.uncompressedSize,mode:n&511||i}}function N(e){if(e.isEncrypted())throw _(`ARCHIVE_UNSAFE_ENTRY`,`Encrypted archive entries are not supported`);let t=e.externalFileAttributes>>>16&61440;if(t!==0&&t!==16384&&t!==32768)throw _(`ARCHIVE_UNSAFE_ENTRY`,`Archive contains a link or special entry`)}function P(e,t){return e.endsWith(`/`)||(t&61440)==16384}function F(){throw _(`ARCHIVE_MANIFEST_MISMATCH`,`Archive contents changed after inspection`)}async function I(e){e.signal?.throwIfAborted();let n=t.resolve(e.archivePath),r=t.resolve(e.outputRoot);if(n===r||n.startsWith(`${r}${t.sep}`))throw RangeError(`archivePath must be outside outputRoot`);await i.mkdir(r,{recursive:!1});try{e.type===`zip`?await O({...e,archivePath:n,outputRoot:r}):await y({...e,archivePath:n,outputRoot:r,gzip:e.type===`tgz`})}catch(e){throw await i.rm(r,{recursive:!0,force:!0}),e}}function L(e){let t=e.toLowerCase();if(t.endsWith(`.tar.gz`)||t.endsWith(`.tgz`))return`tgz`;if(t.endsWith(`.tar`))return`tar`;if(t.endsWith(`.zip`)||t.endsWith(`.ipa`))return`zip`}function R(e){if(!Number.isSafeInteger(e.maxBytes)||e.maxBytes<0)throw RangeError(`maxBytes must be a non-negative safe integer`);let t=0,n=new o({transform(n,r,i){let a=t+n.byteLength;if(!Number.isSafeInteger(a)||a>e.maxBytes){i(e.createLimitError());return}t=a,i(null,n)}});return Object.defineProperty(n,"bytesSeen",{enumerable:!0,get:()=>t}),n}export{u as a,d as i,L as n,I as r,R as t};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{_ as e}from"./sdk-contracts.js";const t=new Set,n=new Map,r=`request_canceled`,i=`request canceled`;function a(e,t){if(typeof e==`string`&&e.length>0)return e;let n=(typeof t==`string`?t:typeof t==`number`&&Number.isFinite(t)?String(t):`generated`).trim().replace(/[^a-zA-Z0-9_-]/g,`_`).slice(0,32)||`generated`,r=Math.random().toString(36).slice(2,10);return`req:${n}:${process.pid}:${Date.now()}:${r}`}const o=5e4,s=1e4;function c(e){if(e.size<=o)return;let t=0;for(let n of e.keys()){if(t>=s)break;e.delete(n),t++}}function l(e){if(e.size<=o)return;let t=0;for(let n of e){if(t>=s)break;e.delete(n),t++}}function u(r){if(!r)return;if(n.has(r))throw new e(`INVALID_ARGS`,`Request ID is already in flight: ${r}`,{requestId:r,reason:`duplicate_request_id`});c(n);let i=new AbortController;return n.set(r,i),t.has(r)&&i.abort(),{requestId:r,controller:i}}function d(e){e&&(l(t),t.add(e),n.get(e)?.abort())}function f(e,r){e&&(r&&(r.requestId!==e||n.get(e)!==r.controller)||(t.delete(e),n.delete(e)))}function p(e){e&&f(e.requestId,e)}function m(e){return e?t.has(e):!1}function h(e){if(e)return n.get(e)?.signal}function g(){return new e(`COMMAND_FAILED`,i,{reason:r,hint:`The request was canceled intentionally (explicit cancel or client disconnect) — no retry is needed unless the cancellation was unintended.`})}function _(e){if(m(e))throw g()}function v(t){return!(t instanceof e)||t.code!==`COMMAND_FAILED`?!1:t.details?.reason===r?!0:t.message===i}export{m as a,u as c,h as i,a as l,f as n,v as o,g as r,d as s,p as t,_ as u};
|
package/dist/src/cli-config.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{_ as e}from"./sdk-contracts.js";import{
|
|
1
|
+
import{_ as e}from"./sdk-contracts.js";import{_ as t}from"./location-coordinates.js";import{i as n}from"./command-catalog.js";import{S as r,d as i,l as a}from"./registry.js";import{D as o,T as s}from"./sdk-android-adb.js";import{n as c,t as l}from"./path-resolution.js";import{r as u}from"./command-schema.js";import d from"node:path";import f from"node:fs";function p(e,t){for(let[n,r]of Object.entries(t))r!==void 0&&(e[n]=r);return e}const m=new Set([`config`,`remoteConfig`,`help`,`version`,`batchSteps`,`githubActionsArtifact`]),h=new Set([`appsFilter`,`iosSimulatorDeviceSet`]),g=S(),_=new Map(g.map(e=>[e.key,e]));function v(e){return _.get(e)}function y(e){return g.filter(t=>t.configurable&&t.supportsCommand(e))}function b(e,t){return v(e)?.supportsCommand(t)??!1}function x(e,t,n,r){return o(T(e),t,n,r)}function S(){let e=new Map;for(let t of r()){let n=e.get(t.key);n?n.push(t):e.set(t.key,[t])}let t=new Map;for(let e of i)t.set(e,new Set([`*`]));for(let e of n()){let n=u(e);for(let r of[...n.allowedFlags??[],...n.supportedFlags??[]]){let n=t.get(r);n&&n.has(`*`)||(n?n.add(e):t.set(r,new Set([e])))}}return[...e.entries()].map(([e,n])=>({key:e,flagDefinitions:n,configurable:!m.has(e),env:{names:h.has(e)?[]:[s(e)]},supportsCommand(n){let r=t.get(e);return r?r.has(`*`)?!0:n?r.has(n):!1:!1}})).sort((e,t)=>C(e.key,t.key))}function C(e,t){let n=e.toLowerCase(),r=t.toLowerCase();return n===r?e<t?-1:+(e>t):n<r?-1:1}function w(e){let t=e.flagDefinitions[0];if(!t)throw Error(`Missing flag definition for option ${e.key}`);return t}function T(e){let t=e.flagDefinitions.find(e=>e.setValue===void 0);if(t)return t;let n=w(e);if(n.type===`enum`){let t=n.enumValues??e.flagDefinitions.map(e=>e.setValue).filter(e=>e!==void 0);return{...n,setValue:void 0,enumValues:t}}return n}function E(e){let t=e.env??process.env;return p(p({},j(O(e.cwd,e.cliFlags.config,t))),F(t,e.command))}const D=new Set(`json.platform.target.device.udid.serial.session.sessionLock.activity.launchArgs.launchUrl.remote.deviceHub.testIme.appsFilter.clean.force.stale.relaunch.shutdown.surface.headless.restart.noRecord.record.recordAs.snapshotInteractiveOnly.snapshotDiff.snapshotDepth.snapshotScope.snapshotRaw.snapshotCustomActions.snapshotForceFull.screenshotPixelDensity.screenshotFullscreen.screenshotScale.screenshotNoStabilize.screenshotNormalizeStatusBar.overlayRefs.networkInclude.baseline.threshold.count.pointerCount.fps.quality.hideTouches.recordingScope.intervalMs.delayMs.durationMs.holdMs.jitterPx.pixels.doubleTap.verify.settle.settleQuietMs.clickButton.backMode.pauseMs.pattern.kind.perfTemplate.responseLevel.verbose.cost.timeoutMs.retries.failFast.recordVideo.replayUpdate.replayMaestro.replayFrom.replayPlanDigest.replayKeepSession.findFirst.findLast.batchOnError.batchMaxSteps.retainPaths.retentionMs.shardAll.shardSplit.noLogin`.split(`.`));function O(e,t,n){let r=t??n.AGENT_DEVICE_CONFIG;return r?[{path:A(r,e,n),required:!0,source:`explicit`}]:[{path:k(n),required:!1,source:`user`},{path:d.resolve(e,`agent-device.json`),required:!1,source:`project`}]}function k(e){return d.join(l(`~`,{env:e}),`.agent-device`,`config.json`)}function A(e,t,n){return c(e,{cwd:t,env:n})}function j(e){let t={};for(let n of e)p(t,M(n));return t}function M(t){let{path:n,required:r}=t;if(!f.existsSync(n)){if(r)throw new e(`INVALID_ARGS`,`Config file not found: ${n}`);return{}}let i;try{i=f.readFileSync(n,`utf8`)}catch(t){throw new e(`INVALID_ARGS`,`Failed to read config file: ${n}`,{cause:t instanceof Error?t.message:String(t)})}let a;try{a=JSON.parse(i)}catch(t){throw new e(`INVALID_ARGS`,`Invalid JSON in config file: ${n}`,{cause:t instanceof Error?t.message:String(t)})}if(!a||typeof a!=`object`||Array.isArray(a))throw new e(`INVALID_ARGS`,`Config file must contain a JSON object: ${n}`);return N(a,{source:t.source,label:`${t.source===`project`?`project `:``}config file ${n}`})}function N(n,r){let i={};for(let[o,s]of Object.entries(n)){let n=o,c=v(n);if(!c)throw o===t.flagKey?new e(`INVALID_ARGS`,`Config key "${o}" in ${r.label} was removed; use "screenshotScale" (0.01-1) to downscale screenshots. Recordings capture at native resolution.`):new e(`INVALID_ARGS`,`Unknown config key "${o}" in ${r.label}.`);if(!c.configurable)throw new e(`INVALID_ARGS`,`Config key "${o}" is not allowed in ${r.label}. This key is not supported in config files.`);if(r.source===`project`&&!D.has(n))throw new e(`INVALID_ARGS`,`Config key "${o}" is not allowed in ${r.label}. Move it to ~/.agent-device/config.json, pass it with --config or AGENT_DEVICE_CONFIG, or provide it through CLI flags/environment variables.`);if(n===`installSource`){i.installSource=a(s,r.label);continue}i[n]=x(c,s,r.label,o)}return i}const P=new Set([`screenshot`,`record`]);function F(n,r){let i=n[t.envVar];if(r!==null&&P.has(r)&&typeof i==`string`&&i.trim().length>0)throw new e(`INVALID_ARGS`,`${t.envVar} was removed. ${t.migration[r===`record`?`record`:`screenshot`]}`);let a={};for(let e of y(r)){if(e.key===`installSource`)continue;let t=e.env.names.map(e=>({name:e,value:n[e]})).find(e=>typeof e.value==`string`&&e.value.trim().length>0);t&&(a[e.key]=x(e,t.value,`environment variable ${t.name}`,t.name))}return a}export{b as n,p as r,E as t};
|
package/dist/src/cli-help.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import{
|
|
2
|
-
`)}function d(e){let t=e.endsWith(`?`),n=t?e.slice(0,-1):e;return t?`[${n}]`:`<${n}>`}function f(e){return
|
|
1
|
+
import{Yn as e}from"./sdk-batch-runner.js";import{i as t}from"./command-catalog.js";import{S as n,d as r,m as i}from"./registry.js";import{n as a}from"./version.js";import{i as o,r as s}from"./command-schema.js";const c=[`Flows: launchApp; runFlow file/inline with platform, visibility, and limited boolean conditions; onFlowStart/onFlowComplete; repeat.times and retry.`,`Interactions: tapOn, doubleTapOn, longPressOn, inputText, eraseText, openLink, hideKeyboard, basic pressKey, and back; targets support index, childOf, label, points, and optional.`,`Assertions and navigation: assertVisible, assertNotVisible, extendedWaitUntil, scroll, scrollUntilVisible, absolute/percentage/target swipe, takeScreenshot, waitForAnimationToEnd, and stopApp.`,`Scripts: ordered runScript file/env scripts with http.post, json, and output variables.`],l=[`Runtime: iOS and Android only; launchApp.clearState supports Android and iOS simulators, launch arguments are Apple-only, and standalone device utility/state commands are unsupported.`,`Expressions: when.true supports boolean literals and maestro.platform comparisons; repeat.while, evalScript, and broader JavaScript expressions are unsupported.`,`Environment: flow env is the default, AD_VAR_* overrides it, and CLI -e KEY=VALUE wins over both.`,`Failure diagnostics: resolved targets and runFlow paths are rendered, while inputText payloads remain hidden; do not place secrets in diagnostic identifiers.`,`Trust: runScript executes trusted scripts, may make http.post network requests, and is not a security sandbox; output keys cannot contain a dot.`,`Errors and tracking: unsupported commands and fields fail with source context when available; open a focused issue only when implementation work is planned.`];function u(){return[`Supported subset:`,...c.map(e=>` - ${e}`),``,`Boundaries:`,...l.map(e=>` - ${e}`)].join(`
|
|
2
|
+
`)}function d(e){let t=e.endsWith(`?`),n=t?e.slice(0,-1):e;return t?`[${n}]`:`<${n}>`}function f(e){return n().filter(t=>t.key===e)}function p(e,t){if(t.usageOverride)return t.usageOverride;let n=(t.positionalArgs??[]).map(d),r=(t.allowedFlags??[]).flatMap(e=>f(e).map(e=>e.usageLabel??e.names[0])).map(e=>`[${e}]`);return[e,...n,...r].join(` `)}function m(){return`agent-device <command> [args] [--json]
|
|
3
3
|
|
|
4
4
|
Automates iOS, Android, macOS, TV, and web apps for AI agents.
|
|
5
|
-
All ${
|
|
5
|
+
All ${t().length} commands: agent-device help commands
|
|
6
6
|
|
|
7
7
|
Start:
|
|
8
8
|
When starting a task with a known app, first run:
|
|
@@ -24,7 +24,7 @@ Loop:
|
|
|
24
24
|
Targets:
|
|
25
25
|
Copy refs exactly: @e12, @e12~s4. Keep @ and any ~sN pin; refs go stale
|
|
26
26
|
after mutations. A literal @handle is label="@handle", not a bare ref.
|
|
27
|
-
Prefer refs, then id/label/role selectors. Selector keys: ${
|
|
27
|
+
Prefer refs, then id/label/role selectors. Selector keys: ${e.join(` `)}.
|
|
28
28
|
Coordinates are last resort: after snapshot -i shows no semantic target, or a
|
|
29
29
|
sparse/AX-unavailable warning says its refs and selectors are invalid.
|
|
30
30
|
Then screenshot, press <x> <y>, and re-snapshot on the changed screen.
|
|
@@ -259,7 +259,7 @@ Vega OS:
|
|
|
259
259
|
vega virtual-device stop
|
|
260
260
|
Use a component ID from the app package or Vega SDK tooling; agent-device app inventory is not yet supported.
|
|
261
261
|
Use --serial VirtualDevice for explicit VVD selection.
|
|
262
|
-
|
|
262
|
+
The VVD is never booted implicitly; start it with vega virtual-device start.
|
|
263
263
|
Snapshot, screenshot, selectors, install, touch/text/gesture, logs, and performance commands remain unsupported until their Vega backends are implemented.
|
|
264
264
|
|
|
265
265
|
Buttons:
|
|
@@ -368,7 +368,7 @@ Diagnostics and traces:
|
|
|
368
368
|
agent-device perf cpu profile report --kind xctrace --out ./artifacts/app-profile.json
|
|
369
369
|
agent-device perf trace start --kind xctrace --template "Animation Hitches" --out ./artifacts/hitches.trace
|
|
370
370
|
agent-device perf trace stop --kind xctrace --out ./artifacts/hitches.trace
|
|
371
|
-
perf xctrace
|
|
371
|
+
perf xctrace keeps the .trace artifact on disk; CPU report returns a bounded weighted top-function summary. Do not dump .trace contents into context.
|
|
372
372
|
For Android native CPU/trace evidence, use perf artifacts instead of raw adb/simpleperf/perfetto output:
|
|
373
373
|
agent-device perf cpu profile start --kind simpleperf --out /tmp/cpu.perf.data
|
|
374
374
|
agent-device perf cpu profile stop --kind simpleperf
|
|
@@ -376,6 +376,10 @@ Diagnostics and traces:
|
|
|
376
376
|
agent-device perf trace start --kind perfetto --out /tmp/app.perfetto-trace
|
|
377
377
|
agent-device perf trace stop --kind perfetto
|
|
378
378
|
Treat native perf output as the agent evidence: for example, state=stopped, outPath=/tmp/app.perfetto-trace, sizeBytes=5392410, method=adb-shell-perfetto. The 5.3 MB raw trace stays in the artifact.
|
|
379
|
+
CPU reports return at most ten top functions in structured data and print five in default CLI output.
|
|
380
|
+
Prefer explicit perf frames, perf memory, perf cpu, or perf trace forms. Bare perf, perf sample, perf metrics, and metrics are deprecated compatibility forms until the next major release.
|
|
381
|
+
On Android, those deprecated aggregate forms retain the released dumpsys cpuinfo point sample for compatibility; new profiling workflows should use perf cpu profile.
|
|
382
|
+
Startup duration belongs to the open command's startup result; read it there instead of using aggregate perf.
|
|
379
383
|
|
|
380
384
|
Memory diagnostics:
|
|
381
385
|
Use perf memory when the symptom is leak/growth/OOM suspicion and you need agent-readable evidence.
|
|
@@ -386,7 +390,7 @@ Memory diagnostics:
|
|
|
386
390
|
{"metrics":{"memory":{"available":true,"totalPssKb":562958,"totalRssKb":570304,"topConsumers":[{"name":"Dalvik Heap","pssKb":213456}]}}}
|
|
387
391
|
Example default snapshot output:
|
|
388
392
|
Memory artifact (android-hprof): /tmp/app.hprof (42MB)
|
|
389
|
-
Prefer perf memory sample over raw dumpsys/leaks output for first-pass agent diagnosis: it keeps arrays bounded
|
|
393
|
+
Prefer perf memory sample over raw dumpsys/leaks output for first-pass agent diagnosis: it keeps arrays bounded and returns only relevant memory evidence.
|
|
390
394
|
Prefer perf memory snapshot over printing heap/memgraph data: snapshots return path, size, kind, method, and support metadata while the large artifact stays on disk for external inspection.
|
|
391
395
|
Unsupported platforms return artifact.available=false with reason/hint; do not pretend a heap or memgraph was captured.
|
|
392
396
|
|
|
@@ -464,7 +468,7 @@ Example:
|
|
|
464
468
|
agent-device react-devtools profile report @c5
|
|
465
469
|
agent-device network dump --include headers
|
|
466
470
|
|
|
467
|
-
Use snapshot, screenshot, logs, network, and perf
|
|
471
|
+
Use snapshot, screenshot, logs, network, perf frames, and perf memory for device/app runtime evidence. Use react-devtools when component internals or React rendering behavior matters.`},cdp:{summary:`React Native CDP targets, JS heap snapshots, and leak triage`,body:`agent-device help cdp
|
|
468
472
|
|
|
469
473
|
Use this when a React Native or Expo app exposes a CDP target through Metro and
|
|
470
474
|
the task needs JavaScript heap growth checks, heap snapshot diffs, allocation
|
|
@@ -570,7 +574,7 @@ Overlays and busy RN UIs:
|
|
|
570
574
|
React DevTools routing:
|
|
571
575
|
Keep the agent-device react-devtools prefix on every React DevTools command.
|
|
572
576
|
Use help react-devtools for status/wait, component trees, props/state/hooks, profile windows, slow renders, rerenders, and remote bridge rules.
|
|
573
|
-
If React DevTools cannot connect, report status and continue with logs, network, perf
|
|
577
|
+
If React DevTools cannot connect, report status and continue with logs, network, perf frames, perf memory, screenshot, and trace evidence instead of blocking the whole flow.
|
|
574
578
|
|
|
575
579
|
CDP memory routing:
|
|
576
580
|
Keep the agent-device cdp prefix on every CDP command.
|
|
@@ -587,7 +591,7 @@ Slow-flow investigation:
|
|
|
587
591
|
If the task says to open the app, include the open command even when it also describes the current screen.
|
|
588
592
|
Use help react-devtools for the narrow React profile window. Profiling plans need both status and wait --connected before profile start.
|
|
589
593
|
Check status before wait/profile. Do not substitute react-devtools start for status; start launches the helper, while status reports connection state.
|
|
590
|
-
Use help debugging for logs clear --restart, logs mark, network dump --include headers, perf
|
|
594
|
+
Use help debugging for logs clear --restart, logs mark, network dump --include headers, perf frames, perf memory, native profiles, traces, and runtime failure evidence.
|
|
591
595
|
For 15-20s async work, use wait with the exact expected text or selector instead of repeated snapshots.
|
|
592
596
|
Report React render offenders separately from network/backend waits and device frame/CPU/memory findings.`},"physical-device":{summary:`Connected phone/tablet setup and iOS signing prerequisites`,body:`agent-device help physical-device
|
|
593
597
|
|
|
@@ -770,6 +774,7 @@ Open and inspect:
|
|
|
770
774
|
agent-device snapshot -i --platform macos
|
|
771
775
|
|
|
772
776
|
Surfaces:
|
|
777
|
+
--surface is an open flag; the session keeps it, so later commands do not repeat it.
|
|
773
778
|
--surface app normal app session
|
|
774
779
|
--surface frontmost-app inspect whichever app is frontmost
|
|
775
780
|
--surface desktop desktop-wide surface
|
|
@@ -777,7 +782,7 @@ Surfaces:
|
|
|
777
782
|
|
|
778
783
|
Menu bar app example:
|
|
779
784
|
agent-device open "Agent Device Tester Menu" --platform macos --surface menubar
|
|
780
|
-
agent-device snapshot -i --platform macos
|
|
785
|
+
agent-device snapshot -i --platform macos
|
|
781
786
|
|
|
782
787
|
Context menu example:
|
|
783
788
|
agent-device click @e66 --button secondary --platform macos
|
|
@@ -793,7 +798,7 @@ Rules:
|
|
|
793
798
|
Use --platform web only for the minimal browser command loop exposed through agent-device.
|
|
794
799
|
|
|
795
800
|
Dependency:
|
|
796
|
-
|
|
801
|
+
Browser mechanics come from a managed, pinned agent-browser backend. agent-device owns command/session/replay integration, selectors/refs at the command surface, and artifact routing; agent-browser owns browser launch, page control, screenshots, and browser-specific behavior.
|
|
797
802
|
Use --platform web when a browser step belongs inside an agent-device session, replay, batch, MCP, or typed-client flow. Use agent-browser directly for standalone web automation.
|
|
798
803
|
Before first use, set up and verify the managed backend:
|
|
799
804
|
agent-device web setup
|
|
@@ -890,7 +895,7 @@ Rules:
|
|
|
890
895
|
scroll takes direction then amount and does not support a selector or --settle: agent-device scroll down 3.
|
|
891
896
|
Keep commands in the report reproducible; use selectors or refs from fresh snapshots, not guessed coordinates.
|
|
892
897
|
Prefer refs for exploration and selectors for deterministic replay.
|
|
893
|
-
Use logs, network, screenshot --overlay-refs, trace, perf
|
|
898
|
+
Use logs, network, screenshot --overlay-refs, trace, perf frames, perf memory, native profiles, or react-devtools only when they add evidence to a specific issue.
|
|
894
899
|
Never delete screenshots, videos, traces, or report artifacts during a session.
|
|
895
900
|
Escalate to help debugging or help react-devtools when runtime symptoms require those tools.`},validate:{summary:`Engineering self-validation with device evidence and cleanup`,body:`agent-device help validate
|
|
896
901
|
|
|
@@ -921,7 +926,7 @@ Evidence:
|
|
|
921
926
|
Visual claim: screenshot, optionally screenshot --overlay-refs when target mapping matters.
|
|
922
927
|
Runtime/logging claim: logs clear --restart, logs mark, reproduce, logs path.
|
|
923
928
|
Network claim: network dump --include headers when headers are relevant.
|
|
924
|
-
Performance claim: perf
|
|
929
|
+
Performance claim: perf frames, perf memory sample, native profile reports, or trace artifacts with bounded output.
|
|
925
930
|
Replay/regression claim: replay or test through the public command path.
|
|
926
931
|
|
|
927
932
|
Report:
|
|
@@ -930,27 +935,27 @@ Report:
|
|
|
930
935
|
|
|
931
936
|
Full command catalog. Use agent-device help <command> for exact flags and behavior.
|
|
932
937
|
|
|
933
|
-
${A(
|
|
938
|
+
${A(t().map(e=>{let t=s(e);return{name:e,schema:t,usage:x(e,t)}}))}
|
|
934
939
|
|
|
935
|
-
${D(`Global Flags:`,T(
|
|
940
|
+
${D(`Global Flags:`,T(r))}
|
|
936
941
|
|
|
937
942
|
${k(`Configuration:`,h)}
|
|
938
943
|
|
|
939
944
|
${O(`Environment:`,g)}
|
|
940
945
|
|
|
941
946
|
${k(`Examples:`,_)}
|
|
942
|
-
`}function w(){return S()}function T(e){return
|
|
947
|
+
`}function w(){return S()}function T(e){return n().filter(t=>e.has(t.key)&&t.usageLabel!==void 0&&t.usageDescription!==void 0)}function E(e,t){return t?e.map(e=>{let n=t[e.key];return n===void 0?e:{...e,usageDescription:n}}):e}function D(e,t){return O(e,t.map(e=>({label:e.usageLabel??``,description:e.usageDescription??``})))}function O(e,t){if(t.length===0)return`${e}\n (none)`;let n=Math.max(...t.map(e=>Math.min(e.label.length,26)))+2,r=[e];for(let e of t){let t=e.label.length<=26?e.label.padEnd(n):`${e.label} `;r.push(` ${t}${e.description}`)}return r.join(`
|
|
943
948
|
`)}function k(e,t){return t.length===0?`${e}\n (none)`:[e,...t.map(e=>` ${e}`)].join(`
|
|
944
|
-
`)}function A(e){return O(`Commands:`,e.map(e=>({label:e.usage,description:e.schema.text.summary})))}function j(e){let t=M(e);if(t)return t;let n=o(e);if(!n)return null;let r=p(e,n),
|
|
949
|
+
`)}function A(e){return O(`Commands:`,e.map(e=>({label:e.usage,description:e.schema.text.summary})))}function j(e){let t=M(e);if(t)return t;let n=o(e);if(!n)return null;let r=p(e,n),a=E(T(new Set(n.allowedFlags??[])),n.flagDescriptionOverrides),s=[];a.length>0&&s.push(D(`Command flags:`,a));let c=s.length>0?`\n\n${s.join(`
|
|
945
950
|
|
|
946
951
|
`)}`:``;return`Usage:
|
|
947
952
|
agent-device ${r}
|
|
948
953
|
|
|
949
|
-
${
|
|
954
|
+
${i(n.text)}${c}
|
|
950
955
|
`}function M(e){let t=y[e];return t?`${N(e,e===`commands`?C():t.body)}
|
|
951
956
|
|
|
952
957
|
Related:
|
|
953
958
|
agent-device help <command> command-specific flags
|
|
954
959
|
agent-device help manual-qa routine QA loop
|
|
955
960
|
agent-device help workflow full automation reference
|
|
956
|
-
`:null}function N(t
|
|
961
|
+
`:null}function N(e,t){let n=`agent-device help ${e}`;return t.startsWith(n)?`agent-device ${a()} — ${e}${t.slice(n.length)}`:t}export{j as buildCommandUsageText,w as buildUsageText};
|