agent-device 0.21.7 → 0.21.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.7.apk → agent-device-android-ime-helper-0.21.8.apk} +0 -0
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.8.apk.sha256 +1 -0
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.7.manifest.json → agent-device-android-ime-helper-0.21.8.manifest.json} +4 -4
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.21.7.apk → agent-device-android-snapshot-helper-0.21.8.apk} +0 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.8.apk.sha256 +1 -0
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.21.7.manifest.json → agent-device-android-snapshot-helper-0.21.8.manifest.json} +6 -6
- package/apple/macos-helper/Package.swift +16 -1
- package/apple/macos-helper/Sources/AgentDeviceMacOSDeviceHub/DeviceHubPose.swift +47 -0
- package/apple/macos-helper/Sources/AgentDeviceMacOSHelper/DeviceHubPose.swift +320 -0
- package/apple/macos-helper/Sources/AgentDeviceMacOSHelper/main.swift +66 -13
- package/apple/macos-helper/Sources/AgentDeviceMacOSInput/MouseClickDelivery.swift +116 -0
- package/apple/macos-helper/Sources/AgentDeviceMacOSInput/MouseClickSchedule.swift +61 -0
- package/apple/macos-helper/Tests/AgentDeviceMacOSDeviceHubTests/DeviceHubPoseTests.swift +30 -0
- package/apple/macos-helper/Tests/AgentDeviceMacOSInputTests/MouseClickScheduleTests.swift +58 -0
- package/dist/src/absence-observation-errors.js +1 -1
- package/dist/src/adapter.js +1 -1
- package/dist/src/agent-browser-lifecycle.js +1 -1
- package/dist/src/agent-browser-process-record.js +1 -1
- package/dist/src/agent-device-client.js +2 -2
- package/dist/src/alert-runtime.js +1 -1
- package/dist/src/android-input-ownership.js +1 -1
- package/dist/src/android.js +1 -1
- package/dist/src/app-launch.js +1 -1
- package/dist/src/app-log-runtime2.js +3 -3
- package/dist/src/cli-help.js +9 -6
- package/dist/src/client-types.d.ts +33 -1
- package/dist/src/command-tools.js +3 -3
- package/dist/src/config.js +1 -1
- package/dist/src/device-claim-inspection.js +1 -1
- package/dist/src/device-claim-rule.js +2 -2
- package/dist/src/device-input-state.d.ts +1 -1
- package/dist/src/device-rotation.js +1 -1
- package/dist/src/device-session.js +1 -1
- package/dist/src/devicectl.js +1 -1
- package/dist/src/display-inventory.js +1 -1
- package/dist/src/durable-resource.js +1 -1
- package/dist/src/exec.js +1 -1
- package/dist/src/find.js +1 -1
- package/dist/src/finders.js +1 -1
- package/dist/src/gesture-runtime.js +1 -1
- package/dist/src/harmonyos.js +1 -1
- package/dist/src/helper.js +2 -2
- package/dist/src/host.js +1 -0
- package/dist/src/interaction-positionals.js +1 -1
- package/dist/src/interaction-ref-policy.js +1 -1
- package/dist/src/interactor-operation-binding.js +1 -0
- package/dist/src/interactor-operation-catalog.js +1 -1
- package/dist/src/interactor.js +4 -5
- package/dist/src/interactor2.js +1 -1
- package/dist/src/internal/bin.js +1 -1
- package/dist/src/internal/daemon.js +2 -2
- package/dist/src/internal/png-worker.d.ts +5 -0
- package/dist/src/internal/png-worker.js +1 -1
- package/dist/src/ios-snapshot-acquisition.js +1 -1
- package/dist/src/ios-snapshot-runtime.js +1 -1
- package/dist/src/lease.js +1 -1
- package/dist/src/linux.js +1 -1
- package/dist/src/local-interactor-operation-set.js +1 -1
- package/dist/src/location-coordinates.js +1 -1
- package/dist/src/macos-facade.js +1 -1
- package/dist/src/mechanics.js +16 -15
- package/dist/src/mobile-snapshot-semantics.js +1 -1
- package/dist/src/parameterized-recorded-fill.js +1 -1
- package/dist/src/perf-facade.js +1 -1
- package/dist/src/perf-runtime-plan.js +1 -1
- package/dist/src/physical-device-control.js +1 -1
- package/dist/src/platform-request-scope.js +1 -1
- package/dist/src/platform-runtime-managed-owner.js +1 -1
- package/dist/src/platform-runtime-unavailable.js +1 -1
- package/dist/src/platform-runtime.js +1 -1
- package/dist/src/platform-runtime2.js +1 -1
- package/dist/src/png-worker-client.js +1 -1
- package/dist/src/provider-webdriver.js +1 -1
- package/dist/src/quality-warnings.js +1 -1
- package/dist/src/registry.js +35 -35
- package/dist/src/replay.js +2 -2
- package/dist/src/request-admission.js +1 -1
- package/dist/src/request-runtime-binding.js +1 -1
- package/dist/src/runner-cache-metadata.js +2 -2
- package/dist/src/runner-client.js +1 -1
- package/dist/src/runner-contract.js +3 -0
- package/dist/src/runner-dev-tools-security.js +1 -0
- package/dist/src/runner-device-readiness.js +1 -0
- package/dist/src/runner-disposal.js +1 -1
- package/dist/src/runner-presentation.js +1 -1
- package/dist/src/runtime.js +2 -2
- package/dist/src/runtime2.js +4 -4
- package/dist/src/runtime4.js +4 -4
- package/dist/src/runtime6.js +1 -1
- package/dist/src/runtime7.js +1 -1
- package/dist/src/runtime8.js +1 -1
- package/dist/src/runtime9.js +1 -1
- package/dist/src/screen-recording-resource-recovery.js +1 -1
- package/dist/src/screenshot-image.js +1 -0
- package/dist/src/screenshot-runtime.js +1 -1
- package/dist/src/script.js +1 -1
- package/dist/src/scroll-gesture.js +1 -1
- package/dist/src/sdk-batch.js +1 -1
- package/dist/src/sdk-contracts.js +2 -2
- package/dist/src/sdk-finders.js +1 -1
- package/dist/src/sdk-selectors.d.ts +15 -6
- package/dist/src/sdk-selectors.js +1 -1
- package/dist/src/selection.js +0 -0
- package/dist/src/selector-runtime.js +1 -1
- package/dist/src/selectors.js +1 -1
- package/dist/src/semantic-index.js +1 -1
- package/dist/src/session-snapshot.js +1 -1
- package/dist/src/session-store.js +3 -3
- package/dist/src/session2.js +2 -2
- package/dist/src/simulator-facade.js +1 -1
- package/dist/src/simulator.js +1 -1
- package/dist/src/snapshot-runtime-binding.js +1 -1
- package/dist/src/snapshot-state.js +1 -1
- package/dist/src/snapshot4.js +1 -1
- package/dist/src/src.js +1 -1
- package/dist/src/src7.js +1 -1
- package/dist/src/src8.js +1 -1
- package/dist/src/text-entry-focus.js +1 -1
- package/dist/src/touch-runtime.js +1 -1
- package/dist/src/tree.js +1 -1
- package/dist/src/type-text-runtime.js +1 -1
- package/dist/src/video.js +1 -1
- package/dist/src/web2.js +1 -1
- package/package.json +3 -1
- package/server.json +2 -2
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.7.apk.sha256 +0 -1
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.7.apk.sha256 +0 -1
- package/dist/src/png-transcode.js +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{D as e}from"./sdk-contracts.js";import{u as t}from"./sdk-device.js";import{
|
|
2
|
-
`)?r:`${r}\n`),a=`active`}catch{if(o)return;a=`recovering`}await e.host.clock.sleep(1e3)}})(),l;return Te({inspect:()=>({backend:r,state:a,startedAt:i}),finish:async()=>l??=(async()=>(o=!0,await c,(await
|
|
1
|
+
import{D as e}from"./sdk-contracts.js";import{u as t}from"./sdk-device.js";import{Qt as n,Xt as r}from"./sdk-batch.js";import{n as i,o as a,r as o,s}from"./request-cancellation.js";import{n as c,t as l}from"./application-lifecycle-runtime.js";import{C as u,E as d,F as ee,I as f,L as te,M as p,O as ne,P as re,T as ie,U as ae,V as m,W as h,_ as g,a as oe,b as _,f as v,h as se,i as ce,j as le,k as ue,l as y,t as de,y as b,z as fe}from"./alert-runtime.js";import{n as pe}from"./audio-probe-runtime.js";import{n as me}from"./perf-runtime.js";import{i as he,n as ge}from"./touch-runtime.js";import{r as _e}from"./platform-runtime-unavailable.js";import{a as ve,n as ye}from"./durable-resource.js";import{t as be}from"./async-lifecycle.js";import{a as x,d as xe,f as Se,n as Ce,o as we,u as Te}from"./src7.js";import{i as Ee,t as De}from"./gesture-admission.js";import{n as Oe}from"./interactor-operation-catalog.js";import{t as S}from"./app-log-runtime.js";import{r as ke,t as Ae}from"./application-lifecycle-interaction.js";import{n as je,r as Me,t as Ne}from"./screen-recording-transport.js";import{setTimeout as Pe}from"node:timers/promises";const C=Object.freeze({available:!0}),Fe=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun iOS direct sessions do not expose portable gesture execution yet.`}),Ie=Object.freeze({available:!1,reason:`unsupported-provider-mode`}),Le=Object.freeze({available:!1,reason:`unsupported-provider-mode`}),Re=Object.freeze({available:!1,reason:`unsupported-platform-leaf`,hint:De}),ze=Object.freeze({available:!1,reason:`unsupported-platform-leaf`,hint:Ee});function w(e,t){if(!t.available)return p({unsupported:t});if(e.platform!==`android`)return p({unsupported:Fe});let n=e.target===`tv`;return p({unsupported:Ie,plan:C,directionalFling:C,multiTouch:n?Re:C,targetAuthoredDrag:n?ze:C,viewport:C})}const Be=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun iOS direct sessions do not expose home yet.`}),Ve=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun iOS direct sessions do not expose tv remote control.`}),He=Object.freeze({available:!1,reason:`unsupported-device-kind`,hint:`tv-remote is supported only on Android TV targets.`}),Ue=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun iOS direct sessions do not expose keyboard actions.`}),We=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun iOS direct sessions do not expose clipboard access yet.`}),Ge=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun iOS direct sessions do not expose settings changes yet.`}),Ke=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun iOS direct sessions do not expose app switcher yet.`}),T=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`No Limrun session exposes this system button.`});function E(e,n){let r=n??C,i=Object.freeze({available:!1,reason:`unsupported-provider-mode`});return Object.freeze({...ee({focus:r}),...d({type:r}),...he({unsupported:i,tap:r,longPress:r,hover:n??i,fill:r,tapElementSelector:n??(t(e)?r:i)}),...w(e,r),...ue({scroll:r})})}function qe(e){let{device:t,signal:n}=e,r=n=>e.getInteractor(t,n);return Object.freeze({...fe({device:t,signal:n,resolveInteractor:r,presentIosAcquisition:e.presentIosAcquisition}),...re({device:t,signal:n,resolveInteractor:r}),...ie({device:t,signal:n,resolveInteractor:r}),...ge({device:t,signal:n,resolveInteractor:r,facts:E(t),pause:async e=>await Pe(e,void 0,{signal:n})}),...ae({device:t,signal:n,resolveInteractor:r}),...le({device:t,signal:n,facts:w(t,C),resolveInteractor:r}),...ne({device:t,signal:n,resolveInteractor:r})})}function D(e,t){return t?Object.freeze({..._({back:t}),...b({orientation:t}),...g({tvRemote:t})}):e.platform===`android`?Object.freeze({..._({back:C}),...b({orientation:C}),...g({tvRemote:e.target===`tv`?C:He})}):Object.freeze({..._({back:C}),...b({orientation:C}),...g({tvRemote:Ve})})}function O(e,t){return t?Object.freeze({...v({unsupported:t})}):e.platform===`android`?Object.freeze({...v({unsupported:Le,read:C,write:C})}):Object.freeze({...v({unsupported:We})})}const Je=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun iOS direct sessions do not expose alert inspection yet.`});function k(e,t){let n=t??(e.platform===`android`?C:Je);return Object.freeze({...de({read:n,wait:n,accept:n,dismiss:n})})}function A(e,t){return t?y({unsupported:t}):e.platform===`android`?y({unsupported:T,home:C,appSwitcher:C}):y({unsupported:T,home:Be,appSwitcher:Ke})}const j=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`fold poses a foldable iPhone simulator through Xcode Device Hub on the host, which no Limrun session exposes.`});function M(){return Object.freeze({setFoldPose:j})}function N(e,t){return Object.freeze({...oe({triggerAppEvent:t??C})})}function P(e,t){let n=t??(e.platform===`android`?C:Ge);return Object.freeze({...ce({setSetting:n})})}function Ye(e,t){let n=t??Ue,r=t===void 0&&e.platform===`android`;return Object.freeze({...se(r?{unsupported:n,status:C,dismiss:C,enter:C}:{unsupported:n})})}const F=Object.freeze({resourceKind:S,version:1,encode:e=>({...e}),decode:e=>e.transport!==`limrun-log-poller`||e.platform!==`ios`&&e.platform!==`android`||!I(e.leaseId)||!I(e.instanceId)||!I(e.appBundleId)||!I(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 Xe(e){if(e.device.platform===`apple`&&!e.device.appleOs)throw TypeError(`Limrun Apple app-log persistence requires an explicit appleOs identity`);return ye({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:ve(F,e.descriptor)})}function I(e){return typeof e==`string`&&e.trim().length>0}async function L(e){let t=new be,n=!1;t.defer(async()=>{n||await e.reader[Symbol.asyncDispose]()});try{let r=await e.host.outputs.readTail(e.outputPath,262144),i=await e.host.outputs.openAppend(e.outputPath);t.defer(async()=>{n||await i[Symbol.asyncDispose]()});let a=Ze(e,i,nt(r));return n=!0,a}finally{await t[Symbol.asyncDispose]()}}function Ze(e,t,n){let r=it(e.reader),i=e.host.clock.now(),a=`active`,o=!1,s=n,c=(async()=>{for(;!o;){try{let n=await Qe(e);if(n.status===`timeout`){a=`failed`;return}if(o)return;let r=$e(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 Te({inspect:()=>({backend:r,state:a,startedAt:i}),finish:async()=>l??=(async()=>(o=!0,await c,(await rt([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 Qe(e){let t=new AbortController,n=i(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 $e(e,t){if(!e||!t)return t;let n=et(t),r=Math.min(e.length,t.length),i=e.slice(e.length-r);return t.slice(tt(i,t,n))}function et(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 tt(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 nt(e){return e.split(`
|
|
3
3
|
`).filter(e=>!e.startsWith(`[agent-device][mark]`)).join(`
|
|
4
|
-
`)}async function nt(e){return(await Promise.allSettled(e.map(async e=>await e[Symbol.asyncDispose]()))).flatMap(e=>e.status===`rejected`?[e.reason]:[])}function rt(e){return e.platform===`ios`?`ios-simulator`:`android`}function it(e){let t=Ae({owner:`Limrun`,openTargetIdentity:`bundle-id`,closeBeforeRelaunch:!0,configureProviderPortReverse:async t=>await e.configurePortReverse(t),binding:ke({device:e.device,signal:e.signal,resolveInteractor:t=>e.getInteractor(e.device,t)})}),n=e.resolveAppReference;return n?Object.freeze({...t,resolveOpenTarget:async e=>await t.resolveOpenTarget(at(e,n)),openApplication:async e=>await t.openApplication(ot(e,n)),closeApplication:async e=>await t.closeApplication(st(e,n))}):t}function at(e,t){return e.target===void 0?e:{...e,target:t(e.target)}}function ot(e,t){return{...e,target:B(e.target,t),positionals:z(e.positionals,t),appBundleId:B(e.appBundleId,t)}}function st(e,t){return{...e,positionals:z(e.positionals,t),appBundleId:B(e.appBundleId,t)}}function z(e,t){let n=e[0];return n===void 0?e:[t(n),...e.slice(1)]}function B(e,t){return e===void 0?void 0:t(e)}function ct(e){let t=s(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 lt=Object.freeze({available:!0}),V=Object.freeze({available:!1,reason:`owner-capability-missing`,hint:`The Limrun provider session is no longer active for this device.`}),ut=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Push notifications are unavailable for Limrun provider-owned devices.`});function H(e,t){let n=ft(e,t);return Object.freeze({deployApp:n,materializeAppSource:n,deployMaterializedApp:n,sendPushNotification:U(e,t)?ut:V})}function dt(e,t,n,r){let i=e.deployApp,a=e.deployMaterializedApp;return!H(e,t).deployApp.available||!i||!a?Object.freeze({}):Object.freeze({deployApp:async e=>W(await i(t,e,n,r)),materializeAppSource:async r=>await pt(e.host,t,r,n),deployMaterializedApp:async e=>W(await a(t,e,n,r))})}function ft(e,t){return ct(t)&&U(e,t)&&e.deployApp&&e.deployMaterializedApp?lt:V}function U(e,t){return e.isSessionActive?.(t)??e.ownsDevice(t)}async function pt(e,t,n,r){return await(t.platform===`apple`?e.appleDeployment:e.androidDeployment).prepareArtifact(n,{signal:r})}function W(t){if(!t)throw new e(`UNSUPPORTED_OPERATION`,`The Limrun provider session is no longer active.`);return t}const mt=Object.freeze({medium:5,high:8});function ht(e){return Object.freeze({screenRecordingStart:async t=>await gt(e,t),screenRecordingReattach:async()=>Me(`Limrun recordings cannot be reattached after daemon restart.`),screenRecordingCleanup:async()=>je(`Limrun recordings cannot be cleaned after daemon restart; the instance disposes them when it terminates.`)})}async function gt(t,n){let r=t.getDeviceSession(t.device);if(!r)throw new e(`UNSUPPORTED_OPERATION`,`Limrun recording requires a live provider session for this device.`,{deviceId:t.device.id});return await Ne({host:t.host,device:t.device,owner:t.owner,input:n,signal:t.signal,transport:{backend:`limrun-recorder`,targetLabel:`Limrun recording`,start:async()=>{await r.startRecording({quality:mt[n.exportQuality??`medium`]})},stop:async()=>(await r.stopRecording()).downloadUrl,collect:async(e,t)=>{await r.downloadRecording({downloadUrl:e,outPath:t})}},support:{scopes:[`app`,`device`,`system`],fps:!1,exportQuality:!0,hideTouches:!1},unsupported:e=>`Limrun recordings do not support ${e.join(`, `)}`})}const G=Object.freeze({available:!0}),K=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Custom snapshot actions are available only for Limrun iOS simulator sessions.`}),_t=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun does not expose viewport resizing.`}),q=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun-owned devices read element text from the captured tree only.`}),vt=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Headless boot is unavailable for provider-owned devices.`}),J=Object.freeze({available:!1,reason:`owner-capability-missing`,hint:`Limrun requires a matching live provider session for this device.`}),yt=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Apple runner preparation is unavailable for Limrun-owned devices.`}),bt=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun iOS appstate is session-owned; no sessionless provider foreground probe is exposed.`}),xt=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun open requires a Limrun-owned iOS simulator or Android emulator.`}),St=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun close requires a Limrun-owned iOS simulator or Android emulator.`}),Y=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Runtime hints are not applied to provider-owned devices.`}),Ct=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun port reverse requires an active Android Limrun session.`}),wt=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun does not expose the audio probe.`});function Tt(e){return{...e,isSessionActive:e.hasLiveSession}}function X(e,t){let n=Et(e,t),r=Dt(e,t),i=Ot(e,t);return l({resolveOpenTarget:n,prepareApplicationOpen:n,openApplication:n,applyRuntimeHints:Y,clearRuntimeHints:Y,closeApplication:r,finalizeApplicationClose:r,prepareAppleRunner:yt,configureProviderPortReverse:i})}function Et(e,t){return a(e)?t?G:J:xt}function Dt(e,t){return a(e)?t?G:J:St}function Ot(e,t){return t?e.platform===`android`?G:Ct:J}function Z(e,n){let r=H(Tt(e),n),i=n.platform===`android`,a=t(n)&&n.kind===`simulator`?G:K;return Object.freeze({device:{family:n.platform,...n.appleOs===void 0?{}:{appleOs:n.appleOs},kind:n.kind,...n.target===void 0?{}:{target:n.target},...n.iosPhysicalDeviceBackend===void 0?{}:{iosPhysicalDeviceBackend:n.iosPhysicalDeviceBackend},providerMode:`provider-runtime`},operations:{appLogInspect:G,appLogDoctor:G,appLogStart:G,appLogReattach:G,appLogCleanup:G,...r,appState:i?G:bt,networkDump:G,screenRecordingStart:G,screenRecordingReattach:G,screenRecordingCleanup:G,...p({capture:G,customActions:a,withoutActiveApp:G}),...f({capture:G}),...g({findText:K}),...m({setViewport:_t}),...D(n),...me({readTextAtPoint:q}),...O(n),...F(n),...k(n),...j(n),...M(),...N(n),...P(n),...A(n),...he({capture:wt,query:wt}),...ge({frames:q,memorySample:q,memorySnapshot:q,nativeCapture:q,profileReport:q}),ensureReady:G,bootTarget:G,bootTargetHeadless:vt,listApps:G,shutdownTarget:{available:!1,reason:`unsupported-provider-mode`,hint:`Limrun owns the target lifecycle for provider-owned devices.`},...X(n,!0)}})}function kt(e,t){let n=Z(e,t);return Object.freeze({device:n.device,operations:{...n.operations,appLogInspect:J,appLogDoctor:J,appLogStart:J,appLogReattach:G,appLogCleanup:G,appState:J,networkDump:J,screenRecordingStart:J,screenRecordingReattach:J,screenRecordingCleanup:J,...p({capture:J,customActions:J,withoutActiveApp:J}),...f({capture:J}),...g({findText:J}),...m({setViewport:J}),...D(t,J),...O(t,J),...F(t,J),...k(t,J),...j(t,J),...M(),...N(t,J),...P(t,J),...A(t,J),ensureReady:J,bootTarget:J,bootTargetHeadless:J,listApps:J,deployApp:J,materializeAppSource:J,deployMaterializedApp:J,sendPushNotification:J,shutdownTarget:J,...X(t,!1)}})}function At(t){let i=n(`limrun`,t.runtimeInstance),o=e=>a(e)&&t.ownsDevice(e),s=e=>o(e)&&t.hasLiveSession(e);return Object.freeze({owner:i,ownsDevice:o,inspectFacts:async e=>s(e)?Z(t,e):_e(e,i,{appLog:J,appState:J,appDeployment:J,network:J,screenshot:J,viewport:J,focus:J,gesture:J,scroll:J,typeText:J,touch:J,elementText:J,back:J,home:J,orientation:J,tvRemote:J,keyboard:J,clipboard:J,appSwitcher:J,actionButton:E,triggerAppEvent:J,setSetting:J,readAlert:J,awaitAlert:J,acceptAlert:J,dismissAlert:J,audioProbeCapture:J,audioProbeQuery:J,perf:J,readiness:J,shutdown:J,lifecycle:X(e,!1)}),bind:async n=>{if(n.intent.kind===`exact-owner`&&!r(n.intent.owner,i))throw new e(`UNSUPPORTED_OPERATION`,`Limrun app-log owner identity does not match`);if(!a(n.device))throw new e(`UNSUPPORTED_PLATFORM`,`Limrun app logs require an iOS simulator or Android emulator device identity`);let o=s(n.device);if(n.intent.kind!==`exact-owner`&&!o)throw new e(`UNSUPPORTED_OPERATION`,`Limrun provider session is no longer live for the selected device`,{reason:`provider-session-unavailable`});return jt(t,i,n.device,n.scope.signal,!o)},shutdown:async()=>void 0})}function jt(t,n,r,i,a){let s=a?kt(t,r):Z(t,r),l=o(),u=xe({codec:I,reattach:async(e,n)=>{if(!$(e,r)||!S(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 R({host:t.host,reader:a.reader,appBundleId:e.appBundleId,outputPath:e.outputPath})}},cleanup:async(e,n)=>$(e,r)&&S(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:Q(r)}),appLogDoctor:async()=>({backend:Q(r),checks:{limrunSessionAvailable:await Mt(t,r,i)},notes:[]}),appLogStart:async a=>{we(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=Ye({sessionId:a.sessionId,device:r,owner:n,fence:a.fence,descriptor:s});c=!0;let l=await R({host:t.host,reader:o,appBundleId:a.appBundleId,outputPath:a.outputPath});return Se(l,e)}catch(e){throw c||await o[Symbol.asyncDispose](),e}},...u,networkDump:async e=>{let n=await t.host.appLogs.readRecent(e.sessionId,e.maxScanLines),i=Q(r),{dump:a}=Ce(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)}:{},...c(it({device:r,signal:i,getInteractor:t.getInteractor,resolveAppReference:e=>t.resolveAppReference?.(r,e)??e,configurePortReverse:t.configurePortReverse}),s.operations),...qe({device:r,signal:i,getInteractor:t.getInteractor,presentIosAcquisition:t.host.snapshot.presentIosAcquisition}),...Oe({device:r,signal:i,resolveInteractor:e=>t.getInteractor(r,e),facts:s.operations}),...dt(Tt(t),r,i,l),...ht({host:t.host,device:r,owner:n,signal:i,getDeviceSession:t.getDeviceSession})};return Object.freeze({device:r,owner:n,facts:s,operations:Object.freeze(a?{appLogReattach:u.appLogReattach,appLogCleanup:u.appLogCleanup}:d),[Symbol.asyncDispose]:async()=>await l[Symbol.asyncDispose]()})}async function Mt(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 Q(e){return e.platform===`apple`?`ios-simulator`:`android`}function $(e,t){if(!a(t))return!1;let n=s(t.id);return n!==void 0&&n.leaseId===e.leaseId&&n.platform===e.platform&&(t.platform===`apple`?e.platform===`ios`:e.platform===`android`)}export{At as createLimrunPlatformRuntimeOwner};
|
|
4
|
+
`)}async function rt(e){return(await Promise.allSettled(e.map(async e=>await e[Symbol.asyncDispose]()))).flatMap(e=>e.status===`rejected`?[e.reason]:[])}function it(e){return e.platform===`ios`?`ios-simulator`:`android`}function at(e){let t=Ae({owner:`Limrun`,openTargetIdentity:`bundle-id`,closeBeforeRelaunch:!0,configureProviderPortReverse:async t=>await e.configurePortReverse(t),binding:ke({device:e.device,signal:e.signal,resolveInteractor:t=>e.getInteractor(e.device,t)})}),n=e.resolveAppReference;return n?Object.freeze({...t,resolveOpenTarget:async e=>await t.resolveOpenTarget(ot(e,n)),openApplication:async e=>await t.openApplication(st(e,n)),closeApplication:async e=>await t.closeApplication(ct(e,n))}):t}function ot(e,t){return e.target===void 0?e:{...e,target:t(e.target)}}function st(e,t){return{...e,target:z(e.target,t),positionals:R(e.positionals,t),appBundleId:z(e.appBundleId,t)}}function ct(e,t){return{...e,positionals:R(e.positionals,t),appBundleId:z(e.appBundleId,t)}}function R(e,t){let n=e[0];return n===void 0?e:[t(n),...e.slice(1)]}function z(e,t){return e===void 0?void 0:t(e)}function lt(e){let t=s(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 ut=Object.freeze({available:!0}),B=Object.freeze({available:!1,reason:`owner-capability-missing`,hint:`The Limrun provider session is no longer active for this device.`}),dt=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Push notifications are unavailable for Limrun provider-owned devices.`});function V(e,t){let n=pt(e,t);return Object.freeze({deployApp:n,materializeAppSource:n,deployMaterializedApp:n,sendPushNotification:H(e,t)?dt:B})}function ft(e,t,n,r){let i=e.deployApp,a=e.deployMaterializedApp;return!V(e,t).deployApp.available||!i||!a?Object.freeze({}):Object.freeze({deployApp:async e=>U(await i(t,e,n,r)),materializeAppSource:async r=>await mt(e.host,t,r,n),deployMaterializedApp:async e=>U(await a(t,e,n,r))})}function pt(e,t){return lt(t)&&H(e,t)&&e.deployApp&&e.deployMaterializedApp?ut:B}function H(e,t){return e.isSessionActive?.(t)??e.ownsDevice(t)}async function mt(e,t,n,r){return await(t.platform===`apple`?e.appleDeployment:e.androidDeployment).prepareArtifact(n,{signal:r})}function U(t){if(!t)throw new e(`UNSUPPORTED_OPERATION`,`The Limrun provider session is no longer active.`);return t}const ht=Object.freeze({medium:5,high:8});function gt(e){return Object.freeze({screenRecordingStart:async t=>await _t(e,t),screenRecordingReattach:async()=>Me(`Limrun recordings cannot be reattached after daemon restart.`),screenRecordingCleanup:async()=>je(`Limrun recordings cannot be cleaned after daemon restart; the instance disposes them when it terminates.`)})}async function _t(t,n){let r=t.getDeviceSession(t.device);if(!r)throw new e(`UNSUPPORTED_OPERATION`,`Limrun recording requires a live provider session for this device.`,{deviceId:t.device.id});return await Ne({host:t.host,device:t.device,owner:t.owner,input:n,signal:t.signal,transport:{backend:`limrun-recorder`,targetLabel:`Limrun recording`,start:async()=>{await r.startRecording({quality:ht[n.exportQuality??`medium`]})},stop:async()=>(await r.stopRecording()).downloadUrl,collect:async(e,t)=>{await r.downloadRecording({downloadUrl:e,outPath:t})}},support:{scopes:[`app`,`device`,`system`],fps:!1,exportQuality:!0,hideTouches:!1},unsupported:e=>`Limrun recordings do not support ${e.join(`, `)}`})}const W=Object.freeze({available:!0}),G=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Custom snapshot actions are available only for Limrun iOS simulator sessions.`}),vt=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun does not expose viewport resizing.`}),K=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun-owned devices read element text from the captured tree only.`}),yt=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Headless boot is unavailable for provider-owned devices.`}),q=Object.freeze({available:!1,reason:`owner-capability-missing`,hint:`Limrun requires a matching live provider session for this device.`}),bt=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Apple runner preparation is unavailable for Limrun-owned devices.`}),xt=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun iOS appstate is session-owned; no sessionless provider foreground probe is exposed.`}),St=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun open requires a Limrun-owned iOS simulator or Android emulator.`}),Ct=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun close requires a Limrun-owned iOS simulator or Android emulator.`}),J=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Runtime hints are not applied to provider-owned devices.`}),wt=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun port reverse requires an active Android Limrun session.`}),Y=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun does not expose the audio probe.`});function Tt(e){return{...e,isSessionActive:e.hasLiveSession}}function X(e,t){let n=Et(e,t),r=Dt(e,t),i=Ot(e,t);return l({resolveOpenTarget:n,prepareApplicationOpen:n,openApplication:n,applyRuntimeHints:J,clearRuntimeHints:J,closeApplication:r,finalizeApplicationClose:r,prepareAppleRunner:bt,configureProviderPortReverse:i})}function Et(e,t){return a(e)?t?W:q:St}function Dt(e,t){return a(e)?t?W:q:Ct}function Ot(e,t){return t?e.platform===`android`?W:wt:q}function Z(e,n){let r=V(Tt(e),n),i=n.platform===`android`,a=t(n)&&n.kind===`simulator`?W:G;return Object.freeze({device:{family:n.platform,...n.appleOs===void 0?{}:{appleOs:n.appleOs},kind:n.kind,...n.target===void 0?{}:{target:n.target},...n.iosPhysicalDeviceBackend===void 0?{}:{iosPhysicalDeviceBackend:n.iosPhysicalDeviceBackend},providerMode:`provider-runtime`},operations:{appLogInspect:W,appLogDoctor:W,appLogStart:W,appLogReattach:W,appLogCleanup:W,...r,appState:i?W:xt,networkDump:W,screenRecordingStart:W,screenRecordingReattach:W,screenRecordingCleanup:W,...m({capture:W,customActions:a,withoutActiveApp:W}),...h({capture:W}),...te({findText:G}),...f({setViewport:vt}),...E(n),...u({readTextAtPoint:K}),...D(n),...Ye(n),...O(n),...A(n),...M(),...N(n),...P(n),...k(n),...pe({capture:Y,query:Y}),...me({frames:K,memorySample:K,memorySnapshot:K,nativeCapture:K,profileReport:K}),ensureReady:W,bootTarget:W,bootTargetHeadless:yt,listApps:W,shutdownTarget:{available:!1,reason:`unsupported-provider-mode`,hint:`Limrun owns the target lifecycle for provider-owned devices.`},...X(n,!0)}})}function kt(e,t){let n=Z(e,t);return Object.freeze({device:n.device,operations:{...n.operations,appLogInspect:q,appLogDoctor:q,appLogStart:q,appLogReattach:W,appLogCleanup:W,appState:q,networkDump:q,screenRecordingStart:q,screenRecordingReattach:q,screenRecordingCleanup:q,...m({capture:q,customActions:q,withoutActiveApp:q}),...h({capture:q}),...te({findText:q}),...f({setViewport:q}),...E(t,q),...D(t,q),...Ye(t,q),...O(t,q),...A(t,q),...M(),...N(t,q),...P(t,q),...k(t,q),ensureReady:q,bootTarget:q,bootTargetHeadless:q,listApps:q,deployApp:q,materializeAppSource:q,deployMaterializedApp:q,sendPushNotification:q,shutdownTarget:q,...X(t,!1)}})}function At(t){let i=r(`limrun`,t.runtimeInstance),o=e=>a(e)&&t.ownsDevice(e),s=e=>o(e)&&t.hasLiveSession(e);return Object.freeze({owner:i,ownsDevice:o,inspectFacts:async e=>s(e)?Z(t,e):_e(e,i,{appLog:q,appState:q,appDeployment:q,network:q,screenshot:q,viewport:q,focus:q,gesture:q,scroll:q,typeText:q,touch:q,elementText:q,back:q,orientation:q,tvRemote:q,keyboard:q,clipboard:q,systemButton:q,fold:j,triggerAppEvent:q,setSetting:q,readAlert:q,awaitAlert:q,acceptAlert:q,dismissAlert:q,audioProbeCapture:q,audioProbeQuery:q,perf:q,readiness:q,shutdown:q,lifecycle:X(e,!1)}),bind:async r=>{if(r.intent.kind===`exact-owner`&&!n(r.intent.owner,i))throw new e(`UNSUPPORTED_OPERATION`,`Limrun app-log owner identity does not match`);if(!a(r.device))throw new e(`UNSUPPORTED_PLATFORM`,`Limrun app logs require an iOS simulator or Android emulator device identity`);let o=s(r.device);if(r.intent.kind!==`exact-owner`&&!o)throw new e(`UNSUPPORTED_OPERATION`,`Limrun provider session is no longer live for the selected device`,{reason:`provider-session-unavailable`});return jt(t,i,r.device,r.scope.signal,!o)},shutdown:async()=>void 0})}function jt(t,n,r,i,a){let s=a?kt(t,r):Z(t,r),l=o(),u=xe({codec:F,reattach:async(e,n)=>{if(!$(e,r)||!x(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 L({host:t.host,reader:a.reader,appBundleId:e.appBundleId,outputPath:e.outputPath})}},cleanup:async(e,n)=>$(e,r)&&x(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:Q(r)}),appLogDoctor:async()=>({backend:Q(r),checks:{limrunSessionAvailable:await Mt(t,r,i)},notes:[]}),appLogStart:async a=>{we(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=Xe({sessionId:a.sessionId,device:r,owner:n,fence:a.fence,descriptor:s});c=!0;let l=await L({host:t.host,reader:o,appBundleId:a.appBundleId,outputPath:a.outputPath});return Se(l,e)}catch(e){throw c||await o[Symbol.asyncDispose](),e}},...u,networkDump:async e=>{let n=await t.host.appLogs.readRecent(e.sessionId,e.maxScanLines),i=Q(r),{dump:a}=Ce(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)}:{},...c(at({device:r,signal:i,getInteractor:t.getInteractor,resolveAppReference:e=>t.resolveAppReference?.(r,e)??e,configurePortReverse:t.configurePortReverse}),s.operations),...qe({device:r,signal:i,getInteractor:t.getInteractor,presentIosAcquisition:t.host.snapshot.presentIosAcquisition}),...Oe({device:r,signal:i,resolveInteractor:e=>t.getInteractor(r,e),facts:s.operations}),...ft(Tt(t),r,i,l),...gt({host:t.host,device:r,owner:n,signal:i,getDeviceSession:t.getDeviceSession})};return Object.freeze({device:r,owner:n,facts:s,operations:Object.freeze(a?{appLogReattach:u.appLogReattach,appLogCleanup:u.appLogCleanup}:d),[Symbol.asyncDispose]:async()=>await l[Symbol.asyncDispose]()})}async function Mt(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 Q(e){return e.platform===`apple`?`ios-simulator`:`android`}function $(e,t){if(!a(t))return!1;let n=s(t.id);return n!==void 0&&n.leaseId===e.leaseId&&n.platform===e.platform&&(t.platform===`apple`?e.platform===`ios`:e.platform===`android`)}export{At as createLimrunPlatformRuntimeOwner};
|
package/dist/src/cli-help.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{r as e}from"./rolldown-runtime.js";import{
|
|
1
|
+
import{r as e}from"./rolldown-runtime.js";import{hr as t}from"./sdk-batch.js";import{r as n}from"./back-mode.js";import{i as r}from"./catalog.js";import{d as i,f as a,v as o}from"./registry.js";import{r as s}from"./version.js";import{n as c,r as l}from"./command-schema.js";import{n as u}from"./cli-command-aliases.js";const d=[`Flows: launchApp (with clearState, permissions, and Apple-only launch arguments; permissions apply after state clearing but before launch, and a launchApp without permissions touches nothing — there is no silent all: allow default); setPermissions (mid-flow permission grants, denials, and resets; all resolves in the backend — one simctl call on iOS, the declared permissions on Android — with specific entries overriding after it); runFlow file/inline with platform, visibility, and limited boolean conditions; onFlowStart/onFlowComplete; repeat.times and retry.`,`Interactions: tapOn, doubleTapOn, longPressOn, inputText on the focused element, eraseText, openLink, hideKeyboard, basic pressKey, and back; selector targets poll until available and support recursive index, childOf, above, below, leftOf, rightOf, containsChild, containsDescendants, points, and optional; outer command labels are metadata, not target selectors.`,'Assertions and navigation: assertVisible, assertNotVisible, assertTrue (literal values and ${VAR} lookups only; "", "false", "0", "null", and "undefined" are falsy, everything else is truthy), extendedWaitUntil, scroll, scrollUntilVisible, absolute/percentage/target swipe, takeScreenshot, waitForAnimationToEnd, clearState, and stopApp.',`Scripts: ordered runScript file/env scripts with http.post, json, and output variables; evalScript inline expressions run flow-scoped JavaScript and write output.* leaves for later steps.`],f=[`Permissions: every entry is one settings permission call, applied in order with all first; the step stops at the first entry the selected platform refuses, earlier entries stay applied, and the error names what landed. Android’s only allow level is while-in-use, so location: inuse and location: never mean allow and deny there, while location: always and photos: limited are Apple-only and fail. On iOS, which service a runtime changes is simctl privacy’s own verdict: current runtimes refuse a targeted notifications change and leave notifications untouched under all.`,`Runtime: iOS and Android only; launchApp.clearState and standalone clearState support Android and iOS simulators, launch arguments are Apple-only, and other standalone device utility/state commands are unsupported.`,"Expressions: evalScript is the only command whose payload is evaluated as JavaScript (flow env and prior output leaves are string-typed); with that exception, fields stay literal or ${VAR} lookup-only — assertTrue supports literals and bare lookups, repeat.while is unsupported, and other expression-shaped payloads fail loud.",`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 and evalScript execute flow scripts in-process via node:vm, which is not a security sandbox; runScript may make http.post network requests and its output keys cannot contain a dot. evalScript is refused outright for a flow accepted over the daemon’s remote HTTP surface, since that context can escape to the host.`,`Errors and tracking: unsupported commands and fields fail with source context when available; open a focused issue only when implementation work is planned.`];function p(){return[`Supported subset:`,...d.map(e=>` - ${e}`),``,`Boundaries:`,...f.map(e=>` - ${e}`)].join(`
|
|
2
2
|
`)}function m(e){let t=e.endsWith(`?`),n=t?e.slice(0,-1):e;return t?`[${n}]`:`<${n}>`}function h(e){return n().filter(t=>t.key===e)}function g(e){if(!e.usageHidden)return e.usageLabel??e.names[0]}function _(e){return(e??[]).flatMap(e=>h(e).map(g).filter(e=>e!==void 0).map(e=>`[${e}]`))}function v(e,t){return[t.usageOverride??[e,...(t.positionalArgs??[]).map(m)].join(` `),..._(t.usageFlags??t.allowedFlags)].join(` `)}function y(){return`agent-device <command> [args] [--json]
|
|
3
3
|
|
|
4
4
|
Automates iOS, Android, macOS, TV, and web apps for AI agents.
|
|
@@ -49,7 +49,7 @@ Guides (agent-device help <topic>):
|
|
|
49
49
|
manual-qa / dogfood / validate / debugging / scripting / gestures
|
|
50
50
|
react-native / react-devtools / cdp / tv / web / macos / remote
|
|
51
51
|
physical-device / ios-system-ui / maestro
|
|
52
|
-
foldable iPhone Duo panels,
|
|
52
|
+
foldable iPhone Duo panels, the fold command, and why refs die on a pose change
|
|
53
53
|
`}var b=e({buildCommandUsageText:()=>L,buildUsageText:()=>A,helpTopicIds:()=>z,resolveHelpTargetUsageText:()=>R});const x=[`Default config files: ~/.agent-device/config.json, ./agent-device.json (project-safe defaults only).`,`Use --config <path> or AGENT_DEVICE_CONFIG for explicit connection/provider defaults; project config cannot select endpoints or credentials.`],S=[{label:`AGENT_DEVICE_SESSION`,description:`Explicit session name`},{label:`AGENT_DEVICE_PLATFORM`,description:`Default platform binding`},{label:`AGENT_DEVICE_SCREENSHOT_SCALE`,description:`Default screenshot scale factor`},{label:`AGENT_DEVICE_SESSION_LOCK`,description:`Bound-session conflict mode`},{label:`AGENT_DEVICE_DAEMON_BASE_URL`,description:`Connect to remote daemon`},{label:`AGENT_DEVICE_DAEMON_AUTH_TOKEN`,description:`Remote daemon service/API token`},{label:`AGENT_DEVICE_CLOUD_BASE_URL`,description:`Bridge/control-plane API origin for cloud auth and /api-keys`}],C=[`agent-device open Settings --platform ios`,`agent-device open https://example.com --platform web`,`agent-device snapshot -i`,`agent-device fill @e3 "test@example.com"`,`agent-device replay ./session.ad`,`agent-device wait absent 'label="Loading..."' 3000`,`agent-device test ./suite --platform android`],w=`Wait failure contract:
|
|
54
54
|
Read error.details.reason in --json, not the message text.
|
|
55
55
|
wait_target_absent: a readable capture ran and found no match.
|
|
@@ -636,6 +636,7 @@ iOS physical-device prerequisites:
|
|
|
636
636
|
If Xcode cannot choose a profile, set AGENT_DEVICE_IOS_PROVISIONING_PROFILE to the profile name/specifier, not a file path.
|
|
637
637
|
AGENT_DEVICE_IOS_SIGNING_IDENTITY is optional; omit it unless xcodebuild asks for a specific identity.
|
|
638
638
|
The profile/team must allow AGENT_DEVICE_IOS_BUNDLE_ID and <id>.uitests.
|
|
639
|
+
A runner startup failure names its class in error details.reason rather than only in prose: signing_no_development_team, signing_provisioning_profile_missing, bundle_identifier_already_registered, signing_unspecified, devtools_security_developer_mode_disabled (the Mac's DevToolsSecurity setting, which says nothing about the device's Developer Mode toggle), device_developer_mode_disabled (read from an iPhone's own report before the runner builds, and the only device state that stops a run up front), device_developer_disk_image_unavailable (also read from the device, and published on a startup failure that named no cause of its own, since iOS 17+ mounts the developer disk image on demand during build and launch rather than gating the build), or build_failed_unclassified when nothing proved a cause. The two device reasons are never inferred from tool output or from each other. Branch on details.reason and follow hint; the message is for humans.
|
|
639
640
|
First-run XCTest setup/build can take longer than normal commands; keep the device connected and use --debug to inspect signing/build diagnostics if setup times out.
|
|
640
641
|
|
|
641
642
|
Android physical-device prerequisites:
|
|
@@ -683,10 +684,12 @@ Screens are handled for you:
|
|
|
683
684
|
The two panels are different sizes and different coordinate spaces (iPhone Duo: 466x678 points closed on the outer panel, 669x951 open on the inner). A pose change therefore invalidates every ref and coordinate. Re-snapshot after any pose change and never carry coordinates or refs across one.
|
|
684
685
|
Check which panel is lit before trusting a geometry claim: agent-device screenshot reports its point size, and 466x678 versus 669x951 says which panel you captured.
|
|
685
686
|
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
687
|
+
Changing the pose:
|
|
688
|
+
agent-device fold closed | half-open | open
|
|
689
|
+
fold presses the pose control in the Xcode Device Hub window for this simulator (Closed, Book, Open) and then reads the hinge angle back from CoreDevice until it agrees: closed is 0 degrees, open is 180, and half-open is any angle between them (Device Hub's Book preset, 130 degrees on iOS 27.1), reported once the hinge stops moving or when the read budget ends while it still reads half-open. The response reports the verified pose, the hinge angle, and the panel the device now lights with its point size. A refusal never names the pose that was asked for: only a hinge whose last reading is some other pose fails, with COMMAND_FAILED and reason fold-pose-unverified. A single-panel simulator fails with UNSUPPORTED_OPERATION.
|
|
690
|
+
Expect a fold to take 10-16 seconds: each hinge read is a five-second devicectl stream, and half-open waits for the hinge to stop moving. Re-snapshot after every fold; refs and coordinates from before it are stale, and the command's message says so.
|
|
691
|
+
Requirements: an iOS simulator session on a foldable device, Xcode 27.1 or newer with Device Hub, and Accessibility permission for the host (agent-device settings permission grant accessibility --platform macos). The command launches Device Hub if needed, reopens its window when it shows none, and selects the simulator through its sidebar by UDID, so no operator step is needed. No official host API sets the pose; the app under test still reads it as UIHinge.status.
|
|
692
|
+
If a task asserts behavior for more than one pose, fold to each pose and re-snapshot, and report which poses the run covered.`},remote:{summary:`Direct proxy, cloud profiles, and remote config`,body:`agent-device help remote
|
|
690
693
|
|
|
691
694
|
Remote connection providers use the same lifecycle:
|
|
692
695
|
connect -> install/open -> commands -> close -> disconnect
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { E as IosTargetActivation, H as DaemonError, I as SnapshotQualityVerdict, M as SnapshotKeyboardBandFact, N as SnapshotNode, R as SnapshotUnchanged, S as DeviceTarget, T as PublicPlatform, U as NormalizedError, _ as SessionIsolationMode, a as DaemonRequest, f as LeaseBackend, g as ResponseLevel, i as DaemonLockPolicy, j as SnapshotCommandOptionFields, m as NetworkIncludeMode, o as DaemonResponse, r as DaemonInstallSource, s as DaemonResponseData, t as DaemonArtifact, v as SessionRuntimeHints, w as PlatformSelector, x as DeviceKind, y as AppleOS, z as SnapshotVisibility } from "./sdk-contracts.js";
|
|
2
2
|
import { t as AppsFilter } from "./app-inventory.js";
|
|
3
|
-
import { B as
|
|
3
|
+
import { B as AndroidSnapshotBackendMetadata, C as FoldPose, D as PermissionMode, E as PermissionAction, F as ScrollInputDirection, H as ScreenshotResultData, I as SwipePattern, L as SwipePreset, O as BackMode, P as ScrollDirection, R as TransformGestureParams, S as DeviceRotation, T as MOBILE_PERMISSION_TARGETS, U as SnapshotDiagnosticsSummary, V as FindLocator, W as SessionSurface, _ as HoverCommandResponseData, b as SettleObservation, g as FindCommandResponseData, h as FillCommandResponseData, k as GesturePointerCount, m as ClickCommandResponseData, p as ScrollCommandResult, v as LongPressCommandResponseData, w as MACOS_PERMISSION_TARGETS, x as TvRemoteButton, y as PressCommandResponseData, z as ClickButton } from "./sdk-selectors.js";
|
|
4
4
|
import { a as RemoteConnectionProfileFields, c as MetroPrepareResult, i as CloudProviderProfileFields, l as MetroReloadOptions, s as MetroPrepareOptions, u as MetroReloadResult } from "./sdk-remote-config.js";
|
|
5
5
|
import { t as BatchRunResult } from "./sdk-batch-runner.js";
|
|
6
6
|
import { r as CloudProviderSessionResult, t as AgentArtifactsResult } from "./cloud-artifacts.js";
|
|
@@ -1014,6 +1014,9 @@ type HomeCommandOptions = DeviceCommandBaseOptions;
|
|
|
1014
1014
|
type OrientationCommandOptions = DeviceCommandBaseOptions & {
|
|
1015
1015
|
orientation: DeviceRotation;
|
|
1016
1016
|
};
|
|
1017
|
+
type FoldCommandOptions = DeviceCommandBaseOptions & {
|
|
1018
|
+
pose: FoldPose;
|
|
1019
|
+
};
|
|
1017
1020
|
type AppSwitcherCommandOptions = DeviceCommandBaseOptions;
|
|
1018
1021
|
type ActionButtonCommandOptions = DeviceCommandBaseOptions;
|
|
1019
1022
|
type TvRemoteCommandOptions = DeviceCommandBaseOptions & {
|
|
@@ -1287,6 +1290,18 @@ type ViewportCommandResult = {
|
|
|
1287
1290
|
message: string;
|
|
1288
1291
|
};
|
|
1289
1292
|
//#endregion
|
|
1293
|
+
//#region packages/contracts/src/fold-runtime.d.ts
|
|
1294
|
+
/**
|
|
1295
|
+
* The lit panel after the pose settled, in the points the next snapshot will use. Reported so an
|
|
1296
|
+
* agent can see that the coordinate space changed without a second capture.
|
|
1297
|
+
*/
|
|
1298
|
+
type FoldScreenReport = Readonly<{
|
|
1299
|
+
/** The CoreDevice display name of the panel the device now lights. */
|
|
1300
|
+
display: string;
|
|
1301
|
+
widthPt: number;
|
|
1302
|
+
heightPt: number;
|
|
1303
|
+
}>;
|
|
1304
|
+
//#endregion
|
|
1290
1305
|
//#region packages/contracts/src/navigation.d.ts
|
|
1291
1306
|
/**
|
|
1292
1307
|
* Closed results of the navigation/global action commands. Each mirrors its
|
|
@@ -1328,6 +1343,21 @@ type OrientationCommandResult = {
|
|
|
1328
1343
|
confirmed?: boolean;
|
|
1329
1344
|
warning?: string;
|
|
1330
1345
|
};
|
|
1346
|
+
/**
|
|
1347
|
+
* `fold` — `{ action: 'fold', pose, hingeAngleDegrees, screen?, message }`.
|
|
1348
|
+
*
|
|
1349
|
+
* Unlike `orientation`, there is no unconfirmed variant: the Apple owner reads the hinge angle
|
|
1350
|
+
* back from CoreDevice after pressing the Device Hub pose control, and reports a pose only when
|
|
1351
|
+
* that reading agrees with the request. `screen` names the panel the device lights afterwards, in
|
|
1352
|
+
* points, because a pose change moves the app to a different coordinate space (ADR 0025).
|
|
1353
|
+
*/
|
|
1354
|
+
type FoldCommandResult = {
|
|
1355
|
+
action: 'fold';
|
|
1356
|
+
pose: FoldPose;
|
|
1357
|
+
hingeAngleDegrees: number;
|
|
1358
|
+
screen?: FoldScreenReport;
|
|
1359
|
+
message: string;
|
|
1360
|
+
};
|
|
1331
1361
|
/** `app-switcher` — `{ action: 'app-switcher', message: 'Opened app switcher' }`. */
|
|
1332
1362
|
type AppSwitcherCommandResult = {
|
|
1333
1363
|
action: 'app-switcher';
|
|
@@ -1561,6 +1591,7 @@ interface CommandResultMap {
|
|
|
1561
1591
|
doctor: DoctorCommandResult;
|
|
1562
1592
|
fill: FillCommandResponseData;
|
|
1563
1593
|
find: FindCommandResponseData;
|
|
1594
|
+
fold: FoldCommandResult;
|
|
1564
1595
|
home: HomeCommandResult;
|
|
1565
1596
|
hover: HoverCommandResponseData;
|
|
1566
1597
|
keyboard: KeyboardCommandResult;
|
|
@@ -1594,6 +1625,7 @@ type AgentDeviceCommandClient = {
|
|
|
1594
1625
|
back: (options?: BackCommandOptions) => Promise<CommandResult<'back'>>;
|
|
1595
1626
|
home: (options?: HomeCommandOptions) => Promise<CommandResult<'home'>>;
|
|
1596
1627
|
orientation: (options: OrientationCommandOptions) => Promise<CommandResult<'orientation'>>;
|
|
1628
|
+
fold: (options: FoldCommandOptions) => Promise<CommandResult<'fold'>>;
|
|
1597
1629
|
appSwitcher: (options?: AppSwitcherCommandOptions) => Promise<CommandResult<'app-switcher'>>;
|
|
1598
1630
|
actionButton: (options?: ActionButtonCommandOptions) => Promise<CommandResult<'action-button'>>;
|
|
1599
1631
|
tvRemote: (options: TvRemoteCommandOptions) => Promise<CommandResult<'tv-remote'>>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{B as e,D as t,L as n,r,z as i}from"./sdk-contracts.js";import{g as a,m as o}from"./sdk-batch-runner.js";import{i as s,t as c}from"./sdk-device.js";import{S as l,c as u,d,p as f,w as ee}from"./sdk-batch.js";import{t as te}from"./back-mode.js";import{t as ne}from"./session.js";import{C as re,S as p,_ as m,b as ie,g as h,h as g,y as ae}from"./registry.js";import{n as oe}from"./success-text.js";import{t as se}from"./output-common.js";import"./device.js";import{t as ce}from"./device-rotation.js";import{t as le}from"./tv-remote.js";import{i as ue,n as _,r as de,t as v}from"./command-metadata.js";import{r as fe}from"./replay-divergence.js";import{n as pe,t as me}from"./cli-output.js";import{r as he,t as ge}from"./recording-stop-observation.js";import{n as _e}from"./error.js";import{n as ve,r as ye,t as be}from"./cli-config.js";import{n as xe}from"./result-serialization.js";const y=[`simulator`,`emulator`,`device`];function b(e){return{type:`number`,...e?{description:e}:{}}}function x(e,t){return{type:`string`,enum:e,...t?{description:t}:{}}}function S(e){return{type:`string`,const:e}}function C(e){return{type:[`string`,`null`],...e?{description:e}:{}}}function w(e,t=[],n){return{type:`object`,...n?{description:n}:{},properties:e,...t.length>0?{required:t}:{}}}const T={type:`array`,items:{type:`string`}},E=w({wallClockMs:b(`Total wall-clock time for the request in milliseconds.`),runnerRoundTrips:b(`Number of real runner round-trips made while serving the request.`),nodeCount:b(`Number of nodes in the original node tree when the response carries one.`)},[`wallClockMs`,`runnerRoundTrips`]),D=w({field:m(),artifactType:m(),path:m(),localPath:m(),fileName:m()},[`field`]);function O(e={}){let t=e.properties??{},n=e.required??[];return w({targetKind:x([`point`,`ref`,`selector`],`Resolved interaction target kind.`),x:b(`Resolved interaction x coordinate when available.`),y:b(`Resolved interaction y coordinate when available.`),referenceWidth:b(`Reference frame width for visualizing the interaction point.`),referenceHeight:b(`Reference frame height for visualizing the interaction point.`),ref:m(`Snapshot ref without the @ prefix when the target was an @ref.`),selector:m(`Selector expression when the target was a selector.`),selectorChain:T,refLabel:m(),targetHittable:g(),hint:m(),warning:m(),message:m(),evidence:j,resolution:Se,cost:E,maestroNonHittableCoordinateFallbackAllowed:g(`Whether the direct iOS Maestro coordinate fallback was allowed for this selector.`),maestroNonHittableCoordinateFallbackUsed:g(`Whether the direct iOS Maestro coordinate fallback was actually used.`),maestroFallbackReason:S(`non-hittable-coordinate`),...t},[`targetKind`,...n])}const k=w({diagnosticRef:m(`Opaque non-@ diagnostic token. Never a snapshot ref: not issued via refsGeneration and cannot be pinned or reused as an @ref target. UTF-8 truncated to 256 bytes.`),role:m(`UTF-8 truncated to 256 bytes.`),label:m(`UTF-8 truncated to 256 bytes.`)},[`diagnosticRef`]),Se={type:`object`,description:`Pre-action disclosure of how the acting path resolved its target. Absent when resolutionDisclosure is inapplicable for the path.`,oneOf:[w({source:S(`runtime`),phase:S(`pre-action`),kind:S(`unique`)},[`source`,`phase`,`kind`]),w({source:S(`runtime`),phase:S(`pre-action`),kind:S(`disambiguated`),matchCount:b(`Total matches resolveSelectorChain found before disambiguation.`),winnerDiagnostic:k,tiebreak:x([`visible`,`deepest`,`smallest-area`,`structural-equivalence`],`The comparison that decided the winner.`),alternatives:{type:`array`,description:`At most 5 losing candidates, document order. Present at default/full response levels and omitted in digest. The winner is never included.`,items:k}},[`source`,`phase`,`kind`,`matchCount`,`winnerDiagnostic`,`tiebreak`]),w({source:S(`ref`),phase:S(`pre-action`),kind:S(`exact`)},[`source`,`phase`,`kind`]),w({source:S(`ref`),phase:S(`pre-action`),kind:S(`label-fallback`)},[`source`,`phase`,`kind`]),w({source:S(`direct-ios`),kind:S(`not-observed`)},[`source`,`kind`])]},A=w({from:m(`Surface the pre-action baseline described: a host bundle id, or app.`),to:m(`Surface the post-action capture describes: a host bundle id, or app.`),disclosure:m(`Agent-facing sentence explaining the surface transition.`)},[`from`,`to`,`disclosure`],`Present when an in-place system surface (web sign-in or Apple Pay sheet) was presented over the app, or left it.`),j=w({foregroundApp:m(`Foreground app bundle id or name, when the capture carries it.`),nodeCount:b(`Node count in the post-action interactive-only capture.`),interactiveNodeCount:b(`Subset of nodeCount the platform reports as hittable.`),digest:m(`Order-independent digest of the post-action node multiset.`),changedFromBefore:g(`Whether the post-action digest differs from the pre-action capture digest. false is evidence, not failure. With surfaceChange present, no digest comparison is made: it reports that surface transition.`),surfaceChange:A},[`nodeCount`,`interactiveNodeCount`,`digest`,`changedFromBefore`]),Ce=w({settled:g(`Whether the UI held the quiet window before the deadline. false is advisory, not failure.`),waitedMs:b(),captures:b(),quietMs:b(),timeoutMs:b(),refsGeneration:b(`Snapshot generation of the stored settled tree; refs on added diff lines were minted from it.`),refs:{type:`array`,items:w({ref:m(`Plain ref body (e12) minted from the stored settled tree.`)},[`ref`])},surfaceChange:A,diff:w({summary:w({additions:b(),removals:b(),unchanged:b()},[`additions`,`removals`,`unchanged`]),lines:{type:`array`,items:w({kind:x([`added`,`removed`]),text:m(),ref:m(`Plain ref body (e12) for added lines.`)},[`kind`,`text`])},truncated:g(`Lines were capped to the response bound.`)},[`summary`,`lines`],`Settled diff vs the pre-action tree (changed lines only).`),tail:{type:`array`,description:`Unchanged interactive refs tail: still-present, actionable elements from the settled tree, attached only when diff carries zero added-line refs (a modal-dismiss/toast-only diff).`,items:w({ref:m(`Plain ref body (e12) minted from the stored settled tree.`),role:m(),label:m()},[`ref`,`role`])},tailTruncated:g(`Present (true) when tail candidates exceeded the response cap.`),hint:m()},[`settled`,`waitedMs`,`captures`,`quietMs`,`timeoutMs`]),M={platform:x(s),target:x(c),device:m(`Human-readable device name.`),id:m(`Stable device id.`),kind:x(y)},N=[`platform`,`target`,`device`,`id`,`kind`],we=w({success:g(),exitCode:b(),stdout:m(),stderr:m(),error:h(`Normalized error detail when shutdown failed.`)},[`success`,`exitCode`,`stdout`,`stderr`]);function P(e){return e.oneOf?{...e,oneOf:e.oneOf.map(P)}:{...e,properties:{...e.properties??{},settle:Ce}}}function Te(e){let t={...e};for(let e of Object.keys(t))f(e)&&(t[e]=P(t[e]));return t}const F=O({properties:{evidence:j,button:x([`secondary`,`middle`]),count:b(`Number of press/click repetitions.`),intervalMs:b(`Delay between repeated press/click actions.`),holdMs:b(`Hold duration for each action.`),jitterPx:b(`Randomization radius in pixels.`),doubleTap:g(`Whether the command requested a double-tap action.`)}}),I={text:m(`Text submitted to the field.`),delayMs:b(`Delay between typed characters in milliseconds.`),evidence:j},Ee=w({resourceId:C(`Android resource id of the exact field that changed.`),className:C(`Android class name of the exact field that changed.`),packageName:C(`Android package name that owns the exact field.`),rect:w({x:b(),y:b(),width:b(),height:b()},[`x`,`y`,`width`,`height`],`Screen-space rectangle of the exact field that changed.`)},[`resourceId`,`className`,`packageName`,`rect`],`Target identity captured before fill and matched after fill.`),De=Te({press:F,click:F,fill:{type:`object`,description:`Fill response. Android may return target-bound unconfirmed evidence when the exact app-owned field changed but formatting prevented raw equality.`,oneOf:[{...O({properties:I,required:[`text`]}),not:w({},[`verification`])},O({properties:{...I,verification:S(`unconfirmed`),requested:m(`Literal text requested by the fill command.`),before:C(`Raw target text captured before the fill.`),after:C(`Raw target text captured after the fill.`),target:Ee},required:[`text`,`verification`,`requested`,`before`,`after`,`target`]})]},longpress:O({properties:{durationMs:b(),gesture:S(`longpress`)}}),hover:O({properties:{gesture:S(`hover`)}}),find:w({ref:m(`Snapshot ref without the @ prefix when the find action returns one.`),refsGeneration:b(`ADR 0014 ref frame epoch for read-only find actions.`),found:g(`Whether a wait/exists/read-only find satisfied its condition.`),waitedMs:b(`Milliseconds waited for a read-only find condition.`),text:m(`Text value returned by find get_text.`),node:h(`Snapshot node for find get_attrs/get_text.`),matches:{type:`array`,description:`Every match for the read-only find list action (#1625): { ref, node } each.`,items:h(`One listed match with its snapshot ref and node.`)},locator:m(`Locator kind used for the find action.`),query:m(`Query argument used for the find action.`),x:b(`Resolved x coordinate for mutating find actions.`),y:b(`Resolved y coordinate for mutating find actions.`),message:m(`Diagnostic message for mutating find actions.`),cost:E},[],`Daemon response data for the find command.`),boot:w({...M,booted:{type:`boolean`,const:!0}},[...N,`booted`]),shutdown:w({...M,shutdown:we},[...N,`shutdown`]),viewport:w({width:b(),height:b(),message:m()},[`width`,`height`,`message`]),back:w({action:S(`back`),mode:x(te),message:m()},[`action`,`mode`,`message`]),home:w({action:S(`home`),message:m()},[`action`,`message`]),orientation:w({action:S(`orientation`),orientation:x(ce),message:m(),confirmed:g(),warning:m()},[`action`,`orientation`,`message`]),"app-switcher":w({action:S(`app-switcher`),message:m()},[`action`,`message`]),"action-button":w({action:S(`action-button`),message:m()},[`action`,`message`]),"tv-remote":w({action:S(`tv-remote`),button:x(le),durationMs:b(),message:m()},[`action`,`button`,`message`]),wait:w({waitedMs:b(),kind:S(`selector`),text:m(),selector:m(),captures:b(),nodeCount:b(),hint:m(),warning:m()},[`waitedMs`]),scroll:w({direction:x([`up`,`down`,`left`,`right`]),edge:x([`top`,`bottom`]),until:m(`Until scrolls only: the selector the passes stopped on.`),passes:b(`Edge and until scrolls only: how many scroll-and-check passes ran.`),amount:b(),pixels:b(),durationMs:b(),message:m(),keyboardAvoided:g(`Present only when an on-screen keyboard forced the swipe into the band above it; the reported pixels were planned against the shorter referenceHeight.`),keyboardMinY:b(`Where the keyboard began, in the same unit as the gesture coordinates. Clipped scrolls only.`)},[`direction`]),prepare:w({action:S(`ios-runner`),platform:x(s),deviceId:m(),deviceName:m(),kind:x(y),durationMs:b(),runner:w({},[]),cache:x([`exact`,`restore-key`,`miss`,`external`]),artifact:x([`valid`,`rebuilt`]),buildMs:b(),connectMs:b(),healthCheckMs:b(),xctestrunPath:m(),recoveryReason:m(),failureReason:m(),timing:w({totalMs:b(),additiveParts:w({buildMs:b(),connectAfterBuildMs:b(),healthCheckMs:b()},[`connectAfterBuildMs`,`healthCheckMs`]),containment:w({connectMs:{type:`array`,items:S(`buildMs`)},healthCheckMs:{type:`array`,items:m()}},[`healthCheckMs`]),note:m()},[`totalMs`,`additiveParts`,`containment`,`note`]),message:m()},[`action`,`platform`,`deviceId`,`deviceName`,`kind`,`durationMs`,`runner`,`connectMs`,`healthCheckMs`,`timing`,`message`]),push:{type:`object`,oneOf:[w({platform:S(`ios`),bundleId:m(),message:m()},[`platform`,`bundleId`,`message`]),w({platform:S(`android`),package:m(),action:m(),extrasCount:b(),message:m()},[`platform`,`package`,`action`,`extrasCount`,`message`])]},"trigger-app-event":w({event:m(),eventUrl:m(),transport:S(`deep-link`),message:m()},[`event`,`eventUrl`,`transport`,`message`]),clipboard:{type:`object`,oneOf:[w({action:S(`read`),text:m()},[`action`,`text`]),w({action:S(`write`),textLength:b(),message:m()},[`action`,`textLength`,`message`])]},appstate:{type:`object`,oneOf:[w({platform:x([`ios`,`macos`]),appName:m(),appBundleId:m(),source:S(`session`),surface:x(ne),device_udid:m(`iOS only — the session device UDID.`),ios_simulator_device_set:{type:[`string`,`null`],description:`iOS only — the simulator set path, or null when unknown.`}},[`platform`,`appName`,`source`,`surface`]),w({platform:S(`android`),package:m(),activity:m()},[`platform`,`package`,`activity`])]},keyboard:w({platform:x([`android`,`ios`]),action:x([`status`,`dismiss`,`enter`]),visible:g(),wasVisible:g(),dismissed:g(),attempts:b(),inputType:m(),type:x([`text`,`number`,`email`,`phone`,`password`,`datetime`,`unknown`]),inputMethodPackage:m(),focusedPackage:m(),focusedResourceId:m(),inputOwner:x([`app`,`ime`,`unknown`]),message:m()},[`platform`,`action`]),doctor:w({status:x([`pass`,`warn`,`fail`,`info`]),summary:m(),kind:x([`auto`,`react-native`,`expo`,`repack`]),platform:m(),target:x(c),targetApp:m(),metro:w({host:m(),port:b()},[`host`,`port`]),checks:{type:`array`,items:w({id:m(),status:x([`pass`,`warn`,`fail`,`info`]),summary:m(),hint:m(),command:m(),evidence:h()},[`id`,`status`,`summary`])}},[`status`,`summary`,`kind`,`checks`]),diff:w({mode:S(`snapshot`),baselineInitialized:g(),summary:w({additions:b(),removals:b(),unchanged:b()},[`additions`,`removals`,`unchanged`]),lines:{type:`array`,items:w({kind:x([`added`,`removed`]),text:m(),ref:m()},[`kind`,`text`])},warnings:T},[`mode`,`baselineInitialized`,`summary`,`lines`]),replay:w({replayed:b(),healed:b(),session:m(),sessionActive:g(`True iff the session is still active — the script had no terminal close.`),artifactPaths:T,snapshotDiagnostics:h(),message:m()},[`replayed`,`healed`,`session`,`sessionActive`,`artifactPaths`,`message`]),test:w({total:b(),executed:b(),passed:b(),failed:b(),skipped:b(),notRun:b(),durationMs:b(),failures:{type:`array`,items:h()},tests:{type:`array`,items:h()},snapshotDiagnostics:h()},[`total`,`executed`,`passed`,`failed`,`skipped`,`notRun`,`durationMs`,`failures`,`tests`]),record:{type:`object`,oneOf:[w({recording:S(`started`),outPath:m(),sessionStateDir:m(),recordingBackend:m(),recordingScope:m(),recordOnlySession:g(),activeSessionApp:h(),showTouches:g()},[`recording`,`outPath`,`sessionStateDir`,`showTouches`]),w({recording:S(`stopped`),outPath:m(),telemetryPath:m(),artifacts:{type:`array`,items:D},recordingBackend:m(),recordingScope:m(),recordOnlySession:g(),activeSessionApp:h(),durationMs:b(),capturedDurationMs:b(),recorder:x(ge,`What the recorder was observed doing when the recording was stopped: confirmed, or lost when the session holding it died. ADR 0024 reserves unconfirmed for the step that gains the probe.`),nativePathDisposition:x(he,`What became of the artifact path the recorder writes to: retirable while it still owes a removal, retired once that removal was verified. ADR 0024 reserves pending.`),showTouches:g(),warning:m(),overlayWarning:m(),chunks:{type:`array`,items:h()}},[`recording`,`outPath`,`artifacts`,`durationMs`,`showTouches`])]},trace:{type:`object`,oneOf:[w({trace:S(`started`),outPath:m()},[`trace`,`outPath`]),w({trace:S(`stopped`),outPath:m(),artifacts:{type:`array`,items:D}},[`trace`,`outPath`,`artifacts`])]}}),Oe={devices:{type:`object`,properties:{devices:{type:`array`,items:{type:`object`,properties:{platform:{type:`string`,enum:s},target:{type:`string`,enum:c},kind:{type:`string`,enum:y},id:{type:`string`},name:{type:`string`}},required:[`platform`,`target`,`kind`,`id`,`name`]}}},required:[`devices`]},apps:{type:`object`,properties:{apps:{type:`array`,items:{type:`string`}}},required:[`apps`]}},L={...De,...Oe},ke={stateDir:{schema:{type:`string`,description:`Agent-device state directory.`},audience:p({operatorConfig:!0})},mcpOutputFormat:{schema:{type:`string`,enum:[`optimized`,`json`],description:`MCP text content format. Defaults to optimized agent-friendly text; use json for JSON text. Structured content is always returned separately.`}},includeCost:{schema:{type:`boolean`,description:`Include per-command agent-cost (cost.wallClockMs, …) in structuredContent. Defaults to off; the default response shape is unchanged.`}},responseLevel:{schema:{type:`string`,enum:[`digest`,`default`,`full`],description:`Response verbosity: token-cheap digest / default (today) / full. Defaults to default; the default response shape is unchanged.`}}},R=Object.entries(ke),z=new Set(R.map(([e])=>e)),Ae=Object.fromEntries(R.flatMap(([e,t])=>t.audience?[[e,t.audience]]:[]));function je(){return Object.fromEntries(R.map(([e,t])=>[e,t.schema]))}function B(e){return n(e)}function V(t){let n=[`Error (${t.code}): ${t.message}`];if(t.cause){let e=t.cause.code?`${t.cause.code} `:``;n.push(`Cause: ${e}${t.cause.message}`)}t.hint&&n.push(`Hint: ${t.hint}`);for(let e of oe(t.details))n.push(`Warning: ${se(e)}`);n.push(..._e(e(t.details))),t.supportedOn&&n.push(`Supported on: ${t.supportedOn}`);let r=fe(t.details);return r&&n.push(r),n.join(`
|
|
2
|
-
`)}function
|
|
1
|
+
import{B as e,D as t,L as n,r,z as i}from"./sdk-contracts.js";import{g as a,m as o}from"./sdk-batch-runner.js";import{i as s,t as c}from"./sdk-device.js";import{S as l,c as u,d,p as f,w as ee}from"./sdk-batch.js";import{t as te}from"./back-mode.js";import{t as ne}from"./session.js";import{C as re,S as p,_ as m,b as ie,g as h,h as g,y as ae}from"./registry.js";import{n as oe}from"./success-text.js";import{t as se}from"./output-common.js";import"./device.js";import{r as ce,t as le}from"./device-rotation.js";import{t as ue}from"./tv-remote.js";import{i as de,n as _,r as fe,t as v}from"./command-metadata.js";import{r as pe}from"./replay-divergence.js";import{n as me,t as he}from"./cli-output.js";import{r as ge,t as _e}from"./recording-stop-observation.js";import{n as ve}from"./error.js";import{n as ye,r as be,t as xe}from"./cli-config.js";import{n as Se}from"./result-serialization.js";const y=[`simulator`,`emulator`,`device`];function b(e){return{type:`number`,...e?{description:e}:{}}}function x(e,t){return{type:`string`,enum:e,...t?{description:t}:{}}}function S(e){return{type:`string`,const:e}}function C(e){return{type:[`string`,`null`],...e?{description:e}:{}}}function w(e,t=[],n){return{type:`object`,...n?{description:n}:{},properties:e,...t.length>0?{required:t}:{}}}const T={type:`array`,items:{type:`string`}},E=w({wallClockMs:b(`Total wall-clock time for the request in milliseconds.`),runnerRoundTrips:b(`Number of real runner round-trips made while serving the request.`),nodeCount:b(`Number of nodes in the original node tree when the response carries one.`)},[`wallClockMs`,`runnerRoundTrips`]),D=w({field:m(),artifactType:m(),path:m(),localPath:m(),fileName:m()},[`field`]);function O(e={}){let t=e.properties??{},n=e.required??[];return w({targetKind:x([`point`,`ref`,`selector`],`Resolved interaction target kind.`),x:b(`Resolved interaction x coordinate when available.`),y:b(`Resolved interaction y coordinate when available.`),referenceWidth:b(`Reference frame width for visualizing the interaction point.`),referenceHeight:b(`Reference frame height for visualizing the interaction point.`),ref:m(`Snapshot ref without the @ prefix when the target was an @ref.`),selector:m(`Selector expression when the target was a selector.`),selectorChain:T,refLabel:m(),targetHittable:g(),hint:m(),warning:m(),message:m(),evidence:j,resolution:Ce,cost:E,maestroNonHittableCoordinateFallbackAllowed:g(`Whether the direct iOS Maestro coordinate fallback was allowed for this selector.`),maestroNonHittableCoordinateFallbackUsed:g(`Whether the direct iOS Maestro coordinate fallback was actually used.`),maestroFallbackReason:S(`non-hittable-coordinate`),...t},[`targetKind`,...n])}const k=w({diagnosticRef:m(`Opaque non-@ diagnostic token. Never a snapshot ref: not issued via refsGeneration and cannot be pinned or reused as an @ref target. UTF-8 truncated to 256 bytes.`),role:m(`UTF-8 truncated to 256 bytes.`),label:m(`UTF-8 truncated to 256 bytes.`)},[`diagnosticRef`]),Ce={type:`object`,description:`Pre-action disclosure of how the acting path resolved its target. Absent when resolutionDisclosure is inapplicable for the path.`,oneOf:[w({source:S(`runtime`),phase:S(`pre-action`),kind:S(`unique`)},[`source`,`phase`,`kind`]),w({source:S(`runtime`),phase:S(`pre-action`),kind:S(`disambiguated`),matchCount:b(`Total matches resolveSelectorChain found before disambiguation.`),winnerDiagnostic:k,tiebreak:x([`visible`,`deepest`,`smallest-area`,`structural-equivalence`],`The comparison that decided the winner.`),alternatives:{type:`array`,description:`At most 5 losing candidates, document order. Present at default/full response levels and omitted in digest. The winner is never included.`,items:k}},[`source`,`phase`,`kind`,`matchCount`,`winnerDiagnostic`,`tiebreak`]),w({source:S(`ref`),phase:S(`pre-action`),kind:S(`exact`)},[`source`,`phase`,`kind`]),w({source:S(`ref`),phase:S(`pre-action`),kind:S(`label-fallback`)},[`source`,`phase`,`kind`]),w({source:S(`direct-ios`),kind:S(`not-observed`)},[`source`,`kind`])]},A=w({from:m(`Surface the pre-action baseline described: a host bundle id, or app.`),to:m(`Surface the post-action capture describes: a host bundle id, or app.`),disclosure:m(`Agent-facing sentence explaining the surface transition.`)},[`from`,`to`,`disclosure`],`Present when an in-place system surface (web sign-in or Apple Pay sheet) was presented over the app, or left it.`),j=w({foregroundApp:m(`Foreground app bundle id or name, when the capture carries it.`),nodeCount:b(`Node count in the post-action interactive-only capture.`),interactiveNodeCount:b(`Subset of nodeCount the platform reports as hittable.`),digest:m(`Order-independent digest of the post-action node multiset.`),changedFromBefore:g(`Whether the post-action digest differs from the pre-action capture digest. false is evidence, not failure. With surfaceChange present, no digest comparison is made: it reports that surface transition.`),surfaceChange:A},[`nodeCount`,`interactiveNodeCount`,`digest`,`changedFromBefore`]),we=w({settled:g(`Whether the UI held the quiet window before the deadline. false is advisory, not failure.`),waitedMs:b(),captures:b(),quietMs:b(),timeoutMs:b(),refsGeneration:b(`Snapshot generation of the stored settled tree; refs on added diff lines were minted from it.`),refs:{type:`array`,items:w({ref:m(`Plain ref body (e12) minted from the stored settled tree.`)},[`ref`])},surfaceChange:A,diff:w({summary:w({additions:b(),removals:b(),unchanged:b()},[`additions`,`removals`,`unchanged`]),lines:{type:`array`,items:w({kind:x([`added`,`removed`]),text:m(),ref:m(`Plain ref body (e12) for added lines.`)},[`kind`,`text`])},truncated:g(`Lines were capped to the response bound.`)},[`summary`,`lines`],`Settled diff vs the pre-action tree (changed lines only).`),tail:{type:`array`,description:`Unchanged interactive refs tail: still-present, actionable elements from the settled tree, attached only when diff carries zero added-line refs (a modal-dismiss/toast-only diff).`,items:w({ref:m(`Plain ref body (e12) minted from the stored settled tree.`),role:m(),label:m()},[`ref`,`role`])},tailTruncated:g(`Present (true) when tail candidates exceeded the response cap.`),hint:m()},[`settled`,`waitedMs`,`captures`,`quietMs`,`timeoutMs`]),M={platform:x(s),target:x(c),device:m(`Human-readable device name.`),id:m(`Stable device id.`),kind:x(y)},N=[`platform`,`target`,`device`,`id`,`kind`],Te=w({success:g(),exitCode:b(),stdout:m(),stderr:m(),error:h(`Normalized error detail when shutdown failed.`)},[`success`,`exitCode`,`stdout`,`stderr`]);function P(e){return e.oneOf?{...e,oneOf:e.oneOf.map(P)}:{...e,properties:{...e.properties??{},settle:we}}}function Ee(e){let t={...e};for(let e of Object.keys(t))f(e)&&(t[e]=P(t[e]));return t}const F=O({properties:{evidence:j,button:x([`secondary`,`middle`]),count:b(`Number of press/click repetitions.`),intervalMs:b(`Delay between repeated press/click actions.`),holdMs:b(`Hold duration for each action.`),jitterPx:b(`Randomization radius in pixels.`),doubleTap:g(`Whether the command requested a double-tap action.`)}}),I={text:m(`Text submitted to the field.`),delayMs:b(`Delay between typed characters in milliseconds.`),evidence:j},De=w({resourceId:C(`Android resource id of the exact field that changed.`),className:C(`Android class name of the exact field that changed.`),packageName:C(`Android package name that owns the exact field.`),rect:w({x:b(),y:b(),width:b(),height:b()},[`x`,`y`,`width`,`height`],`Screen-space rectangle of the exact field that changed.`)},[`resourceId`,`className`,`packageName`,`rect`],`Target identity captured before fill and matched after fill.`),Oe=Ee({press:F,click:F,fill:{type:`object`,description:`Fill response. Android may return target-bound unconfirmed evidence when the exact app-owned field changed but formatting prevented raw equality.`,oneOf:[{...O({properties:I,required:[`text`]}),not:w({},[`verification`])},O({properties:{...I,verification:S(`unconfirmed`),requested:m(`Literal text requested by the fill command.`),before:C(`Raw target text captured before the fill.`),after:C(`Raw target text captured after the fill.`),target:De},required:[`text`,`verification`,`requested`,`before`,`after`,`target`]})]},longpress:O({properties:{durationMs:b(),gesture:S(`longpress`)}}),hover:O({properties:{gesture:S(`hover`)}}),find:w({ref:m(`Snapshot ref without the @ prefix when the find action returns one.`),refsGeneration:b(`ADR 0014 ref frame epoch for read-only find actions.`),found:g(`Whether a wait/exists/read-only find satisfied its condition.`),waitedMs:b(`Milliseconds waited for a read-only find condition.`),text:m(`Text value returned by find get_text.`),node:h(`Snapshot node for find get_attrs/get_text.`),matches:{type:`array`,description:`Every match for the read-only find list action (#1625): { ref, node } each.`,items:h(`One listed match with its snapshot ref and node.`)},locator:m(`Locator kind used for the find action.`),query:m(`Query argument used for the find action.`),x:b(`Resolved x coordinate for mutating find actions.`),y:b(`Resolved y coordinate for mutating find actions.`),message:m(`Diagnostic message for mutating find actions.`),cost:E},[],`Daemon response data for the find command.`),boot:w({...M,booted:{type:`boolean`,const:!0}},[...N,`booted`]),shutdown:w({...M,shutdown:Te},[...N,`shutdown`]),viewport:w({width:b(),height:b(),message:m()},[`width`,`height`,`message`]),back:w({action:S(`back`),mode:x(te),message:m()},[`action`,`mode`,`message`]),home:w({action:S(`home`),message:m()},[`action`,`message`]),orientation:w({action:S(`orientation`),orientation:x(le),message:m(),confirmed:g(),warning:m()},[`action`,`orientation`,`message`]),"app-switcher":w({action:S(`app-switcher`),message:m()},[`action`,`message`]),fold:w({action:S(`fold`),pose:x(ce),hingeAngleDegrees:b(`Hinge angle CoreDevice read back after the pose settled.`),screen:w({display:m(`CoreDevice name of the panel the device now lights.`),widthPt:b(),heightPt:b()},[`display`,`widthPt`,`heightPt`]),message:m()},[`action`,`pose`,`hingeAngleDegrees`,`message`]),"action-button":w({action:S(`action-button`),message:m()},[`action`,`message`]),"tv-remote":w({action:S(`tv-remote`),button:x(ue),durationMs:b(),message:m()},[`action`,`button`,`message`]),wait:w({waitedMs:b(),kind:S(`selector`),text:m(),selector:m(),captures:b(),nodeCount:b(),hint:m(),warning:m()},[`waitedMs`]),scroll:w({direction:x([`up`,`down`,`left`,`right`]),edge:x([`top`,`bottom`]),until:m(`Until scrolls only: the selector the passes stopped on.`),passes:b(`Edge and until scrolls only: how many scroll-and-check passes ran.`),amount:b(),pixels:b(),durationMs:b(),message:m(),keyboardAvoided:g(`Present only when an on-screen keyboard forced the swipe into the band above it; the reported pixels were planned against the shorter referenceHeight.`),keyboardMinY:b(`Where the keyboard began, in the same unit as the gesture coordinates. Clipped scrolls only.`)},[`direction`]),prepare:w({action:S(`ios-runner`),platform:x(s),deviceId:m(),deviceName:m(),kind:x(y),durationMs:b(),runner:w({},[]),cache:x([`exact`,`restore-key`,`miss`,`external`]),artifact:x([`valid`,`rebuilt`]),buildMs:b(),connectMs:b(),healthCheckMs:b(),xctestrunPath:m(),recoveryReason:m(),failureReason:m(),timing:w({totalMs:b(),additiveParts:w({buildMs:b(),connectAfterBuildMs:b(),healthCheckMs:b()},[`connectAfterBuildMs`,`healthCheckMs`]),containment:w({connectMs:{type:`array`,items:S(`buildMs`)},healthCheckMs:{type:`array`,items:m()}},[`healthCheckMs`]),note:m()},[`totalMs`,`additiveParts`,`containment`,`note`]),message:m()},[`action`,`platform`,`deviceId`,`deviceName`,`kind`,`durationMs`,`runner`,`connectMs`,`healthCheckMs`,`timing`,`message`]),push:{type:`object`,oneOf:[w({platform:S(`ios`),bundleId:m(),message:m()},[`platform`,`bundleId`,`message`]),w({platform:S(`android`),package:m(),action:m(),extrasCount:b(),message:m()},[`platform`,`package`,`action`,`extrasCount`,`message`])]},"trigger-app-event":w({event:m(),eventUrl:m(),transport:S(`deep-link`),message:m()},[`event`,`eventUrl`,`transport`,`message`]),clipboard:{type:`object`,oneOf:[w({action:S(`read`),text:m()},[`action`,`text`]),w({action:S(`write`),textLength:b(),message:m()},[`action`,`textLength`,`message`])]},appstate:{type:`object`,oneOf:[w({platform:x([`ios`,`macos`]),appName:m(),appBundleId:m(),source:S(`session`),surface:x(ne),device_udid:m(`iOS only — the session device UDID.`),ios_simulator_device_set:{type:[`string`,`null`],description:`iOS only — the simulator set path, or null when unknown.`}},[`platform`,`appName`,`source`,`surface`]),w({platform:S(`android`),package:m(),activity:m()},[`platform`,`package`,`activity`])]},keyboard:w({platform:x([`android`,`ios`]),action:x([`status`,`dismiss`,`enter`]),visible:g(),wasVisible:g(),dismissed:g(),attempts:b(),inputType:m(),type:x([`text`,`number`,`email`,`phone`,`password`,`datetime`,`unknown`]),inputMethodPackage:m(),focusedPackage:m(),focusedResourceId:m(),inputOwner:x([`app`,`ime`,`unknown`]),message:m()},[`platform`,`action`]),doctor:w({status:x([`pass`,`warn`,`fail`,`info`]),summary:m(),kind:x([`auto`,`react-native`,`expo`,`repack`]),platform:m(),target:x(c),targetApp:m(),metro:w({host:m(),port:b()},[`host`,`port`]),checks:{type:`array`,items:w({id:m(),status:x([`pass`,`warn`,`fail`,`info`]),summary:m(),hint:m(),command:m(),evidence:h()},[`id`,`status`,`summary`])}},[`status`,`summary`,`kind`,`checks`]),diff:w({mode:S(`snapshot`),baselineInitialized:g(),summary:w({additions:b(),removals:b(),unchanged:b()},[`additions`,`removals`,`unchanged`]),lines:{type:`array`,items:w({kind:x([`added`,`removed`]),text:m(),ref:m()},[`kind`,`text`])},warnings:T},[`mode`,`baselineInitialized`,`summary`,`lines`]),replay:w({replayed:b(),healed:b(),session:m(),sessionActive:g(`True iff the session is still active — the script had no terminal close.`),artifactPaths:T,snapshotDiagnostics:h(),message:m()},[`replayed`,`healed`,`session`,`sessionActive`,`artifactPaths`,`message`]),test:w({total:b(),executed:b(),passed:b(),failed:b(),skipped:b(),notRun:b(),durationMs:b(),failures:{type:`array`,items:h()},tests:{type:`array`,items:h()},snapshotDiagnostics:h()},[`total`,`executed`,`passed`,`failed`,`skipped`,`notRun`,`durationMs`,`failures`,`tests`]),record:{type:`object`,oneOf:[w({recording:S(`started`),outPath:m(),sessionStateDir:m(),recordingBackend:m(),recordingScope:m(),recordOnlySession:g(),activeSessionApp:h(),showTouches:g()},[`recording`,`outPath`,`sessionStateDir`,`showTouches`]),w({recording:S(`stopped`),outPath:m(),telemetryPath:m(),artifacts:{type:`array`,items:D},recordingBackend:m(),recordingScope:m(),recordOnlySession:g(),activeSessionApp:h(),durationMs:b(),capturedDurationMs:b(),recorder:x(_e,`What the recorder was observed doing when the recording was stopped: confirmed, or lost when the session holding it died. ADR 0024 reserves unconfirmed for the step that gains the probe.`),nativePathDisposition:x(ge,`What became of the artifact path the recorder writes to: retirable while it still owes a removal, retired once that removal was verified. ADR 0024 reserves pending.`),showTouches:g(),warning:m(),overlayWarning:m(),chunks:{type:`array`,items:h()}},[`recording`,`outPath`,`artifacts`,`durationMs`,`showTouches`])]},trace:{type:`object`,oneOf:[w({trace:S(`started`),outPath:m()},[`trace`,`outPath`]),w({trace:S(`stopped`),outPath:m(),artifacts:{type:`array`,items:D}},[`trace`,`outPath`,`artifacts`])]}}),ke={devices:{type:`object`,properties:{devices:{type:`array`,items:{type:`object`,properties:{platform:{type:`string`,enum:s},target:{type:`string`,enum:c},kind:{type:`string`,enum:y},id:{type:`string`},name:{type:`string`}},required:[`platform`,`target`,`kind`,`id`,`name`]}}},required:[`devices`]},apps:{type:`object`,properties:{apps:{type:`array`,items:{type:`string`}}},required:[`apps`]}},L={...Oe,...ke},Ae={stateDir:{schema:{type:`string`,description:`Agent-device state directory.`},audience:p({operatorConfig:!0})},mcpOutputFormat:{schema:{type:`string`,enum:[`optimized`,`json`],description:`MCP text content format. Defaults to optimized agent-friendly text; use json for JSON text. Structured content is always returned separately.`}},includeCost:{schema:{type:`boolean`,description:`Include per-command agent-cost (cost.wallClockMs, …) in structuredContent. Defaults to off; the default response shape is unchanged.`}},responseLevel:{schema:{type:`string`,enum:[`digest`,`default`,`full`],description:`Response verbosity: token-cheap digest / default (today) / full. Defaults to default; the default response shape is unchanged.`}}},R=Object.entries(Ae),z=new Set(R.map(([e])=>e)),je=Object.fromEntries(R.flatMap(([e,t])=>t.audience?[[e,t.audience]]:[]));function Me(){return Object.fromEntries(R.map(([e,t])=>[e,t.schema]))}function B(e){return n(e)}function V(t){let n=[`Error (${t.code}): ${t.message}`];if(t.cause){let e=t.cause.code?`${t.cause.code} `:``;n.push(`Cause: ${e}${t.cause.message}`)}t.hint&&n.push(`Hint: ${t.hint}`);for(let e of oe(t.details))n.push(`Warning: ${se(e)}`);n.push(...ve(e(t.details))),t.supportedOn&&n.push(`Supported on: ${t.supportedOn}`);let r=pe(t.details);return r&&n.push(r),n.join(`
|
|
2
|
+
`)}function Ne(e,t,n){let r=xe({command:e,cwd:process.cwd(),cliFlags:t}),i={};for(let[t,a]of Object.entries(r))Object.hasOwn(n,t)&&be(t,e)&&(i[t]=a);return ye(i,t)}const Pe={devices:async e=>({devices:e.map(Se)}),apps:async e=>({apps:e})};async function Fe(e,t){let n=Pe[e];return n?await n(t):t}function Ie(){let e=new Map;return{pinInput:(t,n,r)=>Xe(t,n,Ve(e,r,n.session)),mergeCommandResult:(t,n,r,i)=>He(e,t,n,r,i),mergeErrorDetails:(t,n,r)=>{let i=H(n,r);Le(e,i,t),Je(e,i,t)}}}function Le(e,t,n){let r=n?.refsGeneration;typeof r==`number`&&U(e,t,i(n),r)}const Re=new Set([`snapshot`,`find`]),ze=new Set(d.map(e=>e.name).filter(_).filter(e=>f(e))),Be=new Set([`press`,`click`,`fill`,`longpress`,`hover`,`get`]);function Ve(e,t,n){return e.get(H(t,n))}function H(e,t){let n=typeof t==`string`&&t.length>0?t:`default`;return`${e??``}\u0000${n}`}function He(e,t,n,r,i){let a=H(r,i);if(ze.has(t)){Ge(e,a,Ke(n));return}Re.has(t)&&(t===`find`?We(e,a,n):Ue(e,a,n))}function Ue(e,t,n){let r=n.refsGeneration;if(typeof r!=`number`){e.delete(t);return}let i=[];for(let{ref:e}of n.refs??[])i.push(e);for(let e of n.nodes??[])i.push(e.ref);U(e,t,i,r)}function We(e,t,n){let r=n.refsGeneration;if(typeof r!=`number`)return;let i=[];typeof n.ref==`string`&&n.ref.startsWith(`@`)&&i.push(n.ref.slice(1));for(let e of n.matches??[])typeof e.ref==`string`&&e.ref.length>0&&i.push(e.ref.startsWith(`@`)?e.ref.slice(1):e.ref);U(e,t,i,r)}function Ge(e,t,n){n?.refsGeneration!==void 0&&U(e,t,[...n.diff?.lines??[],...n.refs??[],...n.tail??[]].map(e=>e.ref).filter(e=>typeof e==`string`),n.refsGeneration)}function Ke(e){let t=e.settle;return typeof t==`object`&&t?t:void 0}function U(e,t,n,r){if(n.length===0)return;let i=e.get(t)??new Map;e.set(t,i),qe(i,n,r)}function qe(e,t,n){for(let r of t)e.delete(r),e.set(r,n);for(;e.size>1e3;)e.delete(e.keys().next().value)}function Je(e,t,n){let r=o(n?.divergence),i=o(r?.screen);if(i?.state!==`available`)return;let a=i.refsGeneration;if(typeof a!=`number`)return;let s=[];Ye(i.refs,s),U(e,t,s,a)}function Ye(e,t){if(Array.isArray(e))for(let n of e){let e=o(n)?.ref;typeof e==`string`&&e.length>0&&t.push(e)}}function Xe(e,t,n){return n===void 0||n.size===0?t:e===`wait`?Ze(t,n)??t:Be.has(e)?Qe(t,n)??t:t}function Ze(e,t){if(typeof e.ref!=`string`)return;let n=W(e.ref,t);return n===e.ref?void 0:{...e,ref:n}}function Qe(e,t){let n=o(e.target);if(n?.kind!==`ref`||typeof n.ref!=`string`)return;let r=W(n.ref,t);return r===n.ref?void 0:{...e,target:{...n,ref:r}}}function W(e,t){if(!e.startsWith(`@`)||e.includes(`~`))return e;let n=t.get(e.slice(1));return n===void 0?e:`${e}~s${n}`}const $e={config:p({operatorPath:`Point the process serving these tools at a config file with the AGENT_DEVICE_CONFIG environment variable.`}),remoteConfig:p({operatorPath:`Configure the remote profile on the process serving these tools, not per tool call.`})},et=Object.fromEntries(fe().flatMap(e=>Object.entries(e.inputAudience).filter(([,e])=>e.kind===`operator`)));function G(e){return{...e.inputAudience,...ie,...je,...$e,...et}}function tt(){return de().map(e=>{let t=e.name in L?L[e.name]:void 0,n=J(e.name,e);return{name:e.name,description:dt(e.name,ae(e)),inputSchema:n,...t?{outputSchema:t}:{}}})}function K(e={}){let n=Ie();return{execute:async(r,i)=>{if(!_(r))throw new t(`INVALID_ARGS`,`Unknown command tool: ${r}`);let a=v(r),o=Y(r,a,i)??X(a.inputSchema,i,r);if(o)return await q(new t(`INVALID_ARGS`,o),n,void 0,i.session);let s=Q(r,a.inputSchema).properties,c=Ne(r,i,s),l=at(c),u=lt(c),d=n.pinInput(r,u,l.client.stateDir),f=await rt(e,l.client);try{let t=await(e.runCommand??it)(f,r,d);return n.mergeCommandResult(r,t,l.client.stateDir,u.session),{isError:!1,structuredContent:await Fe(r,t),content:[{type:`text`,text:await ft({name:r,input:u,result:t,outputFormat:l.outputFormat,responseLevel:l.client.responseLevel})}]}}catch(e){return await q(e,n,l.client.stateDir,u.session)}}}}async function q(e,t,n,r){let i=B(e);return t.mergeErrorDetails(i.details,n,r),{isError:!0,structuredContent:i,content:[{type:`text`,text:V(i)}]}}const nt=K();async function rt(e,t){if(e.createClient)return await e.createClient(t);let{createAgentDeviceClient:n}=await import(`./agent-device-client.js`).then(e=>e.t);return n(t)}async function it(e,t,n){return await(await import(`./command-surface.js`).then(e=>e.t)).runCommand(e,t,n)}function at(e){return{client:ot(e),outputFormat:ct(e.mcpOutputFormat)}}function ot(e){let n=e.stateDir,r=e.includeCost,i=e.responseLevel,a={};if(n!==void 0){if(typeof n!=`string`||n.length===0)throw new t(`INVALID_ARGS`,`Expected stateDir to be a non-empty string.`);a.stateDir=n}if(r!==void 0){if(typeof r!=`boolean`)throw new t(`INVALID_ARGS`,`Expected includeCost to be a boolean.`);r&&(a.cost=!0)}let o=st(i);return o!==void 0&&(a.responseLevel=o),a}function st(e){if(e===void 0)return;let n=r.find(t=>t===e);if(n===void 0)throw new t(`INVALID_ARGS`,`Expected responseLevel to be one of 'digest', 'default', or 'full'.`);return n}function ct(e){if(e===void 0)return`optimized`;if(e!==`optimized`&&e!==`json`)throw new t(`INVALID_ARGS`,`Expected mcpOutputFormat to be "optimized" or "json".`);return e}function lt(e){return Object.fromEntries(Object.entries(e).filter(([e])=>!z.has(e)))}function J(e,t){let n=G(t),r=Q(e,t.inputSchema);return{...r,properties:Object.fromEntries(Object.entries(r.properties).filter(([e])=>n[e]?.kind!==`operator`))}}function Y(e,t,n){let r=J(e,t).properties,i=G(t);for(let t of Object.keys(n)){if(Object.hasOwn(r,t))continue;let n=Object.hasOwn(i,t)?i[t]:void 0;if(n?.kind!==`retired`)return n?.kind===`operator`?re(t,n.source):`${t} is not an accepted argument for the ${e} tool.`}}function X(e,t,n){if(!(!e||t===void 0)){if(Array.isArray(t))return Z(t,(t,r)=>X(e.items,t,`${n}[${r}]`));if(a(t))return Z(e.oneOf??[],e=>X(e,t,n))??Z(Object.entries(e.properties??{}),([e,r])=>Object.hasOwn(t,e)?ut(r,t,e,`${n}.${e}`):void 0)}}function ut(e,t,n,r){let i=e.commandInputFor;if(i===void 0)return X(e,t[n],r);let o=t[n],s=u(t[i]);if(s===void 0||!a(o))return;let c=Y(s,v(s),o);return c===void 0?void 0:`${r}: ${c}`}function Z(e,t){for(let[n,r]of e.entries()){let e=t(r,n);if(e)return e}}function dt(e,t){let n=ee(e);if(n.envelopeMs===`unbounded`)return`${t} Streams progress; no fixed client timeout.`;let r=Math.round(n.envelopeMs/1e3);return n.budget.source===`none`?`${t} Times out after ${r}s.`:`${t} Times out after ${r}s; a caller-supplied budget extends it.`}function Q(e,t){let n=l(e);return{...t,properties:{...t.properties,...n&&!t.properties?.noRecord?{noRecord:{type:`boolean`,description:`Do not record this action.`}}:{},...Me()}}}async function ft(e){if(e.outputFormat===`json`||e.responseLevel!==void 0&&e.responseLevel!=="default")return $(e.result);let t=await he({name:e.name,input:e.input,result:e.result});return typeof t?.text==`string`?pt(e.name,t):$(t?.data??e.result)}function pt(e,t){let n=t.text??``;if(!me(e))return n;let r=t.stderr?.trimEnd()??``;return r===``?n:`${n}${n.endsWith(`
|
|
3
3
|
`)?``:`
|
|
4
|
-
`}${r}`}function $(e){return typeof e==`string`?e:JSON.stringify(e,null,2)}export{B as a,V as i,K as n,z as o,
|
|
4
|
+
`}${r}`}function $(e){return typeof e==`string`?e:JSON.stringify(e,null,2)}export{B as a,V as i,K as n,z as o,tt as r,nt as t};
|
package/dist/src/config.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const e=18e4,t=6e4,n=6e4,r=2e4,i=12e4,a=1e4,o=15e3,s=2e4,c=5e3,l=
|
|
1
|
+
const e=18e4,t=6e4,n=6e4,r=2e4,i=12e4,a=1e4,o=15e3,s=2e4,c=5e3,l=2e4,u=.5,d=15e3,f=2e4,p=1e3,m=5e3;export{i as a,f as c,p as d,m as f,o as h,r as i,t as l,s as m,n,u as o,d as p,e as r,l as s,c as t,a as u};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as e,m as t,v as n}from"./sdk-device.js";import{
|
|
1
|
+
import{a as e,m as t,v as n}from"./sdk-device.js";import{Jt as r}from"./sdk-batch.js";import{n as i,v as a}from"./owner-identity.js";import"./process.js";import{t as o}from"./daemon-registration.js";import{r as s}from"./durable-resource.js";import"./src7.js";import c from"node:path";import l from"node:fs";import u from"node:crypto";import d from"node:os";function f(e){return p(`family`in e?e.family:e.platform,e.appleOs,e.id)}function p(e,t,n){return`local:${e}:${t??`none`}:${n}`}function m(){let e=process.env.AGENT_DEVICE_CLAIMS_DIR?.trim();return e?c.resolve(e):c.join(d.homedir(),`.agent-device`,`device-claims`)}function h(e){let t=u.createHash(`sha256`).update(e).digest(`hex`);return c.join(m(),`${t}.json`)}function g(e){return{deviceKey:e.deviceKey,ownerToken:e.ownerToken,ownerPid:e.ownerPid,ownerStartTime:e.ownerStartTime}}function _(e){return e.schemaVersion===3}function v(e){return r(e.allocator.instanceId)}function y(e){return D(e)?e.schemaVersion===3?S(e):e.schemaVersion===2?O(e):e.schemaVersion===1?k(e):null:null}function b(e){return D(e)&&e.schemaVersion===3}const x=[`ownerPid`,`ownerStartTime`,`ownerToken`,`session`,`workspace`,`abandonedAtMs`];function S(e){if(e.kind!==`allocator`||C(e))return null;let t=w(e);return t&&{schemaVersion:3,kind:`allocator`,...t}}function C(e){return x.some(t=>e[t]!==void 0)}function w(e){if(!D(e.device)||!P(e.device.name))return null;let t=e.device.name,n=s(e.device),r=F(e.deviceKey),i=F(e.stateDir),a=T(e.allocator),o=N(e);return!n||!r||!i||!a||!o||r!==f(n)?null:{deviceKey:r,device:{...n,name:t},stateDir:i,allocator:a,createdAtMs:o.createdAtMs,updatedAtMs:o.updatedAtMs}}function T(e){if(!D(e))return null;let t=E(e.instanceId),n=E(e.identityIncarnationId);return t&&n?{instanceId:t,identityIncarnationId:n}:null}function E(e){return P(e)&&e===e.trim()?e:null}function D(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function O(e){if(!D(e.device)||!P(e.device.name))return null;let t=s(e.device);return t?A(e,t,e.device.name):null}function k(n){if(!D(n.device))return null;let r=n.device,i=r.name;if(!P(i)||!t(r.platform))return null;let a=e(r.platform),o=s({id:r.id,family:a.platform,kind:r.kind,target:r.target,...r.appleOs===void 0?a.platform===`apple`?{appleOs:r.platform===`macos`?`macos`:`ios`}:{}:{appleOs:r.appleOs},...r.iosPhysicalDeviceBackend===void 0?{}:{iosPhysicalDeviceBackend:r.iosPhysicalDeviceBackend}});return o?A(n,o,i):null}function A(e,t,n){let r=j(e),i=M(e),a=N(e);return!r||!i||!a||r.deviceKey!==f(t)?null:{schemaVersion:2,...r,device:{...t,name:n},...i,...a}}function j(e){let t=F(e.deviceKey),n=F(e.session),r=F(e.workspace),i=F(e.stateDir);return!t||!n||!r||!i?null:{deviceKey:t,session:n,workspace:r,stateDir:i}}function M(e){let{ownerPid:t,ownerStartTime:n}=e,r=F(e.ownerToken);return!I(t)||!r||n!==null&&!P(n)?null:{ownerPid:t,ownerStartTime:n,ownerToken:r}}function N(e){let{createdAtMs:t,updatedAtMs:n,abandonedAtMs:r}=e;return!L(t)||!L(n)||r!==void 0&&!L(r)?null:{createdAtMs:t,updatedAtMs:n,...L(r)?{abandonedAtMs:r}:{}}}function P(e){return typeof e==`string`&&e.length>0}function F(e){return P(e)?e:null}function I(e){return typeof e==`number`&&Number.isInteger(e)&&e>0}function L(e){return typeof e==`number`&&Number.isFinite(e)}function R(e){let t=m(),n=z(t);if(`claims`in n)return n.claims;let r=n.entries.filter(e=>e.isFile()&&e.name.endsWith(`.json`)).map(e=>K(c.join(t,e.name))).filter(e=>e!==null).filter(t=>B(t.claim??t.allocatorClaim,e)),i=a(r.flatMap(e=>e.claim?[e.claim.ownerPid]:[]));return r.map(e=>e.claim?J(e,i.get(e.claim.ownerPid)??null):e)}function z(e){try{return{entries:l.readdirSync(e,{withFileTypes:!0})}}catch(t){let n=t.code;return n===`ENOENT`||n===`ENOTDIR`?{claims:[]}:{claims:[{fileName:c.basename(e),classification:`unknown`,error:String(t)}]}}}function B(e,t){return!e||[V(e,t.udid??t.serial),H(e,t.device),U(e,t.platform)].every(Boolean)}function V(e,t){return!t||e.device.id===t}function H(e,t){return!t||e.device.name===t||e.device.id===t}function U(e,t){return n({platform:e.device.family,appleOs:e.device.appleOs},t)}function W(e){let t=K(e);return t?.claim?J(t,a([t.claim.ownerPid]).get(t.claim.ownerPid)??null):t}function G(e){let t=K(e);return t?.allocatorClaim||t?.classification===`allocator-inconsistent`?t:null}function K(e){let t=c.basename(e);try{return q(t,l.readFileSync(e,`utf8`))}catch(e){let n=e.code;return n===`ENOENT`||n===`ENOTDIR`?null:{fileName:t,classification:`unknown`,error:String(e)}}}function q(e,t){try{let n=JSON.parse(t),r=y(n);return r?_(r)?{fileName:e,deviceKey:r.deviceKey,allocatorClaim:r,classification:`allocator-held`}:{fileName:e,deviceKey:r.deviceKey,claim:r,classification:`unknown`}:{fileName:e,classification:b(n)?`allocator-inconsistent`:`inconsistent`}}catch(t){return{fileName:e,classification:`inconsistent`,error:String(t)}}}function J(e,t){let n=e.claim;if(!n)return e;let r={pid:n.ownerPid,startTime:n.ownerStartTime},a=i({owner:r,stateDir:n.stateDir},t),s=a===`live`&&o({...r,stateDir:n.stateDir});return{...e,classification:s?`owner-daemon-superseded`:a}}function Y(e){switch(e){case`owner-process-dead`:case`owner-process-reused`:case`owner-state-dir-gone`:case`owner-daemon-superseded`:return!0;case`live`:case`unknown`:case`inconsistent`:return!1;case`allocator-inconsistent`:return!1;case`allocator-held`:return!1}}function X(e){switch(e){case`owner-process-dead`:case`owner-daemon-superseded`:return!0;case`live`:case`owner-process-reused`:case`owner-state-dir-gone`:case`unknown`:case`inconsistent`:return!1;case`allocator-inconsistent`:return!1;case`allocator-held`:return!1}}export{G as a,f as c,R as i,h as l,Y as n,v as o,W as r,g as s,X as t,m as u};
|