agent-device 0.15.2 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +51 -155
- package/android-multitouch-helper/README.md +41 -0
- package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.16.0.apk +0 -0
- package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.16.0.apk.sha256 +1 -0
- package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.16.0.manifest.json +10 -0
- package/android-snapshot-helper/README.md +2 -0
- package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.16.0.apk +0 -0
- package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.16.0.apk.sha256 +1 -0
- package/android-snapshot-helper/dist/{agent-device-android-snapshot-helper-0.15.2.manifest.json → agent-device-android-snapshot-helper-0.16.0.manifest.json} +6 -6
- package/dist/src/1231.js +1 -1
- package/dist/src/1769.js +7 -7
- package/dist/src/2099.js +1 -0
- package/dist/src/221.js +4 -4
- package/dist/src/3622.js +3 -0
- package/dist/src/7519.js +1 -0
- package/dist/src/7556.js +1 -1
- package/dist/src/89.js +1 -0
- package/dist/src/940.js +1 -1
- package/dist/src/9542.js +2 -2
- package/dist/src/9639.js +2 -2
- package/dist/src/989.js +1 -1
- package/dist/src/android-adb.d.ts +26 -0
- package/dist/src/android-adb.js +1 -1
- package/dist/src/android-snapshot-helper.d.ts +30 -0
- package/dist/src/batch.d.ts +9 -9
- package/dist/src/cli.js +494 -76
- package/dist/src/index.d.ts +47 -5
- package/dist/src/internal/daemon.js +69 -45
- package/dist/src/server.js +2 -2
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/AgentDeviceRunnerUITests-Bridging-Header.h +1 -0
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedGesture.h +19 -0
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedGesture.m +297 -0
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +144 -5
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +328 -23
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Lifecycle.swift +3 -1
- package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +8 -0
- package/package.json +9 -3
- package/server.json +2 -2
- package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.15.2.apk +0 -0
- package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.15.2.apk.sha256 +0 -1
- package/dist/src/1393.js +0 -1
- package/dist/src/2151.js +0 -438
- package/dist/src/3572.js +0 -1
- package/dist/src/7599.js +0 -3
- package/dist/src/9671.js +0 -1
package/dist/src/7556.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{AppError as e}from"./9152.js";function t(e,l,o,u={}){let c=i(o);if(!c)return{matches:[],score:0};let a=0,s=[];for(let t of e){if(u.requireRect&&!t.rect)continue;let e=function(e,t,i){switch(t){case"role":return function(e,t){let r=n(e??"");return r?r===t?2:+!!r.includes(t):0}(e.type,i);case"label":return r(e.label,i);case"value":return r(e.value,i);case"id":return r(e.identifier,i);default:return Math.max(r(e.label,i),r(e.value,i),r(e.identifier,i))}}(t,l,c);if(!(e<=0)){if(e>a){a=e,s.length=0,s.push(t);continue}e===a&&s.push(t)}}return{matches:s,score:a}}function r(e,t){let r=i(e??"");return r?r===t?2:+!!r.includes(t):0}function i(e){return e.trim().toLowerCase().replace(/\s+/g," ")}function n(e){let t=e.trim();return t?t=(t.split(".").pop()??t).replace(/XCUIElementType/gi,"").toLowerCase():""}function l(t){let r="any",i=0;["text","label","value","role","id"].includes(t[0])&&(r=t[0],i=1);let n=t[i]??"",l=t.slice(i+1);if(0===l.length)return{locator:r,query:n,action:"click"};let o=l[0]
|
|
1
|
+
import{AppError as e}from"./9152.js";function t(e,l,o,u={}){let c=i(o);if(!c)return{matches:[],score:0};let a=0,s=[];for(let t of e){if(u.requireRect&&!t.rect)continue;let e=function(e,t,i){switch(t){case"role":return function(e,t){let r=n(e??"");return r?r===t?2:+!!r.includes(t):0}(e.type,i);case"label":return r(e.label,i);case"value":return r(e.value,i);case"id":return r(e.identifier,i);default:return Math.max(r(e.label,i),r(e.value,i),r(e.identifier,i))}}(t,l,c);if(!(e<=0)){if(e>a){a=e,s.length=0,s.push(t);continue}e===a&&s.push(t)}}return{matches:s,score:a}}function r(e,t){let r=i(e??"");return r?r===t?2:+!!r.includes(t):0}function i(e){return e.trim().toLowerCase().replace(/\s+/g," ")}function n(e){let t=e.trim();return t?t=(t.split(".").pop()??t).replace(/XCUIElementType/gi,"").toLowerCase():""}function l(t){let r="any",i=0;["text","label","value","role","id"].includes(t[0])&&(r=t[0],i=1);let n=t[i]??"",l=t.slice(i+1);if(0===l.length)return{locator:r,query:n,action:"click"};let o=l[0]?.toLowerCase();if("get"===o){let t=l[1]?.toLowerCase();if("text"===t)return{locator:r,query:n,action:"get_text"};if("attrs"===t)return{locator:r,query:n,action:"get_attrs"};throw new e("INVALID_ARGS","find get only supports text or attrs")}if("wait"===o)return{locator:r,query:n,action:"wait",timeoutMs:function(e){if(!e)return null;let t=Number(e);return Number.isFinite(t)?t:null}(l[1])??void 0};if("exists"===o)return{locator:r,query:n,action:"exists"};if("click"===o)return{locator:r,query:n,action:"click"};if("focus"===o)return{locator:r,query:n,action:"focus"};if("fill"===o)return{locator:r,query:n,action:"fill",value:l.slice(1).join(" ")};if("type"===o)return{locator:r,query:n,action:"type",value:l.slice(1).join(" ")};throw new e("INVALID_ARGS",`Unsupported find action: ${l[0]}`)}export{t as findBestMatchesByLocator,n as normalizeRole,i as normalizeText,l as parseFindArgs};
|
package/dist/src/89.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var t;let e;import{DEFAULT_BATCH_MAX_STEPS as r}from"./1231.js";import{jsonSchemaField as a,stringField as i,batchCommandNames as n,toSelectorSnapshotOptions as o,booleanSchema as s,integerSchema as p,assertAllowedKeys as c,requiredEnum as d,looseObjectField as l,requiredField as u,listMcpExposedCommandNames as m,readFieldInput as h,commonToClientOptions as g,integerField as f,numberField as y,booleanField as b,readInputRecord as v,repeatedFields as w,stringSchema as x,stringArrayField as M,toClientElementTarget as S,customField as k,optionalEnum as I,enumField as P,toRepeatedOptions as R,pointField as U,command_input_readPoint as C,toClientInteractionTarget as E,interactionTargetField as T,fieldsInputSchema as j,requiredNumber as A,selectorSnapshotFields as F,elementTargetField as N,readCommonInput as O,looseObjectSchema as B,optionalInteger as H}from"./2099.js";function D(t){return{...t,invoke:async(e,r)=>await t.run(e,t.readInput(r))}}function L(t,e,r,a){return D({name:t,description:e,inputSchema:j(r),readInput:t=>h(t,r),run:a})}let _=["app","frontmost-app","desktop","menubar"],$=["duration","text","ref","selector"],G=["start","stop"],q=[L("devices","List available devices.",{},(t,e)=>t.devices.list(e)),L("boot","Boot or prepare a selected device without using CLI positional arguments.",{headless:b("Boot without showing simulator UI when supported.")},(t,e)=>t.devices.boot(e)),L("apps","List installed apps.",{appsFilter:P(["user-installed","all"])},(t,e)=>t.apps.list(e)),L("session","List active sessions.",{action:P(["list"])},async(t,{action:e,...r})=>({sessions:await t.sessions.list(r)})),L("open","Open an app, deep link, URL, or platform surface.",{app:i("App name, bundle id, package, or URL."),url:i("Optional URL passed with an app shell."),surface:P(_),activity:i("Android activity name."),launchConsole:i("Launch console mode."),relaunch:b("Force relaunch."),saveScript:a({oneOf:[s(),x()]}),noRecord:b("Do not record this action.")},(t,e)=>t.apps.open(e)),L("close","Close an app or end the active session.",{app:i("Optional app to close."),shutdown:b("Shutdown the session/device where supported."),saveScript:a({oneOf:[s(),x()]})},(t,e)=>e.app?t.apps.close(e):t.sessions.close(function(t){let{app:e,...r}=t;return r}(e))),L("install","Install an app binary.",{app:u(i()),appPath:u(i("Path to app binary."))},(t,e)=>t.apps.install(e)),L("reinstall","Reinstall an app binary.",{app:u(i()),appPath:u(i("Path to app binary."))},(t,e)=>t.apps.reinstall(e)),L("install-from-source","Install an app from a structured source.",{source:u(a(B("Install source object."))),retainPaths:b(),retentionMs:f()},(t,e)=>t.apps.installFromSource(e)),L("push","Deliver a push payload.",{app:u(i()),payload:u(a({oneOf:[x(),B()]}))},(t,e)=>t.apps.push(e)),L("trigger-app-event","Trigger an app-defined event.",{event:u(i()),payload:l()},(t,e)=>t.apps.triggerEvent(e)),L("snapshot","Capture an accessibility snapshot.",{interactiveOnly:b(),compact:b(),depth:f(),scope:i(),raw:b(),forceFull:b()},(t,e)=>t.capture.snapshot(e)),L("screenshot","Capture a screenshot.",{path:i("Output path."),overlayRefs:b(),fullscreen:b(),maxSize:f(),stabilize:b(),surface:P(_)},(t,e)=>t.capture.screenshot(e)),L("diff","Diff accessibility snapshots.",{kind:u(a({type:"string",const:"snapshot"})),out:i(),interactiveOnly:b(),compact:b(),depth:f(),scope:i(),raw:b()},(t,e)=>t.capture.diff(e)),L("wait","Wait for duration, text, ref, or selector.",{kind:P($),durationMs:f(),text:i(),ref:i(),selector:i(),timeoutMs:f(),depth:f(),scope:i(),raw:b()},(t,e)=>{var r;let a;return t.command.wait((I(r=e,"kind",$),a={...r},delete a.kind,a))}),L("alert","Inspect or handle platform alerts.",{action:P(["get","accept","dismiss","wait"]),timeoutMs:f()},(t,e)=>t.command.alert(e)),L("appstate","Show foreground app or activity.",{},(t,e)=>t.command.appState(e)),L("back","Navigate back.",{mode:P(["in-app","system"])},(t,e)=>t.command.back(e)),L("home","Go to the home screen.",{},(t,e)=>t.command.home(e)),L("rotate","Rotate device orientation.",{orientation:u(P(["portrait","portrait-upside-down","landscape-left","landscape-right"]))},(t,e)=>t.command.rotate(e)),L("app-switcher","Open the app switcher.",{},(t,e)=>t.command.appSwitcher(e)),L("keyboard","Inspect or dismiss the keyboard.",{action:P(["status","dismiss"])},(t,e)=>t.command.keyboard(e)),L("clipboard","Read or write clipboard text.",{action:u(P(["read","write"])),text:i()},(t,e)=>t.command.clipboard(e)),L("react-native","Run supported React Native app automation helpers.",{action:u(P(["dismiss-overlay"]))},(t,e)=>t.command.reactNative(e)),L("replay","Replay a recorded session.",{path:u(i()),update:b(),backend:i(),env:M()},(t,e)=>t.replay.run(e)),L("test","Run one or more .ad scripts.",{paths:u(M()),update:b(),env:M(),failFast:b(),timeoutMs:f(),retries:f(),artifactsDir:i(),reportJunit:i()},(t,e)=>t.replay.test(e)),L("perf","Show session performance metrics.",{},(t,e)=>t.observability.perf(e)),L("logs","Manage session app logs.",{action:P(["path","start","stop","doctor","mark","clear"]),message:i(),restart:b()},(t,e)=>t.observability.logs(e)),L("network","Show recent HTTP traffic.",{action:P(["dump","log"]),limit:f(),include:P(["summary","headers","body","all"])},(t,e)=>t.observability.network(e)),L("record","Start or stop screen recording.",{action:u(P(G)),path:i(),fps:f(),quality:a(p()),hideTouches:b()},(t,e)=>t.recording.record(e)),L("trace","Start or stop trace capture.",{action:u(P(G)),path:i()},(t,e)=>t.recording.trace(e)),L("settings","Change OS settings and app permissions.",{setting:u(i()),state:u(i()),latitude:y(),longitude:y(),permission:i(),mode:P(["full","limited"])},(t,e)=>t.settings.update(e)),L("metro","Prepare Metro runtime or reload React Native apps.",{action:u(P(["prepare","reload"])),projectRoot:i(),kind:a(x()),publicBaseUrl:i(),proxyBaseUrl:i(),bearerToken:i(),bridgeScope:a({type:"object",additionalProperties:!0}),launchUrl:i(),port:f(),listenHost:i(),statusHost:i(),startupTimeoutMs:f(),probeTimeoutMs:f(),reuseExisting:b(),installDependenciesIfNeeded:b(),runtimeFilePath:i(),logPath:i(),metroHost:i(),metroPort:f(),bundleUrl:i(),timeoutMs:f()},async(t,e)=>{var r,a,i;return"prepare"===e.action?await t.metro.prepare({projectRoot:(r=e).projectRoot,kind:r.kind,publicBaseUrl:r.publicBaseUrl,proxyBaseUrl:r.proxyBaseUrl,bearerToken:r.bearerToken,bridgeScope:r.bridgeScope??((a=r).tenant&&a.runId&&a.leaseId?{tenantId:a.tenant,runId:a.runId,leaseId:a.leaseId}:void 0),port:r.port,listenHost:r.listenHost,statusHost:r.statusHost,startupTimeoutMs:r.startupTimeoutMs,probeTimeoutMs:r.probeTimeoutMs,reuseExisting:r.reuseExisting,installDependenciesIfNeeded:r.installDependenciesIfNeeded,runtimeFilePath:r.runtimeFilePath}):await t.metro.reload({metroHost:(i=e).metroHost,metroPort:i.metroPort,bundleUrl:i.bundleUrl,timeoutMs:i.timeoutMs})})],K=["pan","fling","pinch","rotate","transform"],z=["up","down","left","right"],J={target:u(T()),button:P(["primary","secondary","middle"],"Pointer button for platforms that support mouse buttons."),...F(),...w()},W={target:u(T()),...F(),...w()},X={target:u(T()),text:u(i("Text to enter into the target.")),delayMs:f("Delay between typed characters.",{min:0}),...F()},Y={target:u(T()),durationMs:f("Long press duration in milliseconds.",{min:0}),...F()},Q={from:u(U("Swipe start point.")),to:u(U("Swipe end point.")),durationMs:f("Swipe duration in milliseconds.",{min:0}),count:f("Number of swipe repetitions.",{min:1}),pauseMs:f("Pause between repeated swipes.",{min:0}),pattern:P(["one-way","ping-pong"])},V={x:u(y("X coordinate.")),y:u(y("Y coordinate."))},Z={text:u(i("Text to type.")),delayMs:f("Delay between typed characters.",{min:0})},tt={direction:u(P(["up","down","left","right","top","bottom"])),amount:y("Platform scroll amount."),pixels:f("Pixel scroll amount.",{min:0})},te={format:u(P(["text","attrs"])),target:u(N()),...F()},tr={predicate:u(P(["visible","hidden","exists","editable","selected","text"])),selector:u(i()),value:i(),...F()},ta={locator:P(["any","text","label","value","role","id"]),query:u(i()),action:P(["click","focus","exists","getText","getAttrs","wait","fill","type"]),value:i(),timeoutMs:f(),first:b(),last:b(),depth:f(),raw:b()},ti={kind:u(P(K,"Gesture variant.")),direction:P(z,"Fling direction."),origin:U("Gesture origin point."),delta:U("Movement delta for pan or transform gestures."),distance:f("Fling distance.",{min:0}),scale:y("Pinch or transform scale."),degrees:y("Rotation in degrees."),velocity:f("Rotate gesture velocity.",{min:0}),durationMs:f("Gesture duration in milliseconds.",{min:0})};function tn(t,e){return void 0===t[e]?void 0:C(t,e)}let to=[D({name:"click",description:"Click or tap a semantic UI target by ref, selector, or point.",inputSchema:j(J),readInput:t=>h(t,J),run:(t,e)=>{var r;return t.interactions.click({...g(r=e),...E(r.target),...o(r),...R(r),button:r.button})}}),D({name:"press",description:"Press a semantic UI target by ref, selector, or point.",inputSchema:j(W),readInput:t=>h(t,W),run:(t,e)=>{var r;return t.interactions.press({...g(r=e),...E(r.target),...o(r),...R(r)})}}),D({name:"fill",description:"Fill text into a semantic UI target by ref, selector, or point.",inputSchema:j(X),readInput:t=>h(t,X),run:(t,e)=>{var r;return t.interactions.fill({...g(r=e),...E(r.target),...o(r),text:r.text,delayMs:r.delayMs})}}),L("longpress","Long press by ref, selector, or point.",Y,(t,e)=>{var r;return t.interactions.longPress({...g(r=e),...E(r.target),...o(r),durationMs:r.durationMs})}),L("swipe","Swipe between two points.",Q,(t,e)=>t.interactions.swipe(e)),L("focus","Focus input at coordinates.",V,(t,e)=>t.interactions.focus(e)),L("type","Type text in the focused field.",Z,(t,e)=>t.interactions.type(e)),L("scroll","Scroll in a direction or to an edge.",tt,(t,e)=>t.interactions.scroll(e)),L("get","Get element text or attributes.",te,(t,e)=>{var r;return t.interactions.get({...g(r=e),...S(r.target),...o(r),format:r.format})}),L("is","Assert UI state.",tr,(t,e)=>t.interactions.is(e)),L("find","Find an element and optionally act on it.",ta,(t,e)=>t.interactions.find(e)),D({name:"gesture",description:"Run a structured gesture.",inputSchema:j(ti),readInput:function(t){let e=v(t),r=O(e),a=d(e,"kind",K);return"pan"===a?{...r,kind:a,origin:C(e,"origin"),delta:C(e,"delta"),durationMs:H(e,"durationMs",{min:0})}:"fling"===a?{...r,kind:a,direction:d(e,"direction",z),origin:C(e,"origin"),distance:H(e,"distance",{min:0}),durationMs:H(e,"durationMs",{min:0})}:"pinch"===a?{...r,kind:a,scale:A(e,"scale"),origin:tn(e,"origin")}:"rotate"===a?{...r,kind:a,degrees:A(e,"degrees"),origin:tn(e,"origin"),velocity:H(e,"velocity",{min:0})}:{...r,kind:a,origin:C(e,"origin"),delta:C(e,"delta"),scale:A(e,"scale"),degrees:A(e,"degrees"),durationMs:H(e,"durationMs",{min:0})}},run:async(t,e)=>{var r,a,i,n,o;switch(e.kind){case"pan":return await t.interactions.pan({...g(r=e),x:r.origin.x,y:r.origin.y,dx:r.delta.x,dy:r.delta.y,durationMs:r.durationMs});case"fling":return await t.interactions.fling({...g(a=e),direction:a.direction,x:a.origin.x,y:a.origin.y,distance:a.distance,durationMs:a.durationMs});case"pinch":return await t.interactions.pinch({...g(i=e),scale:i.scale,x:i.origin?.x,y:i.origin?.y});case"rotate":return await t.interactions.rotateGesture({...g(n=e),degrees:n.degrees,x:n.origin?.x,y:n.origin?.y,velocity:n.velocity});case"transform":return await t.interactions.transformGesture({...g(o=e),x:o.origin.x,y:o.origin.y,dx:o.delta.x,dy:o.delta.y,scale:o.scale,degrees:o.degrees,durationMs:o.durationMs})}}}),...q,D({name:"batch",description:"Run multiple structured command steps in one daemon request.",inputSchema:j(e={steps:u(k({type:"array",description:"Structured batch steps. Each step uses a command name and the same input object as that command tool.",items:{type:"object",properties:{command:{type:"string",enum:t=n,description:"Command name to run with structured input."},input:{type:"object",additionalProperties:!0,description:"Structured command input for the nested command. Use the matching MCP tool schema for this object."},runtime:{type:"object",additionalProperties:!0,description:"Optional per-step runtime payload."}},required:["command","input"],additionalProperties:!1}},(e,r)=>(function(t,e){if(!Array.isArray(t))throw Error("Expected steps to be an array.");return t.map((t,r)=>{var a,i,n;let o;return a=t,i=r+1,n=e,c(o=function(t,e){if(!t||"object"!=typeof t||Array.isArray(t))throw Error(`Invalid batch step ${e}.`);return t}(a,i),["command","input","runtime"],`Batch step ${i}`),{command:d(o,"command",n),input:function(t,e){let r=t.input;if(!r||"object"!=typeof r||Array.isArray(r))throw Error(`Batch step ${e} input must be an object.`);return r}(o,i),...function(t,e){let r=t.runtime;if(void 0!==r&&(!r||"object"!=typeof r||Array.isArray(r)))throw Error(`Batch step ${e} runtime must be an object.`);return void 0===r?{}:{runtime:r}}(o,i)}})})(e[r],t))),onError:P(["stop"],"Batch failure policy."),maxSteps:f("Maximum number of steps accepted for this batch.",{min:1,max:1e3}),out:i("Optional output path for command artifacts.")}),readInput:t=>(function(t,e){let a=h(t,e),i=a.maxSteps??r;if(!Number.isInteger(i)||i<1||i>1e3)throw Error(`Invalid batch maxSteps: ${String(a.maxSteps)}`);if(a.steps.length>i)throw Error(`batch has ${a.steps.length} steps; max allowed is ${i}.`);return{...a}})(t,e),run:(t,e)=>{var r;return t.batch.run({...g(r=e),steps:r.steps,onError:r.onError,maxSteps:r.maxSteps,out:r.out})}})],ts=new Map(to.map(t=>[t.name,t]));function tp(){return m().map(t=>{var e;if(!tl(t))throw Error(`Missing command for MCP-exposed command: ${t}`);return e=t,ts.get(e)})}function tc(){return to.map(t=>t.name)}function td(){return[...to]}function tl(t){return ts.has(t)}async function tu(t,e,r){var a;return await (a=e,ts.get(a)).invoke(t,r)}export{tl as isCommandName,td as listCommandDefinitions,tc as listCommandNames,tp as listMcpToolDefinitions,tu as runCommand};
|
package/dist/src/940.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{AppError as e}from"./9152.js";import{normalizeText as t}from"./7556.js";let r=new Set(["id","role","text","label","value","appname","windowtitle"]),n=new Set(["visible","hidden","editable","selected","enabled","hittable"]),l=new Set([...r,...n]);function i(t){let r=t.trim();if(!r)throw new e("INVALID_ARGS","Selector expression cannot be empty");let n=function(t){let r=[],n="",l=null;for(let i=0;i<t.length;i+=1){let u=t[i];if(('"'===u||"'"===u)&&!h(t,i)){l=f(l,u),n+=u;continue}if(!l&&"|"===u&&"|"===t[i+1]){let l=n.trim();if(!l)throw new e("INVALID_ARGS",`Invalid selector fallback expression: ${t}`);r.push(l),n="",i+=1;continue}n+=u}let i=n.trim();if(!i)throw new e("INVALID_ARGS",`Invalid selector fallback expression: ${t}`);return r.push(i),r}(r);if(0===n.length)throw new e("INVALID_ARGS","Selector expression cannot be empty");return{raw:r,selectors:n.map(t=>(function(t){let r=t.trim();if(!r)throw new e("INVALID_ARGS","Selector segment cannot be empty");let n=function(t){let r=[],n="",l=null;for(let e=0;e<t.length;e+=1){let i=t
|
|
1
|
+
import{AppError as e}from"./9152.js";import{normalizeText as t}from"./7556.js";let r=new Set(["id","role","text","label","value","appname","windowtitle"]),n=new Set(["visible","hidden","editable","selected","enabled","hittable"]),l=new Set([...r,...n]);function i(t){let r=t.trim();if(!r)throw new e("INVALID_ARGS","Selector expression cannot be empty");let n=function(t){let r=[],n="",l=null;for(let i=0;i<t.length;i+=1){let u=t[i];if(('"'===u||"'"===u)&&!h(t,i)){l=f(l,u),n+=u;continue}if(!l&&"|"===u&&"|"===t[i+1]){let l=n.trim();if(!l)throw new e("INVALID_ARGS",`Invalid selector fallback expression: ${t}`);r.push(l),n="",i+=1;continue}n+=u}let i=n.trim();if(!i)throw new e("INVALID_ARGS",`Invalid selector fallback expression: ${t}`);return r.push(i),r}(r);if(0===n.length)throw new e("INVALID_ARGS","Selector expression cannot be empty");return{raw:r,selectors:n.map(t=>(function(t){let r=t.trim();if(!r)throw new e("INVALID_ARGS","Selector segment cannot be empty");let n=function(t){let r=[],n="",l=null;for(let e=0;e<t.length;e+=1){let i=t.charAt(e);if(('"'===i||"'"===i)&&!h(t,e)){l=f(l,i),n+=i;continue}if(!l&&/\s/.test(i)){n.trim()&&r.push(n.trim()),n="";continue}n+=i}if(l)throw new e("INVALID_ARGS",`Unclosed quote in selector: ${t}`);return n.trim()&&r.push(n.trim()),r}(r);if(0===n.length)throw new e("INVALID_ARGS",`Invalid selector segment: ${t}`);return{raw:r,terms:n.map(s)}})(t))}}function u(e){try{return i(e)}catch{return null}}function o(e){let t=e.trim();if(!t)return!1;if("||"===t)return!0;let r=t.indexOf("=");if(-1!==r){let e=t.slice(0,r).trim().toLowerCase();return l.has(e)}return l.has(t.toLowerCase())}function a(e,t={}){if(0===e.length)return null;let r=t.preferTrailingValue??!1,n=0,l=[];for(;n<e.length;){let t=e[n];if(void 0===t||!o(t))break;n+=1;let r=e.slice(0,n).join(" ").trim();r&&u(r)&&l.push(n)}if(0===l.length)return null;let i=l.at(-1);if(void 0===i)return null;let c=i;if(r)for(let t=l.length-1;t>=0;t-=1){let r=l[t];if(void 0!==r&&r<e.length){c=r;break}}let s=e.slice(0,c).join(" ").trim();return s?{selectorExpression:s,rest:e.slice(c)}:null}function c(e){let t=e[0]??"",r=a(e.slice(1),{preferTrailingValue:"text"===t});return{predicate:t,split:r}}function s(t){let r=t.trim();if(!r)throw new e("INVALID_ARGS","Empty selector term");let i=r.indexOf("=");if(-1===i){let l=r.toLowerCase();if(!n.has(l))throw new e("INVALID_ARGS",`Invalid selector term "${t}", expected key=value`);return{key:l,value:!0}}let u=r.slice(0,i).trim().toLowerCase(),o=r.slice(i+1).trim();if(!l.has(u))throw new e("INVALID_ARGS",`Unknown selector key: ${u}`);if(!o)throw new e("INVALID_ARGS",`Missing selector value for key: ${u}`);if(n.has(u)){let t,r="true"===(t=d(o).toLowerCase())||"false"!==t&&null;if(null===r)throw new e("INVALID_ARGS",`Invalid boolean value for ${u}: ${o}`);return{key:u,value:r}}return{key:u,value:d(o)}}function f(e,t){return e?e===t?null:e:t}function d(e){let t=e.trim();return t.startsWith('"')&&t.endsWith('"')||t.startsWith("'")&&t.endsWith("'")?t.slice(1,-1).replace(/\\(["'])/g,"$1"):t}function h(e,t){let r=0;for(let n=t-1;n>=0&&"\\"===e[n];n-=1)r+=1;return r%2==1}function p(e){var t;let r,n=w(e.label),l=w(e.value),i=w(e.identifier),u=(t=i)&&!/^[\w.]+:id\/[\w.-]+$/i.test(t)&&!/^_?NS:\d+$/i.test(t)?i:"";return(r=g(e.type??"")).includes("textfield")||r.includes("securetextfield")||r.includes("searchfield")||r.includes("edittext")||r.includes("textview")||r.includes("textarea")?l||n||u:n||l||u}function m(e){let t=e.replace(/\s+/g," ").trim();return t.length<=48?t:`${t.slice(0,45)}...`}function b(e,t){var r;let n=p(e),l=function(e,t){if("text-view"===t||"text-field"===t||"search"===t)return!0;let r=g(e.type??""),n=`${e.role??""} ${e.subrole??""}`.toLowerCase();return r.includes("textview")||r.includes("textarea")||r.includes("textfield")||r.includes("securetextfield")||r.includes("searchfield")||r.includes("edittext")||n.includes("text area")||n.includes("text field")}(e,t);return{text:n,isLargeSurface:l,shouldSummarize:l&&!!(r=n)&&(r.length>80||/[\r\n]/.test(r))}}function w(e){return"string"==typeof e?e.trim():""}function g(e){let t=e.trim().replace(/XCUIElementType/gi,"").replace(/^AX/,"").toLowerCase(),r=Math.max(t.lastIndexOf("."),t.lastIndexOf("/"));return -1!==r&&(t=t.slice(r+1)),t}function v(e,t){let r=t.toLowerCase();return e.find(e=>{let t=(e.label??"").toLowerCase(),n=(e.value??"").toLowerCase(),l=(e.identifier??"").toLowerCase();return t.includes(r)||n.includes(r)||l.includes(r)})??null}function x(e,t){let r=[e.label,e.value,e.identifier].map(e=>"string"==typeof e?e.trim():"").find(e=>e&&e.length>0);return r&&S(r)?r:function(e,t){if(!e.rect)return;let r=e.rect.y+e.rect.height/2,n=null;for(let e of t){if(!e.rect)continue;let t=[e.label,e.value,e.identifier].map(e=>"string"==typeof e?e.trim():"").find(e=>e&&e.length>0);if(!t||!S(t))continue;let l=Math.abs(e.rect.y+e.rect.height/2-r);(!n||l<n.distance)&&(n={label:t,distance:l})}return n?.label}(e,t)??(r&&S(r)?r:void 0)}function S(e){let t=e.trim();return!(!t||/^(true|false)$/i.test(t)||/^\d+$/.test(t))}function I(e){let t=[],r=[];for(let n of e){let e=n.depth??0;for(;t.length>0&&e<=t[t.length-1];)t.pop();let l=g(n.type??""),i=[n.label,n.value,n.identifier].map(e=>"string"==typeof e?e.trim():"").find(e=>e&&e.length>0),u=!!i&&S(i);if(("group"===l||"ioscontentgroup"===l)&&!u){t.push(e);continue}let o=Math.max(0,e-t.length);r.push({...n,depth:o})}return r}function $(e,t){let r=g(e);return!r||("android"===t?r.includes("edittext")||r.includes("autocompletetextview"):r.includes("textfield")||r.includes("securetextfield")||r.includes("searchfield")||r.includes("textview")||r.includes("textarea")||"search"===r)}function A(e,t){return t.hittable?t:y(e,t,e=>!0===e.hittable)}function y(e,t,r){let n=t,l=new Set;for(;void 0!==n.parentIndex&&!l.has(n.ref);){l.add(n.ref);let t=e[n.parentIndex];if(!t)break;if(r(t))return t;n=t}return null}function N(e){return[e.label,e.value,e.identifier].map(e=>"string"==typeof e?e.trim():"").filter(e=>e.length>0)[0]??""}function L(e){return p(e)}function _(e){return!0===e.hittable||!!e.rect&&e.rect.width>0&&e.rect.height>0}function C(e,t){return $(e.type??"",t)&&!1!==e.enabled}function R(e,t,r){return t.terms.every(t=>(function(e,t,r){switch(t.key){case"id":return V(e.identifier,String(t.value));case"role":return V(g(e.type??""),String(t.value));case"label":return V(e.label,String(t.value));case"value":return V(e.value,String(t.value));case"text":return V(N(e),String(t.value));case"appname":return V(e.appName,String(t.value));case"windowtitle":return V(e.windowTitle,String(t.value));case"visible":return _(e)===!!t.value;case"hidden":return!_(e)==!!t.value;case"editable":return C(e,r)===!!t.value;case"selected":return!0===e.selected==!!t.value;case"enabled":return!1!==e.enabled==!!t.value;case"hittable":return!0===e.hittable==!!t.value;default:return!1}})(e,t,r))}function V(e,r){return t(e??"")===t(r)}function G(e,t,r){let n=r.requireRect??!1,l=r.requireUnique??!0,i=[];for(let[u,o]of t.selectors.entries()){let t=function(e,t,r,n){let l=0,i=null,u=null,o=!1;for(let a of e){if(n&&!a.rect||!R(a,t,r))continue;if(l+=1,i??=a,!u){u=a;continue}let e=function(e,t){let r=e.depth??0,n=t.depth??0;if(r!==n)return r>n?1:-1;let l=k(e),i=k(t);return l!==i?l<i?1:-1:0}(a,u);e>0?(u=a,o=!1):0===e&&(o=!0)}return{count:l,firstNode:i,disambiguated:o?null:u}}(e,o,r.platform,n);if(i.push({selector:o.raw,matches:t.count}),0!==t.count&&t.firstNode){if(l&&1!==t.count){if(!r.disambiguateAmbiguous||!t.disambiguated)continue;return{node:t.disambiguated,selector:o,selectorIndex:u,matches:t.count,diagnostics:i}}return{node:t.firstNode,selector:o,selectorIndex:u,matches:t.count,diagnostics:i}}}return null}function T(e,t,r){let n=r.requireRect??!1,l=[];for(let[i,u]of t.selectors.entries()){let t=function(e,t,r,n){let l=0;for(let i of e)(!n||i.rect)&&R(i,t,r)&&(l+=1);return l}(e,u,r.platform,n);if(l.push({selector:u.raw,matches:t}),t>0)return{selectorIndex:i,selector:u,matches:t,diagnostics:l}}return null}function D(e,t,r){if(0===t.length)return`Selector did not match: ${e.raw}`;let n=t.map(e=>`${e.selector} -> ${e.matches}`).join(", ");return r.unique??!0?`Selector did not resolve uniquely (${n})`:`Selector did not match (${n})`}function k(e){return e.rect?e.rect.width*e.rect.height:1/0}function q(e,t,r={}){let n=[],l=g(e.type??""),i=U(e.identifier),u=U(e.label),o=U(e.value),a=U(N(e)),c="fill"===r.action;i&&n.push(`id=${M(i)}`),l&&u&&n.push(c?`role=${M(l)} label=${M(u)} editable=true`:`role=${M(l)} label=${M(u)}`),u&&n.push(c?`label=${M(u)} editable=true`:`label=${M(u)}`),o&&n.push(c?`value=${M(o)} editable=true`:`value=${M(o)}`),a&&a!==u&&a!==o&&n.push(c?`text=${M(a)} editable=true`:`text=${M(a)}`),l&&c&&!n.some(e=>e.includes("editable=true"))&&n.push(`role=${M(l)} editable=true`);let s=Array.from(new Set(n));return 0===s.length&&l&&s.push(c?`role=${M(l)} editable=true`:`role=${M(l)}`),0===s.length&&_(e)&&s.push("visible=true"),s}function M(e){return JSON.stringify(e)}function U(e){if(!e)return null;let t=e.trim();return t||null}export{q as buildSelectorChainForNode,m as buildTextPreview,b as describeTextSurface,L as extractNodeReadText,N as extractNodeText,p as extractReadableText,y as findNearestAncestor,A as findNearestHittableAncestor,v as findNodeByLabel,T as findSelectorChainMatch,D as formatSelectorFailure,$ as isFillableType,C as isNodeEditable,_ as isNodeVisible,o as isSelectorToken,R as matchesSelector,g as normalizeType,i as parseSelectorChain,I as pruneGroupNodes,x as resolveRefLabel,G as resolveSelectorChain,c as splitIsSelectorArgs,a as splitSelectorFromArgs,w as trimText,u as tryParseSelectorChain};
|
package/dist/src/9542.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import e from"node:net";import t from"node:http";import a from"node:https";import r from"node:fs";import o from"node:path";import{pipeline as n}from"node:stream/promises";import i from"node:os";import{createHash as s,randomUUID as l}from"node:crypto";import{Writable as c}from"node:stream";import{toAppErrorCode as d,AppError as p}from"./9152.js";import{runCmdSync as u,runCmd as m,runCmdDetached as f}from"./9818.js";import{readVersion as h,findProjectRoot as y}from"./9671.js";import{createRequestId as w,withDiagnosticTimer as v,emitDiagnostic as I}from"./7599.js";import{isAgentDeviceDaemonProcess as g,stopProcessForTakeover as b}from"./8656.js";import{readRect as A,settingsCommandCodec as k,PUBLIC_COMMANDS as P,elementTargetCodec as S,asRecord as _,longPressCommandCodec as M,buildAppIdentifiers as E,buildDeviceIdentifiers as D,computeDaemonCodeSignature as T,resolveDaemonTransportPreference as N,readRequiredNumber as U,readPoint as C,parsing_stripUndefined as R,readOptionalString as L,readRequiredPlatform as O,readRequiredDeviceKind as x,findCommandCodec as F,INTERNAL_COMMANDS as B,fillCommandCodec as q,typeCommandCodec as z,isRecord as $,readRequiredString as j,readNullableString as H,readDeviceTarget as K,isCommandCodec as V,screenshotFlagsFromOptions as G,resolveDaemonPaths as J,resolveDaemonServerMode as W,waitCommandCodec as Y,interactionTargetCodec as Q}from"./3572.js";import{sleep as X}from"./4829.js";import{reloadMetro as Z,prepareMetroRuntime as ee}from"./1974.js";function et(e){return new Promise((t,a)=>{let r="";e.setEncoding("utf8"),e.on("data",e=>{r+=e}),e.on("end",()=>t(r)),e.on("error",a)})}let ea="sha256";async function er(e){let t=await eo(e.localPath,e.platform),a=e.baseUrl.endsWith("/")?e.baseUrl:`${e.baseUrl}/`;try{let r=await el({normalizedBase:a,token:e.token,artifact:t});if(r?.kind==="cache-hit")return r.uploadId;if(r?.kind==="direct-upload")try{return await ec(t.payloadPath,r),await ep({normalizedBase:a,token:e.token,uploadId:r.uploadId})}catch{}return await es({normalizedBase:a,token:e.token,artifact:t})}finally{t.cleanup()}}async function eo(e,t){var a,n,i;let s,l=r.statSync(e),c=o.basename(e),d=l.isDirectory(),p=("ios"===(a=t)||"android"===a?a:void 0)??(n=e,i=l,s=n.toLowerCase(),i.isDirectory()&&s.endsWith(".app")||s.endsWith(".ipa")?"ios":s.endsWith(".apk")||s.endsWith(".aab")?"android":void 0),u=[];try{let t=d?await en(e,u):e,a=r.statSync(t);return{payloadPath:t,fileName:c,artifactType:d?"app-bundle":"file",platform:p,contentType:d?"application/gzip":"application/octet-stream",sha256:await eu(t),sizeBytes:a.size,cleanup:()=>ei(u)}}catch(e){throw ei(u),e}}async function en(e,t){let a=r.mkdtempSync(o.join(i.tmpdir(),`agent-device-upload-${l()}-`));t.push(a);let n=o.join(a,`${o.basename(e)}.tar.gz`);return await m("tar",["czf",n,"-C",o.dirname(e),o.basename(e)],{env:{...process.env,COPYFILE_DISABLE:"1"}}),n}function ei(e){for(let t of e)r.rmSync(t,{recursive:!0,force:!0})}async function es(e){let{normalizedBase:t,token:a,artifact:r}=e,o=new URL("upload",t),n={"content-type":r.contentType,"x-artifact-type":r.artifactType,"x-artifact-filename":r.fileName,"x-artifact-hash":r.sha256,"x-artifact-hash-algorithm":ea,"transfer-encoding":"chunked"};a&&(n.authorization=`Bearer ${a}`,n["x-agent-device-token"]=a);let i=await ed({url:o,method:"POST",headers:n,payloadPath:r.payloadPath,timeoutMessage:"Artifact upload timed out",timeoutHint:"The upload to the remote daemon exceeded the 5-minute timeout.",errorMessage:"Failed to upload artifact to remote daemon",errorHint:"Verify the remote daemon is reachable and supports artifact uploads."});try{let e=JSON.parse(i.body);if(!e.ok||!e.uploadId)throw new p("COMMAND_FAILED",`Upload failed: ${i.body}`);return e.uploadId}catch(e){if(e instanceof p)throw e;throw new p("COMMAND_FAILED",`Invalid upload response: ${i.body}`)}}async function el(e){let t=new URL("upload/preflight",e.normalizedBase),a={"content-type":"application/json"};e.token&&(a.authorization=`Bearer ${e.token}`,a["x-agent-device-token"]=e.token);let r=await fetch(t,{method:"POST",headers:a,signal:AbortSignal.timeout(3e4),body:JSON.stringify({sha256:e.artifact.sha256,fileName:e.artifact.fileName,sizeBytes:e.artifact.sizeBytes,artifactType:e.artifact.artifactType,...e.artifact.platform?{platform:e.artifact.platform}:{},contentType:e.artifact.contentType})}).catch(()=>void 0);if(r?.ok)return function(e){var t;if(!e||"object"!=typeof e||!0!==e.ok||"string"!=typeof e.uploadId)return;if(!0===e.cacheHit)return{kind:"cache-hit",uploadId:e.uploadId};let a=e.upload;if(!a||"string"!=typeof a.url)return;let r=a.headers??{};if(!(!(t=r)||"object"!=typeof t||Array.isArray(t))&&Object.values(t).every(e=>"string"==typeof e))return{kind:"direct-upload",uploadId:e.uploadId,url:a.url,headers:r}}(await r.json().catch(()=>void 0))}async function ec(e,t){let a=await ed({url:new URL(t.url),method:"PUT",headers:t.headers,payloadPath:e,timeoutMessage:"Direct artifact upload timed out",timeoutHint:"The direct upload ticket did not accept the artifact within the timeout.",errorMessage:"Failed to upload artifact with direct upload ticket"});if(a.statusCode<200||a.statusCode>=300)throw new p("COMMAND_FAILED","Direct artifact upload failed",{statusCode:a.statusCode,statusMessage:a.statusMessage})}async function ed(e){let o="https:"===e.url.protocol?a:t;return await new Promise((t,a)=>{let i=o.request({protocol:e.url.protocol,host:e.url.hostname,port:e.url.port,method:e.method,path:e.url.pathname+e.url.search,headers:e.headers},e=>{et(e).then(a=>{clearTimeout(s),t({statusCode:e.statusCode??500,statusMessage:e.statusMessage,body:a})}).catch(a)}),s=setTimeout(()=>{i.destroy(),a(new p("COMMAND_FAILED",e.timeoutMessage,{timeoutMs:3e5,...e.timeoutHint?{hint:e.timeoutHint}:{}}))},3e5);i.on("error",t=>{clearTimeout(s),a(new p("COMMAND_FAILED",e.errorMessage,e.errorHint?{hint:e.errorHint}:{},t))}),i.on("close",()=>clearTimeout(s)),n(r.createReadStream(e.payloadPath),i).catch(e=>{i.destroy(),a(new p("COMMAND_FAILED","Failed to read local artifact",{},e instanceof Error?e:Error(String(e))))})})}async function ep(e){let t=new URL("upload/finalize",e.normalizedBase),a={"content-type":"application/json"};e.token&&(a.authorization=`Bearer ${e.token}`,a["x-agent-device-token"]=e.token);let r=await fetch(t,{method:"POST",headers:a,signal:AbortSignal.timeout(3e4),body:JSON.stringify({uploadId:e.uploadId})}).catch(e=>{throw new p("COMMAND_FAILED","Failed to finalize direct artifact upload",{},e)});if(!r.ok)throw new p("COMMAND_FAILED","Direct artifact upload finalize failed",{status:r.status,statusText:r.statusText});let o=await r.json().catch(()=>void 0);if(!o?.ok||!o.uploadId)throw new p("COMMAND_FAILED","Invalid upload finalize response");return o.uploadId}async function eu(e){let t=s(ea),a=new c({write(e,a,r){t.update(e),r()}});return await n(r.createReadStream(e),a).catch(e=>{throw new p("COMMAND_FAILED","Failed to read local artifact",{},e instanceof Error?e:void 0)}),t.digest("hex")}let em=["xcodebuild .*AgentDeviceRunnerUITests/RunnerTests/testCommand","xcodebuild .*AgentDeviceRunner\\.env\\.session-","xcodebuild build-for-testing .*ios-runner/AgentDeviceRunner/AgentDeviceRunner\\.xcodeproj"],ef=new e.BlockList;async function eh(t){let a=t.meta?.requestId??w(),r=!!(t.meta?.debug||t.flags?.verbose),o=function(t){let a,r=t.flags?.stateDir??process.env.AGENT_DEVICE_STATE_DIR,o=function(e){let t;if(e){try{t=new URL(e)}catch(t){throw new p("INVALID_ARGS","Invalid daemon base URL",{daemonBaseUrl:e},t instanceof Error?t:void 0)}if("http:"!==t.protocol&&"https:"!==t.protocol)throw new p("INVALID_ARGS","Daemon base URL must use http or https",{daemonBaseUrl:e});return t.toString().replace(/\/+$/,"")}}(t.flags?.daemonBaseUrl??process.env.AGENT_DEVICE_DAEMON_BASE_URL),n=t.flags?.daemonAuthToken??process.env.AGENT_DEVICE_DAEMON_AUTH_TOKEN;var i=o,s=n;if(!(!i||"localhost"===(a=new URL(i).hostname.trim().toLowerCase().replace(/^\[(.*)\]$/,"$1"))||(e.isIPv4(a)?ef.check(a,"ipv4"):!!e.isIPv6(a)&&ef.check(a,"ipv6")))&&("string"!=typeof s||!(s.trim().length>0)))throw new p("INVALID_ARGS","Remote daemon base URL for non-loopback hosts requires daemon authentication",{daemonBaseUrl:i,hint:"Provide --daemon-auth-token or AGENT_DEVICE_DAEMON_AUTH_TOKEN when using a non-loopback remote daemon URL."});let l=t.flags?.daemonTransport??process.env.AGENT_DEVICE_DAEMON_TRANSPORT,c=N(l);if(o&&"socket"===c)throw new p("INVALID_ARGS","Remote daemon base URL only supports HTTP transport. Remove --daemon-transport socket.",{daemonBaseUrl:o});let d=W(t.flags?.daemonServerMode??process.env.AGENT_DEVICE_DAEMON_SERVER_MODE??("dual"===l?"dual":void 0));return{paths:J(r),transportPreference:c,serverMode:d,remoteBaseUrl:o,remoteAuthToken:n}}(t),n="test"===t.command?void 0:9e4,i=await v("daemon_startup",async()=>await eb(o),{requestId:a,session:t.session}),s=await ey(t,i),l={...t,positionals:s.positionals,flags:s.flags,token:i.token,meta:{...t.meta??{},requestId:a,debug:r,cwd:t.meta?.cwd,tenantId:t.meta?.tenantId??t.flags?.tenant,runId:t.meta?.runId??t.flags?.runId,leaseId:t.meta?.leaseId??t.flags?.leaseId,sessionIsolation:t.meta?.sessionIsolation??t.flags?.sessionIsolation,lockPolicy:t.meta?.lockPolicy,lockPlatform:t.meta?.lockPlatform,...s.uploadedArtifactId?{uploadedArtifactId:s.uploadedArtifactId}:{},...s.clientArtifactPaths?{clientArtifactPaths:s.clientArtifactPaths}:{},...s.installSource?{installSource:s.installSource}:{}}};return I({level:"info",phase:"daemon_request_prepare",data:{requestId:a,command:t.command,session:t.session}}),await v("daemon_request",async()=>await eR(i,l,o.transportPreference,n),{requestId:a,command:t.command})}async function ey(e,t){let a,n=[...e.positionals??[]],i=e.flags?{...e.flags}:void 0,s=e.meta?.installSource,l={};if(ez(t)){let r=function(e,t){if("screenshot"===e.command){let a=eI(e,"path",".png");return t[0]?{field:"path",localPath:a,positionalIndex:0,positionalPath:eg("screenshot",".png")}:{field:"path",localPath:a,positionalIndex:0,flagPath:eg("screenshot",".png")}}if("record"===e.command&&"start"===(t[0]??"").toLowerCase()){let t=eI(e,"outPath",".mp4",1);return{field:"outPath",localPath:t,positionalIndex:1,positionalPath:eg("recording",o.extname(t)||".mp4")}}return null}(e,n);r&&(void 0!==r.positionalPath&&(n[r.positionalIndex]=r.positionalPath),void 0!==r.flagPath&&((i??={}).out=r.flagPath),l[r.field]=r.localPath);let c=await ev(e,t);c&&(s=c.installSource,a=c.uploadedArtifactId??a)}let c=()=>ew({positionals:n,flags:i,installSource:s,uploadedArtifactId:a,clientArtifactPaths:l});if(!ez(t)||"install"!==e.command&&"reinstall"!==e.command||n.length<2)return c();let d=n[1];if(d.startsWith("remote:"))return n[1]=d.slice(7),ew({positionals:n,flags:i,clientArtifactPaths:l});let p=o.isAbsolute(d)?d:o.resolve(e.meta?.cwd??process.cwd(),d);return r.existsSync(p)?(a=await er({localPath:p,baseUrl:t.baseUrl,token:t.token,platform:e.flags?.platform}),c()):ew({positionals:n,flags:i,clientArtifactPaths:l})}function ew(e){return{positionals:e.positionals,flags:e.flags,installSource:e.installSource,uploadedArtifactId:e.uploadedArtifactId,...Object.keys(e.clientArtifactPaths).length>0?{clientArtifactPaths:e.clientArtifactPaths}:{}}}async function ev(e,t){let a=e.meta?.installSource;if("install_source"!==e.command||!a||"path"!==a.kind)return null;let n=a.path.trim();if(!n)return{installSource:a};if(n.startsWith("remote:"))return{installSource:{...a,path:n.slice(7)}};let i=o.isAbsolute(n)?n:o.resolve(e.meta?.cwd??process.cwd(),n);if(!r.existsSync(i))return{installSource:{...a,path:i}};let s=await er({localPath:i,baseUrl:t.baseUrl,token:t.token,platform:e.flags?.platform});return{installSource:{...a,path:i},uploadedArtifactId:s}}function eI(e,t,a,r=0){let n=e.positionals?.[r]??e.flags?.out,i=`${"path"===t?"screenshot":"recording"}-${Date.now()}${a}`,s=n&&n.trim().length>0?n:i;return o.isAbsolute(s)?s:o.resolve(e.meta?.cwd??process.cwd(),s)}function eg(e,t){let a=t.startsWith(".")?t:`.${t}`;return o.posix.join("/tmp",`agent-device-${e}-${Date.now()}-${Math.random().toString(36).slice(2,8)}${a}`)}async function eb(e){let t,a;if(e.remoteBaseUrl){let t={transport:"http",token:e.remoteAuthToken??"",pid:0,baseUrl:e.remoteBaseUrl};if(await eN(t,"http"))return t;throw new p("COMMAND_FAILED","Remote daemon is unavailable",{daemonBaseUrl:e.remoteBaseUrl,hint:"Verify AGENT_DEVICE_DAEMON_BASE_URL points to a reachable daemon with GET /health and POST /rpc."})}let r=eS(e.paths.infoPath),o=h(),n=T((a=eC()).useSrc?a.srcPath:a.distPath,a.root),i=!!r&&await eN(r,e.transportPreference);if(r&&r.version===o&&r.codeSignature===n&&i)return r;r&&(r.version!==o||r.codeSignature!==n||!i)&&(await eP(r),eT(e.paths.infoPath)),function(e){let t=eE(e);if(!t.hasLock||t.hasInfo)return;let a=e_(e.lockPath);if(!a)return eT(e.lockPath);g(a.pid,a.processStartTime)||eT(e.lockPath)}(e.paths);let s=0,l=[];for(let a=1;a<=2;a+=1){try{await eU(e)}catch(r){if(t=r instanceof Error?r.message:String(r),l.push(await eM(e.paths,"start_error")),a<2){await X(150);continue}break}let r=await eA(15e3,e);if(r)return r;if(await ek(e.paths)){s+=1;continue}let o=eE(e.paths),n=a<2,i=await eM(e.paths,"startup_timeout",{stopLiveProcesses:!1});if(l.push(i),i.retainedInfoProcess||i.retainedLockProcess){let t=await eA(15e3,e);if(t)return t;break}if(!n)break;o.hasInfo||o.hasLock||await X(150)}let c=eE(e.paths);throw new p("COMMAND_FAILED","Failed to start daemon",{kind:"daemon_startup_failed",infoPath:e.paths.infoPath,lockPath:e.paths.lockPath,startupTimeoutMs:15e3,startupAttempts:2,lockRecoveryCount:s,cleanupResults:l,startError:t,metadataState:c,hint:function(e,t=J(process.env.AGENT_DEVICE_STATE_DIR)){return e.hasLock&&!e.hasInfo?`agent-device attempted to clean stale daemon metadata automatically, but ${t.lockPath} still exists without ${t.infoPath}. Retry with --debug; if this persists, remove ${t.lockPath} after confirming no agent-device daemon process is running.`:e.hasLock&&e.hasInfo?`agent-device attempted to clean stale daemon metadata automatically, but ${t.infoPath} and ${t.lockPath} still remain. Retry with --debug; if this persists, remove both files after confirming no agent-device daemon process is running.`:"agent-device did not observe reachable daemon metadata after retrying. Stale metadata was cleaned automatically when safe; retry with --debug and check daemon diagnostics logs."}(c,e.paths)})}async function eA(e,t){let a=Date.now();for(;Date.now()-a<e;){let e=eS(t.paths.infoPath);if(e&&await eN(e,t.transportPreference))return e;await X(100)}return null}async function ek(e){let t=eE(e);if(!t.hasLock||t.hasInfo)return!1;let a=e_(e.lockPath);return!(a&&g(a.pid,a.processStartTime))&&(eT(e.lockPath),!0)}async function eP(e){await b(e.pid,{termTimeoutMs:3e3,killTimeoutMs:1e3,expectedStartTime:e.processStartTime})}function eS(e){let t=eD(e);if(!t||"object"!=typeof t)return null;let a="string"==typeof t.token&&t.token.length>0?t.token:null;if(!a)return null;let r=Number.isInteger(t.port)&&Number(t.port)>0,o=Number.isInteger(t.httpPort)&&Number(t.httpPort)>0;if(!r&&!o)return null;let n=t.transport,i="string"==typeof t.version?t.version:void 0,s="string"==typeof t.codeSignature?t.codeSignature:void 0,l="string"==typeof t.processStartTime?t.processStartTime:void 0,c=Number.isInteger(t.pid)&&Number(t.pid)>0;return{token:a,port:r?Number(t.port):void 0,httpPort:o?Number(t.httpPort):void 0,transport:"socket"===n||"http"===n||"dual"===n?n:void 0,pid:c?Number(t.pid):0,version:i,codeSignature:s,processStartTime:l}}function e_(e){let t=eD(e);return t&&"object"==typeof t&&Number.isInteger(t.pid)&&Number(t.pid)>0?{pid:Number(t.pid),processStartTime:"string"==typeof t.processStartTime?t.processStartTime:void 0,startedAt:"number"==typeof t.startedAt?t.startedAt:void 0}:null}ef.addSubnet("127.0.0.0",8,"ipv4"),ef.addAddress("::1","ipv6"),ef.addSubnet("::ffff:127.0.0.0",104,"ipv6");async function eM(e,t,a={}){let o=a.stopLiveProcesses??!0,n={reason:t,removedInfo:!1,removedLock:!1,stoppedInfoProcess:!1,stoppedLockProcess:!1};try{var i,s,l,c;let t=r.existsSync(e.infoPath),a=eS(e.infoPath);if(a){let t=g(a.pid,a.processStartTime);t&&!o?n.retainedInfoProcess=!0:(t&&(await eP(a),n.stoppedInfoProcess=!0),i=e.infoPath,eT(i),n.removedInfo=!0)}else t&&(s=e.infoPath,eT(s),n.removedInfo=!0);let d=r.existsSync(e.lockPath),p=e_(e.lockPath);if(p){let t=g(p.pid,p.processStartTime);t&&!o?n.retainedLockProcess=!0:(t&&(await b(p.pid,{termTimeoutMs:3e3,killTimeoutMs:1e3,expectedStartTime:p.processStartTime}),n.stoppedLockProcess=!0),l=e.lockPath,eT(l),n.removedLock=!0)}else d&&(c=e.lockPath,eT(c),n.removedLock=!0)}catch(e){n.error=e instanceof Error?e.message:String(e)}return I({level:n.error?"warn":"info",phase:"daemon_startup_metadata_cleanup",data:n}),n}function eE(e){return{hasInfo:r.existsSync(e.infoPath),hasLock:r.existsSync(e.lockPath)}}function eD(e){if(!r.existsSync(e))return null;try{return JSON.parse(r.readFileSync(e,"utf8"))}catch{return null}}function eT(e){try{r.existsSync(e)&&r.unlinkSync(e)}catch{}}async function eN(r,o){var n;return"http"===eL(r,o)?await function(e){let r=e.baseUrl?e$(e.baseUrl,"health"):e.httpPort?`http://127.0.0.1:${e.httpPort}/health`:null;if(!r)return Promise.resolve(!1);let o=new URL(r),n="https:"===o.protocol?a:t,i=e.baseUrl?3e3:500;return new Promise(e=>{let t=n.request({protocol:o.protocol,host:o.hostname,port:o.port,path:o.pathname+o.search,method:"GET",timeout:i},t=>{t.resume(),e((t.statusCode??500)<500)});t.on("timeout",()=>{t.destroy(),e(!1)}),t.on("error",()=>{e(!1)}),t.end()})}(r):await ((n=r.port)?new Promise(t=>{let a=e.createConnection({host:"127.0.0.1",port:n},()=>{a.destroy(),t(!0)});a.on("error",()=>{t(!1)})}):Promise.resolve(!1))}async function eU(e){let t=eC(),a=t.useSrc?["--experimental-strip-types",t.srcPath]:[t.distPath],r={...process.env,AGENT_DEVICE_STATE_DIR:e.paths.baseDir,AGENT_DEVICE_DAEMON_SERVER_MODE:e.serverMode};f(process.execPath,a,{env:r})}function eC(){let e=y(),t=[o.join(e,"dist","src","internal","daemon.js"),o.join(e,"dist","src","daemon.js")],a=t.find(e=>r.existsSync(e))??t[0],n=o.join(e,"src","daemon.ts"),i=t.some(e=>r.existsSync(e)),s=r.existsSync(n);if(!i&&!s)throw new p("COMMAND_FAILED","Daemon entry not found",{distPaths:t,srcPath:n});return{root:e,distPath:a,distPaths:t,srcPath:n,useSrc:process.execArgv.includes("--experimental-strip-types")?s:!i&&s}}async function eR(e,t,a,r){return"http"===eL(e,a)?await eq(e,t,r):await eB(e,t,r)}function eL(e,t){if(e.baseUrl){if("socket"===t)throw new p("COMMAND_FAILED","Remote daemon endpoint only supports HTTP transport",{daemonBaseUrl:e.baseUrl});return"http"}if("http"===t||"socket"===t){var a=e,r=t;if(eO(a,r))return r;throw new p("COMMAND_FAILED","http"===r?"Daemon HTTP endpoint is unavailable":"Daemon socket endpoint is unavailable")}let o=("socket"===e.transport||"dual"===e.transport?["socket","http"]:["http","socket"]).find(t=>eO(e,t));if(o)return o;throw new p("COMMAND_FAILED","Daemon metadata has no reachable transport")}function eO(e,t){return"http"===t?!!e.httpPort:!!e.port}function ex(e,t,a,r,o,n){let i=o?{terminated:0}:function(){let e=0;try{for(let t of em){let a=u("pkill",["-f",t],{allowFailure:!0});0===a.exitCode&&(e+=1)}return{terminated:e}}catch(t){return{terminated:e,error:t instanceof Error?t.message:String(t)}}}(),s=!o&&"snapshot"!==r,l=s?function(e,t){let a=!1;try{g(e.pid,e.processStartTime)&&(process.kill(e.pid,"SIGKILL"),a=!0)}catch{b(e.pid,{termTimeoutMs:3e3,killTimeoutMs:1e3,expectedStartTime:e.processStartTime})}finally{eT(t.infoPath),eT(t.lockPath)}return{forcedKill:a}}(e,t):{forcedKill:!1};return I({level:"error",phase:"daemon_request_timeout",data:{timeoutMs:n,requestId:a,command:r,timedOutRunnerPidsTerminated:i.terminated,timedOutRunnerCleanupError:i.error,daemonPidReset:s?e.pid:void 0,daemonPidForceKilled:s?l.forcedKill:void 0,daemonPreservedAfterTimeout:!o&&!s,daemonBaseUrl:e.baseUrl}}),new p("COMMAND_FAILED","Daemon request timed out",{timeoutMs:n,requestId:a,hint:function(e){let{remote:t,resetDaemon:a,command:r}=e;return t?"Retry with --debug and verify the remote daemon URL, auth token, and remote host logs.":a?"Retry with --debug and check daemon diagnostics logs. Timed-out iOS runner xcodebuild processes were terminated when detected.":`Retry with --debug and check daemon diagnostics logs. The timed-out ${r??"request"} request was canceled and iOS runner work was aborted when detected; the daemon was kept alive so the session can still be closed or inspected.`}({remote:o,resetDaemon:s,command:r})})}function eF(e,t,a){return I({level:"error",phase:"daemon_request_socket_error",data:{requestId:t,message:e instanceof Error?e.message:String(e)}}),new p("COMMAND_FAILED","Failed to communicate with daemon",{requestId:t,hint:a?"Retry command. If this persists, verify the remote daemon URL, auth token, and remote host reachability.":"Retry command. If this persists, clean stale daemon metadata and start a fresh session."},e instanceof Error?e:void 0)}async function eB(t,a,r){let o=t.port;if(!o)throw new p("COMMAND_FAILED","Daemon socket endpoint is unavailable");return new Promise((n,i)=>{let s=e.createConnection({host:"127.0.0.1",port:o},()=>{s.write(`${JSON.stringify(a)}
|
|
2
|
-
`)}),l=J(a.flags?.stateDir??process.env.AGENT_DEVICE_STATE_DIR),c="number"==typeof r?setTimeout(()=>{s.destroy(),i(ex(t,l,a.meta?.requestId,a.command,!1,r))},r):void 0,d="";s.setEncoding("utf8"),s.on("data",e=>{let t=(d+=e).indexOf("\n");if(-1===t)return;let r=d.slice(0,t).trim();if(r)try{let e=JSON.parse(r);s.end(),c&&clearTimeout(c),n(e)}catch(e){c&&clearTimeout(c),i(new p("COMMAND_FAILED","Invalid daemon response",{requestId:a.meta?.requestId,line:r},e instanceof Error?e:void 0))}}),s.on("error",e=>{c&&clearTimeout(c),i(eF(e,a.meta?.requestId,!1))})})}async function eq(e,r,o){var n,i,s;let l,c=e.baseUrl?new URL(e$(e.baseUrl,"rpc")):e.httpPort?new URL(`http://127.0.0.1:${e.httpPort}/rpc`):null;if(!c)throw new p("COMMAND_FAILED","Daemon HTTP endpoint is unavailable");let u=JSON.stringify((n=r,i={includeTokenParam:!e.baseUrl},l=n.meta?.requestId??w(),"lease_allocate"!==(s=n.command)&&"lease_heartbeat"!==s&&"lease_release"!==s?{jsonrpc:"2.0",id:l,method:"agent_device.command",params:n}:{jsonrpc:"2.0",id:l,method:function(e){switch(e){case"lease_allocate":return"agent_device.lease.allocate";case"lease_heartbeat":return"agent_device.lease.heartbeat";case"lease_release":return"agent_device.lease.release"}}(n.command),params:function(e,t,a){let r={...a.includeTokenParam?{token:e.token}:{},session:e.session,tenantId:e.meta?.tenantId,runId:e.meta?.runId};switch(t){case"lease_allocate":return{...r,ttlMs:e.meta?.leaseTtlMs,backend:e.meta?.leaseBackend};case"lease_heartbeat":return{...r,leaseId:e.meta?.leaseId,ttlMs:e.meta?.leaseTtlMs};case"lease_release":return{...r,leaseId:e.meta?.leaseId}}}(n,n.command,i)})),m={"content-type":"application/json","content-length":Buffer.byteLength(u)};return e.baseUrl&&e.token&&(m.authorization=`Bearer ${e.token}`,m["x-agent-device-token"]=e.token),await new Promise((n,i)=>{let s=J(r.flags?.stateDir??process.env.AGENT_DEVICE_STATE_DIR),l=("https:"===c.protocol?a:t).request({protocol:c.protocol,host:c.hostname,port:c.port,method:"POST",path:c.pathname+c.search,headers:m},t=>{et(t).then(t=>{h&&clearTimeout(h),function(e,t){let{info:a,req:r,resolve:o,reject:n}=t;try{let t=JSON.parse(e);if(t.error){let e=t.error.data??{};n(new p(d(null!=e.code?String(e.code):void 0,"COMMAND_FAILED"),String(e.message??t.error.message??"Daemon RPC request failed"),{..."object"==typeof e.details&&e.details?e.details:{},hint:"string"==typeof e.hint?e.hint:void 0,diagnosticId:"string"==typeof e.diagnosticId?e.diagnosticId:void 0,logPath:"string"==typeof e.logPath?e.logPath:void 0,requestId:r.meta?.requestId}));return}if(!t.result||"object"!=typeof t.result)return void n(new p("COMMAND_FAILED","Invalid daemon RPC response",{requestId:r.meta?.requestId}));if(a.baseUrl&&t.result.ok)return void ej(a,r,t.result).then(o).catch(n);o(t.result)}catch(t){n(new p("COMMAND_FAILED","Invalid daemon response",{requestId:r.meta?.requestId,line:e},t instanceof Error?t:void 0))}}(t,{info:e,req:r,resolve:n,reject:i})}).catch(e=>{h&&clearTimeout(h),i(new p("COMMAND_FAILED","Failed to read daemon response",{requestId:r.meta?.requestId},e instanceof Error?e:void 0))})}),f=ez(e),h="number"==typeof o?setTimeout(()=>{l.destroy(),i(ex(e,s,r.meta?.requestId,r.command,f,o))},o):void 0;l.on("error",e=>{h&&clearTimeout(h),i(eF(e,r.meta?.requestId,f))}),l.write(u),l.end()})}function ez(e){return"string"==typeof e.baseUrl&&e.baseUrl.length>0}function e$(e,t){return new URL(t,e.endsWith("/")?e:`${e}/`).toString()}async function ej(e,t,a){let r=Array.isArray(a.data?.artifacts)?a.data.artifacts:[];if(0===r.length||!e.baseUrl)return a;let n=a.data?{...a.data}:{},i=[];for(let a of r){if(!a||"object"!=typeof a||"string"!=typeof a.artifactId){i.push(a);continue}let r=function(e,t){if(e.localPath&&e.localPath.trim().length>0)return e.localPath;let a=t.meta?.clientArtifactPaths?.[e.field];if(a&&a.trim().length>0)return a;let r=e.fileName?.trim()||`${e.field}-${Date.now()}`;return o.resolve(t.meta?.cwd??process.cwd(),r)}(a,t);await eH({baseUrl:e.baseUrl,token:e.token,artifactId:a.artifactId,destinationPath:r,requestId:t.meta?.requestId}),n[a.field]=r,i.push({...a,localPath:r})}return n.artifacts=i,{ok:!0,data:n}}async function eH(e){var i,s;let l,c=new URL((i=e.baseUrl,s=e.artifactId,l=i.endsWith("/")?i:`${i}/`,new URL(`artifacts/${encodeURIComponent(s)}`,l).toString())),d="https:"===c.protocol?a:t;await r.promises.mkdir(o.dirname(e.destinationPath),{recursive:!0}),await new Promise((t,a)=>{let o=!1,i=e.timeoutMs??9e4,s=n=>{if(!o){if(o=!0,clearTimeout(u),n)return void r.promises.rm(e.destinationPath,{force:!0}).finally(()=>a(n));t()}},l=d.request({protocol:c.protocol,host:c.hostname,port:c.port,method:"GET",path:c.pathname+c.search,headers:e.token?{authorization:`Bearer ${e.token}`,"x-agent-device-token":e.token}:void 0},t=>{if((t.statusCode??500)>=400){let a="";t.setEncoding("utf8"),t.on("data",e=>{a+=e}),t.on("end",()=>{s(new p("COMMAND_FAILED","Failed to download remote artifact",{artifactId:e.artifactId,statusCode:t.statusCode,requestId:e.requestId,body:a}))});return}t.on("aborted",()=>{s(new p("COMMAND_FAILED","Remote artifact download was interrupted",{artifactId:e.artifactId,requestId:e.requestId}))}),n(t,r.createWriteStream(e.destinationPath)).then(()=>s(),e=>s(e instanceof Error?e:Error(String(e))))}),u=setTimeout(()=>{l.destroy(new p("COMMAND_FAILED","Remote artifact download timed out",{artifactId:e.artifactId,requestId:e.requestId,timeoutMs:i}))},i);l.on("error",t=>{t instanceof p?s(t):s(new p("COMMAND_FAILED","Failed to download remote artifact",{artifactId:e.artifactId,requestId:e.requestId,timeoutMs:i},t instanceof Error?t:void 0))}),l.end()})}function eK(e,t){let a=L(e,"bundleId"),r=L(e,"package");return{app:j(e,"app"),appPath:j(e,"appPath"),platform:O(e,"platform"),appId:a??r,bundleId:a,package:r,identifiers:E({session:t,bundleId:a,packageName:r})}}function eV(e){let{record:t,platform:a,id:r,name:o,target:n}=eJ(e,"name");return{platform:a,target:n,kind:x(t,"kind"),id:r,name:o,booted:"boolean"==typeof t.booted?t.booted:void 0,identifiers:D(a,r,o),...eW(a,r)}}function eG(e){let{record:t,platform:a,id:r,name:o,target:n}=eJ(e,"name"),i=j(t,"device"),s={session:o,...D(a,r,i)};return{name:o,createdAt:U(t,"createdAt"),device:{platform:a,target:n,id:r,name:i,identifiers:s,...eW(a,r,H(t,"ios_simulator_device_set"))},identifiers:s}}function eJ(e,t){let a=_(e);return{record:a,platform:O(a,"platform"),id:j(a,"id"),name:j(a,t),target:K(a,"target")}}function eW(e,t,a){return{ios:"ios"===e?{udid:t,...void 0!==a?{simulatorSetPath:a}:{}}:void 0,android:"android"===e?{serial:t}:void 0}}function eY(e){return e??"default"}function eQ(e={},t={}){var a;let r,o=t.transport??eh,n=async(t,a=[],r={})=>{var n,i;let s=(n=e,i=r,{...n,...i}),l=await o({session:eY(s.session),command:t,positionals:a,flags:R({stateDir:s.stateDir,daemonBaseUrl:s.daemonBaseUrl,daemonAuthToken:s.daemonAuthToken,daemonTransport:s.daemonTransport,daemonServerMode:s.daemonServerMode,tenant:s.tenant,sessionIsolation:s.sessionIsolation,runId:s.runId,leaseId:s.leaseId,leaseBackend:s.leaseBackend,platform:s.platform,target:s.target,device:s.device,udid:s.udid,serial:s.serial,iosSimulatorDeviceSet:s.iosSimulatorDeviceSet,androidDeviceAllowlist:s.androidDeviceAllowlist,surface:s.surface,activity:s.activity,launchConsole:s.launchConsole,relaunch:s.relaunch,shutdown:s.shutdown,saveScript:s.saveScript,noRecord:s.noRecord,backMode:s.backMode,metroHost:s.metroHost,metroPort:s.metroPort,bundleUrl:s.bundleUrl,launchUrl:s.launchUrl,snapshotInteractiveOnly:s.interactiveOnly,snapshotCompact:s.compact,snapshotDepth:s.depth,snapshotScope:s.scope,snapshotRaw:s.raw,snapshotForceFull:s.forceFull,...G(s),appsFilter:s.appsFilter,out:s.out,count:s.count,fps:s.fps,quality:s.quality,hideTouches:s.hideTouches,intervalMs:s.intervalMs,delayMs:s.delayMs,holdMs:s.holdMs,jitterPx:s.jitterPx,pixels:s.pixels,doubleTap:s.doubleTap,clickButton:s.clickButton,pauseMs:s.pauseMs,pattern:s.pattern,headless:s.headless,restart:s.restart,replayUpdate:s.replayUpdate,replayBackend:s.replayBackend,replayEnv:s.replayEnv,replayShellEnv:s.replayShellEnv,failFast:s.failFast,timeoutMs:s.timeoutMs,retries:s.retries,artifactsDir:s.artifactsDir,reportJunit:s.reportJunit,findFirst:s.findFirst,findLast:s.findLast,networkInclude:s.networkInclude,batchOnError:s.batchOnError,batchMaxSteps:s.batchMaxSteps,batchSteps:s.batchSteps,verbose:s.debug}),runtime:s.runtime,meta:R({requestId:s.requestId,cwd:s.cwd,debug:s.debug,lockPolicy:s.lockPolicy,lockPlatform:s.lockPlatform,tenantId:s.tenant,runId:s.runId,leaseId:s.leaseId,leaseBackend:s.leaseBackend,leaseTtlMs:s.leaseTtlMs,sessionIsolation:s.sessionIsolation,installSource:s.installSource,retainMaterializedPaths:s.retainMaterializedPaths,materializedPathRetentionMs:s.materializedPathRetentionMs,materializationId:s.materializationId})});return l.ok||function(e){throw new p(d(e.code),e.message,{...e.details??{},hint:e.hint,diagnosticId:e.diagnosticId,logPath:e.logPath})}(l.error),l.data??{}},i=async(e={})=>{let t=await n(B.sessionList,[],e);return(Array.isArray(t.sessions)?t.sessions:[]).map(eG)},s=async(e,t=[],a={})=>await n(e,t,a),l=(t={})=>{var a,r;return eY((a=e,r=t,{...a,...r}).session)};return{command:(a=async e=>await n(e.command,e.positionals,e.options),r=async e=>await a(e),{wait:async e=>{var t;return await r((t=e,{command:P.wait,positionals:Y.encode(t),options:t}))},alert:async(e={})=>{var t;let a;return await r((a=(t=e).action??"get",{command:P.alert,positionals:[a,...void 0!==t.timeoutMs?[String(t.timeoutMs)]:[]],options:t}))},appState:async(e={})=>await r({command:P.appState,positionals:[],options:e}),back:async(e={})=>await r({command:P.back,positionals:[],options:{...e,backMode:e.mode}}),home:async(e={})=>await r({command:P.home,positionals:[],options:e}),rotate:async e=>await r({command:P.rotate,positionals:[e.orientation],options:e}),appSwitcher:async(e={})=>await r({command:P.appSwitcher,positionals:[],options:e}),keyboard:async(e={})=>await r({command:P.keyboard,positionals:e.action?[e.action]:[],options:e}),clipboard:async e=>{var t;return await r("read"===(t=e).action?{command:P.clipboard,positionals:["read"],options:t}:{command:P.clipboard,positionals:["write",t.text],options:t})},reactNative:async e=>await r({command:P.reactNative,positionals:[e.action],options:e})}),devices:{list:async(e={})=>{let t=await n(P.devices,[],e);return(Array.isArray(t.devices)?t.devices:[]).map(eV)},boot:async(e={})=>await s(P.boot,[],e)},sessions:{list:async(e={})=>await i(e),close:async(e={})=>{let t=l(e),a=(await n(P.close,[],e)).shutdown;return{session:t,shutdown:"object"==typeof a&&null!==a?a:void 0,identifiers:{session:t}}}},apps:{install:async e=>eK(await n(P.install,[e.app,e.appPath],e),l(e)),reinstall:async e=>eK(await n(P.reinstall,[e.app,e.appPath],e),l(e)),installFromSource:async e=>(function(e,t){let a=L(e,"bundleId"),r=L(e,"packageName"),o=a??r??L(e,"appId"),n=L(e,"launchTarget")??r??a??o;if(!n)throw new p("COMMAND_FAILED",'Daemon response is missing "launchTarget".',{response:e});return{appName:L(e,"appName"),appId:o,bundleId:a,packageName:r,launchTarget:n,installablePath:L(e,"installablePath"),archivePath:L(e,"archivePath"),materializationId:L(e,"materializationId"),materializationExpiresAt:L(e,"materializationExpiresAt"),identifiers:E({session:t,bundleId:a,packageName:r,appId:o})}})(await n(B.installSource,[],{...e,installSource:e.source,retainMaterializedPaths:e.retainPaths,materializedPathRetentionMs:e.retentionMs}),l(e)),list:async(e={})=>{let t=await n(P.apps,[],e);return Array.isArray(t.apps)?t.apps.filter(e=>"string"==typeof e):[]},open:async e=>{let t=l(e),a=e.app?e.url?[e.app,e.url]:[e.app]:[],r=await n(P.open,a,e),o=function(e){let t=e.platform,a=L(e,"id"),r=L(e,"device");if("ios"!==t&&"macos"!==t&&"android"!==t&&"linux"!==t||!a||!r)return;let o=K(e,"target"),n=D(t,a,r);return{platform:t,target:o,id:a,name:r,identifiers:n,ios:"ios"===t?{udid:L(e,"device_udid")??a,simulatorSetPath:H(e,"ios_simulator_device_set")}:void 0,android:"android"===t?{serial:L(e,"serial")??a}:void 0}}(r),i=L(r,"appBundleId");return{session:t,appName:L(r,"appName"),appBundleId:i,appId:i,startup:function(e){if($(e)&&"number"==typeof e.durationMs&&"string"==typeof e.measuredAt&&"string"==typeof e.method)return{durationMs:e.durationMs,measuredAt:e.measuredAt,method:e.method,appTarget:L(e,"appTarget"),appBundleId:L(e,"appBundleId")}}(r.startup),runtime:function(e){if(!$(e))return;let t=e.platform,a=L(e,"metroHost"),r="number"==typeof e.metroPort?e.metroPort:void 0;return{platform:"ios"===t||"android"===t?t:void 0,metroHost:a,metroPort:r,bundleUrl:L(e,"bundleUrl"),launchUrl:L(e,"launchUrl")}}(r.runtime),device:o,identifiers:{session:t,deviceId:o?.id,deviceName:o?.name,udid:o?.ios?.udid,serial:o?.android?.serial,appId:i,appBundleId:i}}},close:async(e={})=>{let t=l(e),a=(await n(P.close,e.app?[e.app]:[],e)).shutdown;return{session:t,closedApp:e.app,shutdown:"object"==typeof a&&null!==a?a:void 0,identifiers:{session:t}}},push:async e=>{var t;return await s(P.push,[e.app,"string"==typeof(t=e.payload)?t:JSON.stringify(t)],e)},triggerEvent:async e=>{var t;return await s(P.triggerAppEvent,[(t=e).event,...t.payload?[JSON.stringify(t.payload)]:[]],e)}},materializations:{release:async e=>{var t;return{released:!0===(t=await n(B.releaseMaterializedPaths,[],{...e,materializationId:e.materializationId})).released,materializationId:j(t,"materializationId"),identifiers:{}}}},leases:{allocate:async e=>e2(await n(B.leaseAllocate,[],{...e,leaseId:void 0,leaseTtlMs:e.ttlMs})),heartbeat:async e=>e2(await n(B.leaseHeartbeat,[],{...e,leaseTtlMs:e.ttlMs})),release:async e=>({released:!0===(await n(B.leaseRelease,[],e)).released})},metro:{prepare:async t=>await ee({projectRoot:t.projectRoot??e.cwd,kind:t.kind,publicBaseUrl:t.publicBaseUrl,proxyBaseUrl:t.proxyBaseUrl,proxyBearerToken:t.bearerToken,bridgeScope:t.bridgeScope,launchUrl:t.launchUrl,companionProfileKey:t.companionProfileKey,companionConsumerKey:t.companionConsumerKey,metroPort:t.port,listenHost:t.listenHost,statusHost:t.statusHost,startupTimeoutMs:t.startupTimeoutMs,probeTimeoutMs:t.probeTimeoutMs,reuseExisting:t.reuseExisting,installDependenciesIfNeeded:t.installDependenciesIfNeeded,runtimeFilePath:t.runtimeFilePath,logPath:t.logPath}),reload:async(t={})=>await Z({metroHost:t.metroHost,metroPort:t.metroPort,bundleUrl:t.bundleUrl,runtime:e.runtime,timeoutMs:t.timeoutMs})},capture:{snapshot:async(e={})=>{var t,a,r,o;let i,s,c,d,p,u=l(e);return t=await n(P.snapshot,[],e),a=u,i=L(t,"appBundleId"),{nodes:Array.isArray(r=t.nodes)?r:[],truncated:!0===t.truncated,appName:L(t,"appName"),appBundleId:i,...(s=eX((o=t).visibility),c=eX(o.androidSnapshot),d=eX(o.unchanged),p=Array.isArray(o.warnings)?o.warnings.filter(e=>"string"==typeof e):void 0,{...s?{visibility:s}:{},...c?{androidSnapshot:c}:{},...d?{unchanged:d}:{},...p?{warnings:p}:{}}),identifiers:{session:a,appId:i,appBundleId:i}}},screenshot:async(e={})=>{let t=l(e),a=await n(P.screenshot,e.path?[e.path]:[],{...e,...G(e)});return{path:j(a,"path"),overlayRefs:function(e){let t=e.overlayRefs;if(!Array.isArray(t))return;let a=[];for(let e of t){if(!$(e))continue;let t=L(e,"ref"),r=A(e,"rect"),o=A(e,"overlayRect"),n=C(e,"center");t&&r&&o&&n&&a.push({ref:t,label:L(e,"label"),rect:r,overlayRect:o,center:n})}return a}(a),identifiers:{session:t}}},diff:async e=>await s(P.diff,[e.kind],{...e,interactiveOnly:e.interactiveOnly,compact:e.compact,depth:e.depth,scope:e.scope,raw:e.raw})},interactions:{click:async e=>await s(P.click,Q.encode(e),{...e,clickButton:e.button}),press:async e=>await s(P.press,Q.encode(e),e),longPress:async e=>await s(P.longPress,M.encode(e),e),swipe:async e=>await s(P.swipe,[String(e.from.x),String(e.from.y),String(e.to.x),String(e.to.y),...e0(e.durationMs)],e),focus:async e=>await s(P.focus,[String(e.x),String(e.y)],e),type:async e=>await s(P.type,z.encode(e),e),fill:async e=>await s(P.fill,q.encode(e),e),scroll:async e=>await s(P.scroll,[e.direction,...e0(e.amount)],e),pinch:async e=>await s(P.pinch,[String(e.scale),...e0(e.x),...e0(e.y)],e),get:async e=>await s(P.get,[e.format,...S.encode(e)],e),is:async e=>await s(P.is,V.encode(e),e),find:async e=>await s(P.find,F.encode(e),{...e,findFirst:e.first,findLast:e.last})},replay:{run:async e=>await s(P.replay,[e.path],{...e,replayUpdate:e.update,replayBackend:e.backend??(!0===e.maestro?"maestro":void 0),replayEnv:e.env,replayShellEnv:e1(process.env)}),test:async e=>await s(P.test,e.paths,{...e,replayUpdate:e.update,replayEnv:e.env,replayShellEnv:e1(process.env)})},batch:{run:async e=>await s(P.batch,[],{...e,batchSteps:e.steps,batchOnError:e.onError,batchMaxSteps:e.maxSteps})},observability:{perf:async(e={})=>await s(P.perf,[],e),logs:async(e={})=>{var t;return await s(P.logs,[(t=e).action??"path",...eZ(t.message)],e)},network:async(e={})=>{var t;return await s(P.network,[...(t=e).action?[t.action]:[],...e0(t.limit)],{...e,networkInclude:e.include})}},recording:{record:async e=>await s(P.record,[e.action,...eZ(e.path)],e),trace:async e=>await s(P.trace,[e.action,...eZ(e.path)],e)},settings:{update:async e=>await s(P.settings,k.encode(e),e)}}}function eX(e){return"object"==typeof e&&null!==e?e:void 0}function eZ(e){return void 0===e?[]:[e]}function e0(e){return void 0===e?[]:[String(e)]}function e1(e){let t={};for(let[a,r]of Object.entries(e))"string"==typeof r&&a.startsWith("AD_VAR_")&&(t[a]=r);return t}function e2(e){let t=e.lease;if(!t||"object"!=typeof t||Array.isArray(t))throw Error("Invalid lease response from daemon");return{leaseId:j(t,"leaseId"),tenantId:j(t,"tenantId"),runId:j(t,"runId"),backend:j(t,"backend"),createdAt:"number"==typeof t.createdAt?t.createdAt:void 0,heartbeatAt:"number"==typeof t.heartbeatAt?t.heartbeatAt:void 0,expiresAt:"number"==typeof t.expiresAt?t.expiresAt:void 0}}export{eQ as createAgentDeviceClient,eh as sendToDaemon};
|
|
1
|
+
import e from"node:net";import t from"node:http";import a from"node:https";import r from"node:fs";import o from"node:os";import n from"node:path";import{pipeline as i}from"node:stream/promises";import{createHash as s,randomUUID as l}from"node:crypto";import{Writable as c}from"node:stream";import{toAppErrorCode as d,AppError as u}from"./9152.js";import{runCmdSync as p,runCmd as m,runCmdDetached as f}from"./9818.js";import{normalizeSession as h,readRequiredString as y,PUBLIC_COMMANDS as w,normalizeMaterializationReleaseResult as g,readVersion as I,readSnapshotNodes as v,findProjectRoot as A,computeDaemonCodeSignature as k,resolveDaemonTransportPreference as b,prepareDaemonCommandRequest as P,normalizeDeployResult as _,normalizeOpenDevice as S,buildMeta as D,resolveSessionName as E,buildFlags as T,readOptionalString as M,resolveDaemonPaths as N,INTERNAL_COMMANDS as C,resolveDaemonServerMode as L,normalizeRuntimeHints as U,normalizeDevice as R,readScreenshotOverlayRefs as O,normalizeStartupSample as x,normalizeInstallFromSourceResult as F}from"./2099.js";import{createRequestId as B,withDiagnosticTimer as q,emitDiagnostic as $}from"./3622.js";import{isAgentDeviceDaemonProcess as j,stopProcessForTakeover as H}from"./8656.js";import{sleep as K}from"./4829.js";import{reloadMetro as z,prepareMetroRuntime as G}from"./1974.js";function V(e){return new Promise((t,a)=>{let r="";e.setEncoding("utf8"),e.on("data",e=>{r+=e}),e.on("end",()=>t(r)),e.on("error",a)})}let W="sha256";async function J(e){let t=await Y(e.localPath,e.platform),a=e.baseUrl.endsWith("/")?e.baseUrl:`${e.baseUrl}/`;try{let r=await ee({normalizedBase:a,token:e.token,artifact:t});if(r?.kind==="cache-hit")return r.uploadId;if(r?.kind==="direct-upload")try{return await et(t.payloadPath,r),await er({normalizedBase:a,token:e.token,uploadId:r.uploadId})}catch{}return await Z({normalizedBase:a,token:e.token,artifact:t})}finally{t.cleanup()}}async function Y(e,t){var a,o,i;let s,l=r.statSync(e),c=n.basename(e),d=l.isDirectory(),u=("ios"===(a=t)||"android"===a?a:void 0)??(o=e,i=l,s=o.toLowerCase(),i.isDirectory()&&s.endsWith(".app")||s.endsWith(".ipa")?"ios":s.endsWith(".apk")||s.endsWith(".aab")?"android":void 0),p=[];try{let t=d?await Q(e,p):e,a=r.statSync(t);return{payloadPath:t,fileName:c,artifactType:d?"app-bundle":"file",platform:u,contentType:d?"application/gzip":"application/octet-stream",sha256:await eo(t),sizeBytes:a.size,cleanup:()=>X(p)}}catch(e){throw X(p),e}}async function Q(e,t){let a=r.mkdtempSync(n.join(o.tmpdir(),`agent-device-upload-${l()}-`));t.push(a);let i=n.join(a,`${n.basename(e)}.tar.gz`);return await m("tar",["czf",i,"-C",n.dirname(e),n.basename(e)],{env:{...process.env,COPYFILE_DISABLE:"1"}}),i}function X(e){for(let t of e)r.rmSync(t,{recursive:!0,force:!0})}async function Z(e){let{normalizedBase:t,token:a,artifact:r}=e,o=new URL("upload",t),n={"content-type":r.contentType,"x-artifact-type":r.artifactType,"x-artifact-filename":r.fileName,"x-artifact-hash":r.sha256,"x-artifact-hash-algorithm":W,"transfer-encoding":"chunked"};a&&(n.authorization=`Bearer ${a}`,n["x-agent-device-token"]=a);let i=await ea({url:o,method:"POST",headers:n,payloadPath:r.payloadPath,timeoutMessage:"Artifact upload timed out",timeoutHint:"The upload to the remote daemon exceeded the 5-minute timeout.",errorMessage:"Failed to upload artifact to remote daemon",errorHint:"Verify the remote daemon is reachable and supports artifact uploads."});try{let e=JSON.parse(i.body);if(!e.ok||!e.uploadId)throw new u("COMMAND_FAILED",`Upload failed: ${i.body}`);return e.uploadId}catch(e){if(e instanceof u)throw e;throw new u("COMMAND_FAILED",`Invalid upload response: ${i.body}`)}}async function ee(e){let t=new URL("upload/preflight",e.normalizedBase),a={"content-type":"application/json"};e.token&&(a.authorization=`Bearer ${e.token}`,a["x-agent-device-token"]=e.token);let r=await fetch(t,{method:"POST",headers:a,signal:AbortSignal.timeout(3e4),body:JSON.stringify({sha256:e.artifact.sha256,fileName:e.artifact.fileName,sizeBytes:e.artifact.sizeBytes,artifactType:e.artifact.artifactType,...e.artifact.platform?{platform:e.artifact.platform}:{},contentType:e.artifact.contentType})}).catch(()=>void 0);if(r?.ok)return function(e){var t;if(!e||"object"!=typeof e||!0!==e.ok||"string"!=typeof e.uploadId)return;if(!0===e.cacheHit)return{kind:"cache-hit",uploadId:e.uploadId};let a=e.upload;if(!a||"string"!=typeof a.url)return;let r=a.headers??{};if(!(!(t=r)||"object"!=typeof t||Array.isArray(t))&&Object.values(t).every(e=>"string"==typeof e))return{kind:"direct-upload",uploadId:e.uploadId,url:a.url,headers:r}}(await r.json().catch(()=>void 0))}async function et(e,t){let a=await ea({url:new URL(t.url),method:"PUT",headers:t.headers,payloadPath:e,timeoutMessage:"Direct artifact upload timed out",timeoutHint:"The direct upload ticket did not accept the artifact within the timeout.",errorMessage:"Failed to upload artifact with direct upload ticket"});if(a.statusCode<200||a.statusCode>=300)throw new u("COMMAND_FAILED","Direct artifact upload failed",{statusCode:a.statusCode,statusMessage:a.statusMessage})}async function ea(e){let o="https:"===e.url.protocol?a:t;return await new Promise((t,a)=>{let n=o.request({protocol:e.url.protocol,host:e.url.hostname,port:e.url.port,method:e.method,path:e.url.pathname+e.url.search,headers:e.headers},e=>{V(e).then(a=>{clearTimeout(s),t({statusCode:e.statusCode??500,statusMessage:e.statusMessage,body:a})}).catch(a)}),s=setTimeout(()=>{n.destroy(),a(new u("COMMAND_FAILED",e.timeoutMessage,{timeoutMs:3e5,...e.timeoutHint?{hint:e.timeoutHint}:{}}))},3e5);n.on("error",t=>{clearTimeout(s),a(new u("COMMAND_FAILED",e.errorMessage,e.errorHint?{hint:e.errorHint}:{},t))}),n.on("close",()=>clearTimeout(s)),i(r.createReadStream(e.payloadPath),n).catch(e=>{n.destroy(),a(new u("COMMAND_FAILED","Failed to read local artifact",{},e instanceof Error?e:Error(String(e))))})})}async function er(e){let t=new URL("upload/finalize",e.normalizedBase),a={"content-type":"application/json"};e.token&&(a.authorization=`Bearer ${e.token}`,a["x-agent-device-token"]=e.token);let r=await fetch(t,{method:"POST",headers:a,signal:AbortSignal.timeout(3e4),body:JSON.stringify({uploadId:e.uploadId})}).catch(e=>{throw new u("COMMAND_FAILED","Failed to finalize direct artifact upload",{},e)});if(!r.ok)throw new u("COMMAND_FAILED","Direct artifact upload finalize failed",{status:r.status,statusText:r.statusText});let o=await r.json().catch(()=>void 0);if(!o?.ok||!o.uploadId)throw new u("COMMAND_FAILED","Invalid upload finalize response");return o.uploadId}async function eo(e){let t=s(W),a=new c({write(e,a,r){t.update(e),r()}});return await i(r.createReadStream(e),a).catch(e=>{throw new u("COMMAND_FAILED","Failed to read local artifact",{},e instanceof Error?e:void 0)}),t.digest("hex")}let en=["xcodebuild .*AgentDeviceRunnerUITests/RunnerTests/testCommand","xcodebuild .*AgentDeviceRunner\\.env\\.session-","xcodebuild build-for-testing .*ios-runner/AgentDeviceRunner/AgentDeviceRunner\\.xcodeproj"],ei=new e.BlockList;async function es(t){let a=t.meta?.requestId??B(),i=!!(t.meta?.debug||t.flags?.verbose),s=function(t){let a,i=t.flags?.stateDir??process.env.AGENT_DEVICE_STATE_DIR,s=t.flags?.daemonBaseUrl??process.env.AGENT_DEVICE_DAEMON_BASE_URL,l=eg(t.command)&&!i&&!s,c=function(e){let t;if(e){try{t=new URL(e)}catch(t){throw new u("INVALID_ARGS","Invalid daemon base URL",{daemonBaseUrl:e},t instanceof Error?t:void 0)}if("http:"!==t.protocol&&"https:"!==t.protocol)throw new u("INVALID_ARGS","Daemon base URL must use http or https",{daemonBaseUrl:e});return t.toString().replace(/\/+$/,"")}}(s),d=t.flags?.daemonAuthToken??process.env.AGENT_DEVICE_DAEMON_AUTH_TOKEN;var p=c,m=d;if(!(!p||"localhost"===(a=new URL(p).hostname.trim().toLowerCase().replace(/^\[(.*)\]$/,"$1"))||(e.isIPv4(a)?ei.check(a,"ipv4"):!!e.isIPv6(a)&&ei.check(a,"ipv6")))&&("string"!=typeof m||!(m.trim().length>0)))throw new u("INVALID_ARGS","Remote daemon base URL for non-loopback hosts requires daemon authentication",{daemonBaseUrl:p,hint:"Provide --daemon-auth-token or AGENT_DEVICE_DAEMON_AUTH_TOKEN when using a non-loopback remote daemon URL."});let f=t.flags?.daemonTransport??process.env.AGENT_DEVICE_DAEMON_TRANSPORT,h=b(f);if(c&&"socket"===h)throw new u("INVALID_ARGS","Remote daemon base URL only supports HTTP transport. Remove --daemon-transport socket.",{daemonBaseUrl:c});let y=L(t.flags?.daemonServerMode??process.env.AGENT_DEVICE_DAEMON_SERVER_MODE??("dual"===f?"dual":void 0));return{paths:N(l?r.mkdtempSync(n.join(o.tmpdir(),"agent-device-replay-daemon-")):i),transportPreference:h,serverMode:y,ownedStateDir:l,remoteBaseUrl:c,remoteAuthToken:d}}(t),l=function(e){if(e.command!==w.test)return e.command===w.replay&&"number"==typeof e.flags?.timeoutMs?e.flags.timeoutMs:9e4}(t),c=await q("daemon_startup",async()=>await em(s),{requestId:a,session:t.session}),d=c.info,p=await el(t,d),m={...t,positionals:p.positionals,flags:p.flags,token:d.token,meta:{...t.meta??{},requestId:a,debug:i,cwd:t.meta?.cwd,tenantId:t.meta?.tenantId??t.flags?.tenant,runId:t.meta?.runId??t.flags?.runId,leaseId:t.meta?.leaseId??t.flags?.leaseId,sessionIsolation:t.meta?.sessionIsolation??t.flags?.sessionIsolation,lockPolicy:t.meta?.lockPolicy,lockPlatform:t.meta?.lockPlatform,...p.uploadedArtifactId?{uploadedArtifactId:p.uploadedArtifactId}:{},...p.clientArtifactPaths?{clientArtifactPaths:p.clientArtifactPaths}:{},...p.installSource?{installSource:p.installSource}:{}}};$({level:"info",phase:"daemon_request_prepare",data:{requestId:a,command:t.command,session:t.session}});try{return await q("daemon_request",async()=>await eL(d,m,s.transportPreference,l),{requestId:a,command:t.command})}finally{await ew(t,c,s)}}async function el(e,t){var a,o;let i,s,l=[...e.positionals??[]],c=e.flags?{...e.flags}:void 0,d=e.meta?.installSource,u={};if(e$(t)){c=function(e,t,a,r){var o,i;let s=function(e,t){if("screenshot"===e.command){let a=eu(e,"path",".png");return t[0]?{field:"path",localPath:a,positionalIndex:0,positionalPath:ep("screenshot",".png")}:{field:"path",localPath:a,positionalIndex:0,flagPath:ep("screenshot",".png")}}if("record"===e.command&&"start"===(t[0]??"").toLowerCase()){let t=eu(e,"outPath",".mp4",1);return{field:"outPath",localPath:t,positionalIndex:1,positionalPath:ep("recording",n.extname(t)||".mp4")}}return null}(e,t);if(!s)return a;void 0!==s.positionalPath&&(t[s.positionalIndex]=s.positionalPath);let l=(o=a,void 0===(i=s.flagPath)?o:{...o??{},out:i});return r[s.field]=s.localPath,l}(e,l,c,u);let a=await ed(e,t);a&&(d=a.installSource,s=a.uploadedArtifactId??s)}let p=()=>ec({positionals:l,flags:c,installSource:d,uploadedArtifactId:s,clientArtifactPaths:u});if(!e$(t)||"install"!==e.command&&"reinstall"!==e.command)return p();let m=l[1];if(void 0===m)return p();if(m.startsWith("remote:"))return l[1]=m.slice(7),ec({positionals:l,flags:c,clientArtifactPaths:u});let f=(a=m,o=e.meta?.cwd,i=n.isAbsolute(a)?a:n.resolve(o??process.cwd(),a),r.existsSync(i)?i:void 0);return f?(s=await J({localPath:f,baseUrl:t.baseUrl,token:t.token,platform:e.flags?.platform}),p()):ec({positionals:l,flags:c,clientArtifactPaths:u})}function ec(e){return{positionals:e.positionals,flags:e.flags,installSource:e.installSource,uploadedArtifactId:e.uploadedArtifactId,...Object.keys(e.clientArtifactPaths).length>0?{clientArtifactPaths:e.clientArtifactPaths}:{}}}async function ed(e,t){let a=e.meta?.installSource;if("install_source"!==e.command||!a||"path"!==a.kind)return null;let o=a.path.trim();if(!o)return{installSource:a};if(o.startsWith("remote:"))return{installSource:{...a,path:o.slice(7)}};let i=n.isAbsolute(o)?o:n.resolve(e.meta?.cwd??process.cwd(),o);if(!r.existsSync(i))return{installSource:{...a,path:i}};let s=await J({localPath:i,baseUrl:t.baseUrl,token:t.token,platform:e.flags?.platform});return{installSource:{...a,path:i},uploadedArtifactId:s}}function eu(e,t,a,r=0){let o=e.positionals?.[r]??e.flags?.out,i=`${"path"===t?"screenshot":"recording"}-${Date.now()}${a}`,s=o&&o.trim().length>0?o:i;return n.isAbsolute(s)?s:n.resolve(e.meta?.cwd??process.cwd(),s)}function ep(e,t){let a=t.startsWith(".")?t:`.${t}`;return n.posix.join("/tmp",`agent-device-${e}-${Date.now()}-${Math.random().toString(36).slice(2,8)}${a}`)}async function em(e){if(e.remoteBaseUrl)return await ef(e);let t=await eh(e);return t?{info:t,startedByClient:!1}:(function(e){let t=eD(e);if(!t.hasLock||t.hasInfo)return;let a=e_(e.lockPath);if(!a)return eT(e.lockPath);j(a.pid,a.processStartTime)||eT(e.lockPath)}(e.paths),await ey(e))}async function ef(e){let t={transport:"http",token:e.remoteAuthToken??"",pid:0,baseUrl:e.remoteBaseUrl};if(await eM(t,"http"))return{info:t,startedByClient:!1};throw new u("COMMAND_FAILED","Remote daemon is unavailable",{daemonBaseUrl:e.remoteBaseUrl,hint:"Verify AGENT_DEVICE_DAEMON_BASE_URL points to a reachable daemon with GET /health and POST /rpc."})}async function eh(e){var t,a;let r,o=ek(e.paths.infoPath);if(!o)return null;let n=await eM(o,e.transportPreference);return(t=o,a=n,t.version===I()&&t.codeSignature===k((r=eC()).useSrc?r.srcPath:r.distPath,r.root)&&a)?o:(await eA(o),eT(e.paths.infoPath),null)}async function ey(e){let t,a=0,r=[];for(let o=1;o<=2;o+=1){try{await eN(e)}catch(a){if(t=a instanceof Error?a.message:String(a),r.push(await eS(e.paths,"start_error")),o<2){await K(150);continue}break}let n=await eI(15e3,e);if(n)return{info:n,startedByClient:!0};if(await ev(e.paths)){a+=1;continue}let i=eD(e.paths),s=o<2,l=await eS(e.paths,"startup_timeout",{stopLiveProcesses:!1});if(r.push(l),l.retainedInfoProcess||l.retainedLockProcess){let t=await eI(15e3,e);if(t)return{info:t,startedByClient:!0};break}if(!s)break;i.hasInfo||i.hasLock||await K(150)}let o=eD(e.paths);throw new u("COMMAND_FAILED","Failed to start daemon",{kind:"daemon_startup_failed",infoPath:e.paths.infoPath,lockPath:e.paths.lockPath,startupTimeoutMs:15e3,startupAttempts:2,lockRecoveryCount:a,cleanupResults:r,startError:t,metadataState:o,hint:function(e,t=N(process.env.AGENT_DEVICE_STATE_DIR)){return e.hasLock&&!e.hasInfo?`agent-device attempted to clean stale daemon metadata automatically, but ${t.lockPath} still exists without ${t.infoPath}. Retry with --debug; if this persists, remove ${t.lockPath} after confirming no agent-device daemon process is running.`:e.hasLock&&e.hasInfo?`agent-device attempted to clean stale daemon metadata automatically, but ${t.infoPath} and ${t.lockPath} still remain. Retry with --debug; if this persists, remove both files after confirming no agent-device daemon process is running.`:"agent-device did not observe reachable daemon metadata after retrying. Stale metadata was cleaned automatically when safe; retry with --debug and check daemon diagnostics logs."}(o,e.paths)})}async function ew(e,t,a){if(!eg(e.command)||!t.startedByClient&&!a.ownedStateDir||e$(t.info))return;let o={pid:t.info.pid,removedInfo:!1,removedLock:!1,removedStateDir:!1,error:void 0};try{await eA(t.info)}catch(e){o.error=e instanceof Error?e.message:String(e)}finally{let e=r.existsSync(a.paths.infoPath);eT(a.paths.infoPath),o.removedInfo=e&&!r.existsSync(a.paths.infoPath);let t=r.existsSync(a.paths.lockPath);eT(a.paths.lockPath),o.removedLock=t&&!r.existsSync(a.paths.lockPath),a.ownedStateDir&&(r.rmSync(a.paths.baseDir,{recursive:!0,force:!0}),o.removedStateDir=!r.existsSync(a.paths.baseDir))}$({level:o.error?"warn":"info",phase:"daemon_replay_cleanup",data:o})}function eg(e){return e===w.replay||e===w.test}async function eI(e,t){let a=Date.now();for(;Date.now()-a<e;){let e=ek(t.paths.infoPath);if(e&&await eM(e,t.transportPreference))return e;await K(100)}return null}async function ev(e){let t=eD(e);if(!t.hasLock||t.hasInfo)return!1;let a=e_(e.lockPath);return!(a&&j(a.pid,a.processStartTime))&&(eT(e.lockPath),!0)}async function eA(e){await H(e.pid,{termTimeoutMs:3e3,killTimeoutMs:1e3,expectedStartTime:e.processStartTime})}function ek(e){var t,a,r;let o,n,i=eE(e);if(!i||"object"!=typeof i)return null;let s="string"==typeof(t=i).token&&t.token.length>0?t.token:null;if(!s)return null;let l=(o=eP((a=i).port),n=eP(a.httpPort),void 0===o&&void 0===n?null:{port:o,httpPort:n});return l?{token:s,...l,transport:"socket"===(r=i.transport)||"http"===r||"dual"===r?r:void 0,pid:eP(i.pid)??0,version:eb(i.version),codeSignature:eb(i.codeSignature),processStartTime:eb(i.processStartTime)}:null}function eb(e){return"string"==typeof e?e:void 0}function eP(e){return Number.isInteger(e)&&Number(e)>0?Number(e):void 0}function e_(e){let t=eE(e);return t&&"object"==typeof t&&Number.isInteger(t.pid)&&Number(t.pid)>0?{pid:Number(t.pid),processStartTime:"string"==typeof t.processStartTime?t.processStartTime:void 0,startedAt:"number"==typeof t.startedAt?t.startedAt:void 0}:null}ei.addSubnet("127.0.0.0",8,"ipv4"),ei.addAddress("::1","ipv6"),ei.addSubnet("::ffff:127.0.0.0",104,"ipv6");async function eS(e,t,a={}){let o=a.stopLiveProcesses??!0,n={reason:t,removedInfo:!1,removedLock:!1,stoppedInfoProcess:!1,stoppedLockProcess:!1};try{var i,s,l,c;let t=r.existsSync(e.infoPath),a=ek(e.infoPath);if(a){let t=j(a.pid,a.processStartTime);t&&!o?n.retainedInfoProcess=!0:(t&&(await eA(a),n.stoppedInfoProcess=!0),i=e.infoPath,eT(i),n.removedInfo=!0)}else t&&(s=e.infoPath,eT(s),n.removedInfo=!0);let d=r.existsSync(e.lockPath),u=e_(e.lockPath);if(u){let t=j(u.pid,u.processStartTime);t&&!o?n.retainedLockProcess=!0:(t&&(await H(u.pid,{termTimeoutMs:3e3,killTimeoutMs:1e3,expectedStartTime:u.processStartTime}),n.stoppedLockProcess=!0),l=e.lockPath,eT(l),n.removedLock=!0)}else d&&(c=e.lockPath,eT(c),n.removedLock=!0)}catch(e){n.error=e instanceof Error?e.message:String(e)}return $({level:n.error?"warn":"info",phase:"daemon_startup_metadata_cleanup",data:n}),n}function eD(e){return{hasInfo:r.existsSync(e.infoPath),hasLock:r.existsSync(e.lockPath)}}function eE(e){if(!r.existsSync(e))return null;try{return JSON.parse(r.readFileSync(e,"utf8"))}catch{return null}}function eT(e){try{r.existsSync(e)&&r.unlinkSync(e)}catch{}}async function eM(r,o){var n;return"http"===eU(r,o)?await function(e){let r=e.baseUrl?ej(e.baseUrl,"health"):e.httpPort?`http://127.0.0.1:${e.httpPort}/health`:null;if(!r)return Promise.resolve(!1);let o=new URL(r),n="https:"===o.protocol?a:t,i=e.baseUrl?3e3:500;return new Promise(e=>{let t=n.request({protocol:o.protocol,host:o.hostname,port:o.port,path:o.pathname+o.search,method:"GET",timeout:i},t=>{t.resume(),e((t.statusCode??500)<500)});t.on("timeout",()=>{t.destroy(),e(!1)}),t.on("error",()=>{e(!1)}),t.end()})}(r):await ((n=r.port)?new Promise(t=>{let a=!1,r=e.createConnection({host:"127.0.0.1",port:n},()=>{o(!0)}),o=e=>{a||(a=!0,r.destroy(),t(e))};r.setTimeout(500),r.on("timeout",()=>{o(!1)}),r.on("error",()=>{o(!1)})}):Promise.resolve(!1))}async function eN(e){let t=eC(),a=t.useSrc?["--experimental-strip-types",t.srcPath]:[t.distPath],r={...process.env,AGENT_DEVICE_STATE_DIR:e.paths.baseDir,AGENT_DEVICE_DAEMON_SERVER_MODE:e.serverMode};f(process.execPath,a,{env:r})}function eC(){let e=A(),t=[n.join(e,"dist","src","internal","daemon.js"),n.join(e,"dist","src","daemon.js")],a=t[0];if(void 0===a)throw new u("COMMAND_FAILED","Daemon dist path list is empty");let o=t.find(e=>r.existsSync(e))??a,i=n.join(e,"src","daemon.ts"),s=t.some(e=>r.existsSync(e)),l=r.existsSync(i);if(!s&&!l)throw new u("COMMAND_FAILED","Daemon entry not found",{distPaths:t,srcPath:i});return{root:e,distPath:o,distPaths:t,srcPath:i,useSrc:process.execArgv.includes("--experimental-strip-types")?l:!s&&l}}async function eL(e,t,a,r){return"http"===eU(e,a)?await eB(e,t,r):await eF(e,t,r)}function eU(e,t){if(e.baseUrl){if("socket"===t)throw new u("COMMAND_FAILED","Remote daemon endpoint only supports HTTP transport",{daemonBaseUrl:e.baseUrl});return"http"}if("http"===t||"socket"===t){var a=e,r=t;if(eR(a,r))return r;throw new u("COMMAND_FAILED","http"===r?"Daemon HTTP endpoint is unavailable":"Daemon socket endpoint is unavailable")}let o=("socket"===e.transport||"dual"===e.transport?["socket","http"]:["http","socket"]).find(t=>eR(e,t));if(o)return o;throw new u("COMMAND_FAILED","Daemon metadata has no reachable transport")}function eR(e,t){return"http"===t?!!e.httpPort:!!e.port}function eO(e,t,a,r,o,n){let i=o?{terminated:0}:function(){let e=0;try{for(let t of en){let a=p("pkill",["-f",t],{allowFailure:!0});0===a.exitCode&&(e+=1)}return{terminated:e}}catch(t){return{terminated:e,error:t instanceof Error?t.message:String(t)}}}(),s=!o&&"snapshot"!==r,l=s?function(e,t){let a=!1;try{j(e.pid,e.processStartTime)&&(process.kill(e.pid,"SIGKILL"),a=!0)}catch{H(e.pid,{termTimeoutMs:3e3,killTimeoutMs:1e3,expectedStartTime:e.processStartTime})}finally{eT(t.infoPath),eT(t.lockPath)}return{forcedKill:a}}(e,t):{forcedKill:!1};return $({level:"error",phase:"daemon_request_timeout",data:{timeoutMs:n,requestId:a,command:r,timedOutRunnerPidsTerminated:i.terminated,timedOutRunnerCleanupError:i.error,daemonPidReset:s?e.pid:void 0,daemonPidForceKilled:s?l.forcedKill:void 0,daemonPreservedAfterTimeout:!o&&!s,daemonBaseUrl:e.baseUrl}}),new u("COMMAND_FAILED","Daemon request timed out",{timeoutMs:n,requestId:a,hint:function(e){let{remote:t,resetDaemon:a,command:r}=e;return t?"Retry with --debug and verify the remote daemon URL, auth token, and remote host logs.":a?"Retry with --debug and check daemon diagnostics logs. Timed-out iOS runner xcodebuild processes were terminated when detected.":`Retry with --debug and check daemon diagnostics logs. The timed-out ${r??"request"} request was canceled and iOS runner work was aborted when detected; the daemon was kept alive so the session can still be closed or inspected.`}({remote:o,resetDaemon:s,command:r})})}function ex(e,t,a){return $({level:"error",phase:"daemon_request_socket_error",data:{requestId:t,message:e instanceof Error?e.message:String(e)}}),new u("COMMAND_FAILED","Failed to communicate with daemon",{requestId:t,hint:a?"Retry command. If this persists, verify the remote daemon URL, auth token, and remote host reachability.":"Retry command. If this persists, clean stale daemon metadata and start a fresh session."},e instanceof Error?e:void 0)}async function eF(t,a,r){let o=t.port;if(!o)throw new u("COMMAND_FAILED","Daemon socket endpoint is unavailable");return new Promise((n,i)=>{let s=e.createConnection({host:"127.0.0.1",port:o},()=>{s.write(`${JSON.stringify(a)}
|
|
2
|
+
`)}),l=N(a.flags?.stateDir??process.env.AGENT_DEVICE_STATE_DIR),c="number"==typeof r?setTimeout(()=>{s.destroy(),i(eO(t,l,a.meta?.requestId,a.command,!1,r))},r):void 0,d="";s.setEncoding("utf8"),s.on("data",e=>{let t=(d+=e).indexOf("\n");if(-1===t)return;let r=d.slice(0,t).trim();if(r)try{let e=JSON.parse(r);s.end(),c&&clearTimeout(c),n(e)}catch(e){c&&clearTimeout(c),i(new u("COMMAND_FAILED","Invalid daemon response",{requestId:a.meta?.requestId,line:r},e instanceof Error?e:void 0))}}),s.on("error",e=>{c&&clearTimeout(c),i(ex(e,a.meta?.requestId,!1))})})}async function eB(e,r,o){var n,i,s;let l,c=e.baseUrl?new URL(ej(e.baseUrl,"rpc")):e.httpPort?new URL(`http://127.0.0.1:${e.httpPort}/rpc`):null;if(!c)throw new u("COMMAND_FAILED","Daemon HTTP endpoint is unavailable");let p=JSON.stringify((n=r,i={includeTokenParam:!e.baseUrl},l=n.meta?.requestId??B(),"lease_allocate"!==(s=n.command)&&"lease_heartbeat"!==s&&"lease_release"!==s?{jsonrpc:"2.0",id:l,method:"agent_device.command",params:n}:{jsonrpc:"2.0",id:l,method:function(e){switch(e){case"lease_allocate":return"agent_device.lease.allocate";case"lease_heartbeat":return"agent_device.lease.heartbeat";case"lease_release":return"agent_device.lease.release"}}(n.command),params:function(e,t,a){let r={...a.includeTokenParam?{token:e.token}:{},session:e.session,tenantId:e.meta?.tenantId,runId:e.meta?.runId};switch(t){case"lease_allocate":return{...r,ttlMs:e.meta?.leaseTtlMs,backend:e.meta?.leaseBackend};case"lease_heartbeat":return{...r,leaseId:e.meta?.leaseId,ttlMs:e.meta?.leaseTtlMs};case"lease_release":return{...r,leaseId:e.meta?.leaseId}}}(n,n.command,i)})),m={"content-type":"application/json","content-length":Buffer.byteLength(p)};return e.baseUrl&&e.token&&(m.authorization=`Bearer ${e.token}`,m["x-agent-device-token"]=e.token),await new Promise((n,i)=>{let s=N(r.flags?.stateDir??process.env.AGENT_DEVICE_STATE_DIR),l=("https:"===c.protocol?a:t).request({protocol:c.protocol,host:c.hostname,port:c.port,method:"POST",path:c.pathname+c.search,headers:m},t=>{V(t).then(t=>{h&&clearTimeout(h),function(e,t){let{info:a,req:r,resolve:o,reject:n}=t;try{var i,s,l;let t=(i=e,JSON.parse(i));if(t.error){let e;return void n((s=t.error,l=r.meta?.requestId,e=s.data??{},new u(d(null!=e.code?String(e.code):void 0,"COMMAND_FAILED"),String(e.message??s.message??"Daemon RPC request failed"),{..."object"==typeof e.details&&e.details?e.details:{},hint:"string"==typeof e.hint?e.hint:void 0,diagnosticId:"string"==typeof e.diagnosticId?e.diagnosticId:void 0,logPath:"string"==typeof e.logPath?e.logPath:void 0,requestId:l})))}if(!t.result||"object"!=typeof t.result)return void n(new u("COMMAND_FAILED","Invalid daemon RPC response",{requestId:r.meta?.requestId}));eq(a,r,t.result,o,n)}catch(t){n(new u("COMMAND_FAILED","Invalid daemon response",{requestId:r.meta?.requestId,line:e},t instanceof Error?t:void 0))}}(t,{info:e,req:r,resolve:n,reject:i})}).catch(e=>{h&&clearTimeout(h),i(new u("COMMAND_FAILED","Failed to read daemon response",{requestId:r.meta?.requestId},e instanceof Error?e:void 0))})}),f=e$(e),h="number"==typeof o?setTimeout(()=>{l.destroy(),i(eO(e,s,r.meta?.requestId,r.command,f,o))},o):void 0;l.on("error",e=>{h&&clearTimeout(h),i(ex(e,r.meta?.requestId,f))}),l.write(p),l.end()})}async function eq(e,t,a,r,o){try{r(e.baseUrl&&a.ok?await eH(e,t,a):a)}catch(e){o(e)}}function e$(e){return"string"==typeof e.baseUrl&&e.baseUrl.length>0}function ej(e,t){return new URL(t,e.endsWith("/")?e:`${e}/`).toString()}async function eH(e,t,a){let r=Array.isArray(a.data?.artifacts)?a.data.artifacts:[];if(0===r.length||!e.baseUrl)return a;let o=a.data?{...a.data}:{},i=[];for(let a of r){if(!a||"object"!=typeof a||"string"!=typeof a.artifactId){i.push(a);continue}let r=function(e,t){if(e.localPath&&e.localPath.trim().length>0)return e.localPath;let a=t.meta?.clientArtifactPaths?.[e.field];if(a&&a.trim().length>0)return a;let r=e.fileName?.trim()||`${e.field}-${Date.now()}`;return n.resolve(t.meta?.cwd??process.cwd(),r)}(a,t);await eK({baseUrl:e.baseUrl,token:e.token,artifactId:a.artifactId,destinationPath:r,requestId:t.meta?.requestId}),o[a.field]=r,i.push({...a,localPath:r})}return o.artifacts=i,{ok:!0,data:o}}async function eK(e){var o,s;let l,c=new URL((o=e.baseUrl,s=e.artifactId,l=o.endsWith("/")?o:`${o}/`,new URL(`artifacts/${encodeURIComponent(s)}`,l).toString())),d="https:"===c.protocol?a:t;await r.promises.mkdir(n.dirname(e.destinationPath),{recursive:!0}),await new Promise((t,a)=>{let o=!1,n=e.timeoutMs??9e4,s=n=>{if(!o){if(o=!0,clearTimeout(p),n)return void r.promises.rm(e.destinationPath,{force:!0}).finally(()=>a(n));t()}},l=d.request({protocol:c.protocol,host:c.hostname,port:c.port,method:"GET",path:c.pathname+c.search,headers:e.token?{authorization:`Bearer ${e.token}`,"x-agent-device-token":e.token}:void 0},t=>{if((t.statusCode??500)>=400){let a="";t.setEncoding("utf8"),t.on("data",e=>{a+=e}),t.on("end",()=>{s(new u("COMMAND_FAILED","Failed to download remote artifact",{artifactId:e.artifactId,statusCode:t.statusCode,requestId:e.requestId,body:a}))});return}t.on("aborted",()=>{s(new u("COMMAND_FAILED","Remote artifact download was interrupted",{artifactId:e.artifactId,requestId:e.requestId}))}),i(t,r.createWriteStream(e.destinationPath)).then(()=>s(),e=>s(e instanceof Error?e:Error(String(e))))}),p=setTimeout(()=>{let t=new u("COMMAND_FAILED","Remote artifact download timed out",{artifactId:e.artifactId,requestId:e.requestId,timeoutMs:n});s(t),l.destroy(t)},n);l.on("error",t=>{t instanceof u?s(t):s(new u("COMMAND_FAILED","Failed to download remote artifact",{artifactId:e.artifactId,requestId:e.requestId,timeoutMs:n},t instanceof Error?t:void 0))}),l.end()})}function ez(e={},t={}){let a=t.transport??es,r=async(t,r=[],o={})=>{var n,i;let s=(n=e,i=o,{...n,...i}),l=await a({session:E(s.session),command:t,positionals:r,flags:T(s),runtime:s.runtime,meta:D(s)});return l.ok||function(e){throw new u(d(e.code),e.message,{...e.details??{},hint:e.hint,diagnosticId:e.diagnosticId,logPath:e.logPath})}(l.error),l.data??{}},o=async(e={})=>{let t=await r(C.sessionList,[],e);return(Array.isArray(t.sessions)?t.sessions:[]).map(h)},n=async(e,t={})=>{let a=P(e,t);return await r(a.command,a.positionals,a.options)},i=(t={})=>{var a,r;return E((a=e,r=t,{...a,...r}).session)};return{command:{wait:async e=>await n("wait",e),alert:async(e={})=>await n("alert",e),appState:async(e={})=>await n("appstate",e),back:async(e={})=>await n("back",e),home:async(e={})=>await n("home",e),rotate:async e=>await n("rotate",e),appSwitcher:async(e={})=>await n("app-switcher",e),keyboard:async(e={})=>await n("keyboard",e),clipboard:async e=>await n("clipboard",e),reactNative:async e=>await n("react-native",e)},devices:{list:async(e={})=>{let t=await n("devices",e);return(Array.isArray(t.devices)?t.devices:[]).map(R)},boot:async(e={})=>await n("boot",e)},sessions:{list:async(e={})=>await o(e),close:async(e={})=>{let t=i(e),a=(await n("close",e)).shutdown;return{session:t,shutdown:"object"==typeof a&&null!==a?a:void 0,identifiers:{session:t}}}},apps:{install:async e=>_(await n("install",e),i(e)),reinstall:async e=>_(await n("reinstall",e),i(e)),installFromSource:async e=>F(await n("install-from-source",e),i(e)),list:async(e={})=>{let t=await n("apps",e);return Array.isArray(t.apps)?t.apps.filter(e=>"string"==typeof e):[]},open:async e=>{let t=i(e),a=await n("open",e),r=S(a),o=M(a,"appBundleId");return{session:t,appName:M(a,"appName"),appBundleId:o,appId:o,startup:x(a.startup),runtime:U(a.runtime),device:r,identifiers:{session:t,deviceId:r?.id,deviceName:r?.name,udid:r?.ios?.udid,serial:r?.android?.serial,appId:o,appBundleId:o}}},close:async(e={})=>{let t=i(e),a=(await n("close",e)).shutdown;return{session:t,closedApp:e.app,shutdown:"object"==typeof a&&null!==a?a:void 0,identifiers:{session:t}}},push:async e=>await n("push",e),triggerEvent:async e=>await n("trigger-app-event",e)},materializations:{release:async e=>g(await r(C.releaseMaterializedPaths,[],{...e,materializationId:e.materializationId}))},leases:{allocate:async e=>eV(await r(C.leaseAllocate,[],{...e,leaseId:void 0,leaseTtlMs:e.ttlMs})),heartbeat:async e=>eV(await r(C.leaseHeartbeat,[],{...e,leaseTtlMs:e.ttlMs})),release:async e=>({released:!0===(await r(C.leaseRelease,[],e)).released})},metro:{prepare:async t=>await G({projectRoot:t.projectRoot??e.cwd,kind:t.kind,publicBaseUrl:t.publicBaseUrl,proxyBaseUrl:t.proxyBaseUrl,proxyBearerToken:t.bearerToken,bridgeScope:t.bridgeScope,launchUrl:t.launchUrl,companionProfileKey:t.companionProfileKey,companionConsumerKey:t.companionConsumerKey,metroPort:t.port,listenHost:t.listenHost,statusHost:t.statusHost,startupTimeoutMs:t.startupTimeoutMs,probeTimeoutMs:t.probeTimeoutMs,reuseExisting:t.reuseExisting,installDependenciesIfNeeded:t.installDependenciesIfNeeded,runtimeFilePath:t.runtimeFilePath,logPath:t.logPath}),reload:async(t={})=>await z({metroHost:t.metroHost,metroPort:t.metroPort,bundleUrl:t.bundleUrl,runtime:e.runtime,timeoutMs:t.timeoutMs})},capture:{snapshot:async(e={})=>{var t,a,r;let o,s,l,c,d,u=i(e);return t=await n("snapshot",e),a=u,o=M(t,"appBundleId"),{nodes:v(t.nodes),truncated:!0===t.truncated,appName:M(t,"appName"),appBundleId:o,...(s=eG((r=t).visibility),l=eG(r.androidSnapshot),c=eG(r.unchanged),d=Array.isArray(r.warnings)?r.warnings.filter(e=>"string"==typeof e):void 0,{...s?{visibility:s}:{},...l?{androidSnapshot:l}:{},...c?{unchanged:c}:{},...d?{warnings:d}:{}}),identifiers:{session:a,appId:o,appBundleId:o}}},screenshot:async(e={})=>{let t=i(e),a=await n("screenshot",e);return{path:y(a,"path"),overlayRefs:O(a),identifiers:{session:t}}},diff:async e=>await n("diff",e)},interactions:{click:async e=>await n("click",e),press:async e=>await n("press",e),longPress:async e=>await n("longpress",e),swipe:async e=>await n("swipe",e),pan:async e=>await n("gesture-pan",e),fling:async e=>await n("gesture-fling",e),focus:async e=>await n("focus",e),type:async e=>await n("type",e),fill:async e=>await n("fill",e),scroll:async e=>await n("scroll",e),pinch:async e=>await n("gesture-pinch",e),rotateGesture:async e=>await n("gesture-rotate",e),transformGesture:async e=>await n("gesture-transform",e),get:async e=>await n("get",e),is:async e=>await n("is",e),find:async e=>await n("find",e)},replay:{run:async e=>await n("replay",e),test:async e=>await n("test",e)},batch:{run:async e=>await n("batch",e)},observability:{perf:async(e={})=>await n("perf",e),logs:async(e={})=>await n("logs",e),network:async(e={})=>await n("network",e)},recording:{record:async e=>await n("record",e),trace:async e=>await n("trace",e)},settings:{update:async e=>await n("settings",e)}}}function eG(e){return"object"==typeof e&&null!==e?e:void 0}function eV(e){let t=e.lease;if(!t||"object"!=typeof t||Array.isArray(t))throw Error("Invalid lease response from daemon");return{leaseId:y(t,"leaseId"),tenantId:y(t,"tenantId"),runId:y(t,"runId"),backend:y(t,"backend"),createdAt:"number"==typeof t.createdAt?t.createdAt:void 0,heartbeatAt:"number"==typeof t.heartbeatAt?t.heartbeatAt:void 0,expiresAt:"number"==typeof t.expiresAt?t.expiresAt:void 0}}export{ez as createAgentDeviceClient,es as sendToDaemon};
|
package/dist/src/9639.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{AsyncLocalStorage as e}from"node:async_hooks";import{runCmdBackground as r,withoutCommandExecutorOverride as t,runCmd as i,withCommandExecutorOverride as n}from"./9818.js";import{AppError as a}from"./9152.js";let o=new e;function l(e){return async(r,n)=>await t(async()=>await i("adb",["-s",e,...r],n))}function s(e){var t;let i=l(e.id);return{exec:i,spawn:(t=e.id,(e,i)=>{let n=r("adb",["-s",t,...e],{...i,allowFailure:!0,captureOutput:!1});return n.wait.catch(()=>{}),n.child}),reverse:
|
|
2
|
-
${a}`.toLowerCase()).includes("listener")&&o.includes("not found"))))throw Error(`Failed to remove Android port reverse ${t}: ${l.stderr}`);for(let e of r.values())e.delete(t)},async removeAllOwned(e,t){for(let i of[...r.get(e)??[]])await this.remove(i,t);r.delete(e)},async list(t){let i=await e(["reverse","--list"],{allowFailure:!0,signal:t?.signal,timeoutMs:t?.timeoutMs});return 0!==i.exitCode?[]:function(e,r){let t=new Map;for(let[e,i]of r)for(let r of i)t.set(r,e);return e.split("\n").map(e=>e.trim().split(/\s+/)).filter(e=>e.length>=3).map(([,e,r])=>({local:e,remote:r,ownerId:t.get(e)}))}(i.stdout,r)}}}function
|
|
1
|
+
import{AsyncLocalStorage as e}from"node:async_hooks";import{runCmdBackground as r,withoutCommandExecutorOverride as t,runCmd as i,withCommandExecutorOverride as n}from"./9818.js";import{AppError as a}from"./9152.js";let o=new e;function l(e){return async(r,n)=>await t(async()=>await i("adb",["-s",e,...r],n))}function s(e){var t;let i=l(e.id);return{exec:i,spawn:(t=e.id,(e,i)=>{let n=r("adb",["-s",t,...e],{...i,allowFailure:!0,captureOutput:!1});return n.wait.catch(()=>{}),n.child}),reverse:g(i),pull:async(e,r,t)=>await i(["pull",e,r],t),install:async(e,r)=>{let{installArgs:t,execOptions:n}=h(r);return await i(["install",...t,e],n)}}}function d(e,r){let t=o.getStore();return r?r:t?.serial===e.id?t.provider.exec:l(e.id)}function u(e,r){if(r)return v(r);let t=o.getStore();return t?.serial===e.id?v(t.provider):s(e)}function c(e){let r=o.getStore();return r?.serial===e.id?r.provider.text:void 0}function w(e){let r=o.getStore();return r?.serial===e.id?r.provider.touch:void 0}function f(e){let r=v(e),t=r.reverse??g(r.exec),i=new Map;return{async ensure(e,r){let n=i.get(e.local);if(n&&n.ownerId!==e.ownerId)throw new a("COMMAND_FAILED",`Android port reverse ${e.local} is already owned by ${n.ownerId??"another session"}`,{current:n,requested:e});n?.remote!==e.remote&&(await t.ensure(e,r),i.set(e.local,{...e}))},async remove(e,r){i.has(e)?(await t.remove(e,r),i.delete(e)):await t.remove(e,r)},async removeAllOwned(e,r){let n=[...i.values()].filter(r=>r.ownerId===e).map(e=>e.local);if(0===n.length)return void await t.removeAllOwned(e,r);for(let e of n)await t.remove(e,r),i.delete(e)},list:async e=>t.list?await t.list(e):[...i.values()]}}function v(e){return"function"==typeof e?{exec:e}:e}async function p(e,r,i){let{device:n,provider:o,...l}=i??{},s=A(n,o),d=s?.pull;if(d)return await t(async()=>await d(e,r,l));let u=s?.exec;if(!u)throw new a("COMMAND_FAILED","Android adb pull requires an adb provider");return await t(async()=>await u(["pull",e,r],l))}async function m(e,r){let{device:i,provider:n,...o}=r??{},l=A(i,n),s=l?.install;if(s)return await t(async()=>await s(e,o));let d=l?.exec;if(!d)throw new a("COMMAND_FAILED","Android adb install requires an adb provider");let{installArgs:u,execOptions:c}=h(o);return await t(async()=>await d(["install",...u,e],c))}function A(e,r){if(r)return v(r);if(e)return u(e);let t=o.getStore();if(t)return v(t.provider)}async function y(e,r,i){var a;if(!e)return await i();let l={provider:"function"==typeof e?{exec:e}:e,serial:r.serial},s=(a=l,(e,r,i)=>{if("adb"!==e)return;let n=function(e,r){if("-s"===e[0]&&e[1]&&e[1]===r)return e.slice(2)}(r,a.serial);if(n)return t(async()=>await a.provider.exec(n,i))});return await o.run(l,async()=>await n(s,i))}function g(e){let r=new Map;return{async ensure(t,i){if(await e(["reverse",t.local,t.remote],{allowFailure:!1,signal:i?.signal,timeoutMs:i?.timeoutMs}),t.ownerId){let e=r.get(t.ownerId)??new Set;e.add(t.local),r.set(t.ownerId,e)}},async remove(t,i){var n,a;let o,l=await e(["reverse","--remove",t],{allowFailure:!0,signal:i?.signal,timeoutMs:i?.timeoutMs});if(0!==l.exitCode&&(n=l.stdout,a=l.stderr,!((o=`${n}
|
|
2
|
+
${a}`.toLowerCase()).includes("listener")&&o.includes("not found"))))throw Error(`Failed to remove Android port reverse ${t}: ${l.stderr}`);for(let e of r.values())e.delete(t)},async removeAllOwned(e,t){for(let i of[...r.get(e)??[]])await this.remove(i,t);r.delete(e)},async list(t){let i=await e(["reverse","--list"],{allowFailure:!0,signal:t?.signal,timeoutMs:t?.timeoutMs});return 0!==i.exitCode?[]:function(e,r){let t=new Map;for(let[e,i]of r)for(let r of i)t.set(r,e);return e.split("\n").map(e=>e.trim().split(/\s+/)).filter(e=>e.length>=3).map(([,e,r])=>({local:e,remote:r,ownerId:t.get(e)}))}(i.stdout,r)}}}function h(e){let{replace:r,allowTestPackages:t,allowDowngrade:i,grantPermissions:n,...a}=e??{},o=[];return r&&o.push("-r"),t&&o.push("-t"),i&&o.push("-d"),n&&o.push("-g"),{installArgs:o,execOptions:a}}export{f as createAndroidPortReverseManager,s as createLocalAndroidAdbProvider,m as installAndroidAdbPackage,p as pullAndroidAdbFile,d as resolveAndroidAdbExecutor,u as resolveAndroidAdbProvider,c as resolveAndroidTextInjector,w as resolveAndroidTouchInjector,y as withAndroidAdbProvider};
|
package/dist/src/989.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import t from"node:dns/promises";import e from"node:net";import{createWriteStream as a,promises as r}from"node:fs";import o from"node:os";import i from"node:path";import{Readable as n}from"node:stream";import{pipeline as s}from"node:stream/promises";import{AppError as l}from"./9152.js";import{runCmd as c}from"./9818.js";import{expandUserHomePath as h}from"./3267.js";let u=[".zip",".tar",".tar.gz",".tgz"],d=Object.freeze([...u]);async function p(t){let e=[];try{let a=await w(t.source,{signal:t.signal,downloadTimeoutMs:t.downloadTimeoutMs});e.push(a.cleanup);let r=await
|
|
1
|
+
import t from"node:dns/promises";import e from"node:net";import{createWriteStream as a,promises as r}from"node:fs";import o from"node:os";import i from"node:path";import{Readable as n}from"node:stream";import{pipeline as s}from"node:stream/promises";import{AppError as l}from"./9152.js";import{runCmd as c}from"./9818.js";import{expandUserHomePath as h}from"./3267.js";let u=[".zip",".tar",".tar.gz",".tgz"],d=Object.freeze([...u]);async function p(t){let e=[];try{let a=await w(t.source,{signal:t.signal,downloadTimeoutMs:t.downloadTimeoutMs});e.push(a.cleanup);let r=await v(a.localPath,{archivePath:void 0,isInstallablePath:t.isInstallablePath,installableLabel:t.installableLabel,allowArchiveExtraction:!1!==t.allowArchiveExtraction,registerCleanup:t=>{e.push(t)}});return{archivePath:r.archivePath,installablePath:r.installablePath,cleanup:async()=>{await g(e)}}}catch(t){throw await g(e),t}}async function w(t,e){if("path"===t.kind)return{localPath:h(t.path),cleanup:async()=>{}};let a=await r.mkdtemp(i.join(o.tmpdir(),"agent-device-source-"));try{return{localPath:await f(a,t.url,t.headers,e),cleanup:async()=>{await r.rm(a,{recursive:!0,force:!0})}}}catch(t){throw await r.rm(a,{recursive:!0,force:!0}),t}}async function f(t,e,r,o){let c;try{c=new URL(e)}catch{throw new l("INVALID_ARGS",`Invalid source URL: ${e}`)}await m(c);let h=o?.signal;if(h?.aborted)throw new l("COMMAND_FAILED","request canceled",{reason:"request_canceled"});let u=o?.downloadTimeoutMs??12e4,d=AbortSignal.timeout(u),p=h?AbortSignal.any([h,d]):d;try{let e=await fetch(c,{headers:r,redirect:"follow",signal:p});if(!e.ok)throw new l("COMMAND_FAILED",`Failed to download app source: ${e.status} ${e.statusText}`,{status:e.status,statusText:e.statusText,url:c.toString()});let o=function(t,e){let a=t.headers.get("content-disposition"),r=a?.match(/filename\*?=(?:UTF-8'')?"?([^";]+)"?/i),o=r?.[1]?.trim();if(o)return i.basename(o);let n=i.basename(e.pathname);return n||"downloaded-artifact.bin"}(e,c),h=i.join(t,o),u=e.body;if(!u)throw new l("COMMAND_FAILED","Download response body was empty",{url:c.toString()});return await s(n.fromWeb(u),a(h)),h}catch(t){if(h?.aborted)throw new l("COMMAND_FAILED","request canceled",{reason:"request_canceled"},t);if(d.aborted)throw new l("COMMAND_FAILED",`App source download timed out after ${u}ms`,{timeoutMs:u,url:c.toString()},t);throw t}}async function m(e){if("http:"!==e.protocol&&"https:"!==e.protocol)throw new l("INVALID_ARGS",`Unsupported source URL protocol: ${e.protocol}`);if(A(e.hostname.toLowerCase()))throw new l("INVALID_ARGS",`Source URL host is not allowed: ${e.hostname}`,{hint:"Use a public artifact URL."});if((await t.lookup(e.hostname,{all:!0,verbatim:!0}).catch(()=>[])).some(t=>L(t.address)))throw new l("INVALID_ARGS",`Source URL host resolved to a private or loopback address: ${e.hostname}`,{hint:"Use a public artifact URL."})}function b(t){var e,a,r,o;let i=t instanceof URL?t:new URL(t),n=i.hostname.toLowerCase();if(!n)return!1;let s=i.pathname;return e=n,a=s,("api.github.com"===e?/^\/repos\/[^/]+\/[^/]+\/actions\/artifacts\/\d+\/zip$/i.test(a):"github.com"===e&&/^\/[^/]+\/[^/]+\/(?:actions\/runs\/\d+\/artifacts\/\d+|suites\/\d+\/artifacts\/\d+)$/i.test(a))||(r=n,o=s,("expo.dev"===r||!!r.endsWith(".expo.dev"))&&/^\/(?:artifacts\/eas\/|accounts\/[^/]+\/projects\/[^/]+\/builds\/)/i.test(o))}function A(t){return!!(!t||"localhost"===t||t.endsWith(".localhost"))||L(t)}function L(t){let a,r=e.isIP(t);return 4===r?function(t){let e=t.split(".").map(t=>Number.parseInt(t,10));if(4!==e.length||e.some(t=>Number.isNaN(t)||t<0||t>255))return!1;let a=e[0],r=e[1];return void 0!==a&&void 0!==r&&(10===a||127===a||169===a&&254===r||172===a&&!!(r>=16)&&!!(r<=31)||192===a&&168===r)}(t):6===r&&!!("::1"===(a=t.toLowerCase())||a.startsWith("fc")||a.startsWith("fd")||a.startsWith("fe80:"))}async function v(t,e){let a=await r.stat(t).catch(()=>null);if(!a)throw new l("INVALID_ARGS",`App source not found: ${t}`);if(e.isInstallablePath(t,a))return{archivePath:e.archivePath,installablePath:t};if(a.isFile()&&S(t)){if(!e.allowArchiveExtraction)throw new l("INVALID_ARGS",`URL sources must point directly to a ${e.installableLabel}; archive extraction is not allowed`,{path:t});let a=await _(t);return e.registerCleanup(a.cleanup),await v(a.outputPath,{...e,archivePath:e.archivePath??t})}if(a.isDirectory()){let a=await I(t,e.isInstallablePath),r=a[0];if(void 0!==r&&1===a.length)return{archivePath:e.archivePath,installablePath:r};if(a.length>1)throw new l("INVALID_ARGS",`Found multiple ${e.installableLabel} candidates under ${t}`,{matches:a});let o=await I(t,(t,e)=>e.isFile()&&S(t)),i=o[0];if(void 0!==i&&1===o.length){if(!e.allowArchiveExtraction)throw new l("INVALID_ARGS",`URL sources must point directly to a ${e.installableLabel}; nested archives are not allowed`,{path:i});let t=await _(i);return e.registerCleanup(t.cleanup),await v(t.outputPath,{...e,archivePath:e.archivePath??i})}if(o.length>1)throw new l("INVALID_ARGS",`Found multiple nested archives under ${t}; expected one ${e.installableLabel} source`,{matches:o})}throw new l("INVALID_ARGS",`Expected ${e.installableLabel} source, but got ${t}`)}async function I(t,e){let a=[],o=[{path:t,depth:0}];for(;o.length>0;){let t=o.shift();if(!t)continue;let n=await r.readdir(t.path,{withFileTypes:!0});for(let r of(n.sort((t,e)=>t.name.localeCompare(e.name)),n)){let n=i.join(t.path,r.name);if(e(n,r)){a.push(n);continue}r.isDirectory()&&t.depth<5&&o.push({path:n,depth:t.depth+1})}}return a}async function _(t){let e=await r.mkdtemp(i.join(o.tmpdir(),"agent-device-archive-"));try{return t.toLowerCase().endsWith(".zip")?await P(t,e):t.toLowerCase().endsWith(".tar.gz")||t.toLowerCase().endsWith(".tgz")?await c("tar",["-xzf",t,"-C",e]):await c("tar",["-xf",t,"-C",e]),{outputPath:e,cleanup:async()=>{await r.rm(e,{recursive:!0,force:!0})}}}catch(t){throw await r.rm(e,{recursive:!0,force:!0}),t}}async function P(t,e){await c("unzip",["-q",t,"-d",e])}function S(t){let e=t.toLowerCase();return u.some(t=>e.endsWith(t))}async function g(t){for(let e of[...t].reverse())await e()}export{d as ARCHIVE_EXTENSIONS,L as isBlockedIpAddress,A as isBlockedSourceHostname,b as isTrustedInstallSourceUrl,p as materializeInstallablePath,m as validateDownloadSourceUrl};
|
|
@@ -50,6 +50,7 @@ export declare type AndroidAdbProvider = {
|
|
|
50
50
|
install?: AndroidAdbInstaller;
|
|
51
51
|
installBundle?: AndroidBundleInstaller;
|
|
52
52
|
text?: AndroidTextInjector;
|
|
53
|
+
touch?: AndroidTouchInjector;
|
|
53
54
|
};
|
|
54
55
|
|
|
55
56
|
export declare type AndroidAdbPuller = (remotePath: string, localPath: string, options?: AndroidAdbTransferOptions) => Promise<AndroidAdbExecutorResult>;
|
|
@@ -149,6 +150,31 @@ export declare type AndroidTextInjectionRequest = {
|
|
|
149
150
|
|
|
150
151
|
export declare type AndroidTextInjector = (request: AndroidTextInjectionRequest) => Promise<void>;
|
|
151
152
|
|
|
153
|
+
declare type AndroidTouchGestureRequest = {
|
|
154
|
+
kind: 'pinch';
|
|
155
|
+
x: number;
|
|
156
|
+
y: number;
|
|
157
|
+
scale: number;
|
|
158
|
+
durationMs?: number;
|
|
159
|
+
} | {
|
|
160
|
+
kind: 'rotate';
|
|
161
|
+
x: number;
|
|
162
|
+
y: number;
|
|
163
|
+
degrees: number;
|
|
164
|
+
durationMs?: number;
|
|
165
|
+
} | {
|
|
166
|
+
kind: 'transform';
|
|
167
|
+
x: number;
|
|
168
|
+
y: number;
|
|
169
|
+
dx: number;
|
|
170
|
+
dy: number;
|
|
171
|
+
scale: number;
|
|
172
|
+
degrees: number;
|
|
173
|
+
durationMs?: number;
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
declare type AndroidTouchInjector = (request: AndroidTouchGestureRequest) => Promise<Record<string, unknown> | void>;
|
|
177
|
+
|
|
152
178
|
declare type ApplePlatform = 'ios' | 'macos';
|
|
153
179
|
|
|
154
180
|
declare type AppsFilter = 'user-installed' | 'all';
|
package/dist/src/android-adb.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{AppError as t}from"./9152.js";import{resolveAppsFilter as e}from"./
|
|
1
|
+
import{AppError as t}from"./9152.js";import{resolveAppsFilter as e}from"./3622.js";import{parseAndroidForegroundApp as i,parseAndroidLaunchablePackages as a,parseAndroidUserInstalledPackages as r,inferAndroidAppName as o,parseAndroidLaunchComponent as n,isAmStartError as d}from"./1769.js";let l="android.intent.category.LAUNCHER",s="android.intent.category.LEANBACK_LAUNCHER";async function c(t,i={}){let a=await A(t,i.target??"auto");return("user-installed"===e(i.filter)?(await p(t)).filter(t=>a.has(t)):Array.from(a)).map(t=>({package:t,name:o(t)})).sort((t,e)=>t.package.localeCompare(e.package))}async function u(t){let e=await f(t,[["shell","dumpsys","window","windows"],["shell","dumpsys","window"]]);if(e)return e;let i=await f(t,[["shell","dumpsys","activity","activities"],["shell","dumpsys","activity"]]);return i||{}}async function A(t,e){return new Set((await Promise.all((function(t){switch(t){case"mobile":return[l];case"tv":return[s];default:return[l,s]}})(e).map(async e=>{var i;let r=await t(["shell","cmd","package","query-activities","--brief","-a","android.intent.action.MAIN","-c",e],{allowFailure:!0});return 0===r.exitCode?0===(i=r.stdout).trim().length?[]:a(i):[]}))).flat())}async function p(e){let i=await e(["shell","pm","list","packages","-3"],{allowFailure:!0});if(0!==i.exitCode)throw new t("COMMAND_FAILED","Failed to list Android user-installed apps",{stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode});return r(i.stdout)}async function f(t,e){for(let a of e){let e=i((await t(a,{allowFailure:!0})).stdout??"");if(e)return e}return null}let w="android.intent.category.LAUNCHER",m="android.intent.category.DEFAULT";async function h(t,e){await t(["shell","am","force-stop",e])}async function C(t,e,i=[w]){for(let a of i){let i=await t(["shell","cmd","package","resolve-activity","--brief","-a","android.intent.action.MAIN","-c",a,e],{allowFailure:!0});if(0!==i.exitCode)continue;let r=n(i.stdout);if(r)return r}return null}async function _(e,i,a={}){let r=a.category??w;if(a.activity){var o,n;return void await e(["shell","am","start","-W","-a","android.intent.action.MAIN","-c",m,"-c",r,"-n",(o=i,(n=a.activity).includes("/")?n:`${o}/${n.startsWith(".")?n:`.${n}`}`)])}let l=await e(["shell","am","start","-W","-a","android.intent.action.MAIN","-c",m,"-c",r,"-p",i],{allowFailure:!0});if(0===l.exitCode&&!d(l.stdout,l.stderr))return;let s=await C(e,i,[r]);if(!s)throw new t("COMMAND_FAILED",`Failed to resolve Android launch component for ${i}`,{stdout:l.stdout,stderr:l.stderr,exitCode:l.exitCode});await e(["shell","am","start","-W","-a","android.intent.action.MAIN","-c",m,"-c",r,"-n",s])}export{captureAndroidLogcatWithAdb,dismissAndroidKeyboardWithAdb,getAndroidKeyboardStatusWithAdb,readAndroidClipboardWithAdb,streamAndroidLogcatWithAdb,writeAndroidClipboardWithAdb}from"./1769.js";export{createAndroidPortReverseManager,createLocalAndroidAdbProvider}from"./9639.js";export{h as forceStopAndroidAppWithAdb,u as getAndroidAppStateWithAdb,c as listAndroidAppsWithAdb,_ as openAndroidAppWithAdb,C as resolveAndroidLaunchComponentWithAdb};
|
|
@@ -61,6 +61,7 @@ declare type AndroidAdbProvider = {
|
|
|
61
61
|
install?: AndroidAdbInstaller;
|
|
62
62
|
installBundle?: AndroidBundleInstaller;
|
|
63
63
|
text?: AndroidTextInjector;
|
|
64
|
+
touch?: AndroidTouchInjector;
|
|
64
65
|
};
|
|
65
66
|
|
|
66
67
|
declare type AndroidAdbPuller = (remotePath: string, localPath: string, options?: AndroidAdbTransferOptions) => Promise<AndroidAdbExecutorResult>;
|
|
@@ -105,6 +106,7 @@ export declare type AndroidSnapshotBackendMetadata = {
|
|
|
105
106
|
fallbackReason?: string;
|
|
106
107
|
installReason?: 'missing' | 'outdated' | 'forced' | 'current' | 'skipped';
|
|
107
108
|
waitForIdleTimeoutMs?: number;
|
|
109
|
+
waitForIdleQuietMs?: number;
|
|
108
110
|
timeoutMs?: number;
|
|
109
111
|
maxDepth?: number;
|
|
110
112
|
maxNodes?: number;
|
|
@@ -126,10 +128,12 @@ export declare type AndroidSnapshotHelperCaptureOptions = {
|
|
|
126
128
|
packageName?: string;
|
|
127
129
|
instrumentationRunner?: string;
|
|
128
130
|
waitForIdleTimeoutMs?: number;
|
|
131
|
+
waitForIdleQuietMs?: number;
|
|
129
132
|
timeoutMs?: number;
|
|
130
133
|
commandTimeoutMs?: number;
|
|
131
134
|
maxDepth?: number;
|
|
132
135
|
maxNodes?: number;
|
|
136
|
+
outputPath?: string;
|
|
133
137
|
};
|
|
134
138
|
|
|
135
139
|
export declare type AndroidSnapshotHelperInstallPolicy = 'missing-or-outdated' | 'always' | 'never';
|
|
@@ -164,6 +168,7 @@ export declare type AndroidSnapshotHelperMetadata = {
|
|
|
164
168
|
helperApiVersion?: string;
|
|
165
169
|
outputFormat: 'uiautomator-xml';
|
|
166
170
|
waitForIdleTimeoutMs?: number;
|
|
171
|
+
waitForIdleQuietMs?: number;
|
|
167
172
|
timeoutMs?: number;
|
|
168
173
|
maxDepth?: number;
|
|
169
174
|
maxNodes?: number;
|
|
@@ -207,6 +212,31 @@ declare type AndroidTextInjectionRequest = {
|
|
|
207
212
|
|
|
208
213
|
declare type AndroidTextInjector = (request: AndroidTextInjectionRequest) => Promise<void>;
|
|
209
214
|
|
|
215
|
+
declare type AndroidTouchGestureRequest = {
|
|
216
|
+
kind: 'pinch';
|
|
217
|
+
x: number;
|
|
218
|
+
y: number;
|
|
219
|
+
scale: number;
|
|
220
|
+
durationMs?: number;
|
|
221
|
+
} | {
|
|
222
|
+
kind: 'rotate';
|
|
223
|
+
x: number;
|
|
224
|
+
y: number;
|
|
225
|
+
degrees: number;
|
|
226
|
+
durationMs?: number;
|
|
227
|
+
} | {
|
|
228
|
+
kind: 'transform';
|
|
229
|
+
x: number;
|
|
230
|
+
y: number;
|
|
231
|
+
dx: number;
|
|
232
|
+
dy: number;
|
|
233
|
+
scale: number;
|
|
234
|
+
degrees: number;
|
|
235
|
+
durationMs?: number;
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
declare type AndroidTouchInjector = (request: AndroidTouchGestureRequest) => Promise<Record<string, unknown> | void>;
|
|
239
|
+
|
|
210
240
|
export declare function captureAndroidSnapshotWithHelper(options: AndroidSnapshotHelperCaptureOptions): Promise<AndroidSnapshotHelperOutput>;
|
|
211
241
|
|
|
212
242
|
export declare function ensureAndroidSnapshotHelper(options: {
|
package/dist/src/batch.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ export declare const BATCH_BLOCKED_COMMANDS: ReadonlySet<string>;
|
|
|
3
3
|
export declare type BatchFlags = Record<string, unknown> & {
|
|
4
4
|
batchOnError?: 'stop';
|
|
5
5
|
batchMaxSteps?: number;
|
|
6
|
-
batchSteps?:
|
|
6
|
+
batchSteps?: DaemonBatchStep[];
|
|
7
7
|
};
|
|
8
8
|
|
|
9
9
|
export declare type BatchInvoke = (req: BatchRequest) => Promise<DaemonResponse>;
|
|
@@ -12,13 +12,6 @@ export declare type BatchRequest = Omit<DaemonRequest, 'flags'> & {
|
|
|
12
12
|
flags?: BatchFlags | Record<string, unknown>;
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
-
export declare type BatchStep = {
|
|
16
|
-
command: string;
|
|
17
|
-
positionals?: string[];
|
|
18
|
-
flags?: Record<string, unknown>;
|
|
19
|
-
runtime?: unknown;
|
|
20
|
-
};
|
|
21
|
-
|
|
22
15
|
export declare type BatchStepResult = {
|
|
23
16
|
step: number;
|
|
24
17
|
command: string;
|
|
@@ -27,7 +20,7 @@ export declare type BatchStepResult = {
|
|
|
27
20
|
durationMs: number;
|
|
28
21
|
};
|
|
29
22
|
|
|
30
|
-
export declare function buildBatchStepFlags(parentFlags: BatchFlags | Record<string, unknown> | undefined, stepFlags:
|
|
23
|
+
export declare function buildBatchStepFlags(parentFlags: BatchFlags | Record<string, unknown> | undefined, stepFlags: DaemonBatchStep['flags'] | Record<string, unknown> | undefined): BatchFlags;
|
|
31
24
|
|
|
32
25
|
declare type DaemonArtifact = {
|
|
33
26
|
field: string;
|
|
@@ -37,6 +30,13 @@ declare type DaemonArtifact = {
|
|
|
37
30
|
path?: string;
|
|
38
31
|
};
|
|
39
32
|
|
|
33
|
+
export declare type DaemonBatchStep = {
|
|
34
|
+
command: string;
|
|
35
|
+
positionals?: string[];
|
|
36
|
+
flags?: Record<string, unknown>;
|
|
37
|
+
runtime?: unknown;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
40
|
declare type DaemonError = {
|
|
41
41
|
code: string;
|
|
42
42
|
message: string;
|