agent-device 0.17.0 → 0.17.2

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.
Files changed (84) hide show
  1. package/README.md +1 -1
  2. package/android-multitouch-helper/dist/{agent-device-android-multitouch-helper-0.17.0.apk → agent-device-android-multitouch-helper-0.17.2.apk} +0 -0
  3. package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.17.2.apk.sha256 +1 -0
  4. package/android-multitouch-helper/dist/{agent-device-android-multitouch-helper-0.17.0.manifest.json → agent-device-android-multitouch-helper-0.17.2.manifest.json} +4 -4
  5. package/android-snapshot-helper/dist/{agent-device-android-snapshot-helper-0.17.0.apk → agent-device-android-snapshot-helper-0.17.2.apk} +0 -0
  6. package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.17.2.apk.sha256 +1 -0
  7. package/android-snapshot-helper/dist/{agent-device-android-snapshot-helper-0.17.0.manifest.json → agent-device-android-snapshot-helper-0.17.2.manifest.json} +6 -6
  8. package/dist/src/123.js +1 -0
  9. package/dist/src/1352.js +1 -1
  10. package/dist/src/1534.js +1 -0
  11. package/dist/src/1620.js +1 -0
  12. package/dist/src/1644.js +2 -0
  13. package/dist/src/2284.js +1 -0
  14. package/dist/src/2403.js +3 -0
  15. package/dist/src/2415.js +28 -29
  16. package/dist/src/2474.js +1 -0
  17. package/dist/src/2672.js +1 -0
  18. package/dist/src/3393.js +1 -0
  19. package/dist/src/4778.js +1 -1
  20. package/dist/src/5898.js +1 -0
  21. package/dist/src/7556.js +1 -1
  22. package/dist/src/7847.js +1 -1
  23. package/dist/src/8173.js +27 -0
  24. package/dist/src/8407.js +1 -0
  25. package/dist/src/8699.js +1 -1
  26. package/dist/src/8806.js +3 -3
  27. package/dist/src/9010.js +1 -0
  28. package/dist/src/9238.js +3 -3
  29. package/dist/src/9471.js +1 -1
  30. package/dist/src/9542.js +3 -3
  31. package/dist/src/9616.js +1 -0
  32. package/dist/src/9673.js +1 -0
  33. package/dist/src/9974.js +1 -0
  34. package/dist/src/android-adb.d.ts +12 -6
  35. package/dist/src/android-adb.js +1 -1
  36. package/dist/src/android-snapshot-helper.d.ts +15 -7
  37. package/dist/src/android.js +1 -1
  38. package/dist/src/apple.js +1 -1
  39. package/dist/src/apps.js +2 -2
  40. package/dist/src/args.js +2 -2
  41. package/dist/src/batch.d.ts +16 -4
  42. package/dist/src/cli.js +18 -42
  43. package/dist/src/command-surface.js +1 -1
  44. package/dist/src/contracts.d.ts +28 -4
  45. package/dist/src/contracts.js +1 -1
  46. package/dist/src/find.js +1 -1
  47. package/dist/src/finders.d.ts +3 -1
  48. package/dist/src/generic.js +13 -11
  49. package/dist/src/index.d.ts +142 -73
  50. package/dist/src/index.js +1 -1
  51. package/dist/src/input-actions.js +1 -1
  52. package/dist/src/interaction.js +1 -1
  53. package/dist/src/internal/png-worker.d.ts +26 -0
  54. package/dist/src/internal/png-worker.js +1 -0
  55. package/dist/src/metro.d.ts +3 -1
  56. package/dist/src/react-native.js +1 -1
  57. package/dist/src/record-trace-recording.js +26 -0
  58. package/dist/src/record-trace.js +1 -26
  59. package/dist/src/remote-config.d.ts +33 -7
  60. package/dist/src/selector-runtime.js +1 -1
  61. package/dist/src/selectors.d.ts +3 -3
  62. package/dist/src/selectors.js +1 -1
  63. package/dist/src/server.js +2 -2
  64. package/dist/src/session.js +10 -11
  65. package/dist/src/snapshot.js +1 -1
  66. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +6 -2
  67. package/package.json +7 -4
  68. package/server.json +2 -2
  69. package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.17.0.apk.sha256 +0 -1
  70. package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.17.0.apk.sha256 +0 -1
  71. package/dist/src/1998.js +0 -1
  72. package/dist/src/2805.js +0 -1
  73. package/dist/src/4057.js +0 -1
  74. package/dist/src/5792.js +0 -1
  75. package/dist/src/6085.js +0 -1
  76. package/dist/src/6232.js +0 -1
  77. package/dist/src/8020.js +0 -1
  78. package/dist/src/8502.js +0 -1
  79. package/dist/src/940.js +0 -1
  80. package/dist/src/9404.js +0 -1
  81. package/dist/src/9533.js +0 -1
  82. package/dist/src/command-metadata.js +0 -1
  83. /package/dist/src/{1393.js → 3675.js} +0 -0
  84. /package/dist/src/{5310.js → 695.js} +0 -0
package/dist/src/9542.js CHANGED
@@ -1,3 +1,3 @@
1
- import e from"node:net";import t from"node:http";import a from"node:https";import r from"node:fs";import n from"node:os";import o 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{formatRequestProgressEvent as h,consumeTextLines as y,shellQuote as w,shouldStreamRequestProgress as g,isDaemonResponseEnvelope as I,isDaemonProgressEnvelope as v,resolveDaemonPaths as A,resolveDaemonServerMode as _,computeDaemonCodeSignature as P,resolveDaemonTransportPreference as k}from"./9238.js";import{readVersion as b,findProjectRoot as S}from"./9671.js";import{createRequestId as D,withDiagnosticTimer as E,emitDiagnostic as M}from"./7599.js";import{isAgentDeviceDaemonProcess as T,stopProcessForTakeover as C}from"./8656.js";import{INTERNAL_COMMANDS as N,PUBLIC_COMMANDS as U}from"./5792.js";import{sleep as L}from"./4829.js";import{reloadMetro as R,prepareMetroRuntime as O}from"./1974.js";import{normalizeSession as x,resolveSessionName as F,buildFlags as q,normalizeStartupSample as B,normalizeInstallFromSourceResult as $,normalizeMaterializationReleaseResult as j,prepareDaemonCommandRequest as H,readSnapshotNodes as K,normalizeRuntimeHints as G,normalizeDeployResult as z,normalizeOpenDevice as V,readScreenshotOverlayRefs as W,buildMeta as J,normalizeDevice as Y}from"./8699.js";import{readRequiredString as Q,readOptionalString as X}from"./7455.js";function Z(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 ee="sha256";async function et(e){let t=await ea(e.localPath,e.platform),a=e.baseUrl.endsWith("/")?e.baseUrl:`${e.baseUrl}/`;try{let r=await ei({normalizedBase:a,token:e.token,artifact:t});if(r?.kind==="cache-hit")return r.uploadId;if(r?.kind==="direct-upload")try{return await es(t.payloadPath,r),await ec({normalizedBase:a,token:e.token,uploadId:r.uploadId})}catch{}return await eo({normalizedBase:a,token:e.token,artifact:t})}finally{t.cleanup()}}async function ea(e,t){var a,n,i;let s,l=r.statSync(e),c=o.basename(e),d=l.isDirectory(),u=("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),p=[];try{let t=d?await er(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 ed(t),sizeBytes:a.size,cleanup:()=>en(p)}}catch(e){throw en(p),e}}async function er(e,t){let a=r.mkdtempSync(o.join(n.tmpdir(),`agent-device-upload-${l()}-`));t.push(a);let i=o.join(a,`${o.basename(e)}.tar.gz`);return await m("tar",["czf",i,"-C",o.dirname(e),o.basename(e)],{env:{...process.env,COPYFILE_DISABLE:"1"}}),i}function en(e){for(let t of e)r.rmSync(t,{recursive:!0,force:!0})}async function eo(e){let{normalizedBase:t,token:a,artifact:r}=e,n=new URL("upload",t),o={"content-type":r.contentType,"x-artifact-type":r.artifactType,"x-artifact-filename":r.fileName,"x-artifact-hash":r.sha256,"x-artifact-hash-algorithm":ee,"transfer-encoding":"chunked"};a&&(o.authorization=`Bearer ${a}`,o["x-agent-device-token"]=a);let i=await el({url:n,method:"POST",headers:o,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 ei(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 es(e,t){let a=await el({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 el(e){let n="https:"===e.url.protocol?a:t;return await new Promise((t,a)=>{let o=n.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=>{Z(e).then(a=>{clearTimeout(s),t({statusCode:e.statusCode??500,statusMessage:e.statusMessage,body:a})}).catch(a)}),s=setTimeout(()=>{o.destroy(),a(new u("COMMAND_FAILED",e.timeoutMessage,{timeoutMs:3e5,...e.timeoutHint?{hint:e.timeoutHint}:{}}))},3e5);o.on("error",t=>{clearTimeout(s),a(new u("COMMAND_FAILED",e.errorMessage,e.errorHint?{hint:e.errorHint}:{},t))}),o.on("close",()=>clearTimeout(s)),i(r.createReadStream(e.payloadPath),o).catch(e=>{o.destroy(),a(new u("COMMAND_FAILED","Failed to read local artifact",{},e instanceof Error?e:Error(String(e))))})})}async function ec(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 n=await r.json().catch(()=>void 0);if(!n?.ok||!n.uploadId)throw new u("COMMAND_FAILED","Invalid upload finalize response");return n.uploadId}async function ed(e){let t=s(ee),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")}function eu(e){let t=h(e);t&&process.stderr.write(`${t}
2
- `)}let ep=["xcodebuild .*AgentDeviceRunnerUITests/RunnerTests/testCommand","xcodebuild .*AgentDeviceRunner\\.env\\.session-","xcodebuild build-for-testing .*ios-runner/AgentDeviceRunner/AgentDeviceRunner\\.xcodeproj"],em=new e.BlockList;async function ef(t){var a,i,s,l,c,d;let p,m,f,h,y,w,g,I=t.meta?.requestId??D(),v=!!(t.meta?.debug||t.flags?.verbose),P=(h=(i=a=t,i.flags?.stateDir??process.env.AGENT_DEVICE_STATE_DIR),y=(s=a,m=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(/\/+$/,"")}}(p=s.flags?.daemonBaseUrl??process.env.AGENT_DEVICE_DAEMON_BASE_URL),function(t,a){let r;if(!(!t||"localhost"===(r=new URL(t).hostname.trim().toLowerCase().replace(/^\[(.*)\]$/,"$1"))||(e.isIPv4(r)?em.check(r,"ipv4"):!!e.isIPv6(r)&&em.check(r,"ipv6")))&&("string"!=typeof a||!(a.trim().length>0)))throw new u("INVALID_ARGS","Remote daemon base URL for non-loopback hosts requires daemon authentication",{daemonBaseUrl:t,hint:"Provide --daemon-auth-token or AGENT_DEVICE_DAEMON_AUTH_TOKEN when using a non-loopback remote daemon URL."})}(m,f=s.flags?.daemonAuthToken??process.env.AGENT_DEVICE_DAEMON_AUTH_TOKEN),{rawBaseUrl:p,remoteBaseUrl:m,authToken:f}),w=function(e,t){let a=e.flags?.daemonTransport??process.env.AGENT_DEVICE_DAEMON_TRANSPORT,r=k(a);if(t&&"socket"===r)throw new u("INVALID_ARGS","Remote daemon base URL only supports HTTP transport. Remove --daemon-transport socket.",{daemonBaseUrl:t});return{preference:r,serverMode:_(e.flags?.daemonServerMode??process.env.AGENT_DEVICE_DAEMON_SERVER_MODE??("dual"===a?"dual":void 0))}}(a,y.remoteBaseUrl),{paths:A((g=(l=a,c=h,d=y.rawBaseUrl,eS(l.command)&&!c&&!d))?r.mkdtempSync(o.join(n.tmpdir(),"agent-device-replay-daemon-")):h),transportPreference:w.preference,serverMode:w.serverMode,ownedStateDir:g,remoteBaseUrl:y.remoteBaseUrl,remoteAuthToken:y.authToken}),b=function(e){if(e.command!==U.test){var t;return"number"==typeof e.flags?.timeoutMs&&((t=e.command)===U.prepare||t===U.replay||t===U.snapshot)?e.flags.timeoutMs:e.command===U.prepare?24e4:9e4}}(t),S=await E("daemon_startup",async()=>await eA(P),{requestId:I,session:t.session}),T=S.info,C=await eh(t,T),N={...t,positionals:C.positionals,flags:C.flags,token:T.token,meta:{...t.meta??{},requestId:I,debug:v,cwd:t.meta?.cwd,sessionExplicit:t.meta?.sessionExplicit,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,...C.uploadedArtifactId?{uploadedArtifactId:C.uploadedArtifactId}:{},...C.clientArtifactPaths?{clientArtifactPaths:C.clientArtifactPaths}:{},...C.installSource?{installSource:C.installSource}:{}}};M({level:"info",phase:"daemon_request_prepare",data:{requestId:I,command:t.command,session:t.session}});try{return await E("daemon_request",async()=>await e$(T,N,P.transportPreference,b),{requestId:I,command:t.command})}finally{await eb(t,S,P)}}async function eh(e,t){let a,r=[...e.positionals??[]],n=e.flags?{...e.flags}:void 0,i=e.meta?.installSource,s={};if(!eY(t))return ew({positionals:r,flags:n,installSource:i,uploadedArtifactId:a,clientArtifactPaths:s});n=function(e,t,a,r){var n,i;let s=function(e,t){if("screenshot"===e.command){let a=eI(e,"path",".png");return t[0]?{field:"path",localPath:a,positionalIndex:0,positionalPath:ev("screenshot",".png")}:{field:"path",localPath:a,positionalIndex:0,flagPath:ev("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:ev("recording",o.extname(t)||".mp4")}}return null}(e,t);if(!s)return a;void 0!==s.positionalPath&&(t[s.positionalIndex]=s.positionalPath);let l=(n=a,void 0===(i=s.flagPath)?n:{...n??{},out:i});return r[s.field]=s.localPath,l}(e,r,n,s);let l=await eg(e,t);l&&(i=l.installSource,a=l.uploadedArtifactId??a);let c=()=>ew({positionals:r,flags:n,installSource:i,uploadedArtifactId:a,clientArtifactPaths:s});return"install"!==e.command&&"reinstall"!==e.command||(a=await ey(e,t,r)??a),c()}async function ey(e,t,a){var n,i;let s,l=a[1];if(void 0===l)return;if(l.startsWith("remote:")){a[1]=l.slice(7);return}let c=(n=l,i=e.meta?.cwd,s=o.isAbsolute(n)?n:o.resolve(i??process.cwd(),n),r.existsSync(s)?s:void 0);if(c)return await et({localPath:c,baseUrl:t.baseUrl,token:t.token,platform:e.flags?.platform})}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 eg(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 et({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 ev(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 eA(e){if(e.remoteBaseUrl)return await e_(e);let t=await eP(e);return t?{info:t,startedByClient:!1}:(function(e){let t=eR(e);if(!t.hasLock||t.hasInfo)return;let a=eU(e.lockPath);if(!a)return ex(e.lockPath);T(a.pid,a.processStartTime)||ex(e.lockPath)}(e.paths),await ek(e))}async function e_(e){let t={transport:"http",token:e.remoteAuthToken??"",pid:0,baseUrl:e.remoteBaseUrl};if(await eF(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 eP(e){var t,a;let r,n=eT(e.paths.infoPath);if(!n)return null;let o=await eF(n,e.transportPreference);return(t=n,a=o,t.version===b()&&t.codeSignature===P((r=eB()).useSrc?r.srcPath:r.distPath,r.root)&&a)?n:(await eM(n),ex(e.paths.infoPath),null)}async function ek(e){let t,a=0,r=[];for(let n=1;n<=2;n+=1){try{await eq(e)}catch(a){if(t=a instanceof Error?a.message:String(a),r.push(await eL(e.paths,"start_error")),n<2){await L(150);continue}break}let o=await eD(15e3,e);if(o)return{info:o,startedByClient:!0};if(await eE(e.paths)){a+=1;continue}let i=eR(e.paths),s=n<2,l=await eL(e.paths,"startup_timeout",{stopLiveProcesses:!1});if(r.push(l),l.retainedInfoProcess||l.retainedLockProcess){let t=await eD(15e3,e);if(t)return{info:t,startedByClient:!0};break}if(!s)break;i.hasInfo||i.hasLock||await L(150)}let n=eR(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:n,hint:function(e,t=A(process.env.AGENT_DEVICE_STATE_DIR)){var a;let r=(a=t,`rm -f ${w(a.infoPath)} ${w(a.lockPath)}`);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 after confirming no agent-device daemon process is running, run: ${r}`: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 after confirming no agent-device daemon process is running, run: ${r}`:e.hasInfo?`agent-device did not observe reachable daemon metadata after retrying, and ${t.infoPath} still remains. Stale metadata was cleaned automatically when safe; retry with --debug. If this persists after confirming no agent-device daemon process is running, run: ${r}`:`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. If stale metadata returns after confirming no agent-device daemon process is running, run: ${r}`}(n,e.paths)})}async function eb(e,t,a){if(!eS(e.command)||!t.startedByClient&&!a.ownedStateDir||eY(t.info))return;let n={pid:t.info.pid,removedInfo:!1,removedLock:!1,removedStateDir:!1,error:void 0};try{await eM(t.info)}catch(e){n.error=e instanceof Error?e.message:String(e)}finally{let e=r.existsSync(a.paths.infoPath);ex(a.paths.infoPath),n.removedInfo=e&&!r.existsSync(a.paths.infoPath);let t=r.existsSync(a.paths.lockPath);ex(a.paths.lockPath),n.removedLock=t&&!r.existsSync(a.paths.lockPath),a.ownedStateDir&&(r.rmSync(a.paths.baseDir,{recursive:!0,force:!0}),n.removedStateDir=!r.existsSync(a.paths.baseDir))}M({level:n.error?"warn":"info",phase:"daemon_replay_cleanup",data:n})}function eS(e){return e===U.replay||e===U.test}async function eD(e,t){let a=Date.now();for(;Date.now()-a<e;){let e=eT(t.paths.infoPath);if(e&&await eF(e,t.transportPreference))return e;await L(100)}return null}async function eE(e){let t=eR(e);if(!t.hasLock||t.hasInfo)return!1;let a=eU(e.lockPath);return!(a&&T(a.pid,a.processStartTime))&&(ex(e.lockPath),!0)}async function eM(e){await C(e.pid,{termTimeoutMs:3e3,killTimeoutMs:1e3,expectedStartTime:e.processStartTime})}function eT(e){var t,a,r;let n,o,i=eO(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=(n=eN((a=i).port),o=eN(a.httpPort),void 0===n&&void 0===o?null:{port:n,httpPort:o});return l?{token:s,...l,transport:"socket"===(r=i.transport)||"http"===r||"dual"===r?r:void 0,pid:eN(i.pid)??0,version:eC(i.version),codeSignature:eC(i.codeSignature),processStartTime:eC(i.processStartTime)}:null}function eC(e){return"string"==typeof e?e:void 0}function eN(e){return Number.isInteger(e)&&Number(e)>0?Number(e):void 0}function eU(e){let t=eO(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}em.addSubnet("127.0.0.0",8,"ipv4"),em.addAddress("::1","ipv6"),em.addSubnet("::ffff:127.0.0.0",104,"ipv6");async function eL(e,t,a={}){let n=a.stopLiveProcesses??!0,o={reason:t,removedInfo:!1,removedLock:!1,stoppedInfoProcess:!1,stoppedLockProcess:!1};try{var i,s,l,c;let t=r.existsSync(e.infoPath),a=eT(e.infoPath);if(a){let t=T(a.pid,a.processStartTime);t&&!n?o.retainedInfoProcess=!0:(t&&(await eM(a),o.stoppedInfoProcess=!0),i=e.infoPath,ex(i),o.removedInfo=!0)}else t&&(s=e.infoPath,ex(s),o.removedInfo=!0);let d=r.existsSync(e.lockPath),u=eU(e.lockPath);if(u){let t=T(u.pid,u.processStartTime);t&&!n?o.retainedLockProcess=!0:(t&&(await C(u.pid,{termTimeoutMs:3e3,killTimeoutMs:1e3,expectedStartTime:u.processStartTime}),o.stoppedLockProcess=!0),l=e.lockPath,ex(l),o.removedLock=!0)}else d&&(c=e.lockPath,ex(c),o.removedLock=!0)}catch(e){o.error=e instanceof Error?e.message:String(e)}return M({level:o.error?"warn":"info",phase:"daemon_startup_metadata_cleanup",data:o}),o}function eR(e){return{hasInfo:r.existsSync(e.infoPath),hasLock:r.existsSync(e.lockPath)}}function eO(e){if(!r.existsSync(e))return null;try{return JSON.parse(r.readFileSync(e,"utf8"))}catch{return null}}function ex(e){try{r.existsSync(e)&&r.unlinkSync(e)}catch{}}async function eF(r,n){var o;return"http"===ej(r,n)?await function(e){let r=e.baseUrl?eQ(e.baseUrl,"health"):e.httpPort?`http://127.0.0.1:${e.httpPort}/health`:null;if(!r)return Promise.resolve(!1);let n=new URL(r),o="https:"===n.protocol?a:t,i=e.baseUrl?3e3:500;return new Promise(e=>{let t=o.request({protocol:n.protocol,host:n.hostname,port:n.port,path:n.pathname+n.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 ((o=r.port)?new Promise(t=>{let a=!1,r=e.createConnection({host:"127.0.0.1",port:o},()=>{n(!0)}),n=e=>{a||(a=!0,r.destroy(),t(e))};r.setTimeout(500),r.on("timeout",()=>{n(!1)}),r.on("error",()=>{n(!1)})}):Promise.resolve(!1))}async function eq(e){let t=eB(),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 eB(){let e=S(),t=[o.join(e,"dist","src","internal","daemon.js"),o.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 n=t.find(e=>r.existsSync(e))??a,i=o.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:n,distPaths:t,srcPath:i,useSrc:process.execArgv.includes("--experimental-strip-types")?l:!s&&l}}async function e$(e,t,a,r){return"http"===ej(e,a)?await eV(e,t,r):await ez(e,t,r)}function ej(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(eH(a,r))return r;throw new u("COMMAND_FAILED","http"===r?"Daemon HTTP endpoint is unavailable":"Daemon socket endpoint is unavailable")}let n=("socket"===e.transport||"dual"===e.transport?["socket","http"]:["http","socket"]).find(t=>eH(e,t));if(n)return n;throw new u("COMMAND_FAILED","Daemon metadata has no reachable transport")}function eH(e,t){return"http"===t?!!e.httpPort:!!e.port}function eK(e,t,a,r,n,o){let i=n?{terminated:0}:function(){let e=0;try{for(let t of ep){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=!n&&"snapshot"!==r,l=s?function(e,t){let a=!1;try{T(e.pid,e.processStartTime)&&(process.kill(e.pid,"SIGKILL"),a=!0)}catch{C(e.pid,{termTimeoutMs:3e3,killTimeoutMs:1e3,expectedStartTime:e.processStartTime})}finally{ex(t.infoPath),ex(t.lockPath)}return{forcedKill:a}}(e,t):{forcedKill:!1};return M({level:"error",phase:"daemon_request_timeout",data:{timeoutMs:o,requestId:a,command:r,timedOutRunnerPidsTerminated:i.terminated,timedOutRunnerCleanupError:i.error,daemonPidReset:s?e.pid:void 0,daemonPidForceKilled:s?l.forcedKill:void 0,daemonPreservedAfterTimeout:!n&&!s,daemonBaseUrl:e.baseUrl}}),new u("COMMAND_FAILED","Daemon request timed out",{timeoutMs:o,requestId:a,hint:function(e){let{remote:t,resetDaemon:a,command:r}=e;if(t)return"Retry with --debug and verify the remote daemon URL, auth token, and remote host logs.";if(!a){let e=r===U.snapshot?" If this was the first Apple-platform snapshot on the device, run agent-device prepare ios-runner with the same --platform before snapshot/test so runner startup is handled explicitly.":"";return`Retry with --debug and check daemon diagnostics logs. The timed-out ${r??"request"} request was canceled and Apple runner work was aborted when detected; the daemon was kept alive so the session can still be closed or inspected.${e}`}return"Retry with --debug and check daemon diagnostics logs. Timed-out Apple runner xcodebuild processes were terminated when detected."}({remote:n,resetDaemon:s,command:r})})}function eG(e,t,a){return M({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 ez(t,a,r){let n=t.port;if(!n)throw new u("COMMAND_FAILED","Daemon socket endpoint is unavailable");return new Promise((o,i)=>{let s=e.createConnection({host:"127.0.0.1",port:n},()=>{s.write(`${JSON.stringify(a)}
3
- `)}),l=A(a.flags?.stateDir??process.env.AGENT_DEVICE_STATE_DIR),c=!1,d="number"==typeof r?setTimeout(()=>{c=!0,s.destroy(),i(eK(t,l,a.meta?.requestId,a.command,!1,r))},r):void 0,p="";s.setEncoding("utf8"),s.on("data",e=>{if(c)return;let t=y(p,e);for(let e of(p=t.buffer,t.lines))try{let t=JSON.parse(e);if(v(t)){eu(t.event);continue}let a=I(t)?t.response:t;c=!0,s.end(),d&&clearTimeout(d),o(a);return}catch(t){c=!0,d&&clearTimeout(d),i(new u("COMMAND_FAILED","Invalid daemon response",{requestId:a.meta?.requestId,line:e},t instanceof Error?t:void 0));return}}),s.on("error",e=>{c||(c=!0,d&&clearTimeout(d),i(eG(e,a.meta?.requestId,!1)))})})}async function eV(e,r,n){var o,i,s;let l,c=e.baseUrl?new URL(eQ(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 d=JSON.stringify((o=r,i={includeTokenParam:!e.baseUrl},l=o.meta?.requestId??D(),"lease_allocate"!==(s=o.command)&&"lease_heartbeat"!==s&&"lease_release"!==s?{jsonrpc:"2.0",id:l,method:"agent_device.command",params:o}:{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"}}(o.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}}}(o,o.command,i)})),p={"content-type":"application/json","content-length":Buffer.byteLength(d)};return e.baseUrl&&e.token&&(p.authorization=`Bearer ${e.token}`,p["x-agent-device-token"]=e.token),await new Promise((o,i)=>{let s=A(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:p},t=>{var a;(a=t.headers?.["content-type"],g(r)&&String(Array.isArray(a)?a.join(","):a??"").includes("application/x-ndjson"))?function(e,t){let{req:a,handleResponseBody:r,reject:n,clearTimeout:o}=t,i="",s=!1,l=e=>{try{let t=JSON.parse(e);if(v(t))return eu(t.event),!1;if(I(t))return s=!0,o(),r(JSON.stringify(t.response)),!0;throw Error("Missing daemon progress response envelope")}catch(t){return s=!0,o(),n(new u("COMMAND_FAILED","Invalid daemon response",{requestId:a.meta?.requestId,line:e},t instanceof Error?t:void 0)),!0}};e.setEncoding("utf8"),e.on("data",e=>{if(s)return;let t=y(i,e);for(let e of(i=t.buffer,t.lines))if(e&&l(e))return}),e.on("end",()=>{if(s)return;let e=i.trim();e&&l(e)||(s=!0,o(),n(new u("COMMAND_FAILED","Invalid daemon response",{requestId:a.meta?.requestId,line:e})))}),e.on("error",e=>{s||(s=!0,o(),n(new u("COMMAND_FAILED","Failed to read daemon response",{requestId:a.meta?.requestId},e instanceof Error?e:void 0)))})}(t,{req:r,reject:i,clearTimeout:()=>{f&&clearTimeout(f)},handleResponseBody:t=>eW(t,{info:e,req:r,resolve:o,reject:i})}):Z(t).then(t=>{f&&clearTimeout(f),eW(t,{info:e,req:r,resolve:o,reject:i})}).catch(e=>{f&&clearTimeout(f),i(new u("COMMAND_FAILED","Failed to read daemon response",{requestId:r.meta?.requestId},e instanceof Error?e:void 0))})}),m=eY(e),f="number"==typeof n?setTimeout(()=>{l.destroy(),i(eK(e,s,r.meta?.requestId,r.command,m,n))},n):void 0;l.on("error",e=>{f&&clearTimeout(f),i(eG(e,r.meta?.requestId,m))}),l.write(d),l.end()})}function eW(e,t){let{info:a,req:r,resolve:n,reject:o}=t;try{var i,s,l;let t=(i=e,JSON.parse(i));if(t.error){let e;return void o((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 o(new u("COMMAND_FAILED","Invalid daemon RPC response",{requestId:r.meta?.requestId}));eJ(a,r,t.result,n,o)}catch(t){o(new u("COMMAND_FAILED","Invalid daemon response",{requestId:r.meta?.requestId,line:e},t instanceof Error?t:void 0))}}async function eJ(e,t,a,r,n){try{r(e.baseUrl&&a.ok?await eX(e,t,a):a)}catch(e){n(e)}}function eY(e){return"string"==typeof e.baseUrl&&e.baseUrl.length>0}function eQ(e,t){return new URL(t,e.endsWith("/")?e:`${e}/`).toString()}async function eX(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 eZ({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 eZ(e){var n,s;let l,c=new URL((n=e.baseUrl,s=e.artifactId,l=n.endsWith("/")?n:`${n}/`,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 n=!1,o=e.timeoutMs??9e4,s=o=>{if(!n){if(n=!0,clearTimeout(p),o)return void r.promises.rm(e.destinationPath,{force:!0}).finally(()=>a(o));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:o});s(t),l.destroy(t)},o);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:o},t instanceof Error?t:void 0))}),l.end()})}function e0(e={},t={}){let a=t.transport??ef,r=async(t,r=[],n={})=>{var o,i;let s=(o=e,i=n,{...o,...i}),l=await a({session:F(s.session),command:t,positionals:r,flags:q(s),runtime:s.runtime,meta:J(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??{}},n=async(e={})=>{let t=await r(N.sessionList,[],e);return(Array.isArray(t.sessions)?t.sessions:[]).map(x)},o=async(e,t={})=>{let a=H(e,t);return await r(a.command,a.positionals,a.options)},i=(t={})=>{var a,r;return F((a=e,r=t,{...a,...r}).session)};return{command:{wait:async e=>await o("wait",e),alert:async(e={})=>await o("alert",e),appState:async(e={})=>await o("appstate",e),back:async(e={})=>await o("back",e),home:async(e={})=>await o("home",e),rotate:async e=>await o("rotate",e),appSwitcher:async(e={})=>await o("app-switcher",e),keyboard:async(e={})=>await o("keyboard",e),clipboard:async e=>await o("clipboard",e),reactNative:async e=>await o("react-native",e),prepare:async e=>await o("prepare",e)},devices:{list:async(e={})=>{let t=await o("devices",e);return(Array.isArray(t.devices)?t.devices:[]).map(Y)},boot:async(e={})=>await o("boot",e)},sessions:{list:async(e={})=>await n(e),close:async(e={})=>{let t=i(e),a=(await o("close",e)).shutdown;return{session:t,shutdown:"object"==typeof a&&null!==a?a:void 0,identifiers:{session:t}}}},apps:{install:async e=>z(await o("install",e),i(e)),reinstall:async e=>z(await o("reinstall",e),i(e)),installFromSource:async e=>$(await o("install-from-source",e),i(e)),list:async(e={})=>{let t=await o("apps",e);return Array.isArray(t.apps)?t.apps.filter(e=>"string"==typeof e):[]},open:async e=>{let t=i(e),a=await o("open",e),r=V(a),n=X(a,"appBundleId");return{session:t,sessionStateDir:X(a,"sessionStateDir"),appName:X(a,"appName"),appBundleId:n,appId:n,startup:B(a.startup),runtime:G(a.runtime),device:r,identifiers:{session:t,deviceId:r?.id,deviceName:r?.name,udid:r?.ios?.udid,serial:r?.android?.serial,appId:n,appBundleId:n}}},close:async(e={})=>{let t=i(e),a=(await o("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 o("push",e),triggerEvent:async e=>await o("trigger-app-event",e)},materializations:{release:async e=>j(await r(N.releaseMaterializedPaths,[],{...e,materializationId:e.materializationId}))},leases:{allocate:async e=>e5(await r(N.leaseAllocate,[],{...e,leaseId:void 0,leaseTtlMs:e.ttlMs})),heartbeat:async e=>e5(await r(N.leaseHeartbeat,[],{...e,leaseTtlMs:e.ttlMs})),release:async e=>({released:!0===(await r(N.leaseRelease,[],e)).released})},metro:{prepare:async t=>await O({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 R({metroHost:t.metroHost,metroPort:t.metroPort,bundleUrl:t.bundleUrl,runtime:e.runtime,timeoutMs:t.timeoutMs})},capture:{snapshot:async(e={})=>{var t,a,r;let n,s,l,c,d,u=i(e);return t=await o("snapshot",e),a=u,n=X(t,"appBundleId"),{nodes:K(t.nodes),truncated:!0===t.truncated,appName:X(t,"appName"),appBundleId:n,...(s=e1((r=t).visibility),l=e1(r.androidSnapshot),c=e1(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:n,appBundleId:n}}},screenshot:async(e={})=>{let t=i(e),a=await o("screenshot",e);return{path:Q(a,"path"),overlayRefs:W(a),identifiers:{session:t}}},diff:async e=>await o("diff",e)},interactions:{click:async e=>await o("click",e),press:async e=>await o("press",e),longPress:async e=>await o("longpress",e),swipe:async e=>await o("swipe",e),pan:async e=>await o("gesture-pan",e),fling:async e=>await o("gesture-fling",e),swipeGesture:async e=>await o("gesture-swipe",e),focus:async e=>await o("focus",e),type:async e=>await o("type",e),fill:async e=>await o("fill",e),scroll:async e=>await o("scroll",e),pinch:async e=>await o("gesture-pinch",e),rotateGesture:async e=>await o("gesture-rotate",e),transformGesture:async e=>await o("gesture-transform",e),get:async e=>await o("get",e),is:async e=>await o("is",e),find:async e=>await o("find",e)},replay:{run:async e=>await o("replay",e),test:async e=>await o("test",e)},batch:{run:async e=>await o("batch",e)},observability:{perf:async(e={})=>await o("perf",e),logs:async(e={})=>await o("logs",e),network:async(e={})=>await o("network",e)},recording:{record:async e=>await o("record",e),trace:async e=>await o("trace",e)},settings:{update:async e=>await o("settings",e)}}}function e1(e){return"object"==typeof e&&null!==e?e:void 0}function e5(e){let t=e.lease;if(!t||"object"!=typeof t||Array.isArray(t))throw Error("Invalid lease response from daemon");return{leaseId:Q(t,"leaseId"),tenantId:Q(t,"tenantId"),runId:Q(t,"runId"),backend:Q(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{e0 as createAgentDeviceClient,ef as sendToDaemon};
1
+ import e from"node:net";import t from"node:http";import a from"node:https";import r from"node:fs";import n from"node:os";import o 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{consumeTextLines as p,shellQuote as f,shouldStreamRequestProgress as m,isDaemonResponseEnvelope as h,resolveDaemonPaths as y,isDaemonProgressEnvelope as w,resolveDaemonServerMode as g,computeDaemonCodeSignature as I,resolveDaemonTransportPreference as v}from"./9238.js";import{runCmdSync as A,runCmd as _,runCmdDetached as b}from"./9818.js";import{readVersion as S,findProjectRoot as k}from"./9671.js";import{createRequestId as P,withDiagnosticTimer as D,emitDiagnostic as M}from"./7599.js";import{isAgentDeviceDaemonProcess as E,stopProcessForTakeover as T}from"./8656.js";import{INTERNAL_COMMANDS as N,PUBLIC_COMMANDS as C}from"./5898.js";import{sleep as U}from"./4829.js";import{reloadMetro as L,prepareMetroRuntime as R}from"./1974.js";import{normalizeSession as O,resolveSessionName as x,buildFlags as $,normalizeStartupSample as F,normalizeInstallFromSourceResult as q,normalizeMaterializationReleaseResult as B,prepareDaemonCommandRequest as j,readSnapshotNodes as K,normalizeRuntimeHints as H,normalizeDeployResult as z,normalizeOpenDevice as G,readScreenshotOverlayRefs as V,buildMeta as W,normalizeDevice as J}from"./8699.js";import{readRequiredString as Y,readOptionalString as Q}from"./7455.js";function X(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)})}function Z(e){let t=Math.max(0,e)/1e3;return t>=10?`${t.toFixed(1)}s`:t>=1?`${t.toFixed(2)}s`:`${t.toFixed(3).replace(/0+$/,"").replace(/\.$/,"")}s`}function ee(e){let t=function(e){var t,a,r;let n,i;if("replay-test"!==e.type||"pass"===e.status||"fail"===e.status&&!e.retrying)return;let s=(t=e,(n=t.title?.trim())?JSON.stringify(n):o.basename(t.file)),l=void 0!==e.durationMs?` (${i=Z((a=e).durationMs??0),a.attempt&&a.attempt>1&&!a.retrying?`total ${i}`:i})`:"",c=void 0===(r=e).attempt?"":"fail"===r.status&&r.retrying&&void 0!==r.maxAttempts?` attempt ${r.attempt}/${r.maxAttempts} retrying`:r.attempt>1?` after ${r.attempt} attempts`:"",d=e.message?.replace(/\s+/g," ").trim();return"skip"===e.status?[`SKIP ${s}`,d?` ${d}`:""].filter(Boolean).join("\n"):[`FAIL ${s}${c}${l}`,d?` ${d}`:"",e.artifactsDir?` artifacts: ${e.artifactsDir}`:""].filter(Boolean).join("\n")}(e);t&&process.stderr.write(`${t}
2
+ `)}let et="sha256";async function ea(e){let t=await er(e.localPath,e.platform),a=e.baseUrl.endsWith("/")?e.baseUrl:`${e.baseUrl}/`;try{let r=await es({normalizedBase:a,token:e.token,artifact:t});if(r?.kind==="cache-hit")return r.uploadId;if(r?.kind==="direct-upload")try{return await el(t.payloadPath,r),await ep({normalizedBase:a,token:e.token,uploadId:r.uploadId})}catch{}return await ei({normalizedBase:a,token:e.token,artifact:t})}finally{t.cleanup()}}async function er(e,t){var a,n,i;let s,l=r.statSync(e),c=o.basename(e),d=l.isDirectory(),u=("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),p=[];try{let t=d?await en(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 ef(t),sizeBytes:a.size,cleanup:()=>eo(p)}}catch(e){throw eo(p),e}}async function en(e,t){let a=r.mkdtempSync(o.join(n.tmpdir(),`agent-device-upload-${l()}-`));t.push(a);let i=o.join(a,`${o.basename(e)}.tar.gz`);return await _("tar",["czf",i,"-C",o.dirname(e),o.basename(e)],{env:{...process.env,COPYFILE_DISABLE:"1"}}),i}function eo(e){for(let t of e)r.rmSync(t,{recursive:!0,force:!0})}async function ei(e){let{normalizedBase:t,token:a,artifact:r}=e,n=new URL("upload",t),o={"content-type":r.contentType,"x-artifact-type":r.artifactType,"x-artifact-filename":r.fileName,"x-artifact-hash":r.sha256,"x-artifact-hash-algorithm":et,"transfer-encoding":"chunked"};a&&(o.authorization=`Bearer ${a}`,o["x-agent-device-token"]=a);let i=await ec({url:n,method:"POST",headers:o,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 es(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 el(e,t){let a=await ec({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 ec(e){return await ed({...e,url:e.url,redirectCount:0,startOffset:0})}async function ed(e){var n,o,s;let l="https:"===e.url.protocol?a:t,c=r.statSync(e.payloadPath).size,d=(n=e.headers,o=e.startOffset,s=c,o<=0?n:{...n,"content-length":Math.max(s-o,0),"content-range":`bytes ${o}-${s-1}/${s}`});return await new Promise((t,a)=>{let n=!1,o=l.request({protocol:e.url.protocol,host:e.url.hostname,port:e.url.port,method:e.method,path:e.url.pathname+e.url.search,headers:d},r=>{n=!0,X(r).then(n=>{clearTimeout(s);let o=r.statusCode??500,i=r.headers.location;if(i&&[301,302,303,307,308].includes(o)){if(e.redirectCount>=5)return void a(new u("COMMAND_FAILED","Artifact upload exceeded redirect limit",{maxRedirects:5,url:e.url.toString()}));let r=new URL(i,e.url);return void ed({...e,url:r,redirectCount:e.redirectCount+1}).then(t,a)}let l=308===o?function(e,t){let a=function(e){let t=eu(e);if(void 0===t)return;let a=Number(t);return Number.isSafeInteger(a)&&a>=0?a:void 0}(e["x-upload-offset"]??e["upload-offset"]);if(void 0!==a)return Math.min(a,t);let r=eu(e.range),n=r?.match(/^bytes=0-(\d+)$/);if(!n)return;let o=Number(n[1]);if(Number.isSafeInteger(o)&&!(o<0))return Math.min(o+1,t)}(r.headers,c):void 0;void 0!==l?l>=c?t({statusCode:200,statusMessage:"Upload already complete",body:""}):l<=e.startOffset?a(new u("COMMAND_FAILED","Artifact upload resume did not advance",{offset:l,previousOffset:e.startOffset,url:e.url.toString()})):ed({...e,startOffset:l}).then(t,a):t({statusCode:o,statusMessage:r.statusMessage,body:n})}).catch(a)}),s=setTimeout(()=>{o.destroy(),a(new u("COMMAND_FAILED",e.timeoutMessage,{timeoutMs:3e5,...e.timeoutHint?{hint:e.timeoutHint}:{}}))},3e5);o.on("error",t=>{n||(clearTimeout(s),a(new u("COMMAND_FAILED",e.errorMessage,e.errorHint?{hint:e.errorHint}:{},t)))}),o.on("close",()=>clearTimeout(s)),i(r.createReadStream(e.payloadPath,{start:e.startOffset}),o).catch(e=>{n||(o.destroy(),a(new u("COMMAND_FAILED","Failed to read local artifact",{},e instanceof Error?e:Error(String(e)))))})})}function eu(e){return Array.isArray(e)?e[0]: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 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 n=await r.json().catch(()=>void 0);if(!n?.ok||!n.uploadId)throw new u("COMMAND_FAILED","Invalid upload finalize response");return n.uploadId}async function ef(e){let t=s(et),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")}async function em(e,t){var a;let r,n=[...e.positionals??[]],i=e.flags?{...e.flags}:void 0,s=e.meta?.installSource,l={};if(!("string"==typeof(a=t).baseUrl&&a.baseUrl.length>0))return ey({positionals:n,flags:i,installSource:s,uploadedArtifactId:r,clientArtifactPaths:l});i=function(e,t,a,r){var n,i;let s=function(e,t){if("screenshot"===e.command){let a=eg(e,"path",".png");return t[0]?{field:"path",localPath:a,positionalIndex:0,positionalPath:eI("screenshot",".png")}:{field:"path",localPath:a,positionalIndex:0,flagPath:eI("screenshot",".png")}}if("record"===e.command&&"start"===(t[0]??"").toLowerCase()){let t=eg(e,"outPath",".mp4",1);return{field:"outPath",localPath:t,positionalIndex:1,positionalPath:eI("recording",o.extname(t)||".mp4")}}return null}(e,t);if(!s)return a;void 0!==s.positionalPath&&(t[s.positionalIndex]=s.positionalPath);let l=(n=a,void 0===(i=s.flagPath)?n:{...n??{},out:i});return r[s.field]=s.localPath,l}(e,n,i,l);let c=await ew(e,t);c&&(s=c.installSource,r=c.uploadedArtifactId??r);let d=()=>ey({positionals:n,flags:i,installSource:s,uploadedArtifactId:r,clientArtifactPaths:l});return"install"!==e.command&&"reinstall"!==e.command||(r=await eh(e,t,n)??r),d()}async function eh(e,t,a){var n,i;let s,l=a[1];if(void 0===l)return;if(l.startsWith("remote:")){a[1]=l.slice(7);return}let c=(n=l,i=e.meta?.cwd,s=o.isAbsolute(n)?n:o.resolve(i??process.cwd(),n),r.existsSync(s)?s:void 0);if(c)return await ea({localPath:c,baseUrl:t.baseUrl,token:t.token,platform:e.flags?.platform})}function ey(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 ew(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 ea({localPath:i,baseUrl:t.baseUrl,token:t.token,platform:e.flags?.platform});return{installSource:{...a,path:i},uploadedArtifactId:s}}function eg(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 eI(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 ev(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 eA({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 eA(e){var n,s;let l,c=new URL((n=e.baseUrl,s=e.artifactId,l=n.endsWith("/")?n:`${n}/`,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 n=!1,o=e.timeoutMs??9e4,s=o=>{if(!n){if(n=!0,clearTimeout(p),o)return void r.promises.rm(e.destinationPath,{force:!0}).finally(()=>a(o));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:o});s(t),l.destroy(t)},o);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:o},t instanceof Error?t:void 0))}),l.end()})}let e_=["xcodebuild .*AgentDeviceRunnerUITests/RunnerTests/testCommand","xcodebuild .*AgentDeviceRunner\\.env\\.session-","xcodebuild build-for-testing .*ios-runner/AgentDeviceRunner/AgentDeviceRunner\\.xcodeproj"],eb=new e.BlockList;async function eS(t){var a,i,s,l,c,d;let p,f,m,h,w,I,A,_=t.meta?.requestId??P(),b=!!(t.meta?.debug||t.flags?.verbose),S=(h=(i=a=t,i.flags?.stateDir??process.env.AGENT_DEVICE_STATE_DIR),w=(s=a,f=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(/\/+$/,"")}}(p=s.flags?.daemonBaseUrl??process.env.AGENT_DEVICE_DAEMON_BASE_URL),function(t,a){let r;if(!(!t||"localhost"===(r=new URL(t).hostname.trim().toLowerCase().replace(/^\[(.*)\]$/,"$1"))||(e.isIPv4(r)?eb.check(r,"ipv4"):!!e.isIPv6(r)&&eb.check(r,"ipv6")))&&("string"!=typeof a||!(a.trim().length>0)))throw new u("INVALID_ARGS","Remote daemon base URL for non-loopback hosts requires daemon authentication",{daemonBaseUrl:t,hint:"Provide --daemon-auth-token or AGENT_DEVICE_DAEMON_AUTH_TOKEN when using a non-loopback remote daemon URL."})}(f,m=s.flags?.daemonAuthToken??process.env.AGENT_DEVICE_DAEMON_AUTH_TOKEN),{rawBaseUrl:p,remoteBaseUrl:f,authToken:m}),I=function(e,t){let a=e.flags?.daemonTransport??process.env.AGENT_DEVICE_DAEMON_TRANSPORT,r=v(a);if(t&&"socket"===r)throw new u("INVALID_ARGS","Remote daemon base URL only supports HTTP transport. Remove --daemon-transport socket.",{daemonBaseUrl:t});return{preference:r,serverMode:g(e.flags?.daemonServerMode??process.env.AGENT_DEVICE_DAEMON_SERVER_MODE??("dual"===a?"dual":void 0))}}(a,w.remoteBaseUrl),{paths:y((A=(l=a,c=h,d=w.rawBaseUrl,eT(l.command)&&!c&&!d))?r.mkdtempSync(o.join(n.tmpdir(),"agent-device-replay-daemon-")):h),transportPreference:I.preference,serverMode:I.serverMode,ownedStateDir:A,remoteBaseUrl:w.remoteBaseUrl,remoteAuthToken:w.authToken}),k=function(e){if(e.command!==C.test){var t;return"number"==typeof e.flags?.timeoutMs&&((t=e.command)===C.prepare||t===C.replay||t===C.snapshot)?e.flags.timeoutMs:e.command===C.prepare?24e4:9e4}}(t),E=await D("daemon_startup",async()=>await ek(S),{requestId:_,session:t.session}),T=E.info,N=await em(t,T),U={...t,positionals:N.positionals,flags:N.flags,token:T.token,meta:{...t.meta??{},requestId:_,debug:b,cwd:t.meta?.cwd,sessionExplicit:t.meta?.sessionExplicit,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,...N.uploadedArtifactId?{uploadedArtifactId:N.uploadedArtifactId}:{},...N.clientArtifactPaths?{clientArtifactPaths:N.clientArtifactPaths}:{},...N.installSource?{installSource:N.installSource}:{}}};M({level:"info",phase:"daemon_request_prepare",data:{requestId:_,command:t.command,session:t.session}});try{return await D("daemon_request",async()=>await eG(T,U,S.transportPreference,k),{requestId:_,command:t.command})}finally{await eE(t,E,S)}}async function ek(e){if(e.remoteBaseUrl)return await eP(e);let t=await eD(e);return t?{info:t,startedByClient:!1}:(function(e){let t=eF(e);if(!t.hasLock||t.hasInfo)return;let a=ex(e.lockPath);if(!a)return eB(e.lockPath);E(a.pid,a.processStartTime)||eB(e.lockPath)}(e.paths),await eM(e))}async function eP(e){let t={transport:"http",token:e.remoteAuthToken??"",pid:0,baseUrl:e.remoteBaseUrl};if(await ej(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 eD(e){var t,a;let r,n=eL(e.paths.infoPath);if(!n)return null;let o=await ej(n,e.transportPreference);return(t=n,a=o,t.version===S()&&t.codeSignature===I((r=ez()).useSrc?r.srcPath:r.distPath,r.root)&&a)?n:(await eU(n),eB(e.paths.infoPath),null)}async function eM(e){let t,a=0,r=[];for(let n=1;n<=2;n+=1){try{await eH(e)}catch(a){if(t=a instanceof Error?a.message:String(a),r.push(await e$(e.paths,"start_error")),n<2){await U(150);continue}break}let o=await eN(15e3,e);if(o)return{info:o,startedByClient:!0};if(await eC(e.paths)){a+=1;continue}let i=eF(e.paths),s=n<2,l=await e$(e.paths,"startup_timeout",{stopLiveProcesses:!1});if(r.push(l),l.retainedInfoProcess||l.retainedLockProcess){let t=await eN(15e3,e);if(t)return{info:t,startedByClient:!0};break}if(!s)break;i.hasInfo||i.hasLock||await U(150)}let n=eF(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:n,hint:function(e,t=y(process.env.AGENT_DEVICE_STATE_DIR)){var a;let r=(a=t,`rm -f ${f(a.infoPath)} ${f(a.lockPath)}`);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 after confirming no agent-device daemon process is running, run: ${r}`: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 after confirming no agent-device daemon process is running, run: ${r}`:e.hasInfo?`agent-device did not observe reachable daemon metadata after retrying, and ${t.infoPath} still remains. Stale metadata was cleaned automatically when safe; retry with --debug. If this persists after confirming no agent-device daemon process is running, run: ${r}`:`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. If stale metadata returns after confirming no agent-device daemon process is running, run: ${r}`}(n,e.paths)})}async function eE(e,t,a){if(!eT(e.command)||!t.startedByClient&&!a.ownedStateDir||e5(t.info))return;let n={pid:t.info.pid,removedInfo:!1,removedLock:!1,removedStateDir:!1,error:void 0};try{await eU(t.info)}catch(e){n.error=e instanceof Error?e.message:String(e)}finally{let e=r.existsSync(a.paths.infoPath);eB(a.paths.infoPath),n.removedInfo=e&&!r.existsSync(a.paths.infoPath);let t=r.existsSync(a.paths.lockPath);eB(a.paths.lockPath),n.removedLock=t&&!r.existsSync(a.paths.lockPath),a.ownedStateDir&&(r.rmSync(a.paths.baseDir,{recursive:!0,force:!0}),n.removedStateDir=!r.existsSync(a.paths.baseDir))}M({level:n.error?"warn":"info",phase:"daemon_replay_cleanup",data:n})}function eT(e){return e===C.replay||e===C.test}async function eN(e,t){let a=Date.now();for(;Date.now()-a<e;){let e=eL(t.paths.infoPath);if(e&&await ej(e,t.transportPreference))return e;await U(100)}return null}async function eC(e){let t=eF(e);if(!t.hasLock||t.hasInfo)return!1;let a=ex(e.lockPath);return!(a&&E(a.pid,a.processStartTime))&&(eB(e.lockPath),!0)}async function eU(e){await T(e.pid,{termTimeoutMs:3e3,killTimeoutMs:1e3,expectedStartTime:e.processStartTime})}function eL(e){var t,a,r;let n,o,i=eq(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=(n=eO((a=i).port),o=eO(a.httpPort),void 0===n&&void 0===o?null:{port:n,httpPort:o});return l?{token:s,...l,transport:"socket"===(r=i.transport)||"http"===r||"dual"===r?r:void 0,pid:eO(i.pid)??0,version:eR(i.version),codeSignature:eR(i.codeSignature),processStartTime:eR(i.processStartTime)}:null}function eR(e){return"string"==typeof e?e:void 0}function eO(e){return Number.isInteger(e)&&Number(e)>0?Number(e):void 0}function ex(e){let t=eq(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}eb.addSubnet("127.0.0.0",8,"ipv4"),eb.addAddress("::1","ipv6"),eb.addSubnet("::ffff:127.0.0.0",104,"ipv6");async function e$(e,t,a={}){let n=a.stopLiveProcesses??!0,o={reason:t,removedInfo:!1,removedLock:!1,stoppedInfoProcess:!1,stoppedLockProcess:!1};try{var i,s,l,c;let t=r.existsSync(e.infoPath),a=eL(e.infoPath);if(a){let t=E(a.pid,a.processStartTime);t&&!n?o.retainedInfoProcess=!0:(t&&(await eU(a),o.stoppedInfoProcess=!0),i=e.infoPath,eB(i),o.removedInfo=!0)}else t&&(s=e.infoPath,eB(s),o.removedInfo=!0);let d=r.existsSync(e.lockPath),u=ex(e.lockPath);if(u){let t=E(u.pid,u.processStartTime);t&&!n?o.retainedLockProcess=!0:(t&&(await T(u.pid,{termTimeoutMs:3e3,killTimeoutMs:1e3,expectedStartTime:u.processStartTime}),o.stoppedLockProcess=!0),l=e.lockPath,eB(l),o.removedLock=!0)}else d&&(c=e.lockPath,eB(c),o.removedLock=!0)}catch(e){o.error=e instanceof Error?e.message:String(e)}return M({level:o.error?"warn":"info",phase:"daemon_startup_metadata_cleanup",data:o}),o}function eF(e){return{hasInfo:r.existsSync(e.infoPath),hasLock:r.existsSync(e.lockPath)}}function eq(e){if(!r.existsSync(e))return null;try{return JSON.parse(r.readFileSync(e,"utf8"))}catch{return null}}function eB(e){try{r.existsSync(e)&&r.unlinkSync(e)}catch{}}async function ej(e,t){let a=eW(e,t);if(await eK(e,a))return!0;let r=eY(e,t,a);return!!r&&await eK(e,r)}async function eK(r,n){var o;return"http"===n?await function(e){let r=e.baseUrl?e2(e.baseUrl,"health"):e.httpPort?`http://127.0.0.1:${e.httpPort}/health`:null;if(!r)return Promise.resolve(!1);let n=new URL(r),o="https:"===n.protocol?a:t,i=e.baseUrl?3e3:500;return new Promise(e=>{let t=o.request({protocol:n.protocol,host:n.hostname,port:n.port,path:n.pathname+n.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 ((o=r.port)?new Promise(t=>{let a=!1,r=e.createConnection({host:"127.0.0.1",port:o},()=>{n(!0)}),n=e=>{a||(a=!0,r.destroy(),t(e))};r.setTimeout(500),r.on("timeout",()=>{n(!1)}),r.on("error",()=>{n(!1)})}):Promise.resolve(!1))}async function eH(e){let t=ez(),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};b(process.execPath,a,{env:r})}function ez(){let e=k(),t=[o.join(e,"dist","src","internal","daemon.js"),o.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 n=t.find(e=>r.existsSync(e))??a,i=o.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:n,distPaths:t,srcPath:i,useSrc:process.execArgv.includes("--experimental-strip-types")?l:!s&&l}}async function eG(e,t,a,r){let n=eW(e,a);try{return await eV(e,t,r,n)}catch(s){var o;let i=eY(e,a,n);if(!i||(o=s,"socket"!==n||!(o instanceof u)||"COMMAND_FAILED"!==o.code||"Failed to communicate with daemon"!==o.message||o.details?.daemonSocketRequestWritten!==!1))throw s;return await eV(e,t,r,i)}}async function eV(e,t,a,r){return"http"===r?await e0(e,t,a):await eZ(e,t,a)}function eW(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(eJ(a,r))return r;throw new u("COMMAND_FAILED","http"===r?"Daemon HTTP endpoint is unavailable":"Daemon socket endpoint is unavailable")}let n=("socket"===e.transport||"dual"===e.transport?["socket","http"]:["http","socket"]).find(t=>eJ(e,t));if(n)return n;throw new u("COMMAND_FAILED","Daemon metadata has no reachable transport")}function eJ(e,t){return"http"===t?!!e.httpPort:!!e.port}function eY(e,t,a){if("auto"!==t||e.baseUrl)return null;let r="socket"===a?"http":"socket";return eJ(e,r)?r:null}function eQ(e,t,a,r,n,o){let i=n?{terminated:0}:function(){let e=0;try{for(let t of e_){let a=A("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=!n&&"snapshot"!==r,l=s?function(e,t){let a=!1;try{E(e.pid,e.processStartTime)&&(process.kill(e.pid,"SIGKILL"),a=!0)}catch{T(e.pid,{termTimeoutMs:3e3,killTimeoutMs:1e3,expectedStartTime:e.processStartTime})}finally{eB(t.infoPath),eB(t.lockPath)}return{forcedKill:a}}(e,t):{forcedKill:!1};return M({level:"error",phase:"daemon_request_timeout",data:{timeoutMs:o,requestId:a,command:r,timedOutRunnerPidsTerminated:i.terminated,timedOutRunnerCleanupError:i.error,daemonPidReset:s?e.pid:void 0,daemonPidForceKilled:s?l.forcedKill:void 0,daemonPreservedAfterTimeout:!n&&!s,daemonBaseUrl:e.baseUrl}}),new u("COMMAND_FAILED","Daemon request timed out",{timeoutMs:o,requestId:a,hint:function(e){let{remote:t,resetDaemon:a,command:r}=e;if(t)return"Retry with --debug and verify the remote daemon URL, auth token, and remote host logs.";if(!a){let e=r===C.snapshot?" If this was the first Apple-platform snapshot on the device, run agent-device prepare ios-runner with the same --platform before snapshot/test so runner startup is handled explicitly.":"";return`Retry with --debug and check daemon diagnostics logs. The timed-out ${r??"request"} request was canceled and Apple runner work was aborted when detected; the daemon was kept alive so the session can still be closed or inspected.${e}`}return"Retry with --debug and check daemon diagnostics logs. Timed-out Apple runner xcodebuild processes were terminated when detected."}({remote:n,resetDaemon:s,command:r})})}function eX(e,t,a,r={}){return M({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",{...r,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 eZ(t,a,r){let n=t.port;if(!n)throw new u("COMMAND_FAILED","Daemon socket endpoint is unavailable");return new Promise((o,i)=>{let s=!1,l=e.createConnection({host:"127.0.0.1",port:n},()=>{s=!0,l.write(`${JSON.stringify(a)}
3
+ `)}),c=y(a.flags?.stateDir??process.env.AGENT_DEVICE_STATE_DIR),d=!1,f="number"==typeof r?setTimeout(()=>{d=!0,l.destroy(),i(eQ(t,c,a.meta?.requestId,a.command,!1,r))},r):void 0;!function(e,t){let{req:a,isSettled:r,resolve:n,reject:o,clearTimeout:i}=t,s="",l=(e,t)=>{i(),o(new u("COMMAND_FAILED","Invalid daemon response",{requestId:a.meta?.requestId,line:e},t instanceof Error?t:void 0))};e.setEncoding("utf8"),e.on("data",t=>{if(r())return;let a=p(s,t);for(let t of(s=a.buffer,a.lines))try{let a=JSON.parse(t);if(w(a)){ee(a.event);continue}let r=h(a)?a.response:a;i(),n(r),e.end();return}catch(e){l(t,e);return}})}(l,{req:a,isSettled:()=>d,clearTimeout:()=>{f&&clearTimeout(f)},resolve:e=>{d=!0,o(e)},reject:e=>{d=!0,i(e)}}),l.on("error",e=>{d||(d=!0,f&&clearTimeout(f),i(eX(e,a.meta?.requestId,!1,{daemonSocketRequestWritten:s})))})})}async function e0(e,r,n){var o,i,s;let l,c=e.baseUrl?new URL(e2(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 d=JSON.stringify((o=r,i={includeTokenParam:!e.baseUrl},l=o.meta?.requestId??P(),"lease_allocate"!==(s=o.command)&&"lease_heartbeat"!==s&&"lease_release"!==s?{jsonrpc:"2.0",id:l,method:"agent_device.command",params:o}:{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"}}(o.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}}}(o,o.command,i)})),f={"content-type":"application/json","content-length":Buffer.byteLength(d)};return e.baseUrl&&e.token&&(f.authorization=`Bearer ${e.token}`,f["x-agent-device-token"]=e.token),await new Promise((o,i)=>{let s=y(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:f},t=>{var a;(a=t.headers?.["content-type"],m(r)&&String(Array.isArray(a)?a.join(","):a??"").includes("application/x-ndjson"))?function(e,t){let{req:a,handleResponseBody:r,reject:n,clearTimeout:o}=t,i="",s=!1,l=e=>{try{let t=JSON.parse(e);if(w(t))return ee(t.event),!1;if(h(t))return s=!0,o(),r(JSON.stringify(t.response)),!0;throw Error("Missing daemon progress response envelope")}catch(t){return s=!0,o(),n(new u("COMMAND_FAILED","Invalid daemon response",{requestId:a.meta?.requestId,line:e},t instanceof Error?t:void 0)),!0}};e.setEncoding("utf8"),e.on("data",e=>{if(s)return;let t=p(i,e);for(let e of(i=t.buffer,t.lines))if(e&&l(e))return}),e.on("end",()=>{if(s)return;let e=i.trim();e&&l(e)||(s=!0,o(),n(new u("COMMAND_FAILED","Invalid daemon response",{requestId:a.meta?.requestId,line:e})))}),e.on("error",e=>{s||(s=!0,o(),n(new u("COMMAND_FAILED","Failed to read daemon response",{requestId:a.meta?.requestId},e instanceof Error?e:void 0)))})}(t,{req:r,reject:i,clearTimeout:()=>{I&&clearTimeout(I)},handleResponseBody:t=>e1(t,{info:e,req:r,resolve:o,reject:i})}):X(t).then(t=>{I&&clearTimeout(I),e1(t,{info:e,req:r,resolve:o,reject:i})}).catch(e=>{I&&clearTimeout(I),i(new u("COMMAND_FAILED","Failed to read daemon response",{requestId:r.meta?.requestId},e instanceof Error?e:void 0))})}),g=e5(e),I="number"==typeof n?setTimeout(()=>{l.destroy(),i(eQ(e,s,r.meta?.requestId,r.command,g,n))},n):void 0;l.on("error",e=>{I&&clearTimeout(I),i(eX(e,r.meta?.requestId,g))}),l.write(d),l.end()})}function e1(e,t){let{info:a,req:r,resolve:n,reject:o}=t;try{var i,s,l;let t=(i=e,JSON.parse(i));if(t.error){let e;return void o((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 o(new u("COMMAND_FAILED","Invalid daemon RPC response",{requestId:r.meta?.requestId}));e3(a,r,t.result,n,o)}catch(t){o(new u("COMMAND_FAILED","Invalid daemon response",{requestId:r.meta?.requestId,line:e},t instanceof Error?t:void 0))}}async function e3(e,t,a,r,n){try{r(e.baseUrl&&a.ok?await ev(e,t,a):a)}catch(e){n(e)}}function e5(e){return"string"==typeof e.baseUrl&&e.baseUrl.length>0}function e2(e,t){return new URL(t,e.endsWith("/")?e:`${e}/`).toString()}function e8(e={},t={}){let a=t.transport??eS,r=async(t,r=[],n={})=>{var o,i;let s=(o=e,i=n,{...o,...i}),l=await a({session:x(s.session),command:t,positionals:r,flags:$(s),runtime:s.runtime,meta:W(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??{}},n=async(e={})=>{let t=await r(N.sessionList,[],e);return(Array.isArray(t.sessions)?t.sessions:[]).map(O)},o=async(e,t={})=>{let a=j(e,t);return await r(a.command,a.positionals,a.options)},i=(t={})=>{var a,r;return x((a=e,r=t,{...a,...r}).session)};return{command:{wait:async e=>await o("wait",e),alert:async(e={})=>await o("alert",e),appState:async(e={})=>await o("appstate",e),back:async(e={})=>await o("back",e),home:async(e={})=>await o("home",e),rotate:async e=>await o("rotate",e),appSwitcher:async(e={})=>await o("app-switcher",e),keyboard:async(e={})=>await o("keyboard",e),clipboard:async e=>await o("clipboard",e),reactNative:async e=>await o("react-native",e),prepare:async e=>await o("prepare",e)},devices:{list:async(e={})=>{let t=await o("devices",e);return(Array.isArray(t.devices)?t.devices:[]).map(J)},boot:async(e={})=>await o("boot",e),shutdown:async(e={})=>await o("shutdown",e)},sessions:{list:async(e={})=>await n(e),close:async(e={})=>{let t=i(e),a=(await o("close",e)).shutdown;return{session:t,shutdown:"object"==typeof a&&null!==a?a:void 0,identifiers:{session:t}}}},apps:{install:async e=>z(await o("install",e),i(e)),reinstall:async e=>z(await o("reinstall",e),i(e)),installFromSource:async e=>q(await o("install-from-source",e),i(e)),list:async(e={})=>{let t=await o("apps",e);return Array.isArray(t.apps)?t.apps.filter(e=>"string"==typeof e):[]},open:async e=>{let t=i(e),a=await o("open",e),r=G(a),n=Q(a,"appBundleId");return{session:t,sessionStateDir:Q(a,"sessionStateDir"),appName:Q(a,"appName"),appBundleId:n,appId:n,startup:F(a.startup),runtime:H(a.runtime),device:r,identifiers:{session:t,deviceId:r?.id,deviceName:r?.name,udid:r?.ios?.udid,serial:r?.android?.serial,appId:n,appBundleId:n}}},close:async(e={})=>{let t=i(e),a=(await o("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 o("push",e),triggerEvent:async e=>await o("trigger-app-event",e)},materializations:{release:async e=>B(await r(N.releaseMaterializedPaths,[],{...e,materializationId:e.materializationId}))},leases:{allocate:async e=>e6(await r(N.leaseAllocate,[],{...e,leaseId:void 0,leaseTtlMs:e.ttlMs})),heartbeat:async e=>e6(await r(N.leaseHeartbeat,[],{...e,leaseTtlMs:e.ttlMs})),release:async e=>({released:!0===(await r(N.leaseRelease,[],e)).released})},metro:{prepare:async t=>await R({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 L({metroHost:t.metroHost,metroPort:t.metroPort,bundleUrl:t.bundleUrl,runtime:e.runtime,timeoutMs:t.timeoutMs})},capture:{snapshot:async(e={})=>{var t,a,r;let n,s,l,c,d,u=i(e);return t=await o("snapshot",e),a=u,n=Q(t,"appBundleId"),{nodes:K(t.nodes),truncated:!0===t.truncated,appName:Q(t,"appName"),appBundleId:n,...(s=e4((r=t).visibility),l=e4(r.androidSnapshot),c=e4(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:n,appBundleId:n}}},screenshot:async(e={})=>{let t=i(e),a=await o("screenshot",e);return{path:Y(a,"path"),overlayRefs:V(a),identifiers:{session:t}}},diff:async e=>await o("diff",e)},interactions:{click:async e=>await o("click",e),press:async e=>await o("press",e),longPress:async e=>await o("longpress",e),swipe:async e=>await o("swipe",e),pan:async e=>await o("gesture-pan",e),fling:async e=>await o("gesture-fling",e),swipeGesture:async e=>await o("gesture-swipe",e),focus:async e=>await o("focus",e),type:async e=>await o("type",e),fill:async e=>await o("fill",e),scroll:async e=>await o("scroll",e),pinch:async e=>await o("gesture-pinch",e),rotateGesture:async e=>await o("gesture-rotate",e),transformGesture:async e=>await o("gesture-transform",e),get:async e=>await o("get",e),is:async e=>await o("is",e),find:async e=>await o("find",e)},replay:{run:async e=>await o("replay",e),test:async e=>await o("test",e)},batch:{run:async e=>await o("batch",e)},observability:{perf:async(e={})=>await o("perf",e),logs:async(e={})=>await o("logs",e),network:async(e={})=>await o("network",e)},recording:{record:async e=>await o("record",e),trace:async e=>await o("trace",e)},settings:{update:async e=>await o("settings",e)}}}function e4(e){return"object"==typeof e&&null!==e?e:void 0}function e6(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{e8 as createAgentDeviceClient,Z as formatDurationSeconds,eS as sendToDaemon};
@@ -0,0 +1 @@
1
+ import"./9152.js";import{PLATFORM_SELECTORS as t}from"./1644.js";let e=["reject","strip"],a=["ios-simulator","ios-instance","android-instance"],n=["socket","http","dual"],r=["auto","socket","http"],i=["none","tenant"],o=["summary","headers","body","all"];function s(t){return{parse:e=>t(e,"$")}}function d(t,e){throw Error(`${t}: ${e}`)}function l(t,e){return(!t||"object"!=typeof t||Array.isArray(t))&&d(e,"Expected an object"),t}function c(t,e){return"string"!=typeof t&&d(e,"Expected a string"),t}function u(t,e){let a=c(t,e).trim();return a||d(e,"Expected a non-empty string"),a}function m(t,e){return Number.isInteger(t)||d(e,"Expected an integer"),t}function f(t,e,a){let n=t[e];return void 0===n?void 0:c(n,`${a}.${e}`)}function $(t,e,a){let n=t[e];if(void 0!==n)return"boolean"!=typeof n&&d(`${a}.${e}`,"Expected a boolean"),n}function p(t,e,a){let n=t[e];return void 0===n?void 0:m(n,`${a}.${e}`)}function I(t,e,a){let n=t[e];return void 0===n?void 0:l(n,`${a}.${e}`)}function h(t,e,a,n){let r=t[e];if(void 0!==r)return"string"==typeof r&&a.includes(r)||d(`${n}.${e}`,`Expected one of: ${a.join(", ")}`),r}function E(t,e){let a=l(t,e),n={};for(let[t,r]of Object.entries(a))n[t]=c(r,`${e}.${t}`);return n}let S=s((t,e)=>{let a=l(t,e);return{platform:h(a,"platform",["ios","android"],e),metroHost:f(a,"metroHost",e),metroPort:p(a,"metroPort",e),bundleUrl:f(a,"bundleUrl",e),launchUrl:f(a,"launchUrl",e)}}),v=s((n,r)=>{var o,s;let v=l(n,r),M=(o=v.positionals,s=`${r}.positionals`,Array.isArray(o)||d(s,"Expected an array"),o),b=I(v,"meta",r);return{token:f(v,"token",r),session:f(v,"session",r),command:c(v.command,`${r}.command`),positionals:M.map((t,e)=>c(t,`${r}.positionals[${String(e)}]`)),flags:I(v,"flags",r),runtime:void 0===v.runtime?void 0:S.parse(v.runtime),meta:void 0===b?void 0:{requestId:f(b,"requestId",`${r}.meta`),debug:$(b,"debug",`${r}.meta`),cwd:f(b,"cwd",`${r}.meta`),sessionExplicit:$(b,"sessionExplicit",`${r}.meta`),tenantId:f(b,"tenantId",`${r}.meta`),runId:f(b,"runId",`${r}.meta`),leaseId:f(b,"leaseId",`${r}.meta`),leaseTtlMs:p(b,"leaseTtlMs",`${r}.meta`),leaseBackend:h(b,"leaseBackend",a,`${r}.meta`),sessionIsolation:h(b,"sessionIsolation",i,`${r}.meta`),uploadedArtifactId:f(b,"uploadedArtifactId",`${r}.meta`),clientArtifactPaths:void 0===b.clientArtifactPaths?void 0:E(b.clientArtifactPaths,`${r}.meta.clientArtifactPaths`),installSource:void 0===b.installSource?void 0:function(t,e){let a=l(t,e),n=c(a.kind,`${e}.kind`);if("url"===n){let t=c(a.url,`${e}.url`),r=void 0===a.headers?void 0:E(a.headers,`${e}.headers`);return r?{kind:n,url:t,headers:r}:{kind:n,url:t}}if("path"===n)return{kind:n,path:c(a.path,`${e}.path`)};if("github-actions-artifact"===n){let t,n,r,i,o;return t=u(a.owner,`${e}.owner`),n=u(a.repo,`${e}.repo`),r=void 0!==a.artifactId,i=void 0!==a.runId,o=void 0!==a.artifactName,(r&&(i||o)&&d(`${e}`,"Expected either artifactId or artifactName, not both"),r||!i||o||d(`${e}`,"Expected artifactName when runId is specified"),r||o||d(`${e}`,"Expected artifactId or artifactName"),r)?{kind:"github-actions-artifact",owner:t,repo:n,artifactId:m(a.artifactId,`${e}.artifactId`)}:{kind:"github-actions-artifact",owner:t,repo:n,...i?{runId:m(a.runId,`${e}.runId`)}:{},artifactName:u(a.artifactName,`${e}.artifactName`)}}d(`${e}.kind`,'Expected "url", "path", or "github-actions-artifact"')}(b.installSource,`${r}.meta.installSource`),retainMaterializedPaths:$(b,"retainMaterializedPaths",`${r}.meta`),materializedPathRetentionMs:p(b,"materializedPathRetentionMs",`${r}.meta`),materializationId:f(b,"materializationId",`${r}.meta`),lockPolicy:h(b,"lockPolicy",e,`${r}.meta`),lockPlatform:h(b,"lockPlatform",t,`${r}.meta`)}}});function M(t,e){return{token:f(t,"token",e),session:f(t,"session",e),tenantId:f(t,"tenantId",e),tenant:f(t,"tenant",e),runId:f(t,"runId",e)}}let b=s((t,e)=>{let n=l(t,e);return{...M(n,e),ttlMs:p(n,"ttlMs",e),backend:h(n,"backend",a,e)}}),_=s((t,e)=>{let a,n={record:a=l(t,e),leaseId:f(a,"leaseId",e),ttlMs:p(a,"ttlMs",e)};return{...M(n.record,e),leaseId:n.leaseId,ttlMs:n.ttlMs}}),A=s((t,e)=>{let a=l(t,e);return void 0!==a.ttlMs&&d(`${e}.ttlMs`,"Unexpected field"),{...M(a,e),leaseId:f(a,"leaseId",e)}}),N=s((t,e)=>{let a,n=l(t,e);return{jsonrpc:f(n,"jsonrpc",e),id:(null==(a=n.id)||"string"!=typeof a&&"number"!=typeof a&&d(`${e}.id`,"Expected a string, number, or null"),a),method:f(n,"method",e),params:n.params}});export{e as DAEMON_LOCK_POLICIES,n as DAEMON_SERVER_MODES,r as DAEMON_TRANSPORT_PREFERENCES,a as LEASE_BACKENDS,o as NETWORK_INCLUDE_MODES,i as SESSION_ISOLATION_MODES,v as daemonCommandRequestSchema,S as daemonRuntimeSchema,N as jsonRpcRequestSchema,b as leaseAllocateSchema,_ as leaseHeartbeatSchema,A as leaseReleaseSchema};
@@ -0,0 +1 @@
1
+ import"./3675.js";import{AppError as t}from"./9152.js";function e(e,i){if(void 0===e||""===e.trim())throw new t("INVALID_ARGS",`settings location set requires ${i}`);return o(Number(e),i)}function i(t){return{latitude:o(t?.latitude,"latitude"),longitude:o(t?.longitude,"longitude")}}function o(e,i){let o="latitude"===i?-90:-180,r="latitude"===i?90:180;if("number"!=typeof e||!Number.isFinite(e)||e<o||e>r)throw new t("INVALID_ARGS",`${i} must be a number from ${o} to ${r}`);return e}export{e as readLocationCoordinate,i as requireLocationCoordinates};
@@ -0,0 +1 @@
1
+ import{PLATFORM_SELECTORS as e,DEVICE_TARGETS as t}from"./1644.js";import"./2672.js";let r=["ref","selector","point"];function i(e){return{type:"string",...e?{description:e}:{}}}function n(e){return{type:"integer",...e?{description:e}:{}}}function o(e){return{type:"boolean",...e?{description:e}:{}}}function s(e){return{type:"object",additionalProperties:!0,...e?{description:e}:{}}}function a(e){return{...e,required:!0}}function d(e){return K(i(e),k)}function c(e){return K({type:"number",...e?{description:e}:{}},$)}function l(e,t={}){var r,i;return K((r=e,i=t,{...n(r),...void 0===i.min?{}:{minimum:i.min},...void 0===i.max?{}:{maximum:i.max}}),(e,r)=>F(e,r,t))}function u(e){return K(o(e),D)}function p(e,t){return K({type:"string",enum:e,...t?{description:t}:{}},(t,r)=>P(t,r,e))}function f(e){return K(s(e),H)}function m(e){return K({type:"array",items:{type:"string"},...e?{description:e}:{}},L)}function b(e){return K(e,(e,t)=>e[t])}function g(e,t){return K(e,t)}function y(){return K({oneOf:[...z(),{type:"object",properties:{kind:{type:"string",const:"point"},x:{type:"number"},y:{type:"number"}},required:["kind","x","y"],additionalProperties:!1}],description:"UI target. This is separate from deviceTarget, which selects the device form."},(e,t)=>void 0===e[t]?void 0:function(e,t){let i=W(e,t),n=U(i,"kind",r);switch(n){case"ref":return{kind:n,ref:T(i,"ref"),label:k(i,"label")};case"selector":return{kind:n,selector:T(i,"selector")};case"point":return{kind:n,x:O(i,"x"),y:O(i,"y")}}}(e,t))}function h(){return K({oneOf:z(),description:"UI element target by snapshot ref or selector expression."},(e,t)=>{let r,i;return void 0===e[t]?void 0:"ref"===(i=U(r=W(e,t),"kind",["ref","selector"]))?{kind:i,ref:T(r,"ref"),label:k(r,"label")}:{kind:i,selector:T(r,"selector")}})}function v(e){return K({type:"object",description:e,properties:{x:{type:"number"},y:{type:"number"}},required:["x","y"],additionalProperties:!1},(e,t)=>void 0===e[t]?void 0:I(e,t))}function w(){return{depth:l("Snapshot traversal depth.",{min:0}),scope:d("Snapshot scope selector used before resolution."),raw:u("Use raw snapshot data during selector resolution.")}}function E(){return{count:l("Number of press/click repetitions.",{min:1}),intervalMs:l("Delay between repeated press/click actions.",{min:0}),holdMs:l("Hold duration for each action.",{min:0}),jitterPx:l("Randomization radius in pixels.",{min:0}),doubleTap:u("Request a double-tap action.")}}function x(r){return function(r,i=[]){return{type:"object",properties:{session:{type:"string",description:"Agent-device session name."},platform:{type:"string",enum:e,description:"Platform selector used to resolve a device."},deviceTarget:{type:"string",enum:t,description:"Device target form. Maps to the CLI --target flag."},target:{type:"string",enum:t,description:"Alias for deviceTarget on commands without a UI target field. Interaction commands reserve target for the UI element."},device:{type:"string",description:"Device name selector."},udid:{type:"string",description:"iOS device UDID selector."},serial:{type:"string",description:"Android serial selector."},iosSimulatorDeviceSet:{type:"string",description:"iOS simulator device-set path used for device resolution."},androidDeviceAllowlist:{type:"string",description:"Android serial allowlist used for device resolution."},daemonBaseUrl:{type:"string",description:"Remote daemon base URL."},daemonAuthToken:{type:"string",description:"Remote daemon auth token."},tenant:{type:"string",description:"Remote tenant identifier."},runId:{type:"string",description:"Lease run identifier."},leaseId:{type:"string",description:"Existing lease identifier."},cwd:{type:"string",description:"Working directory for command execution."},debug:{type:"boolean",description:"Enable debug diagnostics."},...r},...i.length>0?{required:i}:{},additionalProperties:!1}}(Object.fromEntries(Object.entries(r).map(([e,t])=>[e,t.schema])),Object.entries(r).flatMap(([e,t])=>t.required?[e]:[]))}function j(e,t){let r=A(e),i=Object.fromEntries(Object.entries(t).flatMap(([e,t])=>{let i=t.read(r,e);if(t.required&&void 0===i)throw Error(`Expected ${e} to be set.`);return void 0===i?[]:[[e,i]]})),n=S(r,{readTargetAlias:!Object.hasOwn(t,"target")});return B({...n,...q(n),...i})}function A(e){if(null==e)return{};if(!e||"object"!=typeof e||Array.isArray(e))throw Error("Expected object arguments.");return e}function S(r,i={}){return{session:k(r,"session"),platform:P(r,"platform",e),deviceTarget:function(e,r){let i=P(e,"deviceTarget",t);if(!1===r.readTargetAlias||void 0===e.target)return i;let n=P(e,"target",t);if(void 0!==i&&n!==i)throw Error("Expected target alias to match deviceTarget when both are set.");return i??n}(r,i),device:k(r,"device"),udid:k(r,"udid"),serial:k(r,"serial"),iosSimulatorDeviceSet:k(r,"iosSimulatorDeviceSet"),androidDeviceAllowlist:k(r,"androidDeviceAllowlist"),daemonBaseUrl:k(r,"daemonBaseUrl"),daemonAuthToken:k(r,"daemonAuthToken"),tenant:k(r,"tenant"),runId:k(r,"runId"),leaseId:k(r,"leaseId"),cwd:k(r,"cwd"),debug:D(r,"debug")}}function I(e,t){let r=W(e,t);return{x:O(r,"x"),y:O(r,"y")}}function T(e,t){let r=e[t];if("string"!=typeof r||0===r.length)throw Error(`Expected ${t} to be a non-empty string.`);return r}function k(e,t){let r=e[t];if(void 0!==r){if("string"!=typeof r||0===r.length)throw Error(`Expected ${t} to be a non-empty string.`);return r}}function O(e,t){let r=e[t];if("number"!=typeof r||!Number.isFinite(r))throw Error(`Expected ${t} to be a finite number.`);return r}function $(e,t){let r=e[t];if(void 0!==r){if("number"!=typeof r||!Number.isFinite(r))throw Error(`Expected ${t} to be a finite number.`);return r}}function F(e,t,r={}){let i=e[t];if(void 0!==i){if(!Number.isInteger(i))throw Error(`Expected ${t} to be an integer.`);if(void 0!==r.min&&i<r.min)throw Error(`Expected ${t} to be at least ${r.min}.`);if(void 0!==r.max&&i>r.max)throw Error(`Expected ${t} to be at most ${r.max}.`);return i}}function D(e,t){let r=e[t];if(void 0!==r){if("boolean"!=typeof r)throw Error(`Expected ${t} to be a boolean.`);return r}}function U(e,t,r){let i=e[t];if("string"!=typeof i||!r.includes(i))throw Error(`Expected ${t} to be one of: ${r.join(", ")}.`);return i}function P(e,t,r){let i=e[t];if(void 0!==i){if("string"!=typeof i||!r.includes(i))throw Error(`Expected ${t} to be one of: ${r.join(", ")}.`);return i}}function q(e){return B({session:e.session,platform:e.platform,target:e.deviceTarget,device:e.device,udid:e.udid,serial:e.serial,iosSimulatorDeviceSet:e.iosSimulatorDeviceSet,androidDeviceAllowlist:e.androidDeviceAllowlist,daemonBaseUrl:e.daemonBaseUrl,daemonAuthToken:e.daemonAuthToken,tenant:e.tenant,runId:e.runId,leaseId:e.leaseId,cwd:e.cwd,debug:e.debug})}function M(e){switch(e.kind){case"ref":return{ref:e.ref,label:e.label};case"selector":return{selector:e.selector};case"point":return{x:e.x,y:e.y}}}function R(e){switch(e.kind){case"ref":return{ref:e.ref,label:e.label};case"selector":return{selector:e.selector}}}function _(e){return{count:e.count,intervalMs:e.intervalMs,holdMs:e.holdMs,jitterPx:e.jitterPx,doubleTap:e.doubleTap}}function C(e){return{depth:e.depth,scope:e.scope,raw:e.raw}}function N(e,t,r){let i=new Set(t),n=Object.keys(e).filter(e=>!i.has(e));if(n.length>0)throw Error(`${r} has unknown field(s): ${n.join(", ")}.`)}function B(e){return Object.fromEntries(Object.entries(e).filter(([,e])=>void 0!==e))}function K(e,t){return{schema:e,required:!1,read:t}}function H(e,t){let r=e[t];if(void 0!==r){if(!r||"object"!=typeof r||Array.isArray(r))throw Error(`Expected ${t} to be an object.`);return r}}function L(e,t){let r=e[t];if(void 0!==r){if(!Array.isArray(r)||r.some(e=>"string"!=typeof e))throw Error(`Expected ${t} to be an array of strings.`);return r}}function z(){return[{type:"object",properties:{kind:{type:"string",const:"ref"},ref:{type:"string",description:"Snapshot element ref such as @e12."},label:{type:"string",description:"Optional human label for the ref."}},required:["kind","ref"],additionalProperties:!1},{type:"object",properties:{kind:{type:"string",const:"selector"},selector:{type:"string",description:"Agent-device selector expression."}},required:["kind","selector"],additionalProperties:!1}]}function W(e,t){let r=e[t];if(!r||"object"!=typeof r||Array.isArray(r))throw Error(`Expected ${t} to be an object.`);return r}export{N as assertAllowedKeys,u as booleanField,o as booleanSchema,q as commonToClientOptions,B as compactRecord,g as customField,h as elementTargetField,p as enumField,x as fieldsInputSchema,l as integerField,n as integerSchema,y as interactionTargetField,b as jsonSchemaField,f as looseObjectField,s as looseObjectSchema,c as numberField,P as optionalEnum,F as optionalInteger,v as pointField,S as readCommonInput,j as readFieldInput,A as readInputRecord,I as readPoint,E as repeatedFields,U as requiredEnum,a as requiredField,O as requiredNumber,w as selectorSnapshotFields,m as stringArrayField,d as stringField,i as stringSchema,R as toClientElementTarget,M as toClientInteractionTarget,_ as toRepeatedOptions,C as toSelectorSnapshotOptions};
@@ -135,7 +135,7 @@ export declare type AndroidPortReverseProvider = {
135
135
  };
136
136
 
137
137
  export declare type AndroidTextInjectionRequest = {
138
- action: 'type' | 'fill';
138
+ action: AndroidTextInputAction;
139
139
  text: string;
140
140
  delayMs?: number;
141
141
  /**
@@ -150,6 +150,8 @@ export declare type AndroidTextInjectionRequest = {
150
150
 
151
151
  export declare type AndroidTextInjector = (request: AndroidTextInjectionRequest) => Promise<void>;
152
152
 
153
+ declare type AndroidTextInputAction = 'type' | 'fill';
154
+
153
155
  declare type AndroidTouchGestureRequest = {
154
156
  kind: 'swipe';
155
157
  x1: number;
@@ -182,8 +184,6 @@ declare type AndroidTouchGestureRequest = {
182
184
 
183
185
  declare type AndroidTouchInjector = (request: AndroidTouchGestureRequest) => Promise<Record<string, unknown> | void>;
184
186
 
185
- declare type ApplePlatform = 'ios' | 'macos';
186
-
187
187
  declare type AppsFilter = 'user-installed' | 'all';
188
188
 
189
189
  export declare function captureAndroidLogcatWithAdb(adb: AndroidAdbExecutor, options?: AndroidLogcatCaptureOptions): Promise<string>;
@@ -192,6 +192,10 @@ export declare function createAndroidPortReverseManager(provider: AndroidAdbProv
192
192
 
193
193
  export declare function createLocalAndroidAdbProvider(device: DeviceInfo): AndroidAdbProvider;
194
194
 
195
+ declare const DEVICE_KINDS: readonly ["simulator", "emulator", "device"];
196
+
197
+ declare const DEVICE_TARGETS: readonly ["mobile", "tv", "desktop"];
198
+
195
199
  declare type DeviceInfo = {
196
200
  platform: Platform;
197
201
  id: string;
@@ -202,9 +206,9 @@ declare type DeviceInfo = {
202
206
  simulatorSetPath?: string;
203
207
  };
204
208
 
205
- declare type DeviceKind = 'simulator' | 'emulator' | 'device';
209
+ declare type DeviceKind = (typeof DEVICE_KINDS)[number];
206
210
 
207
- declare type DeviceTarget = 'mobile' | 'tv' | 'desktop';
211
+ declare type DeviceTarget = (typeof DEVICE_TARGETS)[number];
208
212
 
209
213
  export declare function dismissAndroidKeyboardWithAdb(adb: AndroidAdbExecutor): Promise<AndroidKeyboardDismissResult>;
210
214
 
@@ -250,7 +254,9 @@ export declare function listAndroidAppsWithAdb(adb: AndroidAdbExecutor, options?
250
254
 
251
255
  export declare function openAndroidAppWithAdb(adb: AndroidAdbExecutor, packageName: string, options?: AndroidOpenAppWithAdbOptions): Promise<void>;
252
256
 
253
- declare type Platform = ApplePlatform | 'android' | 'linux';
257
+ declare type Platform = (typeof PLATFORMS)[number];
258
+
259
+ declare const PLATFORMS: readonly ["ios", "macos", "android", "linux"];
254
260
 
255
261
  export declare function readAndroidClipboardWithAdb(adb: AndroidAdbExecutor): Promise<string>;
256
262
 
@@ -1 +1 @@
1
- import{AppError as t}from"./9152.js";import{resolveAppsFilter as e}from"./1393.js";import{parseAndroidForegroundApp as i,parseAndroidLaunchablePackages as a,parseAndroidUserInstalledPackages as r,inferAndroidAppName as o,parseAndroidLaunchComponent as n,isAmStartError as d}from"./8806.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 _="android.intent.category.LAUNCHER",m="android.intent.category.DEFAULT";async function w(t,e){await t(["shell","am","force-stop",e])}async function h(t,e,i=[_]){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 C(e,i,a={}){let r=a.category??_;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 h(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,streamAndroidLogcatWithAdb}from"./8806.js";export{createAndroidPortReverseManager,createLocalAndroidAdbProvider}from"./9639.js";export{dismissAndroidKeyboardWithAdb,getAndroidKeyboardStatusWithAdb,readAndroidClipboardWithAdb,writeAndroidClipboardWithAdb}from"./8133.js";export{w as forceStopAndroidAppWithAdb,u as getAndroidAppStateWithAdb,c as listAndroidAppsWithAdb,C as openAndroidAppWithAdb,h as resolveAndroidLaunchComponentWithAdb};
1
+ import{AppError as t}from"./9152.js";import{resolveAppsFilter as e}from"./3675.js";import{parseAndroidForegroundApp as i,parseAndroidLaunchablePackages as a,parseAndroidUserInstalledPackages as r,inferAndroidAppName as o,parseAndroidLaunchComponent as n,isAmStartError as d}from"./8806.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 _="android.intent.category.LAUNCHER",m="android.intent.category.DEFAULT";async function w(t,e){await t(["shell","am","force-stop",e])}async function h(t,e,i=[_]){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 C(e,i,a={}){let r=a.category??_;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 h(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,streamAndroidLogcatWithAdb}from"./8806.js";export{createAndroidPortReverseManager,createLocalAndroidAdbProvider}from"./9639.js";export{dismissAndroidKeyboardWithAdb,getAndroidKeyboardStatusWithAdb,readAndroidClipboardWithAdb,writeAndroidClipboardWithAdb}from"./8133.js";export{w as forceStopAndroidAppWithAdb,u as getAndroidAppStateWithAdb,c as listAndroidAppsWithAdb,C as openAndroidAppWithAdb,h as resolveAndroidLaunchComponentWithAdb};
@@ -103,23 +103,25 @@ export declare type AndroidSnapshotBackendMetadata = {
103
103
  backend: 'android-helper' | 'uiautomator-dump';
104
104
  helperVersion?: string;
105
105
  helperApiVersion?: string;
106
- helperTransport?: 'instrumentation' | 'persistent-session';
106
+ helperTransport?: AndroidSnapshotHelperTransport;
107
107
  helperSessionReused?: boolean;
108
108
  fallbackReason?: string;
109
- installReason?: 'missing' | 'outdated' | 'forced' | 'current' | 'skipped';
109
+ installReason?: AndroidSnapshotHelperInstallReason;
110
110
  waitForIdleTimeoutMs?: number;
111
111
  waitForIdleQuietMs?: number;
112
112
  timeoutMs?: number;
113
113
  maxDepth?: number;
114
114
  maxNodes?: number;
115
115
  rootPresent?: boolean;
116
- captureMode?: 'interactive-windows' | 'active-window';
116
+ captureMode?: AndroidSnapshotCaptureMode;
117
117
  windowCount?: number;
118
118
  nodeCount?: number;
119
119
  helperTruncated?: boolean;
120
120
  elapsedMs?: number;
121
121
  };
122
122
 
123
+ declare type AndroidSnapshotCaptureMode = 'interactive-windows' | 'active-window';
124
+
123
125
  export declare type AndroidSnapshotHelperArtifact = {
124
126
  apkPath: string;
125
127
  manifest: AndroidSnapshotHelperManifest;
@@ -145,12 +147,14 @@ export declare type AndroidSnapshotHelperCaptureOptions = {
145
147
 
146
148
  export declare type AndroidSnapshotHelperInstallPolicy = 'missing-or-outdated' | 'always' | 'never';
147
149
 
150
+ declare type AndroidSnapshotHelperInstallReason = 'missing' | 'outdated' | 'forced' | 'current' | 'skipped';
151
+
148
152
  export declare type AndroidSnapshotHelperInstallResult = {
149
153
  packageName: string;
150
154
  versionCode: number;
151
155
  installedVersionCode?: number;
152
156
  installed: boolean;
153
- reason: 'missing' | 'outdated' | 'forced' | 'current' | 'skipped';
157
+ reason: AndroidSnapshotHelperInstallReason;
154
158
  };
155
159
 
156
160
  export declare type AndroidSnapshotHelperManifest = {
@@ -180,12 +184,12 @@ export declare type AndroidSnapshotHelperMetadata = {
180
184
  maxDepth?: number;
181
185
  maxNodes?: number;
182
186
  rootPresent?: boolean;
183
- captureMode?: 'interactive-windows' | 'active-window';
187
+ captureMode?: AndroidSnapshotCaptureMode;
184
188
  windowCount?: number;
185
189
  nodeCount?: number;
186
190
  truncated?: boolean;
187
191
  elapsedMs?: number;
188
- transport?: 'instrumentation' | 'persistent-session';
192
+ transport?: AndroidSnapshotHelperTransport;
189
193
  sessionReused?: boolean;
190
194
  };
191
195
 
@@ -205,8 +209,10 @@ export declare type AndroidSnapshotHelperPreparedArtifact = AndroidSnapshotHelpe
205
209
  cleanup?: () => Promise<void>;
206
210
  };
207
211
 
212
+ declare type AndroidSnapshotHelperTransport = 'instrumentation' | 'persistent-session';
213
+
208
214
  declare type AndroidTextInjectionRequest = {
209
- action: 'type' | 'fill';
215
+ action: AndroidTextInputAction;
210
216
  text: string;
211
217
  delayMs?: number;
212
218
  /**
@@ -221,6 +227,8 @@ declare type AndroidTextInjectionRequest = {
221
227
 
222
228
  declare type AndroidTextInjector = (request: AndroidTextInjectionRequest) => Promise<void>;
223
229
 
230
+ declare type AndroidTextInputAction = 'type' | 'fill';
231
+
224
232
  declare type AndroidTouchGestureRequest = {
225
233
  kind: 'swipe';
226
234
  x1: number;
@@ -1,4 +1,4 @@
1
- import e from"node:crypto";import t from"node:fs/promises";import r from"node:path";import{promises as i}from"node:fs";import{normalizeError as a,AppError as n}from"./9152.js";import{withDiagnosticTimer as o,emitDiagnostic as s}from"./7599.js";import{readVersion as d,findProjectRoot as l}from"./9671.js";import{resolveAndroidTouchInjector as u,resolveAndroidAdbProvider as c,resolveAndroidAdbExecutor as p,installAndroidAdbPackage as m}from"./9639.js";import{appSwitcherAndroid as h,homeAndroid as f,scrollAndroid as w,longPressAndroid as _,typeAndroid as A,getAndroidScreenSize as g,pressAndroid as y,focusAndroid as N,swipeAndroid as I,rotateAndroid as v,fillAndroid as M,backAndroid as C}from"./input-actions.js";import{requireLocationCoordinates as S}from"./1998.js";import{parseAppearanceAction as R,summarizeCommandAttemptFailures as D,parseSettingState as E,parsePermissionTarget as x,parsePermissionAction as k}from"./6629.js";import{openAndroidDevice as b,runAndroidAdb as O,openAndroidApp as L,resolveAndroidApp as F,closeAndroidApp as P}from"./8806.js";import{writeAndroidClipboardText as T,readAndroidClipboardText as U}from"./8133.js";import{snapshotAndroid as $}from"./2415.js";import{sleep as G}from"./4829.js";let K="android-multitouch-helper-v1",V="ANDROID_MULTITOUCH_HELPER_NO_FINAL_RESULT",H="ANDROID_MULTITOUCH_HELPER_REPORTED_FAILURE";async function q(e,t){let r=await X(e,{kind:"swipe",...t});if(r)return r;try{return await Q(e,{kind:"swipe",...t})}catch(r){return s({level:"warn",phase:"android_swipe_helper_fallback",data:{error:a(r).message}}),await I(e,t.x1,t.y1,t.x2,t.y2,t.durationMs),{backend:"adb-input-swipe-fallback"}}}async function B(e,t){if(!Number.isFinite(t.scale)||t.scale<=0)throw new n("INVALID_ARGS","gesture pinch requires scale > 0");let r=await J(e,t.x,t.y);return await W(e,{kind:"pinch",x:r.x,y:r.y,scale:t.scale,durationMs:t.durationMs})}async function j(e,t){if(!Number.isFinite(t.degrees))throw new n("INVALID_ARGS","gesture rotate requires finite degrees");if(void 0!==t.velocity&&(!Number.isFinite(t.velocity)||0===t.velocity))throw new n("INVALID_ARGS","gesture rotate velocity must be a non-zero number");let r=await J(e,t.x,t.y),i=t.degrees;return await W(e,{kind:"rotate",x:r.x,y:r.y,degrees:i,durationMs:t.durationMs})}async function z(e,t){if(!Number.isFinite(t.scale)||t.scale<=0)throw new n("INVALID_ARGS","gesture transform requires scale > 0");if(!Number.isFinite(t.degrees))throw new n("INVALID_ARGS","gesture transform requires finite degrees");if(![t.x,t.y,t.dx,t.dy].every(Number.isFinite))throw new n("INVALID_ARGS","gesture transform requires finite x y dx dy");return await W(e,{kind:"transform",x:t.x,y:t.y,dx:t.dx,dy:t.dy,scale:t.scale,degrees:t.degrees,durationMs:t.durationMs})}async function J(e,t,r){if(void 0!==t&&void 0!==r)return{x:t,y:r};let i=await g(e);return{x:Math.round(i.width/2),y:Math.round(i.height/2)}}async function W(e,t){let r=await X(e,t);return r||await Q(e,t)}async function X(e,t){let r=u(e);if(r)return{backend:"provider-native-touch",...await r(t)??{}}}async function Q(e,t){let r=p(e),i=await ee(),a=c(e),n=await o("android_multitouch_helper_install",async()=>{var t;return await et({adb:r,adbProvider:a,artifact:i,deviceKey:(t=e,`${t.platform}:${t.id}`)})},{packageName:i.manifest.packageName,versionCode:i.manifest.versionCode});s({phase:"android_multitouch_helper_install_decision",data:n});let d=await o("android_multitouch_helper_gesture",async()=>await Y({adb:r,request:function(e){var t;let r=Math.round(void 0!==(t=e).durationMs?t.durationMs:"swipe"===t.kind||"pinch"===t.kind?300:Math.min(Math.max(300,16*Math.ceil(Math.abs(t.degrees)/3)),2400));switch(e.kind){case"swipe":return{kind:"swipe",x1:Math.round(e.x1),y1:Math.round(e.y1),x2:Math.round(e.x2),y2:Math.round(e.y2),durationMs:r};case"pinch":return{kind:"pinch",x:Math.round(e.x),y:Math.round(e.y),scale:e.scale,radius:160,durationMs:r};case"rotate":return{kind:"rotate",x:Math.round(e.x),y:Math.round(e.y),degrees:e.degrees,radius:160,durationMs:r};case"transform":return{kind:"transform",x:Math.round(e.x),y:Math.round(e.y),dx:Math.round(e.dx),dy:Math.round(e.dy),scale:e.scale,degrees:e.degrees,durationMs:r}}}(t),packageName:i.manifest.packageName,instrumentationRunner:i.manifest.instrumentationRunner}),{packageName:i.manifest.packageName,version:i.manifest.version});return{backend:"android-multitouch-helper",helperVersion:i.manifest.version,installReason:n.reason,...d}}async function Y(e){let t,r=Buffer.from(JSON.stringify({protocol:K,...e.request})).toString("base64"),i=await e.adb(["shell","am","instrument","-w","-e","payloadBase64",r,e.instrumentationRunner],{allowFailure:!0,timeoutMs:45e3});try{t=function(e){let t=(function(e){let t=[],r=null;for(let i of e.split(/\r?\n/))i.startsWith("INSTRUMENTATION_RESULT: ")?(r??={},function(e,t){let r=e.indexOf("=");r>=0&&(t[e.slice(0,r)]=e.slice(r+1))}(i.slice(24),r)):i.startsWith("INSTRUMENTATION_CODE: ")&&r&&(t.push(r),r=null);return r&&t.push(r),t})(e).find(e=>e.agentDeviceProtocol===K);if(!t)throw new n(V,"Android multi-touch helper did not return a final result");if("true"!==t.ok){var r;throw new n(H,(r=t).message&&"null"!==r.message?r.message:r.errorType||"Android multi-touch helper returned an error",{errorType:t.errorType,helper:t})}return{kind:t.kind,helperApiVersion:t.helperApiVersion,injectedEvents:Z(t.injectedEvents),elapsedMs:Z(t.elapsedMs)}}(`${i.stdout}
1
+ import e from"node:crypto";import t from"node:fs/promises";import r from"node:path";import{promises as i}from"node:fs";import{normalizeError as a,AppError as n}from"./9152.js";import{withDiagnosticTimer as o,emitDiagnostic as s}from"./7599.js";import{readVersion as d,findProjectRoot as l}from"./9671.js";import{resolveAndroidTouchInjector as u,resolveAndroidAdbProvider as c,resolveAndroidAdbExecutor as p,installAndroidAdbPackage as m}from"./9639.js";import{appSwitcherAndroid as h,homeAndroid as f,scrollAndroid as w,longPressAndroid as _,typeAndroid as A,getAndroidScreenSize as g,pressAndroid as y,focusAndroid as N,swipeAndroid as I,rotateAndroid as v,fillAndroid as M,backAndroid as C}from"./input-actions.js";import{requireLocationCoordinates as S}from"./9673.js";import{parseAppearanceAction as R,summarizeCommandAttemptFailures as D,parseSettingState as E,parsePermissionTarget as x,parsePermissionAction as k}from"./6629.js";import{openAndroidDevice as b,runAndroidAdb as O,openAndroidApp as L,resolveAndroidApp as F,closeAndroidApp as P}from"./8806.js";import{writeAndroidClipboardText as T,readAndroidClipboardText as U}from"./8133.js";import{snapshotAndroid as $}from"./2415.js";import{sleep as G}from"./4829.js";let K="android-multitouch-helper-v1",V="ANDROID_MULTITOUCH_HELPER_NO_FINAL_RESULT",H="ANDROID_MULTITOUCH_HELPER_REPORTED_FAILURE";async function q(e,t){let r=await X(e,{kind:"swipe",...t});if(r)return r;try{return await Q(e,{kind:"swipe",...t})}catch(r){return s({level:"warn",phase:"android_swipe_helper_fallback",data:{error:a(r).message}}),await I(e,t.x1,t.y1,t.x2,t.y2,t.durationMs),{backend:"adb-input-swipe-fallback"}}}async function B(e,t){if(!Number.isFinite(t.scale)||t.scale<=0)throw new n("INVALID_ARGS","gesture pinch requires scale > 0");let r=await J(e,t.x,t.y);return await W(e,{kind:"pinch",x:r.x,y:r.y,scale:t.scale,durationMs:t.durationMs})}async function j(e,t){if(!Number.isFinite(t.degrees))throw new n("INVALID_ARGS","gesture rotate requires finite degrees");if(void 0!==t.velocity&&(!Number.isFinite(t.velocity)||0===t.velocity))throw new n("INVALID_ARGS","gesture rotate velocity must be a non-zero number");let r=await J(e,t.x,t.y),i=t.degrees;return await W(e,{kind:"rotate",x:r.x,y:r.y,degrees:i,durationMs:t.durationMs})}async function z(e,t){if(!Number.isFinite(t.scale)||t.scale<=0)throw new n("INVALID_ARGS","gesture transform requires scale > 0");if(!Number.isFinite(t.degrees))throw new n("INVALID_ARGS","gesture transform requires finite degrees");if(![t.x,t.y,t.dx,t.dy].every(Number.isFinite))throw new n("INVALID_ARGS","gesture transform requires finite x y dx dy");return await W(e,{kind:"transform",x:t.x,y:t.y,dx:t.dx,dy:t.dy,scale:t.scale,degrees:t.degrees,durationMs:t.durationMs})}async function J(e,t,r){if(void 0!==t&&void 0!==r)return{x:t,y:r};let i=await g(e);return{x:Math.round(i.width/2),y:Math.round(i.height/2)}}async function W(e,t){let r=await X(e,t);return r||await Q(e,t)}async function X(e,t){let r=u(e);if(r)return{backend:"provider-native-touch",...await r(t)??{}}}async function Q(e,t){let r=p(e),i=await ee(),a=c(e),n=await o("android_multitouch_helper_install",async()=>{var t;return await et({adb:r,adbProvider:a,artifact:i,deviceKey:(t=e,`${t.platform}:${t.id}`)})},{packageName:i.manifest.packageName,versionCode:i.manifest.versionCode});s({phase:"android_multitouch_helper_install_decision",data:n});let d=await o("android_multitouch_helper_gesture",async()=>await Y({adb:r,request:function(e){var t;let r=Math.round(void 0!==(t=e).durationMs?t.durationMs:"swipe"===t.kind||"pinch"===t.kind?300:Math.min(Math.max(300,16*Math.ceil(Math.abs(t.degrees)/3)),2400));switch(e.kind){case"swipe":return{kind:"swipe",x1:Math.round(e.x1),y1:Math.round(e.y1),x2:Math.round(e.x2),y2:Math.round(e.y2),durationMs:r};case"pinch":return{kind:"pinch",x:Math.round(e.x),y:Math.round(e.y),scale:e.scale,radius:160,durationMs:r};case"rotate":return{kind:"rotate",x:Math.round(e.x),y:Math.round(e.y),degrees:e.degrees,radius:160,durationMs:r};case"transform":return{kind:"transform",x:Math.round(e.x),y:Math.round(e.y),dx:Math.round(e.dx),dy:Math.round(e.dy),scale:e.scale,degrees:e.degrees,durationMs:r}}}(t),packageName:i.manifest.packageName,instrumentationRunner:i.manifest.instrumentationRunner}),{packageName:i.manifest.packageName,version:i.manifest.version});return{backend:"android-multitouch-helper",helperVersion:i.manifest.version,installReason:n.reason,...d}}async function Y(e){let t,r=Buffer.from(JSON.stringify({protocol:K,...e.request})).toString("base64"),i=await e.adb(["shell","am","instrument","-w","-e","payloadBase64",r,e.instrumentationRunner],{allowFailure:!0,timeoutMs:45e3});try{t=function(e){let t=(function(e){let t=[],r=null;for(let i of e.split(/\r?\n/))i.startsWith("INSTRUMENTATION_RESULT: ")?(r??={},function(e,t){let r=e.indexOf("=");r>=0&&(t[e.slice(0,r)]=e.slice(r+1))}(i.slice(24),r)):i.startsWith("INSTRUMENTATION_CODE: ")&&r&&(t.push(r),r=null);return r&&t.push(r),t})(e).find(e=>e.agentDeviceProtocol===K);if(!t)throw new n(V,"Android multi-touch helper did not return a final result");if("true"!==t.ok){var r;throw new n(H,(r=t).message&&"null"!==r.message?r.message:r.errorType||"Android multi-touch helper returned an error",{errorType:t.errorType,helper:t})}return{kind:t.kind,helperApiVersion:t.helperApiVersion,injectedEvents:Z(t.injectedEvents),elapsedMs:Z(t.elapsedMs)}}(`${i.stdout}
2
2
  ${i.stderr}`)}catch(e){if(e instanceof n){if(e.code===H)throw new n("COMMAND_FAILED",e.message,e.details,e);if(e.code!==V)throw e}throw new n("COMMAND_FAILED",0===i.exitCode?"Android multi-touch helper output could not be parsed":"Android multi-touch helper failed before returning parseable output",{stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode},e)}if(0!==i.exitCode)throw new n("COMMAND_FAILED","Android multi-touch helper failed",{stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode,helper:t});return t}function Z(e){if(void 0===e)return;let t=Number(e);return Number.isFinite(t)?t:void 0}async function ee(){let e=d(),i=r.join(l(),"android-multitouch-helper","dist"),o=r.join(i,`agent-device-android-multitouch-helper-${e}.manifest.json`);try{let e=function(e){if(!e||"object"!=typeof e||Array.isArray(e))throw new n("INVALID_ARGS","Android multi-touch helper manifest must be an object.");return{name:es(e.name,"name","android-multitouch-helper"),version:eo(e.version,"version"),assetName:eo(e.assetName,"assetName"),sha256:function(e){let t=eo(e,"sha256").trim().toLowerCase();if(64!==t.length||!/^[0-9a-f]+$/.test(t))throw new n("INVALID_ARGS","Android multi-touch helper manifest sha256 must be a 64-character hex string.");return t}(e.sha256),packageName:es(e.packageName,"packageName","com.callstack.agentdevice.multitouchhelper"),versionCode:function(e,t){if(!Number.isInteger(e))throw new n("INVALID_ARGS",`Android multi-touch helper manifest ${t} must be an integer.`);return e}(e.versionCode,"versionCode"),instrumentationRunner:es(e.instrumentationRunner,"instrumentationRunner","com.callstack.agentdevice.multitouchhelper/.MultiTouchInstrumentation"),statusProtocol:es(e.statusProtocol,"statusProtocol",K)}}(JSON.parse(await t.readFile(o,"utf8"))),a=r.join(i,e.assetName);return await t.access(a),{apkPath:a,manifest:e}}catch(e){throw new n("UNSUPPORTED_OPERATION","Android touch gestures require the bundled Android touch helper artifact, but it was not found or could not be read",{manifestPath:o,error:a(e).message},e)}}async function et(e){let{adb:t,artifact:r}=e,i=r.manifest.packageName,a=r.manifest.versionCode,o=`${e.deviceKey}\0${i}\0${a}`;if(er.has(o))return{packageName:i,versionCode:a,installed:!1,reason:"current"};let s=await ei(t,i);if(void 0!==s&&s>=a)return er.add(o),{packageName:i,versionCode:a,installedVersionCode:s,installed:!1,reason:"current"};await ea(r);let d=await m(r.apkPath,{provider:e.adbProvider,replace:!0,allowTestPackages:!0,allowFailure:!0,timeoutMs:3e4});if(0!==d.exitCode)throw new n("COMMAND_FAILED","Failed to install Android multi-touch helper",{packageName:i,versionCode:a,stdout:d.stdout,stderr:d.stderr,exitCode:d.exitCode});return er.add(o),{packageName:i,versionCode:a,installedVersionCode:s,installed:!0,reason:void 0===s?"missing":"outdated"}}let er=new Set;async function ei(e,t){let r=await e(["shell","cmd","package","list","packages","--show-versioncode",t],{allowFailure:!0,timeoutMs:5e3});if(0!==r.exitCode)return;let i=RegExp(`package:${t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}(?:\\s|$).*versionCode:(\\d+)`).exec(`${r.stdout}
3
3
  ${r.stderr}`);return i?Number(i[1]):void 0}async function ea(e){let t=await en(e.apkPath);if(t!==e.manifest.sha256)throw new n("COMMAND_FAILED","Android multi-touch helper APK checksum mismatch",{apkPath:e.apkPath,expectedSha256:e.manifest.sha256,actualSha256:t})}async function en(r){let i=e.createHash("sha256");return i.update(await t.readFile(r)),i.digest("hex")}function eo(e,t){if("string"!=typeof e||0===e.length)throw new n("INVALID_ARGS",`Android multi-touch helper manifest ${t} is required.`);return e}function es(e,t,r){if(e!==r)throw new n("INVALID_ARGS",`Android multi-touch helper manifest ${t} must be "${r}".`);return r}let ed=["window_animation_scale","transition_animation_scale","animator_duration_scale"];async function el(e,t,r,i,a){switch(t.toLowerCase()){case"wifi":{let t=E(r);await O(e,["shell","svc","wifi",t?"enable":"disable"]);return}case"airplane":{let t=E(r);await O(e,["shell","settings","put","global","airplane_mode_on",t?"1":"0"]),await O(e,["shell","am","broadcast","-a","android.intent.action.AIRPLANE_MODE","--ez","state",t?"true":"false"]);return}case"location":{if("set"===r.toLowerCase()){if("emulator"!==e.kind)throw new n("UNSUPPORTED_OPERATION","Android precise location coordinates are supported only on emulators.",{deviceId:e.id,hint:"Use an Android emulator for adb emu geo fix, or configure location through device/provider tooling."});let{latitude:t,longitude:r}=S(a);return await O(e,["emu","geo","fix",String(r),String(t)]),{latitude:t,longitude:r}}let t=E(r);await O(e,["shell","settings","put","secure","location_mode",t?"3":"0"]);return}case"animations":{let t=E(r)?"1":"0";for(let r of ed)await O(e,["shell","settings","put","global",r,t]);return{scale:t,keys:[...ed]}}case"appearance":{let t=await ec(e,r);await O(e,["shell","cmd","uimode","night","dark"===t?"yes":"no"]);return}case"clear-app-state":{if("clear"!==r.toLowerCase())throw new n("INVALID_ARGS","settings clear-app-state only supports clear.");if(!i)throw new n("INVALID_ARGS","settings clear-app-state requires an app id or an active app session.");let t=await F(e,i);if("intent"===t.type)throw new n("INVALID_ARGS","settings clear-app-state requires a package name, not an intent.");await O(e,["shell","am","force-stop",t.value],{allowFailure:!0});let a=await O(e,["shell","pm","clear",t.value],{allowFailure:!0});if(0!==a.exitCode||!/\bSuccess\b/i.test(a.stdout))throw new n("COMMAND_FAILED",`Failed to clear Android app data for ${t.value}`,{package:t.value,stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode});return{package:t.value,cleared:!0}}case"fingerprint":{let t=function(e){let t=e.trim().toLowerCase();if("match"===t)return"match";if("nonmatch"===t)return"nonmatch";throw new n("INVALID_ARGS",`Invalid fingerprint state: ${e}. Use match|nonmatch.`)}(r);await eu(e,t);return}case"permission":{if(!i)throw new n("INVALID_ARGS","permission setting requires an active app in session");let t=k(r),o=function(e,t){let r=x(e);if(t?.trim())throw new n("INVALID_ARGS",`Permission mode is only supported for photos. Received: ${t}.`);if("camera"===r)return{kind:"pm",value:"android.permission.CAMERA",type:"camera"};if("microphone"===r)return{kind:"pm",value:"android.permission.RECORD_AUDIO",type:"microphone"};if("photos"===r)return{kind:"pm",value:"android.permission.READ_MEDIA_IMAGES",type:"photos"};if("contacts"===r)return{kind:"pm",value:"android.permission.READ_CONTACTS",type:"contacts"};if("notifications"===r)return{kind:"notifications",appOps:"POST_NOTIFICATION",permission:"android.permission.POST_NOTIFICATIONS"};throw new n("INVALID_ARGS",`Unsupported permission target on Android: ${e}. Use camera|microphone|photos|contacts|notifications.`)}(a?.permissionTarget,a?.permissionMode);if("notifications"===o.kind)return void await em(e,i,t,o);let s="grant"===t?"grant":"revoke";if("photos"===o.type)return void await ep(e,i,s);await O(e,["shell","pm",s,i,o.value]);return}default:throw new n("INVALID_ARGS",`Unsupported setting: ${t}`)}}async function eu(e,t){var r;let i,a,o=(r=e,a=[["shell","cmd","fingerprint","touch",i="match"===t?"1":"9999"],["shell","cmd","fingerprint","finger",i]],"emulator"===r.kind&&a.push(["emu","finger","touch",i]),a),s=[];for(let t of o){let r=await O(e,t,{allowFailure:!0});if(0===r.exitCode)return;s.push({args:t,stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode})}let d=D(s);if(s.length>0&&s.every(e=>{var t,r;let i;return t=e.stdout,r=e.stderr,(i=`${t}
4
4
  ${r}`.toLowerCase()).includes("unknown command")||i.includes("can't find service: fingerprint")||i.includes("service fingerprint was not found")||i.includes("fingerprint cmd unavailable")||i.includes("emu command is not supported")||i.includes("emulator console is not running")||i.includes("fingerprint")&&i.includes("not found")}))throw new n("UNSUPPORTED_OPERATION","Android fingerprint simulation is not supported on this target/runtime.",{deviceId:e.id,action:t,hint:"Use an Android emulator with biometric support, or a device/runtime that exposes cmd fingerprint.",attempts:d});throw new n("COMMAND_FAILED","Failed to simulate Android fingerprint.",{deviceId:e.id,action:t,attempts:d})}async function ec(e,t){let r=R(t);if("toggle"!==r)return r;let i=await O(e,["shell","cmd","uimode","night"],{allowFailure:!0});if(0!==i.exitCode)throw new n("COMMAND_FAILED","Failed to read current Android appearance",{stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode});let a=function(e,t){let r=/night mode:\s*(yes|no|auto)\b/i.exec(`${e}
package/dist/src/apple.js CHANGED
@@ -1 +1 @@
1
- import{AppError as e}from"./9152.js";import{shouldUseSynthesizedIosDrag as a,runMacOsScreenshotAction as t,runIosRunnerCommand as n}from"./2415.js";import{buildScrollGesturePlan as d}from"./9533.js";import{writeIosClipboardText as o,openIosApp as r,openIosDevice as i,screenshotIos as p,closeIosApp as l,setIosSetting as s,readIosClipboardText as u}from"./apps.js";import{withDiagnosticTimer as c}from"./7599.js";function m(e,a,t,n){return{command:"tap",x:t,y:n,..."ios"===e.platform&&"tv"!==e.target?{synthesized:!0}:{},appBundleId:a.appBundleId}}function y(e,t,n,d,o,r,i,p){var l,s;let u=a(e),c=u?(l=i,s=p.synthesizedDefaultDurationMs,void 0===l?s:Math.min(1e4,Math.max(16,Math.round(l)))):i??p.legacyDefaultDurationMs;return{command:"drag",x:n,y:d,x2:o,y2:r,...void 0!==c?{durationMs:c}:{},...u?{synthesized:!0}:{},appBundleId:t.appBundleId}}function f(e,a,t){return{command:"remotePress",remoteButton:e,...void 0!==t?{durationMs:t}:{},...void 0!==a?{appBundleId:a}:{}}}async function I(e,a,t,n,o,r,i){if("tv"===a.target)return w(await e(a,f(o,t.appBundleId),n),r);let p=i??await v(e,a,t,n),l=d({direction:o,amount:r?.amount,pixels:r?.pixels,referenceWidth:p.referenceWidth,referenceHeight:p.referenceHeight});return w(await e(a,y(a,t,p.originX+l.x1,p.originY+l.y1,p.originX+l.x2,p.originY+l.y2,void 0,{synthesizedDefaultDurationMs:250}),n),{amount:l.amount,pixels:l.pixels,preferProvidedPixels:!0})}async function v(a,t,n,d){let o=await a(t,{command:"interactionFrame",appBundleId:n.appBundleId},d),r=h(o.x),i=h(o.y),p=h(o.referenceWidth),l=h(o.referenceHeight);if(void 0===r||void 0===i||void 0===p||void 0===l)throw new e("COMMAND_FAILED","interactionFrame did not return a usable frame");return{originX:r,originY:i,referenceWidth:p,referenceHeight:l}}function h(e){return"number"==typeof e&&Number.isFinite(e)?e:void 0}function w(e,a){var t;let{x1:n,y1:d,x2:o,y2:r}={x1:h((t=e).x),y1:h(t.y),x2:h(t.x2),y2:h(t.y2)},i=h(e.referenceWidth),p=h(e.referenceHeight),l=void 0!==n&&void 0!==o?Math.round(Math.abs(o-n)):void 0,s=void 0!==d&&void 0!==r?Math.round(Math.abs(r-d)):void 0,u=a?.preferProvidedPixels&&void 0!==a.pixels?a.pixels:l&&l>0?l:s&&s>0?s:void 0;return{...void 0!==n?{x1:n}:{},...void 0!==d?{y1:d}:{},...void 0!==o?{x2:o}:{},...void 0!==r?{y2:r}:{},...void 0!==i?{referenceWidth:i}:{},...void 0!==p?{referenceHeight:p}:{},...a?.amount!==void 0?{amount:a.amount}:{},...void 0!==u?{pixels:u}:{}}}function B(a,d){let v,{overrides:h,runnerOpts:w}={runnerOpts:v={verbose:d.verbose,logPath:d.logPath,traceLogPath:d.traceLogPath,requestId:d.requestId},overrides:{tap:async(e,t)=>await n(a,m(a,d,e,t),v),tapElementSelector:async e=>await n(a,{command:"tap",selectorKey:e.key,selectorValue:e.value,allowNonHittableCoordinateFallback:e.allowNonHittableCoordinateFallback,appBundleId:d.appBundleId},v),doubleTap:async(e,t)=>await n(a,{command:"tapSeries",x:e,y:t,count:1,intervalMs:0,doubleTap:!0,appBundleId:d.appBundleId},v),swipe:async(e,t,o,r,i)=>await n(a,y(a,d,e,t,o,r,i,{synthesizedDefaultDurationMs:250}),v),pan:async(e,t,o,r,i)=>await n(a,y(a,d,e,t,o,r,i,{synthesizedDefaultDurationMs:500,legacyDefaultDurationMs:500}),v),fling:async(e,t,o,r,i)=>await n(a,{command:"drag",x:e,y:t,x2:o,y2:r,durationMs:i??16,appBundleId:d.appBundleId},v),longPress:async(e,t,o)=>await n(a,{command:"longPress",x:e,y:t,durationMs:o,appBundleId:d.appBundleId},v),focus:async(e,t)=>await n(a,m(a,d,e,t),v),type:async(e,t)=>{await n(a,{command:"type",text:e,delayMs:t,textEntryMode:"\n"===e?void 0:"append",appBundleId:d.appBundleId},v)},fillElementSelector:async(e,t,o)=>await n(a,{command:"type",selectorKey:e.key,selectorValue:e.value,allowNonHittableCoordinateFallback:e.allowNonHittableCoordinateFallback,text:t,delayMs:o,textEntryMode:"replace",appBundleId:d.appBundleId},v),fill:async(e,t,o,r)=>await n(a,{command:"type",x:e,y:t,text:o,delayMs:r,textEntryMode:"replace",appBundleId:d.appBundleId},v),scroll:async(e,t)=>await I(n,a,d,v,e,t),pinch:async(e,t,o)=>{await n(a,{command:"pinch",scale:e,x:t,y:o,appBundleId:d.appBundleId},v)},rotateGesture:async(e,t,o,r)=>{await n(a,{command:"rotateGesture",degrees:e,x:t,y:o,velocity:r,appBundleId:d.appBundleId},v)},transformGesture:async e=>await n(a,{command:"transformGesture",x:e.x,y:e.y,dx:e.dx,dy:e.dy,scale:e.scale,degrees:e.degrees,durationMs:e.durationMs,appBundleId:d.appBundleId},v)}};return{open:(e,t)=>r(a,e,{appBundleId:t?.appBundleId,launchConsole:t?.launchConsole,launchArgs:t?.launchArgs,url:t?.url}),openDevice:()=>i(a),close:e=>l(a,e),screenshot:async(e,n)=>{"macos"===a.platform&&n?.surface&&"app"!==n.surface?await t(e,{surface:n.surface,fullscreen:n.fullscreen}):await p(a,e,n?.appBundleId,n?.fullscreen,w)},snapshot:async t=>{var d;let o={nodes:Array.isArray((d=await c("snapshot_capture",async()=>await n(a,{command:"snapshot",appBundleId:t?.appBundleId,interactiveOnly:t?.interactiveOnly,compact:t?.compact,depth:t?.depth,scope:t?.scope,raw:t?.raw},w),{backend:"xctest"})).nodes)?d.nodes:void 0,truncated:"boolean"==typeof d.truncated?d.truncated:void 0},r=o.nodes??[];if(0===r.length&&"simulator"===a.kind)throw new e("COMMAND_FAILED","XCTest snapshot returned 0 nodes on iOS simulator.");return{nodes:r,truncated:o.truncated??!1,backend:"xctest"}},back:async e=>{"tv"===a.target?await n(a,f("menu",d.appBundleId),w):await n(a,{command:"system"===e?"backSystem":"backInApp",appBundleId:d.appBundleId},w)},home:async()=>{"tv"===a.target?await n(a,f("home",d.appBundleId),w):await n(a,{command:"home",appBundleId:d.appBundleId},w)},rotate:async e=>{await n(a,{command:"rotate",orientation:e,appBundleId:d.appBundleId},w)},appSwitcher:async()=>{await n(a,{command:"appSwitcher",appBundleId:d.appBundleId},w)},readClipboard:()=>u(a),writeClipboard:e=>o(a,e),setSetting:(e,t,n,d)=>s(a,e,t,n,d),...h}}export{B as createAppleInteractor};
1
+ import{AppError as e}from"./9152.js";import{buildScrollGesturePlan as a}from"./1620.js";import{runMacOsScreenshotAction as t,runIosRunnerCommand as n}from"./2415.js";import{writeIosClipboardText as d,openIosApp as o,openIosDevice as r,screenshotIos as i,closeIosApp as p,setIosSetting as l,readIosClipboardText as u}from"./apps.js";import{withDiagnosticTimer as c}from"./7599.js";function s(e,a,t,n){return{command:"tap",x:t,y:n,..."ios"===e.platform&&"tv"!==e.target?{synthesized:!0}:{},appBundleId:a.appBundleId}}function m(e,a,t,n,d,o,r,i){var p,l;let u="ios"===e.platform&&"tv"!==e.target?(p=r,l=i.defaultDurationMs,void 0===p?l:Math.min(1e4,Math.max(16,Math.round(p)))):r??i.legacyDefaultDurationMs;return{command:"drag",x:t,y:n,x2:d,y2:o,...void 0!==u?{durationMs:u}:{},appBundleId:a.appBundleId}}function y(e,a,t){return{command:"remotePress",remoteButton:e,...void 0!==t?{durationMs:t}:{},...void 0!==a?{appBundleId:a}:{}}}async function f(e,t,n,d,o,r,i){if("tv"===t.target)return w(await e(t,y(o,n.appBundleId),d),r);let p=i??await I(e,t,n,d),l=a({direction:o,amount:r?.amount,pixels:r?.pixels,referenceWidth:p.referenceWidth,referenceHeight:p.referenceHeight});return w(await e(t,m(t,n,p.originX+l.x1,p.originY+l.y1,p.originX+l.x2,p.originY+l.y2,void 0,{defaultDurationMs:250}),d),{amount:l.amount,pixels:l.pixels,preferProvidedPixels:!0})}async function I(a,t,n,d){let o=await a(t,{command:"interactionFrame",appBundleId:n.appBundleId},d),r=v(o.x),i=v(o.y),p=v(o.referenceWidth),l=v(o.referenceHeight);if(void 0===r||void 0===i||void 0===p||void 0===l)throw new e("COMMAND_FAILED","interactionFrame did not return a usable frame");return{originX:r,originY:i,referenceWidth:p,referenceHeight:l}}function v(e){return"number"==typeof e&&Number.isFinite(e)?e:void 0}function w(e,a){var t;let{x1:n,y1:d,x2:o,y2:r}={x1:v((t=e).x),y1:v(t.y),x2:v(t.x2),y2:v(t.y2)},i=v(e.referenceWidth),p=v(e.referenceHeight),l=void 0!==n&&void 0!==o?Math.round(Math.abs(o-n)):void 0,u=void 0!==d&&void 0!==r?Math.round(Math.abs(r-d)):void 0,c=a?.preferProvidedPixels&&void 0!==a.pixels?a.pixels:l&&l>0?l:u&&u>0?u:void 0;return{...void 0!==n?{x1:n}:{},...void 0!==d?{y1:d}:{},...void 0!==o?{x2:o}:{},...void 0!==r?{y2:r}:{},...void 0!==i?{referenceWidth:i}:{},...void 0!==p?{referenceHeight:p}:{},...a?.amount!==void 0?{amount:a.amount}:{},...void 0!==c?{pixels:c}:{}}}function B(a,I){let v,{overrides:w,runnerOpts:B}={runnerOpts:v={verbose:I.verbose,logPath:I.logPath,traceLogPath:I.traceLogPath,requestId:I.requestId},overrides:{tap:async(e,t)=>await n(a,s(a,I,e,t),v),tapElementSelector:async e=>await n(a,{command:"tap",selectorKey:e.key,selectorValue:e.value,allowNonHittableCoordinateFallback:e.allowNonHittableCoordinateFallback,appBundleId:I.appBundleId},v),doubleTap:async(e,t)=>await n(a,{command:"tapSeries",x:e,y:t,count:1,intervalMs:0,doubleTap:!0,appBundleId:I.appBundleId},v),swipe:async(e,t,d,o,r)=>await n(a,m(a,I,e,t,d,o,r,{defaultDurationMs:250}),v),pan:async(e,t,d,o,r)=>await n(a,m(a,I,e,t,d,o,r,{defaultDurationMs:500,legacyDefaultDurationMs:500}),v),fling:async(e,t,d,o,r)=>await n(a,{command:"drag",x:e,y:t,x2:d,y2:o,durationMs:r??16,appBundleId:I.appBundleId},v),longPress:async(e,t,d)=>await n(a,{command:"longPress",x:e,y:t,durationMs:d,appBundleId:I.appBundleId},v),focus:async(e,t)=>await n(a,s(a,I,e,t),v),type:async(e,t)=>{await n(a,{command:"type",text:e,delayMs:t,textEntryMode:"\n"===e?void 0:"append",appBundleId:I.appBundleId},v)},fillElementSelector:async(e,t,d)=>await n(a,{command:"type",selectorKey:e.key,selectorValue:e.value,allowNonHittableCoordinateFallback:e.allowNonHittableCoordinateFallback,text:t,delayMs:d,textEntryMode:"replace",appBundleId:I.appBundleId},v),fill:async(e,t,d,o)=>await n(a,{command:"type",x:e,y:t,text:d,delayMs:o,textEntryMode:"replace",appBundleId:I.appBundleId},v),scroll:async(e,t)=>await f(n,a,I,v,e,t),pinch:async(e,t,d)=>{await n(a,{command:"pinch",scale:e,x:t,y:d,appBundleId:I.appBundleId},v)},rotateGesture:async(e,t,d,o)=>{await n(a,{command:"rotateGesture",degrees:e,x:t,y:d,velocity:o,appBundleId:I.appBundleId},v)},transformGesture:async e=>await n(a,{command:"transformGesture",x:e.x,y:e.y,dx:e.dx,dy:e.dy,scale:e.scale,degrees:e.degrees,durationMs:e.durationMs,appBundleId:I.appBundleId},v)}};return{open:(e,t)=>o(a,e,{appBundleId:t?.appBundleId,launchConsole:t?.launchConsole,launchArgs:t?.launchArgs,url:t?.url}),openDevice:()=>r(a),close:e=>p(a,e),screenshot:async(e,n)=>{"macos"===a.platform&&n?.surface&&"app"!==n.surface?await t(e,{surface:n.surface,fullscreen:n.fullscreen}):await i(a,e,n?.appBundleId,n?.fullscreen,B)},snapshot:async t=>{var d;let o={nodes:Array.isArray((d=await c("snapshot_capture",async()=>await n(a,{command:"snapshot",appBundleId:t?.appBundleId,interactiveOnly:t?.interactiveOnly,compact:t?.compact,depth:t?.depth,scope:t?.scope,raw:t?.raw},B),{backend:"xctest"})).nodes)?d.nodes:void 0,truncated:"boolean"==typeof d.truncated?d.truncated:void 0},r=o.nodes??[];if(0===r.length&&"simulator"===a.kind)throw new e("COMMAND_FAILED","XCTest snapshot returned 0 nodes on iOS simulator.");return{nodes:r,truncated:o.truncated??!1,backend:"xctest"}},back:async e=>{"tv"===a.target?await n(a,y("menu",I.appBundleId),B):await n(a,{command:"system"===e?"backSystem":"backInApp",appBundleId:I.appBundleId},B)},home:async()=>{"tv"===a.target?await n(a,y("home",I.appBundleId),B):await n(a,{command:"home",appBundleId:I.appBundleId},B)},rotate:async e=>{await n(a,{command:"rotate",orientation:e,appBundleId:I.appBundleId},B)},appSwitcher:async()=>{await n(a,{command:"appSwitcher",appBundleId:I.appBundleId},B)},readClipboard:()=>u(a),writeClipboard:e=>d(a,e),setSetting:(e,t,n,d)=>l(a,e,t,n,d),...w}}export{B as createAppleInteractor};