agent-device 0.18.0 → 0.18.1

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 (158) hide show
  1. package/README.md +3 -2
  2. package/android-multitouch-helper/dist/{agent-device-android-multitouch-helper-0.18.0.apk → agent-device-android-multitouch-helper-0.18.1.apk} +0 -0
  3. package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.18.1.apk.sha256 +1 -0
  4. package/android-multitouch-helper/dist/{agent-device-android-multitouch-helper-0.18.0.manifest.json → agent-device-android-multitouch-helper-0.18.1.manifest.json} +4 -4
  5. package/android-snapshot-helper/dist/{agent-device-android-snapshot-helper-0.18.0.apk → agent-device-android-snapshot-helper-0.18.1.apk} +0 -0
  6. package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.18.1.apk.sha256 +1 -0
  7. package/android-snapshot-helper/dist/{agent-device-android-snapshot-helper-0.18.0.manifest.json → agent-device-android-snapshot-helper-0.18.1.manifest.json} +6 -6
  8. package/apple-runner/AgentDeviceRunner/AgentDeviceRunner/AgentDeviceRunnerApp.m +156 -0
  9. package/{ios-runner → apple-runner}/AgentDeviceRunner/AgentDeviceRunner.xcodeproj/project.pbxproj +10 -16
  10. package/{ios-runner → apple-runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+AXSnapshotFallback.swift +2 -0
  11. package/{ios-runner → apple-runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +3 -1
  12. package/{ios-runner → apple-runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandJournal.swift +2 -0
  13. package/{ios-runner → apple-runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+FlatSnapshotFiltering.swift +2 -4
  14. package/{ios-runner → apple-runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +9 -36
  15. package/{ios-runner → apple-runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScrollGesture.swift +2 -0
  16. package/{ios-runner → apple-runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SequenceExecution.swift +2 -0
  17. package/{ios-runner → apple-runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +2 -0
  18. package/{ios-runner → apple-runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCapturePlan.swift +2 -0
  19. package/{ios-runner → apple-runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntry.swift +0 -1
  20. package/dist/src/1986.js +1 -0
  21. package/dist/src/2748.js +1 -1
  22. package/dist/src/2948.js +21 -21
  23. package/dist/src/314.js +1 -1
  24. package/dist/src/3340.js +8 -7
  25. package/dist/src/432.js +4 -4
  26. package/dist/src/4418.js +1 -1
  27. package/dist/src/4428.js +3 -3
  28. package/dist/src/485.js +1 -0
  29. package/dist/src/495.js +5 -0
  30. package/dist/src/5484.js +1 -1
  31. package/dist/src/587.js +1 -1
  32. package/dist/src/5913.js +4 -0
  33. package/dist/src/6849.js +1 -0
  34. package/dist/src/6918.js +1 -1
  35. package/dist/src/6967.js +1 -0
  36. package/dist/src/760.js +1 -0
  37. package/dist/src/7871.js +1 -0
  38. package/dist/src/8225.js +1 -1
  39. package/dist/src/8391.js +1 -0
  40. package/dist/src/8404.js +2 -0
  41. package/dist/src/8414.js +2 -0
  42. package/dist/src/8875.js +1 -1
  43. package/dist/src/8936.js +1 -1
  44. package/dist/src/9581.js +3 -3
  45. package/dist/src/9624.js +1 -1
  46. package/dist/src/9722.js +37 -32
  47. package/dist/src/android-adb.d.ts +19 -54
  48. package/dist/src/android-adb.js +1 -1
  49. package/dist/src/android.js +5 -5
  50. package/dist/src/apps.js +9 -11
  51. package/dist/src/audio-probe.js +1 -0
  52. package/dist/src/batch.d.ts +33 -25
  53. package/dist/src/batch.js +1 -1
  54. package/dist/src/cli-help.js +66 -16
  55. package/dist/src/cli.js +33 -21
  56. package/dist/src/contracts.d.ts +32 -122
  57. package/dist/src/contracts.js +1 -1
  58. package/dist/src/debug-symbols.js +3 -0
  59. package/dist/src/devices.js +1 -1
  60. package/dist/src/devices~1.js +1 -1
  61. package/dist/src/devices~2.js +1 -1
  62. package/dist/src/find.js +1 -1
  63. package/dist/src/finders.d.ts +2 -6
  64. package/dist/src/finders.js +1 -1
  65. package/dist/src/generic.js +1 -9
  66. package/dist/src/handler-utils.js +1 -0
  67. package/dist/src/index.d.ts +438 -171
  68. package/dist/src/index.js +1 -1
  69. package/dist/src/input-actions.js +1 -1
  70. package/dist/src/input-actions~1.js +1 -1
  71. package/dist/src/install-source.d.ts +0 -26
  72. package/dist/src/install-source.js +1 -1
  73. package/dist/src/interaction.js +1 -1
  74. package/dist/src/interactor.js +1 -0
  75. package/dist/src/internal/bin.js +1 -1
  76. package/dist/src/internal/companion-tunnel.js +1 -1
  77. package/dist/src/internal/png-worker.js +1 -1
  78. package/dist/src/lease.js +1 -1
  79. package/dist/src/linux.js +1 -1
  80. package/dist/src/metro.d.ts +10 -134
  81. package/dist/src/metro.js +1 -1
  82. package/dist/src/notifications.js +1 -1
  83. package/dist/src/react-native.js +1 -1
  84. package/dist/src/record-trace-recording.js +3 -3
  85. package/dist/src/record-trace.js +1 -1
  86. package/dist/src/remote-config.d.ts +14 -16
  87. package/dist/src/remote-config.js +1 -1
  88. package/dist/src/runner-sequence.js +1 -0
  89. package/dist/src/selector-runtime.js +1 -1
  90. package/dist/src/selectors.d.ts +7 -3
  91. package/dist/src/selectors.js +1 -1
  92. package/dist/src/server.js +2 -2
  93. package/dist/src/session.js +11 -11
  94. package/dist/src/simulator.js +2 -2
  95. package/dist/src/snapshot.js +2 -2
  96. package/dist/src/web.js +1 -1
  97. package/macos-helper/Sources/AgentDeviceMacOSHelper/AudioProbe.swift +297 -0
  98. package/macos-helper/Sources/AgentDeviceMacOSHelper/main.swift +30 -0
  99. package/package.json +15 -11
  100. package/server.json +2 -2
  101. package/android-multitouch-helper/README.md +0 -41
  102. package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.18.0.apk.sha256 +0 -1
  103. package/android-snapshot-helper/README.md +0 -88
  104. package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.18.0.apk.sha256 +0 -1
  105. package/dist/src/1848.js +0 -4
  106. package/dist/src/2577.js +0 -1
  107. package/dist/src/2954.js +0 -2
  108. package/dist/src/4291.js +0 -1
  109. package/dist/src/4723.js +0 -1
  110. package/dist/src/5341.js +0 -1
  111. package/dist/src/5910.js +0 -2
  112. package/dist/src/6024.js +0 -1
  113. package/dist/src/733.js +0 -1
  114. package/dist/src/7394.js +0 -6
  115. package/dist/src/8275.js +0 -2
  116. package/dist/src/9919.js +0 -6
  117. package/dist/src/android-snapshot-helper.d.ts +0 -359
  118. package/dist/src/android-snapshot-helper.js +0 -1
  119. package/dist/src/apple.js +0 -1
  120. package/dist/src/device-ready.js +0 -2
  121. package/ios-runner/AgentDeviceRunner/AgentDeviceRunner/AgentDeviceRunnerApp.swift +0 -17
  122. package/ios-runner/AgentDeviceRunner/AgentDeviceRunner/Assets.xcassets/AccentColor.colorset/Contents.json +0 -11
  123. package/ios-runner/AgentDeviceRunner/AgentDeviceRunner/Assets.xcassets/AppIcon.appiconset/Contents.json +0 -36
  124. package/ios-runner/AgentDeviceRunner/AgentDeviceRunner/Assets.xcassets/AppIcon.appiconset/logo.jpg +0 -0
  125. package/ios-runner/AgentDeviceRunner/AgentDeviceRunner/Assets.xcassets/Contents.json +0 -6
  126. package/ios-runner/AgentDeviceRunner/AgentDeviceRunner/Assets.xcassets/Logo.imageset/Contents.json +0 -21
  127. package/ios-runner/AgentDeviceRunner/AgentDeviceRunner/Assets.xcassets/Logo.imageset/logo.jpg +0 -0
  128. package/ios-runner/AgentDeviceRunner/AgentDeviceRunner/Assets.xcassets/PoweredBy.imageset/Contents.json +0 -21
  129. package/ios-runner/AgentDeviceRunner/AgentDeviceRunner/Assets.xcassets/PoweredBy.imageset/powered-by.png +0 -0
  130. package/ios-runner/AgentDeviceRunner/AgentDeviceRunner/ContentView.swift +0 -34
  131. package/ios-runner/README.md +0 -53
  132. package/ios-runner/RUNNER_PROTOCOL.md +0 -76
  133. /package/{ios-runner → apple-runner}/AgentDeviceRunner/AgentDeviceRunner.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -0
  134. /package/{ios-runner → apple-runner}/AgentDeviceRunner/AgentDeviceRunner.xcodeproj/xcshareddata/xcschemes/AgentDeviceRunner.xcscheme +0 -0
  135. /package/{ios-runner → apple-runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/AgentDeviceRunnerUITests-Bridging-Header.h +0 -0
  136. /package/{ios-runner → apple-runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/AgentDeviceRunnerUITests.entitlements +0 -0
  137. /package/{ios-runner → apple-runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.h +0 -0
  138. /package/{ios-runner → apple-runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.m +0 -0
  139. /package/{ios-runner → apple-runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerObjCExceptionCatcher.h +0 -0
  140. /package/{ios-runner → apple-runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerObjCExceptionCatcher.m +0 -0
  141. /package/{ios-runner → apple-runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedGesture.h +0 -0
  142. /package/{ios-runner → apple-runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedGesture.m +0 -0
  143. /package/{ios-runner → apple-runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Alert.swift +0 -0
  144. /package/{ios-runner → apple-runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Environment.swift +0 -0
  145. /package/{ios-runner → apple-runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Exceptions.swift +0 -0
  146. /package/{ios-runner → apple-runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Lifecycle.swift +0 -0
  147. /package/{ios-runner → apple-runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +0 -0
  148. /package/{ios-runner → apple-runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScreenRecorder.swift +0 -0
  149. /package/{ios-runner → apple-runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SystemModal.swift +0 -0
  150. /package/{ios-runner → apple-runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Transport.swift +0 -0
  151. /package/{ios-runner → apple-runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TvRemote.swift +0 -0
  152. /package/{ios-runner → apple-runner}/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests.swift +0 -0
  153. /package/{ios-runner → apple-runner}/AgentDeviceRunner/AgentDeviceRunnerUITests.xctestplan +0 -0
  154. /package/{ios-runner → apple-runner}/AgentDeviceRunner/RecordingScripts/recording-overlay.swift +0 -0
  155. /package/{ios-runner → apple-runner}/AgentDeviceRunner/RecordingScripts/recording-resize.swift +0 -0
  156. /package/{ios-runner → apple-runner}/AgentDeviceRunner/RecordingScripts/recording-trim.swift +0 -0
  157. /package/dist/src/{4069.js → 4917.js} +0 -0
  158. /package/dist/src/{9836.js → 893.js} +0 -0
package/dist/src/cli.js CHANGED
@@ -1,29 +1,41 @@
1
- import{pathToFileURL as e}from"node:url";import t from"node:fs";import n,{randomBytes as r,randomUUID as o}from"node:crypto";import a from"node:path";import s from"node:http";import{Readable as i}from"node:stream";import{pipeline as l}from"node:stream/promises";import{resolveRemoteConfigProfile as c,resolveRemoteConfigPath as d,REMOTE_CONFIG_FIELD_SPECS as u,parseSourceValue as f,buildPrimaryEnvVarName as p}from"./4723.js";import{isClientBackedCliCommandName as m,listCliCommandNames as g,isRecord as h}from"./5341.js";import{getCliCommandSchema as v,applyCommandDefaults as w,getCommandSchema as y}from"./9581.js";import{asAppError as I,normalizeError as A,AppError as S}from"./733.js";import{buildCommandUsageText as _,buildUsageText as k}from"./cli-help.js";import{ensureCompanionTunnel as D,stopCompanionTunnel as C}from"./8275.js";import{REACT_DEVTOOLS_COMPANION_RUN_ARG as N}from"./4069.js";import{runCmdStreaming as b,runCmd as P}from"./8875.js";import{createRequestId as R,withDiagnosticsScope as U,getDiagnosticsMeta as x,flushDiagnosticsToSessionFile as E,emitDiagnostic as T}from"./432.js";import{isCommandName as L,printHumanError as B,getFlagDefinition as M,listCommandFamilyCliReaders as $,colorize as O,parseInstallSourceConfig as K,formatScreenshotDiffText as V,getFlagDefinitions as G,formatSnapshotDiffText as j,leaseScopeFromOptions as H,supportsColor as F,GLOBAL_FLAG_KEYS as q,leaseScopeToCommandFlags as W,leaseScopeToConnectionMetadata as J,printJson as z}from"./2948.js";import{buildDaemonHealthPayload as Z,resolveDaemonPaths as Y}from"./1848.js";import{stopMetroTunnel as X}from"./metro.js";import{resolveDevice as Q}from"./5910.js";import{setupManagedAgentBrowser as ee,localCommandPolicy as et,doctorManagedAgentBrowser as en,timingSafeStringEqual as er,createAgentDevice as eo}from"./2577.js";import{buildDaemonHttpAuthHeaders as ea,sendToDaemon as es,ensureDaemon as ei,createAgentDeviceClient as el,buildDaemonHttpBaseUrl as ec,buildDaemonHttpUrl as ed,resolveClientSettings as eu,DAEMON_HTTP_BASE_PATH as ef}from"./9919.js";import"./9836.js";import{stringifyMaestroYamlDocuments as ep,parseReplayScriptDetailed as em,formatMaestroPoint as eg,readReplayScriptMetadata as eh}from"./4428.js";import{resolveUserPath as ev,expandUserHomePath as ew}from"./9612.js";import{formatCliOutput as ey}from"./cli-output.js";import{runCommand as eI}from"./command-surface.js";import{createLocalArtifactAdapter as eA}from"./314.js";import{daemonRuntimeSchema as eS}from"./4291.js";import{readVersion as e_}from"./1404.js";import{maybeRunUpgradeNotifier as ek}from"./5448.js";import{parseSelectorChain as eD}from"./587.js";function eC(e,t){for(let[n,r]of Object.entries(t))void 0!==r&&(e[n]=r);return e}let eN=new Set(["config","remoteConfig","help","version","batchSteps","githubActionsArtifact"]),eb=new Set(["appsFilter","iosSimulatorDeviceSet","sessionLocked","sessionLockConflicts"]),eP=function(){let e=new Map;for(let t of G()){let n=e.get(t.key);n?n.push(t):e.set(t.key,[t])}let t=new Map;for(let e of q)t.set(e,new Set(["*"]));for(let e of g()){let n=v(e);for(let r of[...n.allowedFlags??[],...n.supportedFlags??[]]){let n=t.get(r);n&&n.has("*")||(n?n.add(e):t.set(r,new Set([e])))}}return[...e.entries()].map(([e,n])=>({key:e,flagDefinitions:n,config:{enabled:!eN.has(e),key:e},env:{names:eb.has(e)?[]:[p(e)]},supportsCommand(n){let r=t.get(e);return!!r&&(!!r.has("*")||!!n&&r.has(n))}})).sort((e,t)=>e.key.localeCompare(t.key))}(),eR=new Map(eP.map(e=>[e.key,e]));function eU(e,t){return eR.get(e)?.supportsCommand(t)??!1}function ex(e){let t=e.flagDefinitions.find(e=>void 0===e.setValue);if(t)return t;let n=function(e){let t=e.flagDefinitions[0];if(!t)throw Error(`Missing flag definition for option ${e.key}`);return t}(e);if("enum"===n.type){let t=n.enumValues??e.flagDefinitions.map(e=>e.setValue).filter(e=>void 0!==e);return{...n,setValue:void 0,enumValues:t}}return n}function eE(e){let t={json:!1,help:!1,version:!1},n=null,r=[],o=[],a=!0;for(let c=0;c<e.length;c+=1){var s,i,l;let d=e[c];if(a&&"--"===d){a=!1;continue}if(!a){n?r.push(d):n=eM(d);continue}if("cdp"===n){r.push(d);continue}let u=d.startsWith("--"),f=d.startsWith("-")&&d.length>1;if(!u&&!f){n?r.push(d):n=eM(d);continue}let[p,m]=u?eT(d):[d,void 0];if(s=n,"-c"===p&&("snapshot"===s||"diff"===s))continue;let g=function(e,t){let n=G().filter(t=>t.names.includes(e));if(n.length<=1)return n[0]??M(e);if(t){let e=n.find(e=>eU(e.key,t));if(e)return e}return M(e)}(p,n);if(i=n,l=g,"react-devtools"===i&&(!l||!eU(l.key,i))){r.push(d);continue}if(!g){if(function(e,t,n){var r;if(r=n,!/^-\d+(\.\d+)?$/.test(r)||!e)return!1;let o=y(e);if(!o||o.allowsExtraPositionals)return!0;let a=o.positionalArgs??[];return 0!==a.length&&(t.length<a.length||a.some(e=>e.includes("?")))}(n,r,d)){n?r.push(d):n=d;continue}throw new S("INVALID_ARGS",`Unknown flag: ${p}`)}let h=function(e,t,n,r){if(void 0!==e.setValue){if(void 0!==n)throw new S("INVALID_ARGS",`Flag ${t} does not take a value.`);return{value:e.setValue,consumeNext:!1}}if("boolean"===e.type){if(void 0!==n)throw new S("INVALID_ARGS",`Flag ${t} does not take a value.`);return{value:!0,consumeNext:!1}}if("booleanOrString"===e.type){if(void 0!==n){if(0===n.trim().length)throw new S("INVALID_ARGS",`Flag ${t} requires a non-empty value when provided.`);return{value:n,consumeNext:!1}}return void 0===r||eB(r)||!function(e){let t=e.trim();return!(!t||/^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//.test(t))&&!!(t.startsWith("./")||t.startsWith("../")||t.startsWith("~/")||t.startsWith("/")||t.includes("/")||t.includes("\\"))}(r)?{value:!0,consumeNext:!1}:{value:r,consumeNext:!0}}let o=n??r;if(void 0===o||void 0===n&&eB(o))throw new S("INVALID_ARGS",`Flag ${t} requires a value.`);if("string"===e.type)return{value:o,consumeNext:void 0===n};if("enum"===e.type){if(!e.enumValues?.includes(o))throw new S("INVALID_ARGS",`Invalid ${eL(t)}: ${o}`);return{value:o,consumeNext:void 0===n}}let a=Number(o);if(!Number.isFinite(a)||"number"==typeof e.min&&a<e.min||"number"==typeof e.max&&a>e.max)throw new S("INVALID_ARGS",`Invalid ${eL(t)}: ${o}`);return{value:Math.floor(a),consumeNext:void 0===n}}(g,p,m,e[c+1]);h.consumeNext&&(c+=1);let v=t[g.key];if(g.multiple){let e=Array.isArray(v)?[...v,h.value]:void 0===v?[h.value]:[v,h.value];t[g.key]=e}else t[g.key]=h.value;o.push({key:g.key,token:p})}return{command:n,positionals:r,flags:t,warnings:[],providedFlags:o}}function eT(e){let t=e.indexOf("=");return -1===t?[e,void 0]:[e.slice(0,t),e.slice(t+1)]}function eL(e){return e.replace(/^-+/,"")}function eB(e){if(!e.startsWith("-")||"-"===e)return!1;let[t]=e.startsWith("--")?eT(e):[e,void 0];return void 0!==M(t)}function eM(e){return"long-press"===e?"longpress":"metrics"===e?"perf":e}let e$={slug:"react-devtools-companion",runArg:N,displayName:"React DevTools companion"};async function eO(e){return await D({...e,definition:e$,localBaseUrl:e.localBaseUrl??"http://127.0.0.1:8097",registerPath:"/api/react-devtools/companion/register",unregisterPath:"/api/react-devtools/companion/unregister",devicePort:e.devicePort??8097})}async function eK(e){return await C({...e,definition:e$})}function eV(e){return"android-instance"===e||"ios-instance"===e}function eG(e){return"target"===e[0]&&("list"===e[1]||"select"===e[1])&&!e.some(e=>"--url"===e||e.startsWith("--url="))}async function ej(e,t={}){let n=function(e,t={}){if(!eG(e)||!t.flags?.metroProxyBaseUrl||!eV(t.flags.leaseBackend))return e;let n=function(e){let t=e?.metroPublicBaseUrl?.trim();if(t){let e,n;return(e=new URL(t)).search="",e.hash="",n=e.pathname.replace(/\/+$/,""),e.pathname=n.endsWith("/index.bundle")?n.slice(0,-13)||"/":n||"/",e.toString().replace(/\/+$/,"")}return null}(t.flags);if(!n)throw new S("INVALID_ARGS","cdp remote bridge target discovery requires a Metro public base URL.",{hint:"Include metroPublicBaseUrl in the remote config so cdp can reach the local or tunneled Metro CDP endpoint without bridge proxy authentication."});return[...e,"--url",n]}(e,t);return(await b("npm",["exec","--yes","--package","agent-cdp@1.6.0","--","agent-cdp",...n],{cwd:t.cwd??process.cwd(),env:t.env??process.env,allowFailure:!0,onStdoutChunk:e=>{process.stdout.write(e)},onStderrChunk:e=>{process.stderr.write(e)}})).exitCode}function eH(e){var n,r,o,a,s;let i,l=ez(e);if(!t.existsSync(l))return null;try{i=JSON.parse(t.readFileSync(l,"utf8"))}catch(t){return e0(e,t),null}return!(!(n=i)||"object"!=typeof n||Array.isArray(n))&&1===n.version&&(r=n,["session","remoteConfigPath","remoteConfigHash","tenant","runId","connectedAt","updatedAt"].every(e=>"string"==typeof r[e]))&&(o=n,["leaseId","leaseBackend","leaseProvider","deviceKey","clientId"].every(e=>void 0===o[e]||"string"==typeof o[e]))&&(void 0===(a=n.daemon)||!(!a||"object"!=typeof a||Array.isArray(a))&&(void 0===(s=a).baseUrl||"string"==typeof s.baseUrl)&&(void 0===s.authToken||"string"==typeof s.authToken)&&(void 0===s.transport||"string"==typeof s.transport)&&(void 0===s.serverMode||"string"==typeof s.serverMode))?i:(e0(e),null)}function eF(e){let n=ez({stateDir:e.stateDir,session:e.state.session});t.mkdirSync(a.dirname(n),{recursive:!0}),eQ(n,e.state),eQ(eZ(e.stateDir),{session:e.state.session})}function eq(e){return{baseUrl:function(e){if(!e)return;let t=new URL(e);for(let e of(t.username="",t.password="",[...t.searchParams.keys()]))/(auth|key|password|secret|token)/i.test(e)&&t.searchParams.delete(e);return t.toString().replace(/\/+$/,"")}(e.daemonBaseUrl),authToken:e.daemonAuthToken,transport:e.daemonTransport,serverMode:e.daemonServerMode}}function eW(e){t.rmSync(ez(e),{force:!0});let n=eZ(e.stateDir);eX(e.stateDir)===e.session&&t.rmSync(n,{force:!0})}function eJ(e){try{return n.createHash("sha256").update(t.readFileSync(e)).digest("hex")}catch(t){throw new S("INVALID_ARGS",`Remote config file not found: ${e}`,{cause:t instanceof Error?t.message:String(t)})}}function ez(e){return a.join(e.stateDir,"remote-connections",`${function(e){let t=e.replaceAll(/[^a-zA-Z0-9._-]/g,"_");if(!t)return"default";if(t===e)return t;let r=n.createHash("sha256").update(e).digest("hex").slice(0,8);return`${t}-${r}`}(e.session)}.json`)}function eZ(e){return a.join(e,"remote-connections",".active-session.json")}function eY(e){let t=eX(e.stateDir);return t?eH({stateDir:e.stateDir,session:t}):null}function eX(e){let n=eZ(e);if(t.existsSync(n))try{let e=JSON.parse(t.readFileSync(n,"utf8"));return"string"==typeof e.session?e.session:void 0}catch{return}}function eQ(e,n){t.writeFileSync(e,`${JSON.stringify(n,null,2)}
2
- `,{encoding:"utf8",mode:384}),t.chmodSync(e,384)}function e0(e,t){T({level:"warn",phase:"remote_connection_state_invalid",data:{session:e.session,cause:t instanceof Error?t.message:t?String(t):void 0}}),eW(e)}let e1=u.map(e=>e.key);function e3(e){let t={};for(let n of e1){let r=e[n];void 0!==r&&(t[n]=r)}return t}let e8=new Set(["connect","connection","close","disconnect","metro","session"]),e2=new Set(["open"]);async function e4(e){let t,{command:n,flags:r,client:o}=e;if(!r.remoteConfig)return{flags:r,runtime:e.runtime};let a=Y(r.stateDir).baseDir,s=c({configPath:r.remoteConfig,cwd:process.cwd(),env:process.env}),i={...e3(s.profile),...r,remoteConfig:s.resolvedPath},l=eH({stateDir:a,session:i.session??"default"});if(l&&l.remoteConfigPath!==s.resolvedPath)throw new S("INVALID_ARGS","A different remote connection is already active for this session. Run connect --force or disconnect before using a different --remote-config.",{session:l.session,activeRemoteConfig:l.remoteConfigPath,requestedRemoteConfig:s.resolvedPath});let d=l??function(e,t,n={}){if(!e.tenant)throw new S("INVALID_ARGS","remote command requires tenant in remote config or via --tenant <id>.");if(!e.runId)throw new S("INVALID_ARGS","remote command requires runId in remote config or via --run-id <id>.");if(!e.daemonBaseUrl)throw new S("INVALID_ARGS","remote command requires daemonBaseUrl in remote config, config, env, or --daemon-base-url.");let r=new Date().toISOString();return{version:1,session:e.session??"default",remoteConfigPath:t,remoteConfigHash:eJ(t),daemon:eq(e),tenant:e.tenant,runId:e.runId,leaseId:e.leaseId,leaseBackend:e.leaseBackend??ti(e),leaseProvider:n.leaseProvider,clientId:n.clientId,deviceKey:n.deviceKey,platform:e.platform,target:e.target,connectedAt:r,updatedAt:r}}(i,s.resolvedPath,s.profile),u={...i,session:d.session},f=function(e,t){if(e)return tc(e,t)?e:void 0}(d.runtime,u.platform)??e.runtime,p=d,m=!l,g="proxy"===p.leaseProvider?te:e9;if(g.shouldAllocate(n)){let e=await e7({command:n,client:o,state:d,nextState:p,nextFlags:u,policy:g});p=e.state,m=m||e.changed,t=e.acquiredLeaseForCleanup}let h=await e5({command:n,flags:u,client:o,state:d,nextState:p,runtime:f,positionals:e.positionals,batchSteps:e.batchSteps,forceRuntimePrepare:e.forceRuntimePrepare});return p=h.state,f=h.runtime,m=m||h.changed,await e6({changed:m,stateDir:a,state:p,client:o,acquiredLeaseForCleanup:t,preparedMetroCleanupOnFailure:h.preparedMetroCleanupOnFailure,metroCleanupToStop:h.metroCleanupToStop}),{flags:{...u,session:p.session,leaseId:p.leaseId,leaseBackend:p.leaseBackend,platform:p.platform??u.platform,target:p.target??u.target},runtime:f,connection:J(H(p))}}async function e5(e){var t,n,r,o,a,s,i;let{command:l,flags:c,state:d,client:u}=e,f=(t=e.nextState,n=c,t.leaseId||!n.leaseId?t:{...t,leaseId:n.leaseId,leaseBackend:n.leaseBackend}),p=e.runtime;if(!function(e,t,n,r=[]){return"cdp"===e?eG(r)&&!!t.metroPublicBaseUrl:!!e2.has(e)||"batch"===e&&!!n&&n.some(e=>{let t=e.command.trim().toLowerCase();return e2.has(t)&&void 0===e.runtime})}(l,c,e.batchSteps,e.positionals)||!tl(c)||(r=e.forceRuntimePrepare,o=p,a=c.platform,!0!==r&&o&&tc(o,a)))return{state:f,runtime:p,changed:!1};if(!f.leaseId)throw new S("INVALID_ARGS",`${l} requires a resolved remote lease before Metro runtime can be prepared.`);let m=await tt(c,u,d.remoteConfigPath,d.session,{tenantId:d.tenant,runId:d.runId,leaseId:f.leaseId}),g=(s=f.metro,i=m.cleanup,s?.projectRoot!==i?.projectRoot||s?.profileKey!==i?.profileKey||s?.consumerKey!==i?.consumerKey);return{state:f={...f,runtime:m.runtime,metro:m.cleanup,updatedAt:new Date().toISOString()},runtime:m.runtime,changed:!0,metroCleanupToStop:g?e.nextState.metro:void 0,preparedMetroCleanupOnFailure:g?m.cleanup:void 0}}async function e6(e){if(e.changed)try{eF({stateDir:e.stateDir,state:e.state})}catch(t){throw await tn(e.preparedMetroCleanupOnFailure),await ts(e.client,e.state,e.acquiredLeaseForCleanup),t}await tn(e.metroCleanupToStop)}async function e7(e){let{command:t,client:n,state:r,nextFlags:o,policy:a}=e,s=r.leaseBackend??ti(o),i=e.nextState,l=await a.resolveLeaseState({command:t,client:n,state:i,flags:o,leaseBackend:s});i=l.state,l.device&&function(e,t){if(e.platform=t.platform,e.target=t.target??e.target,"ios"===t.platform){e.udid=t.id;return}"android"===t.platform&&(e.serial=t.id)}(o,l.device);let c=i.leaseBackend??s??function(e,t){let n=ti(e);if(n)return n;throw new S("INVALID_ARGS",`${t} requires --platform ios|android or --lease-backend when the remote connection has not resolved a lease yet.`)}(o,t);var d,u,f,p,m,g,h,v=r,w=o,y=c;if(v.leaseBackend&&v.leaseBackend!==y)throw new S("INVALID_ARGS","Active remote connection is already bound to a different lease backend. Re-run connect --force to replace it.",{session:v.session,leaseBackend:v.leaseBackend});if(v.platform&&w.platform&&v.platform!==w.platform)throw new S("INVALID_ARGS","Active remote connection is already bound to a different platform. Re-run connect --force to replace it.",{session:v.session,platform:v.platform});if(v.target&&w.target&&v.target!==w.target)throw new S("INVALID_ARGS","Active remote connection is already bound to a different target. Re-run connect --force to replace it.",{session:v.session,target:v.target});let I=await td(n,i,c,a),A=I.lease;return(o.leaseId=A.leaseId,o.leaseBackend=c,o.platform=i.platform??o.platform,o.target=i.target??o.target,d=i,u=A,f=c,d.leaseId===u.leaseId&&d.leaseBackend===f&&d.deviceKey===(u.deviceKey??d.deviceKey))?{state:i,changed:!1,acquiredLeaseForCleanup:I.acquired?A:void 0}:{state:(p=i,m=A,g=c,h=o,{...p,leaseId:m.leaseId,leaseBackend:g,leaseProvider:m.leaseProvider??p.leaseProvider,clientId:m.clientId??p.clientId,deviceKey:m.deviceKey??p.deviceKey,platform:p.platform??h.platform,target:p.target??h.target,updatedAt:new Date().toISOString()}),changed:!0,acquiredLeaseForCleanup:I.acquired?A:void 0}}let e9={shouldAllocate:e=>!e8.has(e),ttlMs:()=>void 0,resolveLeaseState:async e=>({state:e.state})},te={shouldAllocate:e=>"devices"!==e&&!e8.has(e),ttlMs:()=>3e5,resolveLeaseState:tu};async function tt(e,t,n,r,o){if(!e.metroProjectRoot&&!e.metroPublicBaseUrl&&!e.metroProxyBaseUrl)return{};if("ios"!==e.platform&&"android"!==e.platform)throw new S("INVALID_ARGS",'Deferred Metro preparation requires platform "ios" or "android".');if(!e.metroPublicBaseUrl&&!e.metroProxyBaseUrl)throw new S("INVALID_ARGS","Deferred Metro preparation requires metroPublicBaseUrl or metroProxyBaseUrl when Metro settings are provided.");let a=await t.metro.prepare({projectRoot:e.metroProjectRoot,kind:function(e){if(void 0!==e){if("auto"===e||"react-native"===e||"expo"===e)return e;throw new S("INVALID_ARGS","metro prepare --kind must be auto, react-native, or expo")}}(e.metroKind),publicBaseUrl:e.metroPublicBaseUrl,proxyBaseUrl:e.metroProxyBaseUrl,bearerToken:e.metroBearerToken,bridgeScope:o,launchUrl:e.launchUrl,companionProfileKey:n,companionConsumerKey:r,port:e.metroPreparePort,listenHost:e.metroListenHost,statusHost:e.metroStatusHost,startupTimeoutMs:e.metroStartupTimeoutMs,probeTimeoutMs:e.metroProbeTimeoutMs,reuseExisting:!e.metroNoReuseExisting&&void 0,installDependenciesIfNeeded:!e.metroNoInstallDeps&&void 0,runtimeFilePath:e.metroRuntimeFile});return{runtime:"ios"===e.platform?a.iosRuntime:a.androidRuntime,cleanup:e.metroProxyBaseUrl?{projectRoot:a.projectRoot,profileKey:n,consumerKey:r}:void 0}}async function tn(e){if(e)try{await X(e)}catch{}}async function tr(e){try{await eK({projectRoot:process.cwd(),stateDir:e.stateDir,profileKey:e.state.remoteConfigPath,consumerKey:e.state.session})}catch{}}async function to(e,t){return!!t.leaseId&&(await e.leases.release({tenant:t.tenant,runId:t.runId,leaseId:t.leaseId,leaseBackend:t.leaseBackend,daemonBaseUrl:t.daemon?.baseUrl,daemonAuthToken:t.daemon?.authToken,daemonTransport:t.daemon?.transport,daemonServerMode:t.daemon?.serverMode,leaseProvider:t.leaseProvider,clientId:t.clientId,deviceKey:t.deviceKey})).released}async function ta(e,t){if(t.leaseId)try{await to(e,t)}catch{}}async function ts(e,t,n){if(n)try{await e.leases.release({tenant:t.tenant,runId:t.runId,leaseId:n.leaseId,leaseBackend:t.leaseBackend??n.backend,leaseProvider:t.leaseProvider??n.leaseProvider,clientId:t.clientId??n.clientId,deviceKey:t.deviceKey??n.deviceKey})}catch{}}function ti(e){return e.leaseBackend?e.leaseBackend:"android"===e.platform?"android-instance":"ios"===e.platform?"ios-instance":void 0}function tl(e){let t=e.metroKind;return!!(e.metroPublicBaseUrl||e.metroProxyBaseUrl||e.metroProjectRoot||t)}function tc(e,t){return!e.platform||!t||"ios"!==t&&"android"!==t||e.platform===t}async function td(e,t,n,r){if(t.leaseId&&t.leaseBackend===n){let o=await tp(e,t.leaseId,{tenant:t.tenant,runId:t.runId,leaseBackend:n,leaseProvider:t.leaseProvider,clientId:t.clientId,deviceKey:t.deviceKey,ttlMs:r.ttlMs(t)});if(o)return{lease:o,acquired:!1}}return{lease:await e.leases.allocate({tenant:t.tenant,runId:t.runId,leaseBackend:n,leaseProvider:t.leaseProvider,clientId:t.clientId,deviceKey:t.deviceKey,ttlMs:r.ttlMs(t)}),acquired:!0}}async function tu(e){var t,n;if("open"!==e.command){if(e.state.leaseId&&e.state.deviceKey)return{state:e.state};throw new S("INVALID_ARGS","No active proxy device lease for this session; run open first.")}let r=await tf(e.client,e.flags),o=(t=r,`${t.platform}:${t.target??"mobile"}:${t.id}`);return{state:{...e.state,deviceKey:o,leaseBackend:e.state.leaseBackend??e.leaseBackend??("ios"===(n=r).platform?"ios-instance":"android"===n.platform?"android-instance":void 0),platform:e.state.platform??r.platform,target:e.state.target??r.target,updatedAt:new Date().toISOString()},device:r}}async function tf(e,t){let n=await e.devices.list({platform:t.platform,target:t.target,device:t.device,udid:t.udid,serial:t.serial,iosSimulatorDeviceSet:t.iosSimulatorDeviceSet,androidDeviceAllowlist:t.androidDeviceAllowlist});return await Q(n.map(e=>({platform:e.platform,id:e.id,name:e.name,kind:e.kind,target:e.target,booted:e.booted})),{platform:t.platform,target:t.target,deviceName:t.device,udid:t.udid,serial:t.serial})}async function tp(e,t,n){try{return await e.leases.heartbeat({tenant:n.tenant,runId:n.runId,leaseId:t,leaseBackend:n.leaseBackend,leaseProvider:n.leaseProvider,clientId:n.clientId,deviceKey:n.deviceKey,ttlMs:n.ttlMs})}catch(e){var r;if((r=e)instanceof S&&"UNAUTHORIZED"===r.code&&(r.details?.reason==="LEASE_NOT_FOUND"||r.details?.reason==="LEASE_EXPIRED"||r.details?.reason==="LEASE_REVOKED"))return;throw e}}async function tm(e,t){let n=await e.text(),r={};if(n.trim().length>0)try{r=JSON.parse(n)}catch(n){throw new S("COMMAND_FAILED",t.invalidJsonMessage,{status:e.status},n instanceof Error?n:void 0)}if(!e.ok)throw new S("UNAUTHORIZED",t.rejectedMessage,{status:e.status,response:r});return r}async function tg(e){return await th({command:e.command,flags:e.flags,stateDir:e.stateDir,allowInteractiveLogin:"connect"===e.command&&!e.flags.noLogin,env:e.env})}async function th(e){let t=e.env??e.io?.env??process.env;if(!e.flags.daemonBaseUrl)return{flags:e.flags,source:"none"};if(tR(e.flags.daemonAuthToken))return{flags:e.flags,source:"flag"};if(tR(t.AGENT_DEVICE_DAEMON_AUTH_TOKEN))return{flags:e.flags,source:"env"};if(!function(e,t){if("1"===t.AGENT_DEVICE_CLOUD_AUTH||"true"===t.AGENT_DEVICE_CLOUD_AUTH||tR(t.AGENT_DEVICE_CLOUD_BASE_URL))return!0;try{let t=new URL(e).hostname.toLowerCase();return"agent-device.dev"===t||t.endsWith(".agent-device.dev")}catch{return!1}}(e.flags.daemonBaseUrl,t))return{flags:e.flags,source:"none"};let n=await tA({stateDir:e.stateDir,flags:e.flags,env:t,io:e.io});if(n)return{flags:{...e.flags,daemonAuthToken:n.accessToken},source:"cli-session"};if(!e.allowInteractiveLogin){if(e.flags.noLogin)throw new S("UNAUTHORIZED","Remote daemon authentication is required.",{hint:"Run agent-device auth login, unset --no-login, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN."});throw tD(e.command,t)}let r=await tw({stateDir:e.stateDir,flags:e.flags,env:t,io:e.io});return{flags:{...e.flags,daemonAuthToken:r.accessToken},source:"login"}}async function tv(e){let t=e.env??e.io?.env??process.env;if(tR(e.flags.daemonAuthToken))return{accessToken:e.flags.daemonAuthToken,cloudBaseUrl:tC(t)};if(tR(t.AGENT_DEVICE_DAEMON_AUTH_TOKEN))return{accessToken:t.AGENT_DEVICE_DAEMON_AUTH_TOKEN,cloudBaseUrl:tC(t)};let n=await tA({stateDir:e.stateDir,flags:e.flags,env:t,io:e.io});if(n)return{accessToken:n.accessToken,cloudBaseUrl:n.cloudBaseUrl};if(e.flags.noLogin)throw new S("UNAUTHORIZED","Cloud connection profile authentication is required.",{hint:"Run agent-device auth login, unset --no-login, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN."});let r=await tw({stateDir:e.stateDir,flags:e.flags,env:t,io:e.io,commandLabel:"agent-device connect"});return{accessToken:r.accessToken,cloudBaseUrl:r.session.cloudBaseUrl}}async function tw(e){let n,r,o,s=e.env??e.io?.env??process.env,i=(d=s,u=e.io,n=u?.stdinIsTTY??process.stdin.isTTY,r=u?.stdoutIsTTY??process.stdout.isTTY,"true"!==(f=d).CI&&"true"!==f.GITHUB_ACTIONS&&"true"!==f.BUILDKITE&&n&&r?(p=d).SSH_TTY||p.SSH_CONNECTION||"true"===p.CODESPACES||p.GITPOD_WORKSPACE_ID||"true"===p.REMOTE_CONTAINERS?"device-code":"local-browser":"non-interactive");if("non-interactive"===i)throw tD(e.commandLabel??"agent-device connect",s);let l=tC(s),c=await tk({baseUrl:l,pathName:"/api/control-plane/device-auth/start",body:{client:"agent-device",tenant:e.flags.tenant,runId:e.flags.runId,daemonBaseUrl:e.flags.daemonBaseUrl,session:e.flags.session},fetchImpl:e.io?.fetch});var d,u,f,p,m,g,h=c;if(!tR(h.deviceCode)||!tR(h.userCode)||!tR(h.verificationUri))throw new S("COMMAND_FAILED","Cloud auth start returned an unusable response.");let v=c.verificationUriComplete??c.verificationUri,w="local-browser"===i?c.verificationUri:(m=c.verificationUri,g=c.userCode,(o=new URL(m)).searchParams.set("user_code",g),o.toString());"local-browser"===i?(tb(e.io,`Opening ${c.verificationUri}...
3
- `),await tN(v,e.io)):tb(e.io,`Open this URL on your machine:
1
+ import{pathToFileURL as e}from"node:url";import t from"node:fs";import r from"node:os";import n from"node:path";import o,{randomBytes as s,randomUUID as a}from"node:crypto";import i from"node:http";import{Readable as l}from"node:stream";import{pipeline as c}from"node:stream/promises";import{asAppError as u,normalizeError as d,AppError as f}from"./485.js";import{isClientBackedCliCommandName as p,INTERNAL_COMMANDS as m,listCliCommandNames as g,PUBLIC_COMMANDS as h,parseBatchStepRuntime as v,isRecord as y}from"./1986.js";import{getCliCommandSchema as w,applyCommandDefaults as I,getCommandSchema as A}from"./9581.js";import{buildCommandUsageText as S,buildUsageText as _}from"./cli-help.js";import{isCommandName as k,printHumanError as D,getFlagDefinition as $,listCommandFamilyCliReaders as b,colorize as C,parseInstallSourceConfig as N,formatScreenshotDiffText as R,formatCliStatusMarker as x,getFlagDefinitions as P,formatSnapshotDiffText as E,leaseScopeFromOptions as T,supportsColor as U,GLOBAL_FLAG_KEYS as M,leaseScopeToCommandFlags as L,leaseScopeToConnectionMetadata as B,printJson as O}from"./2948.js";import{ensureCompanionTunnel as V,stopCompanionTunnel as j}from"./8404.js";import{REACT_DEVTOOLS_COMPANION_RUN_ARG as G}from"./4917.js";import{resolveDevice as F,isNonDefaultResponseLevel as K,device_PLATFORM_SELECTORS as H}from"./6849.js";import{resolveUserPath as q,expandUserHomePath as W}from"./9612.js";import{runCmdStreaming as J,runCmd as z}from"./8875.js";import{createRequestId as Z,withDiagnosticsScope as Y,getDiagnosticsMeta as X,flushDiagnosticsToSessionFile as Q,emitDiagnostic as ee}from"./432.js";import{localCommandPolicy as et,isCloudWebDriverProviderName as er,CLOUD_WEBDRIVER_PROVIDERS as en,timingSafeStringEqual as eo,createAgentDevice as es}from"./7871.js";import{buildDaemonHealthPayload as ea,readNodeHttpRequestBody as ei,resolveDaemonPaths as el}from"./5913.js";import{stopMetroTunnel as ec}from"./6967.js";import{buildDaemonHttpAuthHeaders as eu,sendToDaemon as ed,ensureDaemon as ef,createAgentDeviceClient as ep,buildDaemonHttpBaseUrl as em,buildDaemonHttpUrl as eg,resolveClientSettings as eh,DAEMON_HTTP_BASE_PATH as ev}from"./495.js";import"./893.js";import{stringifyMaestroYamlDocuments as ey,parseReplayScriptDetailed as ew,formatMaestroPoint as eI,readReplayScriptMetadata as eA}from"./4428.js";import{formatCliOutput as eS}from"./cli-output.js";import{runCommand as e_}from"./command-surface.js";import{createLocalArtifactAdapter as ek}from"./314.js";import{readVersion as eD}from"./1404.js";import{maybeRunUpgradeNotifier as e$}from"./5448.js";import{parseSelectorChain as eb}from"./587.js";function eC(e,t){for(let[r,n]of Object.entries(t))void 0!==n&&(e[r]=n);return e}let eN=new Set(["1","true","yes","on"]),eR=new Set(["0","false","no","off"]);function ex(e){return`AGENT_DEVICE_${e.replace(/([A-Z])/g,"_$1").replace(/[^A-Za-z0-9_]/g,"_").toUpperCase()}`}function eP(e,t,r,n){if(e.multiple)return(Array.isArray(t)?t:[t]).map(t=>eP({...e,multiple:!1},t,r,n));if("boolean"===e.type){var o=t,s=r,a=n;if("boolean"==typeof o)return o;if("string"==typeof o){let e=eE(o);if(void 0!==e)return e}throw new f("INVALID_ARGS",`Invalid value for "${a}" in ${s}. Expected boolean.`)}if("booleanOrString"===e.type){if("boolean"==typeof t)return t;if("string"==typeof t&&void 0!==eE(t))return eE(t);if("string"==typeof t&&t.trim().length>0)return t;throw new f("INVALID_ARGS",`Invalid value for "${n}" in ${r}. Expected boolean or non-empty string.`)}if("string"===e.type){if("string"==typeof t&&t.trim().length>0)return t;throw new f("INVALID_ARGS",`Invalid value for "${n}" in ${r}. Expected non-empty string.`)}if("enum"===e.type){if(void 0!==e.setValue){var i=e,l=t,c=r,u=n;let o=i.setValue;if(l===o)return o;if("string"==typeof l){let e=l.trim();if(""===e||"true"===e||"1"===e)return o;if("false"===e||"0"===e)return}if(!0===l)return o;if(!1!==l)throw new f("INVALID_ARGS",`Invalid value for "${u}" in ${c}. Expected boolean-like value for enum flag.`);return}if("string"!=typeof t||!e.enumValues?.includes(t))throw new f("INVALID_ARGS",`Invalid value for "${n}" in ${r}. Expected one of: ${e.enumValues?.join(", ")}.`);return t}let d="number"==typeof t?t:"string"==typeof t?Number(t):NaN;if(!Number.isFinite(d)||!Number.isInteger(d))throw new f("INVALID_ARGS",`Invalid value for "${n}" in ${r}. Expected integer.`);if("number"==typeof e.min&&d<e.min)throw new f("INVALID_ARGS",`Invalid value for "${n}" in ${r}. Must be >= ${e.min}.`);if("number"==typeof e.max&&d>e.max)throw new f("INVALID_ARGS",`Invalid value for "${n}" in ${r}. Must be <= ${e.max}.`);return d}function eE(e){let t=e.trim().toLowerCase();return!!eN.has(t)||!eR.has(t)&&void 0}let eT=new Set(["config","remoteConfig","help","version","batchSteps","githubActionsArtifact"]),eU=new Set(["appsFilter","iosSimulatorDeviceSet","sessionLocked","sessionLockConflicts"]),eM=function(){let e=new Map;for(let t of P()){let r=e.get(t.key);r?r.push(t):e.set(t.key,[t])}let t=new Map;for(let e of M)t.set(e,new Set(["*"]));for(let e of g()){let r=w(e);for(let n of[...r.allowedFlags??[],...r.supportedFlags??[]]){let r=t.get(n);r&&r.has("*")||(r?r.add(e):t.set(n,new Set([e])))}}return[...e.entries()].map(([e,r])=>({key:e,flagDefinitions:r,config:{enabled:!eT.has(e),key:e},env:{names:eU.has(e)?[]:[ex(e)]},supportsCommand(r){let n=t.get(e);return!!n&&(!!n.has("*")||!!r&&n.has(r))}})).sort((e,t)=>e.key.localeCompare(t.key))}(),eL=new Map(eM.map(e=>[e.key,e]));function eB(e,t){return eL.get(e)?.supportsCommand(t)??!1}function eO(e){let t=e.flagDefinitions.find(e=>void 0===e.setValue);if(t)return t;let r=function(e){let t=e.flagDefinitions[0];if(!t)throw Error(`Missing flag definition for option ${e.key}`);return t}(e);if("enum"===r.type){let t=r.enumValues??e.flagDefinitions.map(e=>e.setValue).filter(e=>void 0!==e);return{...r,setValue:void 0,enumValues:t}}return r}function eV(e){let t={json:!1,help:!1,version:!1},r=null,n=[],o=[],s=!0;for(let c=0;c<e.length;c+=1){var a,i,l;let u=e[c];if(s&&"--"===u){s=!1;continue}if(!s){r?n.push(u):r=eK(u);continue}if("cdp"===r){n.push(u);continue}let d=u.startsWith("--"),p=u.startsWith("-")&&u.length>1;if(!d&&!p){r?n.push(u):r=eK(u);continue}let[m,g]=d?ej(u):[u,void 0];if(a=r,"-c"===m&&("snapshot"===a||"diff"===a))continue;let h=function(e,t){let r=P().filter(t=>t.names.includes(e));if(r.length<=1)return r[0]??$(e);if(t){let e=r.find(e=>eB(e.key,t));if(e)return e}return $(e)}(m,r);if(i=r,l=h,"react-devtools"===i&&(!l||!eB(l.key,i))){n.push(u);continue}if(!h){if(function(e,t,r){var n;if(n=r,!/^-\d+(\.\d+)?$/.test(n)||!e)return!1;let o=A(e);if(!o||o.allowsExtraPositionals)return!0;let s=o.positionalArgs??[];return 0!==s.length&&(t.length<s.length||s.some(e=>e.includes("?")))}(r,n,u)){r?n.push(u):r=u;continue}throw new f("INVALID_ARGS",`Unknown flag: ${m}`)}let v=function(e,t,r,n){if(void 0!==e.setValue){if(void 0!==r)throw new f("INVALID_ARGS",`Flag ${t} does not take a value.`);return{value:e.setValue,consumeNext:!1}}if("boolean"===e.type){if(void 0!==r)throw new f("INVALID_ARGS",`Flag ${t} does not take a value.`);return{value:!0,consumeNext:!1}}if("booleanOrString"===e.type){if(void 0!==r){if(0===r.trim().length)throw new f("INVALID_ARGS",`Flag ${t} requires a non-empty value when provided.`);return{value:r,consumeNext:!1}}return void 0===n||eF(n)||!function(e){let t=e.trim();return!(!t||/^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//.test(t))&&!!(t.startsWith("./")||t.startsWith("../")||t.startsWith("~/")||t.startsWith("/")||t.includes("/")||t.includes("\\"))}(n)?{value:!0,consumeNext:!1}:{value:n,consumeNext:!0}}let o=r??n;if(void 0===o||void 0===r&&eF(o))throw new f("INVALID_ARGS",`Flag ${t} requires a value.`);if("string"===e.type)return{value:o,consumeNext:void 0===r};if("enum"===e.type){if(!e.enumValues?.includes(o))throw new f("INVALID_ARGS",`Invalid ${eG(t)}: ${o}`);return{value:o,consumeNext:void 0===r}}let s=Number(o);if(!Number.isFinite(s)||"number"==typeof e.min&&s<e.min||"number"==typeof e.max&&s>e.max)throw new f("INVALID_ARGS",`Invalid ${eG(t)}: ${o}`);return{value:Math.floor(s),consumeNext:void 0===r}}(h,m,g,e[c+1]);v.consumeNext&&(c+=1);let y=t[h.key];if(h.multiple){let e=Array.isArray(y)?[...y,v.value]:void 0===y?[v.value]:[y,v.value];t[h.key]=e}else t[h.key]=v.value;o.push({key:h.key,token:m})}return{command:r,positionals:n,flags:t,warnings:[],providedFlags:o}}function ej(e){let t=e.indexOf("=");return -1===t?[e,void 0]:[e.slice(0,t),e.slice(t+1)]}function eG(e){return e.replace(/^-+/,"")}function eF(e){if(!e.startsWith("-")||"-"===e)return!1;let[t]=e.startsWith("--")?ej(e):[e,void 0];return void 0!==$(t)}function eK(e){return"long-press"===e?"longpress":"metrics"===e?"perf":e}let eH=["onSuiteStart","onTestStart","onTestStep","onTestResult","onSuiteEnd","getExitCode"];async function eq(e){let t=function(e){if(e.startsWith("file:"))return e;let t=e.startsWith("~/")?n.join(r.homedir(),e.slice(2)):e;return n.resolve(process.cwd(),t)}(e.modulePath),o=function(e,t){let r=e.createReporter??e.default??e.reporter;if(!r)throw new f("INVALID_ARGS",`Custom test reporter ${t} must export default, createReporter, or reporter.`);return"function"==typeof r?r:()=>r}(await eW(t),e.modulePath);var s=await o({spec:e.raw,modulePath:t}),a=e.modulePath;if(!s||"object"!=typeof s)throw new f("INVALID_ARGS",`Custom test reporter ${a} must export a reporter object or factory.`);if("string"!=typeof s.name||0===s.name.trim().length)throw new f("INVALID_ARGS",`Custom test reporter ${a} must define name.`);for(let e of eH)if(void 0!==s[e]&&"function"!=typeof s[e])throw new f("INVALID_ARGS",`Custom test reporter ${a} ${e} must be a function.`);return s}async function eW(t){try{let r=t.startsWith("file:")?t:e(t).href;return await import(r)}catch(r){let e=r instanceof Error?r.message:String(r);throw new f("INVALID_ARGS",`Failed to load custom test reporter ${t}: ${e}`)}}function eJ(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 ez(e){var r,o;let s=(r=e).artifactsDir?n.join(r.artifactsDir,`attempt-${r.attempts}`,"replay-timing.ndjson"):void 0;if(!s)return[];let a=function(e){try{return t.readFileSync(e,"utf8").split(/\r?\n/).filter(e=>e.trim().length>0).flatMap(e=>{try{let t=JSON.parse(e);return e1(t)?[t]:[]}catch{return[]}})}catch{return[]}}(s);if(0===a.length)return[];let i=[],l=[];for(let e of a){if("replay_action_start"===(o=e).type&&eZ(o)&&eY(o,"line")&&eX(o,"command")&&(void 0===o.positionals||Array.isArray(o.positionals))){i.push(e);continue}(function(e){var t;return["replay_action_stop"===e.type&&eZ(e)&&eY(e,"line")&&eX(e,"command"),void 0===(t=e).ok||"boolean"==typeof t.ok,eY(e,"durationMs"),eX(e,"errorCode"),void 0===e.resultTiming||e1(e.resultTiming)].every(Boolean)})(e)&&l.push({stop:e,start:function(e,t){let r=t.command,n=e.findIndex(e=>e.step===t.step&&(void 0===r||void 0===e.command||e.command===r));if(!(n<0))return e.splice(n,1)[0]}(i,e)})}return l}function eZ(e){return"number"==typeof e.step}function eY(e,t){return void 0===e[t]||"number"==typeof e[t]}function eX(e,t){return void 0===e[t]||"string"==typeof e[t]}function eQ(e,t){var r,n,o,s;let a,i,l=!1===e.ok?"[FAIL] ":!0===e.ok?"":"[info] ";return` ${l}${r=t,n=e,[function(e){if(!e)return"unknown";if(!e.startsWith("__maestro"))return e;let t=e.slice(9);return t.length>0?t[0].toLowerCase()+t.slice(1):e}(r?.command??n.command),...(r?.positionals??[]).map(e0)].join(" ")}${o=e,s=t,(i=["number"==typeof(a=s?.line??o.line)?`line ${a}`:"","number"==typeof o.durationMs?eJ(o.durationMs):"",o.errorCode??"",o.resultTiming?`timing ${JSON.stringify(o.resultTiming)}`:""].filter(Boolean)).length>0?` (${i.join(", ")})`:""}`}function e0(e){return"string"==typeof e?JSON.stringify(e):"number"==typeof e||"boolean"==typeof e?String(e):JSON.stringify(e)}function e1(e){return!!e&&"object"==typeof e&&!Array.isArray(e)}let e3=["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"],e8="\x1b[0m";function e2(e,t){return C(e,t,{validateStream:!1})}function e4(e,t={}){var r;let n;if("number"!=typeof e.shardIndex)return"";let o="number"==typeof e.shardCount?e.shardCount:"?",s=(r=e,(n=r.deviceName?.trim())||r.deviceId?.trim()||void 0),a=` [${e.shardIndex+1}/${o}${s?` ${s}`:""}]`;return t.useColor?e2(a,"dim"):a}function e5(e){return`\r\x1b[2K${e}`}function e6(e){return"number"==typeof e&&Number.isFinite(e)&&e>0?Math.floor(e):80}function e9(e,t){let r=e6(t);return e7(e)<=r?e:r<=0?"":r<=3?".".repeat(r):`${function(e,t){if(t<=0)return"";let r=0,n="";for(let o=0;o<e.length&&r<t;){let t=te(e,o);if(t){n+=t,o+=t.length;continue}n+=e[o],o+=1,r+=1}return n}(e,r-3)}...${e.includes("\x1b[")?e8:""}`}function e7(e){let t=0;for(let r=0;r<e.length;){let n=te(e,r);if(n){r+=n.length;continue}t+=1,r+=1}return t}function te(e,t){if(!e.startsWith("\x1b[",t))return null;for(let n=t+2;n<e.length;n+=1){var r;if((r=e.charCodeAt(n))>=64&&r<=126)return e.slice(t,n+1)}return null}function tt(e){return{file:e.file,title:e.title,durationMs:e.durationMs??0,attempts:e.attempt??1,artifactsDir:e.artifactsDir,session:e.session??""}}function tr(e){return+(e.failed>0)}function tn(e){return"failed"===e.status}function to(e){return"passed"===e.status&&e.attempts>1}function ts(e){let t=th(e),r=n.basename(e.file),o=t&&t.length>0?t:r;return`${o}${tv(e)}`}function ta(e,t){return"artifactsDir"in e&&e.artifactsDir?`${t}: ${e.artifactsDir}`:void 0}function ti(e){return e.hint?`hint: ${e.hint}`:void 0}function tl(e,t){return e.diagnosticId?`${t}: ${e.diagnosticId}`:void 0}function tc(e,t){return e.logPath?`${t}: ${e.logPath}`:void 0}function tu(e,t,r={}){r.includeMessage&&e.push(`errorMessage: ${t.message}`),tf(e,ti(t)),tf(e,tl(t,"diagnosticId")),tf(e,tc(t,"logPath")),!1!==r.includeDetails&&td(e,t,r.detailsIndent)}function td(e,t,r){let n=t.details?JSON.stringify(t.details,null,r):void 0;n&&e.push(`details: ${n}`)}function tf(e,t){t&&e.push(t)}function tp(e){return(Math.max(0,e)/1e3).toFixed(3)}function tm(e){return e.replaceAll("&","&amp;").replaceAll("<","&lt;").replaceAll(">","&gt;").replaceAll('"',"&quot;").replaceAll("'","&apos;")}function tg(e){return void 0!==e}function th(e){let t=e.title?.trim();return t&&t.length>0?t:void 0}function tv(e){var t;let r;if(!("shardIndex"in e)||"number"!=typeof e.shardIndex)return"";let n="number"==typeof e.shardCount?e.shardCount:"?",o=(r="deviceName"in(t=e)?t.deviceName?.trim():void 0)||("deviceId"in t?t.deviceId?.trim():void 0)||void 0;return` [${e.shardIndex+1}/${n}${o?` ${o}`:""}]`}let ty="\x1b[?25l",tw="\x1b[?25h";function tI(e){return e.stderr.isTTY&&!process.env.CI}function tA(e){var t,r;let n,o=e.trim();if(!o)throw new f("INVALID_ARGS","Test reporter spec cannot be empty.");if((t=o).startsWith(".")||t.startsWith("/")||t.startsWith("~")||t.startsWith("file:"))return{kind:"custom",modulePath:o,raw:o};let{name:s,value:a}=(n=(r=o).indexOf(":"))<0?{name:r.trim()}:{name:r.slice(0,n).trim(),value:r.slice(n+1)};if("default"===s){if(void 0!==a)throw new f("INVALID_ARGS","The default test reporter does not accept options.");return{kind:"builtin",name:s,raw:o}}if("junit"===s)return void 0===a?{kind:"builtin",name:s,raw:o}:{kind:"builtin",name:s,raw:o,outputPath:a};throw new f("INVALID_ARGS",`Unknown test reporter "${s}". Built-in reporters: default, junit:<path>. Custom reporters must be file paths.`)}let tS={"suite-start":"onSuiteStart","test-start":"onTestStart","test-step":"onTestStep","test-result":"onTestResult"};async function t_(e){let t,r=(t=e.reporters&&e.reporters.length>0?e.reporters.map(tA):e.json?[]:[tA("default")],e.reportJunit&&t.push(tA(`junit:${e.reportJunit}`)),t);return await Promise.all(r.map(t$))}async function tk(e,t,r){for(let n of e)await n.onSuiteEnd?.(t,r)}function tD(e,t,r,n){let o=n instanceof Error?n.message:String(n);r.stderr.write(`Reporter ${e.name} ${String(t)} failed: ${o}
2
+ `)}async function t$(e){let r;if("custom"===e.kind)return await eq(e);if("default"===e.name){let e,t,r,o,s,a,i;return o=!1,s=(r,o)=>{i(),t="test-step"===r.type?r:void 0;let s=(e??=function(e={}){let t=new Set,r=!1,o=0;return{render(s){var a,i;if("suite-start"===s.type){t.clear(),r=!1;return}if("test-step"===s.type){if(!e.liveProgress)return;r=!0;let t=e3[o%e3.length]??e3[0];return o+=1,{text:e5(function(e,t,r){let o=e.title?.trim(),s=n.basename(e.file),a=U(process.stderr),i=function(e,t={}){return t.useColor?e2(e,"blue"):e}(r,{useColor:a}),l=e4(e,{useColor:a}),c=function(e,t={}){let r=e.stepIndex??0,n=e.stepTotal??0,o=`${r}/${n}`,s=e.stepCommand?.trim(),a=e.stepValue?.trim();if(!t.useColor){let e=[o,s,a].filter(Boolean).join(" ");return` [${e}]`}let i=e2("[","dim"),l=e2("]","dim"),c=[e2(o,"dim"),s?e2(s,"magenta"):"",a?e2(a,"green"):""].filter(Boolean);return` ${i}${c.join(" ")}${l}`}(e,{useColor:a}),u=`${l}${c}`,d=`${i} `;if(!o)return e9(`${d}${s}${u}`,t.columns);let f=e9(o,Math.max(0,e6(t.columns)-e7(d)-e7(u)));return e9(`${d}${f}${u}`,t.columns)}(s.test,e,t)),newline:!1}}if("test-result"!==s.type)return;if("pass"===(a=s.test).status||"skip"===a.status||"fail"===a.status&&!a.retrying){let e,r=(e="number"==typeof(i=s.test).shardIndex?i.shardIndex:"",[i.status,i.index,i.total,i.file,i.title??"",e].join("\0"));if(t.has(r))return;t.add(r)}let l=function(e,t={}){var r,o,s,a,i;let l,c,u,d,f,p,m;if("fail"===e.status&&e.retrying)return;let g=[(r=e,u=U(process.stderr),d="pass"===(o=r).status?x("pass",{passFormat:o.attempt&&o.attempt>1?"yellow":"green"}):x("fail"===o.status?"fail":"skip"),f=(s=r,l=s.title?.trim(),c=n.basename(s.file),l||c),p=e4(r,{useColor:u}),m=void 0!==r.durationMs?` ${function(e,t={}){let r=eJ(e.durationMs??0);return t.useColor?e2(r,"yellow"):r}(r,{useColor:u})}`:"",`${d} ${f}${p}${m}`)];return function(e,t,r){var o,s,a,i;let l;if(o=t,!0===r.verbose&&"fail"===o.status)return;let c="fail"===(s=t).status&&s.title?.trim()?` file: ${n.basename(s.file)}`:void 0,u=function(e){let t=e.message?.replace(/\s+/g," ").trim();if(t)return` ${"fail"===e.status?`failed at: ${t}`:t}`}(t);c&&e.push(c),u&&e.push(u),a=e,i=t,l=i.hint?.replace(/\s+/g," ").trim(),"fail"===i.status&&l&&a.push(` hint: ${l}`),e.push(...function(e){if("fail"!==e.status||e.retrying)return[];let t=[];return e.session&&t.push(` session: ${e.session}`),e.artifactsDir&&t.push(` artifacts: ${e.artifactsDir}`),t}(t))}(g,e,t),t.verbose&&g.push(...("pass"===(a=e).status||"fail"===a.status)&&a.artifactsDir&&a.attempt?(function(e){if("skipped"===e.status)return[];let t=ez(e);return 0===t.length?[]:[e.attempts>1?`steps (attempt ${e.attempts}):`:"steps:",...t.map(({stop:e,start:t})=>eQ(e,t))]})("pass"===a.status?{...tt(a),status:"passed",replayed:0,healed:0}:{...tt(i=a),status:"failed",error:{code:"COMMAND_FAILED",message:i.message??"Unknown test failure"}}).map(e=>` ${e}`):[]),g.join("\n")}(s.test,e);if(!l)return;let c=r?e5(l):l;return r=!1,{text:c,newline:!0}}}}({verbose:o.verbose,liveProgress:tI(o),columns:o.stderr.columns})).render(r);s&&(o.stderr.write(s.newline?`${s.text}
3
+ `:s.text),"test-step"===r.type&&tI(o)&&a(o))},a=n=>{!r&&t&&(r=setInterval(()=>{if(!t)return;let r=e?.render(t);r&&n.stderr.write(r.newline?`${r.text}
4
+ `:r.text)},80),r.unref?.())},i=()=>{r&&(clearInterval(r),r=void 0)},{name:"default",onSuiteStart:(e,t)=>{!o&&tI(t)&&(t.stderr.write(ty),o=!0),s({type:"suite-start",suite:e},t)},onTestStep:(e,t)=>{s({type:"test-step",test:e},t)},onTestResult:(e,t)=>{s({type:"test-result",test:e},t)},onSuiteEnd:(e,r)=>{var s,a,l,c;let u,d,f,p,m,g,h,v;i(),t=void 0,o&&(r.stderr.write(tw),o=!1),s=e,a=r,u=s.tests.filter(to),a.stdout.write(`${(l=s,c=u.length,d="number"==typeof l.durationMs?l.durationMs:void 0,f=U(),p=function(e,t={}){let r=`${e} passed`;return t.useColor?C(r,"green"):r}(l.passed,{useColor:f}),m=function(e,t={}){let r=`(${e})`;return t.useColor?C(r,"dim"):r}(l.total,{useColor:f}),g=l.failed>0?`, ${l.failed} failed`:"",h=c>0?`, ${c} flaky`:"",v=void 0!==d?` in ${function(e,t={}){let r=eJ(e);return t.useColor?C(r,"yellow"):r}(d,{useColor:f})}`:"",`Test summary: ${p} ${m}${g}${h}${v}`)}
5
+ `),function(e,t){if(0!==e.length)for(let r of(t.stdout.write("\n"),t.stdout.write("Failures:\n"),e))t.stdout.write(` ${ts(r)}
6
+ `),function(e,t,r){let o=th(e)?`file: ${n.basename(e.file)}`:void 0;for(let n of(o&&t.stdout.write(`${r}${o}
7
+ `),t.stdout.write(`${r}${e.error?.message??"Unknown test failure"}
8
+ `),[ti(e.error),ta(e,"artifacts"),tc(e.error,"log"),tl(e.error,"diagnostic")].filter(tg)))t.stdout.write(`${r}${n}
9
+ `);if(t.debug)for(let n of function(e){let t=ez(e),r=t.findIndex(({stop:e})=>!1===e.ok);if(r<0)return[];let n=t.slice(Math.max(0,r-2),r+1);return[e.attempts>1?`steps (attempt ${e.attempts}):`:"steps:",...n.map(({stop:e,start:t})=>eQ(e,t))]}(e))t.stdout.write(`${r}${n}
10
+ `)}(r,t," ")}(s.tests.filter(tn),a),function(e,t){if(0!==e.length)for(let r of(t.stdout.write("\n"),t.stdout.write("Flaky tests:\n"),e))for(let e of(t.stdout.write(` ${U()?C("✓","yellow"):"✓"} ${ts(r)} after ${r.attempts} attempts${function(e){let t=["number"==typeof e.finalAttemptDurationMs?`passed attempt ${eJ(e.finalAttemptDurationMs)}`:"",e.durationMs>0?`total ${eJ(e.durationMs)}`:""].filter(Boolean);return t.length>0?` (${t.join(", ")})`:""}(r)}
11
+ `),r.attemptFailures??[])){let r="number"==typeof e.durationMs?` (${eJ(e.durationMs)})`:"";t.stdout.write(` attempt ${e.attempt} failed${r}: ${e.message}
12
+ `)}}(u,a)},getExitCode:tr}}return r=function(e){if(e&&e.trim().length>0)return e;throw new f("INVALID_ARGS","The junit test reporter requires an output path. Use --reporter junit:<path>.")}(e.outputPath),{name:"junit",onSuiteEnd:e=>(function(e,r){let o=n.dirname(e);try{t.mkdirSync(o,{recursive:!0}),t.writeFileSync(e,function(e){let t=['<?xml version="1.0" encoding="UTF-8"?>',"<testsuites>",` <testsuite name="agent-device replay suite" tests="${e.total}" failures="${e.failed}" skipped="${e.skipped}" time="${tp(e.durationMs)}">`];for(let r of e.tests)t.push(...function(e){let t=tm(`${th(e)??n.basename(e.file)}${tv(e)}`),r=tm(`${"."===n.dirname(e.file)?e.file:n.dirname(e.file)}${tv(e)}`),o=tm(e.file),s=tp(e.durationMs),a=[` <testcase classname="${r}" name="${t}" file="${o}" time="${s}">`];"failed"===e.status?a.push(` <failure message="${tm(e.error.message)}">${tm(function(e){let t=[e.error.message];return tu(t,e.error,{includeDetails:!1}),tf(t,ta(e,"artifactsDir")),td(t,e.error,2),t.join("\n")}(e))}</failure>`):"skipped"===e.status&&a.push(` <skipped message="${tm(e.message)}" />`);let i=function(e){let t=[`status: ${e.status}`,`durationMs: ${e.durationMs}`];return function(e,t){var r,n;for(let r of(tf(e,"attempts"in t?`attempts: ${t.attempts}`:void 0),tf(e,"session"in t?`session: ${t.session}`:void 0),tf(e,"replayed"in t?`replayed: ${t.replayed}`:void 0),tf(e,"healed"in t?`healed: ${t.healed}`:void 0),"passed"!==t.status?[]:(t.warnings??[]).map(e=>`warning: ${e}`)))e.push(r);tf(e,ta(t,"artifactsDir")),"shardIndex"in t&&"number"==typeof t.shardIndex&&(e.push(`shardIndex: ${t.shardIndex}`),tf(e,"number"==typeof t.shardCount?`shardCount: ${t.shardCount}`:void 0),tf(e,"string"==typeof t.deviceId?`deviceId: ${t.deviceId}`:void 0),tf(e,"string"==typeof t.deviceName?`deviceName: ${t.deviceName}`:void 0)),"failed"===t.status&&(r=e,n=t,r.push(`errorCode: ${n.error.code}`),tu(r,n.error,{includeMessage:!0})),tf(e,to(t)?"flaky: true":void 0)}(t,e),t.join("\n")}(e);return i&&a.push(` <system-out>${tm(i)}</system-out>`),a.push(" </testcase>"),a}(r));return t.push(" </testsuite>"),t.push("</testsuites>"),`${t.join("\n")}
13
+ `}(r),"utf8")}catch(r){let t=r instanceof Error?r.message:String(r);throw new f("COMMAND_FAILED",`Failed to write JUnit report to ${e}: ${t}`)}})(r,e),getExitCode:tr}}async function tb(e){let{suite:t,json:r,debug:n,verbose:o,reporter:s,reportJunit:a}=e,i=e.reporterRuntime??await tC({debug:n,verbose:o,reporter:s,reportJunit:a,json:r});await tk(i.reporters,t,i.context),r&&O({success:!0,data:t});var l=i.reporters;let c=tr(t);for(let e of l){let r=e.getExitCode?.(t);void 0!==r&&(c=Math.max(c,r))}return c}async function tC(e){var t;let r=await t_({reporters:e.reporter,reportJunit:e.reportJunit,json:e.json}),n={debug:(t={debug:e.debug,verbose:e.verbose}).debug,verbose:t.verbose??t.debug,stdout:tN(process.stdout),stderr:tN(process.stderr)};return{reporters:r,context:n,onProgress(e){!function(e,t,r){let n=function(e){if("command"===e.type)return;if("replay-test-suite"===e.type)return{type:"suite-start",suite:{total:e.total,runnable:e.runnable,skipped:e.skipped,artifactsDir:e.artifactsDir,shardMode:e.shardMode,shardCount:e.shardCount}};let t={file:e.file,title:e.title,index:e.index,total:e.total,attempt:e.attempt,maxAttempts:e.maxAttempts,session:e.session,artifactsDir:e.artifactsDir,shardIndex:e.shardIndex,shardCount:e.shardCount,deviceId:e.deviceId,deviceName:e.deviceName};return"start"===e.status?{type:"test-start",test:t}:"progress"===e.status?{type:"test-step",test:{...t,stepIndex:e.stepIndex,stepTotal:e.stepTotal,stepCommand:e.stepCommand,stepValue:e.stepValue}}:{type:"test-result",test:{...t,status:e.status,durationMs:e.durationMs,retrying:e.retrying,message:e.message,hint:e.hint}}}(t);if(!n)return;let o=tS[n.type];for(let t of e)try{let e=function(e,t,r){switch(t.type){case"suite-start":return e.onSuiteStart?.(t.suite,r);case"test-start":return e.onTestStart?.(t.test,r);case"test-step":return e.onTestStep?.(t.test,r);case"test-result":return e.onTestResult?.(t.test,r)}}(t,n,r);e instanceof Promise&&e.catch(e=>tD(t,o,r,e))}catch(e){tD(t,o,r,e)}}(r,e,n)}}}function tN(e){return{isTTY:!0===e.isTTY,columns:e.columns,write:t=>e.write(t)}}let tR={slug:"react-devtools-companion",runArg:G,displayName:"React DevTools companion"};async function tx(e){return await V({...e,definition:tR,localBaseUrl:e.localBaseUrl??"http://127.0.0.1:8097",registerPath:"/api/react-devtools/companion/register",unregisterPath:"/api/react-devtools/companion/unregister",devicePort:e.devicePort??8097})}async function tP(e){return await j({...e,definition:tR})}let tE=[{key:"stateDir",type:"string",path:!0},{key:"daemonBaseUrl",type:"string"},{key:"daemonAuthToken",type:"string"},{key:"daemonTransport",type:"enum",enumValues:["auto","socket","http"]},{key:"daemonServerMode",type:"enum",enumValues:["socket","http","dual"]},{key:"tenant",type:"string"},{key:"sessionIsolation",type:"enum",enumValues:["none","tenant"]},{key:"runId",type:"string"},{key:"leaseId",type:"string"},{key:"leaseBackend",type:"enum",enumValues:["ios-simulator","ios-instance","android-instance"]},{key:"platform",type:"enum",enumValues:H},{key:"target",type:"enum",enumValues:["mobile","tv","desktop"]},{key:"device",type:"string"},{key:"udid",type:"string"},{key:"serial",type:"string"},{key:"iosSimulatorDeviceSet",type:"string",path:!0,env:!1},{key:"androidDeviceAllowlist",type:"string"},{key:"session",type:"string"},{key:"providerApp",type:"string"},{key:"providerOsVersion",type:"string"},{key:"providerProject",type:"string"},{key:"providerBuild",type:"string"},{key:"providerSessionName",type:"string"},{key:"awsProjectArn",type:"string"},{key:"awsDeviceArn",type:"string"},{key:"awsAppArn",type:"string"},{key:"awsRegion",type:"string"},{key:"awsInteractionMode",type:"enum",enumValues:["INTERACTIVE","NO_VIDEO","VIDEO_ONLY"]},{key:"metroProjectRoot",type:"string",path:!0},{key:"metroKind",type:"enum",enumValues:["auto","react-native","expo"]},{key:"metroPublicBaseUrl",type:"string"},{key:"metroProxyBaseUrl",type:"string"},{key:"metroBearerToken",type:"string"},{key:"metroPreparePort",type:"int",min:1,max:65535},{key:"metroListenHost",type:"string"},{key:"metroStatusHost",type:"string"},{key:"metroStartupTimeoutMs",type:"int",min:1},{key:"metroProbeTimeoutMs",type:"int",min:1},{key:"metroRuntimeFile",type:"string",path:!0},{key:"metroNoReuseExisting",type:"boolean"},{key:"metroNoInstallDeps",type:"boolean"}],tT=[...tE,{key:"leaseProvider",type:"string",env:!1},{key:"deviceKey",type:"string",env:!1},{key:"clientId",type:"string",env:!1}],tU=new Map(tT.map(e=>[e.key,e]));function tM(e){let t=e.env??process.env;return q(e.configPath,{cwd:e.cwd,env:t})}function tL(e){let r=function(e){let r,o,s=e.env??process.env,a=tM(e);if(!t.existsSync(a))throw new f("INVALID_ARGS",`Remote config file not found: ${a}`);try{r=t.readFileSync(a,"utf8")}catch(e){throw new f("INVALID_ARGS",`Failed to read remote config file: ${a}`,{cause:e instanceof Error?e.message:String(e)})}try{o=JSON.parse(r)}catch(e){throw new f("INVALID_ARGS",`Invalid JSON in remote config file: ${a}`,{cause:e instanceof Error?e.message:String(e)})}if(!o||"object"!=typeof o||Array.isArray(o))throw new f("INVALID_ARGS",`Remote config file must contain a JSON object: ${a}`);let i={},l=o,c=n.dirname(a);for(let[e,t]of Object.entries(l)){let r=tU.get(e);if(!r)throw new f("INVALID_ARGS",`Unsupported remote config key "${e}" in remote config file ${a}.`);let n=eP(r,t,`remote config file ${a}`,e);i[r.key]="string"==typeof n&&"path"in r&&r.path?q(n,{cwd:c,env:s}):n}return{resolvedPath:a,profile:i}}(e);return{resolvedPath:r.resolvedPath,profile:function(...e){let t={};for(let r of e)if(r)for(let e of tT){let n=r[e.key];void 0!==n&&(t[e.key]=n)}return t}(function(e=process.env){let t={};for(let r of tT){let n=(function(e){let t=tU.get(e);return t?.env===!1?[]:[ex(e)]})(r.key).map(t=>({name:t,value:e[t]})).find(e=>"string"==typeof e.value&&e.value.trim().length>0);n&&(t[r.key]=eP(r,n.value,`environment variable ${n.name}`,n.name))}return t}(e.env),r.profile)}}function tB(e){return"android-instance"===e||"ios-instance"===e}function tO(e){return"target"===e[0]&&("list"===e[1]||"select"===e[1])&&!e.some(e=>"--url"===e||e.startsWith("--url="))}async function tV(e,t={}){let r=function(e,t={}){if(!tO(e)||!t.flags?.metroProxyBaseUrl||!tB(t.flags.leaseBackend))return e;let r=function(e){let t=e?.metroPublicBaseUrl?.trim();if(t){let e,r;return(e=new URL(t)).search="",e.hash="",r=e.pathname.replace(/\/+$/,""),e.pathname=r.endsWith("/index.bundle")?r.slice(0,-13)||"/":r||"/",e.toString().replace(/\/+$/,"")}return null}(t.flags);if(!r)throw new f("INVALID_ARGS","cdp remote bridge target discovery requires a Metro public base URL.",{hint:"Include metroPublicBaseUrl in the remote config so cdp can reach the local or tunneled Metro CDP endpoint without bridge proxy authentication."});return[...e,"--url",r]}(e,t);return(await J("npm",["exec","--yes","--package","agent-cdp@1.6.0","--","agent-cdp",...r],{cwd:t.cwd??process.cwd(),env:t.env??process.env,allowFailure:!0,onStdoutChunk:e=>{process.stdout.write(e)},onStderrChunk:e=>{process.stderr.write(e)}})).exitCode}function tj(e){var r,n,o,s,a;let i,l=tq(e);if(!t.existsSync(l))return null;try{i=JSON.parse(t.readFileSync(l,"utf8"))}catch(t){return tY(e,t),null}return!(!(r=i)||"object"!=typeof r||Array.isArray(r))&&1===r.version&&(n=r,["session","remoteConfigPath","remoteConfigHash","tenant","runId","connectedAt","updatedAt"].every(e=>"string"==typeof n[e]))&&(o=r,["leaseId","leaseBackend","leaseProvider","deviceKey","clientId"].every(e=>void 0===o[e]||"string"==typeof o[e]))&&(void 0===(s=r.daemon)||!(!s||"object"!=typeof s||Array.isArray(s))&&(void 0===(a=s).baseUrl||"string"==typeof a.baseUrl)&&(void 0===a.authToken||"string"==typeof a.authToken)&&(void 0===a.transport||"string"==typeof a.transport)&&(void 0===a.serverMode||"string"==typeof a.serverMode))?i:(tY(e),null)}function tG(e){let r=tq({stateDir:e.stateDir,session:e.state.session});t.mkdirSync(n.dirname(r),{recursive:!0}),tZ(r,e.state),tZ(tW(e.stateDir),{session:e.state.session})}function tF(e){return{baseUrl:function(e){if(!e)return;let t=new URL(e);for(let e of(t.username="",t.password="",[...t.searchParams.keys()]))/(auth|key|password|secret|token)/i.test(e)&&t.searchParams.delete(e);return t.toString().replace(/\/+$/,"")}(e.daemonBaseUrl),authToken:e.daemonAuthToken,transport:e.daemonTransport,serverMode:e.daemonServerMode}}function tK(e){t.rmSync(tq(e),{force:!0});let r=tW(e.stateDir);tz(e.stateDir)===e.session&&t.rmSync(r,{force:!0})}function tH(e){try{return o.createHash("sha256").update(t.readFileSync(e)).digest("hex")}catch(t){throw new f("INVALID_ARGS",`Remote config file not found: ${e}`,{cause:t instanceof Error?t.message:String(t)})}}function tq(e){return n.join(e.stateDir,"remote-connections",`${function(e){let t=e.replaceAll(/[^a-zA-Z0-9._-]/g,"_");if(!t)return"default";if(t===e)return t;let r=o.createHash("sha256").update(e).digest("hex").slice(0,8);return`${t}-${r}`}(e.session)}.json`)}function tW(e){return n.join(e,"remote-connections",".active-session.json")}function tJ(e){let t=tz(e.stateDir);return t?tj({stateDir:e.stateDir,session:t}):null}function tz(e){let r=tW(e);if(t.existsSync(r))try{let e=JSON.parse(t.readFileSync(r,"utf8"));return"string"==typeof e.session?e.session:void 0}catch{return}}function tZ(e,r){t.writeFileSync(e,`${JSON.stringify(r,null,2)}
14
+ `,{encoding:"utf8",mode:384}),t.chmodSync(e,384)}function tY(e,t){ee({level:"warn",phase:"remote_connection_state_invalid",data:{session:e.session,cause:t instanceof Error?t.message:t?String(t):void 0}}),tK(e)}let tX=tE.map(e=>e.key);function tQ(e){let t={};for(let r of tX){let n=e[r];void 0!==n&&(t[r]=n)}return t}let t0=new Set(["connect","connection","close","disconnect","metro","session"]),t1=new Set(["open"]),t3=new Set([h.open,h.install,h.reinstall,m.installSource]);async function t8(e){let t,{command:r,flags:n,client:o}=e;if(!n.remoteConfig)return{flags:n,runtime:e.runtime};let s=el(n.stateDir).baseDir,a=tL({configPath:n.remoteConfig,cwd:process.cwd(),env:process.env}),i={...tQ(a.profile),...n,remoteConfig:a.resolvedPath},l=tj({stateDir:s,session:i.session??"default"});if(l&&l.remoteConfigPath!==a.resolvedPath)throw new f("INVALID_ARGS","A different remote connection is already active for this session. Run connect --force or disconnect before using a different --remote-config.",{session:l.session,activeRemoteConfig:l.remoteConfigPath,requestedRemoteConfig:a.resolvedPath});let c=l??function(e,t,r={}){if(!e.tenant)throw new f("INVALID_ARGS","remote command requires tenant in remote config or via --tenant <id>.");if(!e.runId)throw new f("INVALID_ARGS","remote command requires runId in remote config or via --run-id <id>.");if(!e.daemonBaseUrl&&!er(r.leaseProvider))throw new f("INVALID_ARGS","remote command requires daemonBaseUrl in remote config, config, env, or --daemon-base-url.");let n=new Date().toISOString();return{version:1,session:e.session??"default",remoteConfigPath:t,remoteConfigHash:tH(t),daemon:tF(e),tenant:e.tenant,runId:e.runId,leaseId:e.leaseId,leaseBackend:e.leaseBackend??rs(e),leaseProvider:r.leaseProvider,clientId:r.clientId,deviceKey:r.deviceKey,platform:e.platform,target:e.target,connectedAt:n,updatedAt:n}}(i,a.resolvedPath,a.profile),u={...i,session:c.session},d=function(e,t){if(e)return ri(e,t)?e:void 0}(c.runtime,u.platform)??e.runtime,p=c,m=!l,g="proxy"===p.leaseProvider?t9:t6;if(g.shouldAllocate(r)){let e=await t5({command:r,client:o,state:c,nextState:p,nextFlags:u,policy:g});p=e.state,m=m||e.changed,t=e.acquiredLeaseForCleanup}let h=await t2({command:r,flags:u,client:o,state:c,nextState:p,runtime:d,positionals:e.positionals,batchSteps:e.batchSteps,forceRuntimePrepare:e.forceRuntimePrepare});return p=h.state,d=h.runtime,m=m||h.changed,await t4({changed:m,stateDir:s,state:p,client:o,acquiredLeaseForCleanup:t,preparedMetroCleanupOnFailure:h.preparedMetroCleanupOnFailure,metroCleanupToStop:h.metroCleanupToStop}),{flags:{...u,session:p.session,leaseId:p.leaseId,leaseBackend:p.leaseBackend,platform:p.platform??u.platform,target:p.target??u.target},runtime:d,connection:B(T(p))}}async function t2(e){var t,r,n,o,s,a,i;let{command:l,flags:c,state:u,client:d}=e,p=(t=e.nextState,r=c,t.leaseId||!r.leaseId?t:{...t,leaseId:r.leaseId,leaseBackend:r.leaseBackend}),m=e.runtime;if(!function(e,t,r,n=[]){return"cdp"===e?tO(n)&&!!t.metroPublicBaseUrl:!!t1.has(e)||"batch"===e&&!!r&&r.some(e=>{let t=e.command.trim().toLowerCase();return t1.has(t)&&void 0===e.runtime})}(l,c,e.batchSteps,e.positionals)||!ra(c)||(n=e.forceRuntimePrepare,o=m,s=c.platform,!0!==n&&o&&ri(o,s)))return{state:p,runtime:m,changed:!1};if(!p.leaseId)throw new f("INVALID_ARGS",`${l} requires a resolved remote lease before Metro runtime can be prepared.`);let g=await t7(c,d,u.remoteConfigPath,u.session,{tenantId:u.tenant,runId:u.runId,leaseId:p.leaseId}),h=(a=p.metro,i=g.cleanup,a?.projectRoot!==i?.projectRoot||a?.profileKey!==i?.profileKey||a?.consumerKey!==i?.consumerKey);return{state:p={...p,runtime:g.runtime,metro:g.cleanup,updatedAt:new Date().toISOString()},runtime:g.runtime,changed:!0,metroCleanupToStop:h?e.nextState.metro:void 0,preparedMetroCleanupOnFailure:h?g.cleanup:void 0}}async function t4(e){if(e.changed)try{tG({stateDir:e.stateDir,state:e.state})}catch(t){throw await re(e.preparedMetroCleanupOnFailure),await ro(e.client,e.state,e.acquiredLeaseForCleanup),t}await re(e.metroCleanupToStop)}async function t5(e){let{command:t,client:r,state:n,nextFlags:o,policy:s}=e,a=n.leaseBackend??rs(o),i=e.nextState,l=await s.resolveLeaseState({command:t,client:r,state:i,flags:o,leaseBackend:a});i=l.state,l.device&&function(e,t){if(e.platform=t.platform,e.target=t.target??e.target,"ios"===t.platform){e.udid=t.id;return}"android"===t.platform&&(e.serial=t.id)}(o,l.device);let c=i.leaseBackend??a??function(e,t){let r=rs(e);if(r)return r;throw new f("INVALID_ARGS",`${t} requires --platform ios|android or --lease-backend when the remote connection has not resolved a lease yet.`)}(o,t);var u,d,p,m,g,h,v,y=n,w=o,I=c;if(y.leaseBackend&&y.leaseBackend!==I)throw new f("INVALID_ARGS","Active remote connection is already bound to a different lease backend. Re-run connect --force to replace it.",{session:y.session,leaseBackend:y.leaseBackend});if(y.platform&&w.platform&&y.platform!==w.platform)throw new f("INVALID_ARGS","Active remote connection is already bound to a different platform. Re-run connect --force to replace it.",{session:y.session,platform:y.platform});if(y.target&&w.target&&y.target!==w.target)throw new f("INVALID_ARGS","Active remote connection is already bound to a different target. Re-run connect --force to replace it.",{session:y.session,target:y.target});let A=await rl(r,i,c,s,o),S=A.lease;return(o.leaseId=S.leaseId,o.leaseBackend=c,o.platform=i.platform??o.platform,o.target=i.target??o.target,u=i,d=S,p=c,u.leaseId===d.leaseId&&u.leaseBackend===p&&u.deviceKey===(d.deviceKey??u.deviceKey))?{state:i,changed:!1,acquiredLeaseForCleanup:A.acquired?S:void 0}:{state:(m=i,g=S,h=c,v=o,{...m,leaseId:g.leaseId,leaseBackend:h,leaseProvider:g.leaseProvider??m.leaseProvider,clientId:g.clientId??m.clientId,deviceKey:g.deviceKey??m.deviceKey,platform:m.platform??v.platform,target:m.target??v.target,updatedAt:new Date().toISOString()}),changed:!0,acquiredLeaseForCleanup:A.acquired?S:void 0}}let t6={shouldAllocate:e=>!t0.has(e),ttlMs:()=>void 0,resolveLeaseState:async e=>({state:e.state})},t9={shouldAllocate:e=>"devices"!==e&&!t0.has(e),ttlMs:()=>3e5,resolveLeaseState:rc};async function t7(e,t,r,n,o){if(!e.metroProjectRoot&&!e.metroPublicBaseUrl&&!e.metroProxyBaseUrl)return{};if("ios"!==e.platform&&"android"!==e.platform)throw new f("INVALID_ARGS",'Deferred Metro preparation requires platform "ios" or "android".');if(!e.metroPublicBaseUrl&&!e.metroProxyBaseUrl)throw new f("INVALID_ARGS","Deferred Metro preparation requires metroPublicBaseUrl or metroProxyBaseUrl when Metro settings are provided.");let s=await t.metro.prepare({projectRoot:e.metroProjectRoot,kind:function(e){if(void 0!==e){if("auto"===e||"react-native"===e||"expo"===e)return e;throw new f("INVALID_ARGS","metro prepare --kind must be auto, react-native, or expo")}}(e.metroKind),publicBaseUrl:e.metroPublicBaseUrl,proxyBaseUrl:e.metroProxyBaseUrl,bearerToken:e.metroBearerToken,bridgeScope:o,launchUrl:e.launchUrl,companionProfileKey:r,companionConsumerKey:n,port:e.metroPreparePort,listenHost:e.metroListenHost,statusHost:e.metroStatusHost,startupTimeoutMs:e.metroStartupTimeoutMs,probeTimeoutMs:e.metroProbeTimeoutMs,reuseExisting:!e.metroNoReuseExisting&&void 0,installDependenciesIfNeeded:!e.metroNoInstallDeps&&void 0,runtimeFilePath:e.metroRuntimeFile});return{runtime:"ios"===e.platform?s.iosRuntime:s.androidRuntime,cleanup:e.metroProxyBaseUrl?{projectRoot:s.projectRoot,profileKey:r,consumerKey:n}:void 0}}async function re(e){if(e)try{await ec(e)}catch{}}async function rt(e){try{await tP({projectRoot:process.cwd(),stateDir:e.stateDir,profileKey:e.state.remoteConfigPath,consumerKey:e.state.session})}catch{}}async function rr(e,t){return t.leaseId?await e.leases.release({tenant:t.tenant,runId:t.runId,leaseId:t.leaseId,leaseBackend:t.leaseBackend,daemonBaseUrl:t.daemon?.baseUrl,daemonAuthToken:t.daemon?.authToken,daemonTransport:t.daemon?.transport,daemonServerMode:t.daemon?.serverMode,leaseProvider:t.leaseProvider,clientId:t.clientId,deviceKey:t.deviceKey}):{released:!1}}async function rn(e,t){if(t.leaseId)try{await rr(e,t)}catch{}}async function ro(e,t,r){if(r)try{await e.leases.release({tenant:t.tenant,runId:t.runId,leaseId:r.leaseId,leaseBackend:t.leaseBackend??r.backend,leaseProvider:t.leaseProvider??r.leaseProvider,clientId:t.clientId??r.clientId,deviceKey:t.deviceKey??r.deviceKey})}catch{}}function rs(e){return e.leaseBackend?e.leaseBackend:"android"===e.platform?"android-instance":"ios"===e.platform?"ios-instance":void 0}function ra(e){let t=e.metroKind;return!!(e.metroPublicBaseUrl||e.metroProxyBaseUrl||e.metroProjectRoot||t)}function ri(e,t){return!e.platform||!t||"ios"!==t&&"android"!==t||e.platform===t}async function rl(e,t,r,n,o){if(t.leaseId&&t.leaseBackend===r){let o=await rd(e,t.leaseId,{tenant:t.tenant,runId:t.runId,leaseBackend:r,leaseProvider:t.leaseProvider,clientId:t.clientId,deviceKey:t.deviceKey,ttlMs:n.ttlMs(t)});if(o)return{lease:o,acquired:!1}}return{lease:await e.leases.allocate({tenant:t.tenant,runId:t.runId,leaseBackend:r,leaseProvider:t.leaseProvider,clientId:t.clientId,deviceKey:t.deviceKey,ttlMs:n.ttlMs(t),platform:t.platform??o.platform,target:t.target??o.target,device:o.device,udid:o.udid,serial:o.serial,providerApp:o.providerApp,providerOsVersion:o.providerOsVersion,providerProject:o.providerProject,providerBuild:o.providerBuild,providerSessionName:o.providerSessionName,awsProjectArn:o.awsProjectArn,awsDeviceArn:o.awsDeviceArn,awsAppArn:o.awsAppArn,awsRegion:o.awsRegion,awsInteractionMode:o.awsInteractionMode}),acquired:!0}}async function rc(e){var t,r;if(!t3.has(e.command)){if(e.state.leaseId&&e.state.deviceKey)return{state:e.state};throw new f("INVALID_ARGS","No active proxy device lease for this session; run open first.")}let n=await ru(e.client,e.flags),o=(t=n,`${t.platform}:${t.target??"mobile"}:${t.id}`);return{state:{...e.state,deviceKey:o,leaseBackend:e.state.leaseBackend??e.leaseBackend??("ios"===(r=n).platform?"ios-instance":"android"===r.platform?"android-instance":void 0),platform:e.state.platform??n.platform,target:e.state.target??n.target,updatedAt:new Date().toISOString()},device:n}}async function ru(e,t){let r=await e.devices.list({platform:t.platform,target:t.target,device:t.device,udid:t.udid,serial:t.serial,iosSimulatorDeviceSet:t.iosSimulatorDeviceSet,androidDeviceAllowlist:t.androidDeviceAllowlist});return await F(r.map(e=>({platform:e.platform,id:e.id,name:e.name,kind:e.kind,target:e.target,booted:e.booted})),{platform:t.platform,target:t.target,deviceName:t.device,udid:t.udid,serial:t.serial})}async function rd(e,t,r){try{return await e.leases.heartbeat({tenant:r.tenant,runId:r.runId,leaseId:t,leaseBackend:r.leaseBackend,leaseProvider:r.leaseProvider,clientId:r.clientId,deviceKey:r.deviceKey,ttlMs:r.ttlMs})}catch(e){var n;if((n=e)instanceof f&&"UNAUTHORIZED"===n.code&&(n.details?.reason==="LEASE_NOT_FOUND"||n.details?.reason==="LEASE_EXPIRED"||n.details?.reason==="LEASE_REVOKED"))return;throw e}}async function rf(e,t){let r=await e.text(),n={};if(r.trim().length>0)try{n=JSON.parse(r)}catch(r){throw new f("COMMAND_FAILED",t.invalidJsonMessage,{status:e.status},r instanceof Error?r:void 0)}if(!e.ok)throw new f("UNAUTHORIZED",t.rejectedMessage,{status:e.status,response:n});return n}async function rp(e){return await rm({command:e.command,flags:e.flags,stateDir:e.stateDir,allowInteractiveLogin:"connect"===e.command&&!e.flags.noLogin,env:e.env})}async function rm(e){let t=e.env??e.io?.env??process.env;if(!e.flags.daemonBaseUrl)return{flags:e.flags,source:"none"};if(rC(e.flags.daemonAuthToken))return{flags:e.flags,source:"flag"};if(rC(t.AGENT_DEVICE_DAEMON_AUTH_TOKEN))return{flags:e.flags,source:"env"};if(!function(e,t){if("1"===t.AGENT_DEVICE_CLOUD_AUTH||"true"===t.AGENT_DEVICE_CLOUD_AUTH||rC(t.AGENT_DEVICE_CLOUD_BASE_URL))return!0;try{let t=new URL(e).hostname.toLowerCase();return"agent-device.dev"===t||t.endsWith(".agent-device.dev")}catch{return!1}}(e.flags.daemonBaseUrl,t))return{flags:e.flags,source:"none"};let r=await rw({stateDir:e.stateDir,flags:e.flags,env:t,io:e.io});if(r)return{flags:{...e.flags,daemonAuthToken:r.accessToken},source:"cli-session"};if(!e.allowInteractiveLogin){if(e.flags.noLogin)throw new f("UNAUTHORIZED","Remote daemon authentication is required.",{hint:"Run agent-device auth login, unset --no-login, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN."});throw r_(e.command,t)}let n=await rh({stateDir:e.stateDir,flags:e.flags,env:t,io:e.io});return{flags:{...e.flags,daemonAuthToken:n.accessToken},source:"login"}}async function rg(e){let t=e.env??e.io?.env??process.env;if(rC(e.flags.daemonAuthToken))return{accessToken:e.flags.daemonAuthToken,cloudBaseUrl:rk(t)};if(rC(t.AGENT_DEVICE_DAEMON_AUTH_TOKEN))return{accessToken:t.AGENT_DEVICE_DAEMON_AUTH_TOKEN,cloudBaseUrl:rk(t)};let r=await rw({stateDir:e.stateDir,flags:e.flags,env:t,io:e.io});if(r)return{accessToken:r.accessToken,cloudBaseUrl:r.cloudBaseUrl};if(e.flags.noLogin)throw new f("UNAUTHORIZED","Cloud connection profile authentication is required.",{hint:"Run agent-device auth login, unset --no-login, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN."});let n=await rh({stateDir:e.stateDir,flags:e.flags,env:t,io:e.io,commandLabel:"agent-device connect"});return{accessToken:n.accessToken,cloudBaseUrl:n.session.cloudBaseUrl}}async function rh(e){let r,o,s,a=e.env??e.io?.env??process.env,i=(u=a,d=e.io,r=d?.stdinIsTTY??process.stdin.isTTY,o=d?.stdoutIsTTY??process.stdout.isTTY,"true"!==(p=u).CI&&"true"!==p.GITHUB_ACTIONS&&"true"!==p.BUILDKITE&&r&&o?(m=u).SSH_TTY||m.SSH_CONNECTION||"true"===m.CODESPACES||m.GITPOD_WORKSPACE_ID||"true"===m.REMOTE_CONTAINERS?"device-code":"local-browser":"non-interactive");if("non-interactive"===i)throw r_(e.commandLabel??"agent-device connect",a);let l=rk(a),c=await rS({baseUrl:l,pathName:"/api/control-plane/device-auth/start",body:{client:"agent-device",tenant:e.flags.tenant,runId:e.flags.runId,daemonBaseUrl:e.flags.daemonBaseUrl,session:e.flags.session},fetchImpl:e.io?.fetch});var u,d,p,m,g,h,v=c;if(!rC(v.deviceCode)||!rC(v.userCode)||!rC(v.verificationUri))throw new f("COMMAND_FAILED","Cloud auth start returned an unusable response.");let y=c.verificationUriComplete??c.verificationUri,w="local-browser"===i?c.verificationUri:(g=c.verificationUri,h=c.userCode,(s=new URL(g)).searchParams.set("user_code",h),s.toString());"local-browser"===i?(r$(e.io,`Opening ${c.verificationUri}...
15
+ `),await rD(y,e.io)):r$(e.io,`Open this URL on your machine:
4
16
  ${w}
5
17
 
6
18
  Waiting for approval for 10 minutes...
7
- `);let y=await t_({cloudBaseUrl:l,deviceCode:c.deviceCode,expiresIn:c.expiresIn,interval:c.interval,fetchImpl:e.io?.fetch,now:e.io?.now}),I=y.cliSession?.refreshCredential??y.cliSession?.refreshToken;if(!tR(y.accessToken)||!tR(I))throw new S("UNAUTHORIZED","Device authorization did not return CLI credentials.");let A=new Date(e.io?.now?.()??Date.now()).toISOString(),_={version:1,id:y.cliSession?.id??`cli-${Date.now().toString(36)}`,cloudBaseUrl:l,workspaceId:y.cliSession?.workspaceId,accountId:y.cliSession?.accountId,name:y.cliSession?.name,refreshCredential:I,createdAt:A,expiresAt:y.cliSession?.expiresAt};return function(e){let n=tI(e.stateDir);t.mkdirSync(a.dirname(n),{recursive:!0,mode:448}),t.writeFileSync(n,`${JSON.stringify(e.session,null,2)}
8
- `,{mode:384});try{t.chmodSync(n,384)}catch{}}({stateDir:e.stateDir,session:_}),{accessToken:y.accessToken,expiresAt:y.expiresAt,session:_}}function ty(e){let n=tI(e.stateDir);if(!t.existsSync(n))return null;try{let e=JSON.parse(t.readFileSync(n,"utf8"));if(1!==e.version||!tR(e.id)||!tR(e.cloudBaseUrl)||!tR(e.refreshCredential)||!tR(e.createdAt))return null;return e}catch{return null}}function tI(e){return a.join(e,"auth","cli-session.json")}async function tA(e){let t=ty({stateDir:e.stateDir});return!t||tP(t.expiresAt,e.io?.now)?null:{accessToken:(await tS({session:t,flags:e.flags,env:e.env,io:e.io})).accessToken,cloudBaseUrl:tC(e.env,t.cloudBaseUrl)}}async function tS(e){let t=tC(e.env,e.session.cloudBaseUrl),n=await tk({baseUrl:t,pathName:"/api/control-plane/cli-session/refresh",body:{refreshCredential:e.session.refreshCredential,tenant:e.flags.tenant,runId:e.flags.runId,daemonBaseUrl:e.flags.daemonBaseUrl,session:e.flags.session},fetchImpl:e.io?.fetch});if(tR(n.accessToken))return{accessToken:n.accessToken,expiresAt:n.expiresAt};if("revoked"===n.status||"revoked"===n.error)throw new S("UNAUTHORIZED","Stored cloud CLI session was revoked.",{hint:"Run agent-device auth login again, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN.",status:n.status,error:n.error});throw new S("UNAUTHORIZED","Failed to refresh CLI session.",{hint:"Run agent-device auth login again, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN.",status:n.status,error:n.error})}async function t_(e){let t=e.now??Date.now,n=Math.min((e.expiresIn??600)*1e3,6e5),r=t()+n,o=Math.max(1e3,(e.interval??5)*1e3);for(;t()<r;){let t=await tk({baseUrl:e.cloudBaseUrl,pathName:"/api/control-plane/device-auth/poll",body:{deviceCode:e.deviceCode},fetchImpl:e.fetchImpl});if("approved"===t.status||tR(t.accessToken))return t;if("slow_down"===t.status||"slow_down"===t.error)o+=1e3;else if("authorization_pending"!==t.status&&"authorization_pending"!==t.error)throw new S("UNAUTHORIZED","Device authorization was not approved.",{status:t.status,error:t.error});await tU(o)}throw new S("TIMEOUT","Device authorization expired before approval.")}async function tk(e){let t=e.fetchImpl??fetch,n=await t(new URL(e.pathName,e.baseUrl),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(e.body),signal:AbortSignal.timeout(15e3)});return await tm(n,{invalidJsonMessage:`Cloud auth endpoint returned invalid JSON (${n.status}).`,rejectedMessage:"Cloud auth endpoint rejected the request."})}function tD(e,t){let n=tC(t);return new S("UNAUTHORIZED",`${e} cannot perform interactive login in CI or a non-interactive shell.`,{hint:`Create a service/API token: ${new URL("/api-keys",n).toString()} Then set AGENT_DEVICE_DAEMON_AUTH_TOKEN=adc_live_...`})}function tC(e,t){let n=e.AGENT_DEVICE_CLOUD_BASE_URL??t??"https://cloud.agent-device.dev";try{return new URL(n).toString().replace(/\/+$/,"")}catch(e){throw new S("INVALID_ARGS","Invalid AGENT_DEVICE_CLOUD_BASE_URL.",{cloudBaseUrl:n},e instanceof Error?e:void 0)}}async function tN(e,t){if(t?.openBrowser)return void await t.openBrowser(e);let n=process.platform;try{"darwin"===n?await P("open",[e],{allowFailure:!0,timeoutMs:5e3}):"win32"===n?await P("cmd",["/c","start","",e],{allowFailure:!0,timeoutMs:5e3}):await P("xdg-open",[e],{allowFailure:!0,timeoutMs:5e3})}catch{tb(t,`Open this URL on your machine:
19
+ `);let I=await rA({cloudBaseUrl:l,deviceCode:c.deviceCode,expiresIn:c.expiresIn,interval:c.interval,fetchImpl:e.io?.fetch,now:e.io?.now}),A=I.cliSession?.refreshCredential??I.cliSession?.refreshToken;if(!rC(I.accessToken)||!rC(A))throw new f("UNAUTHORIZED","Device authorization did not return CLI credentials.");let S=new Date(e.io?.now?.()??Date.now()).toISOString(),_={version:1,id:I.cliSession?.id??`cli-${Date.now().toString(36)}`,cloudBaseUrl:l,workspaceId:I.cliSession?.workspaceId,accountId:I.cliSession?.accountId,name:I.cliSession?.name,refreshCredential:A,createdAt:S,expiresAt:I.cliSession?.expiresAt};return function(e){let r=ry(e.stateDir);t.mkdirSync(n.dirname(r),{recursive:!0,mode:448}),t.writeFileSync(r,`${JSON.stringify(e.session,null,2)}
20
+ `,{mode:384});try{t.chmodSync(r,384)}catch{}}({stateDir:e.stateDir,session:_}),{accessToken:I.accessToken,expiresAt:I.expiresAt,session:_}}function rv(e){let r=ry(e.stateDir);if(!t.existsSync(r))return null;try{let e=JSON.parse(t.readFileSync(r,"utf8"));if(1!==e.version||!rC(e.id)||!rC(e.cloudBaseUrl)||!rC(e.refreshCredential)||!rC(e.createdAt))return null;return e}catch{return null}}function ry(e){return n.join(e,"auth","cli-session.json")}async function rw(e){let t=rv({stateDir:e.stateDir});return!t||rb(t.expiresAt,e.io?.now)?null:{accessToken:(await rI({session:t,flags:e.flags,env:e.env,io:e.io})).accessToken,cloudBaseUrl:rk(e.env,t.cloudBaseUrl)}}async function rI(e){let t=rk(e.env,e.session.cloudBaseUrl),r=await rS({baseUrl:t,pathName:"/api/control-plane/cli-session/refresh",body:{refreshCredential:e.session.refreshCredential,tenant:e.flags.tenant,runId:e.flags.runId,daemonBaseUrl:e.flags.daemonBaseUrl,session:e.flags.session},fetchImpl:e.io?.fetch});if(rC(r.accessToken))return{accessToken:r.accessToken,expiresAt:r.expiresAt};if("revoked"===r.status||"revoked"===r.error)throw new f("UNAUTHORIZED","Stored cloud CLI session was revoked.",{hint:"Run agent-device auth login again, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN.",status:r.status,error:r.error});throw new f("UNAUTHORIZED","Failed to refresh CLI session.",{hint:"Run agent-device auth login again, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN.",status:r.status,error:r.error})}async function rA(e){let t=e.now??Date.now,r=Math.min((e.expiresIn??600)*1e3,6e5),n=t()+r,o=Math.max(1e3,(e.interval??5)*1e3);for(;t()<n;){let t=await rS({baseUrl:e.cloudBaseUrl,pathName:"/api/control-plane/device-auth/poll",body:{deviceCode:e.deviceCode},fetchImpl:e.fetchImpl});if("approved"===t.status||rC(t.accessToken))return t;if("slow_down"===t.status||"slow_down"===t.error)o+=1e3;else if("authorization_pending"!==t.status&&"authorization_pending"!==t.error)throw new f("UNAUTHORIZED","Device authorization was not approved.",{status:t.status,error:t.error});await rN(o)}throw new f("TIMEOUT","Device authorization expired before approval.")}async function rS(e){let t=e.fetchImpl??fetch,r=await t(new URL(e.pathName,e.baseUrl),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(e.body),signal:AbortSignal.timeout(15e3)});return await rf(r,{invalidJsonMessage:`Cloud auth endpoint returned invalid JSON (${r.status}).`,rejectedMessage:"Cloud auth endpoint rejected the request."})}function r_(e,t){let r=rk(t);return new f("UNAUTHORIZED",`${e} cannot perform interactive login in CI or a non-interactive shell.`,{hint:`Create a service/API token: ${new URL("/api-keys",r).toString()} Then set AGENT_DEVICE_DAEMON_AUTH_TOKEN=adc_live_...`})}function rk(e,t){let r=e.AGENT_DEVICE_CLOUD_BASE_URL??t??"https://cloud.agent-device.dev";try{return new URL(r).toString().replace(/\/+$/,"")}catch(e){throw new f("INVALID_ARGS","Invalid AGENT_DEVICE_CLOUD_BASE_URL.",{cloudBaseUrl:r},e instanceof Error?e:void 0)}}async function rD(e,t){if(t?.openBrowser)return void await t.openBrowser(e);let r=process.platform;try{"darwin"===r?await z("open",[e],{allowFailure:!0,timeoutMs:5e3}):"win32"===r?await z("cmd",["/c","start","",e],{allowFailure:!0,timeoutMs:5e3}):await z("xdg-open",[e],{allowFailure:!0,timeoutMs:5e3})}catch{r$(t,`Open this URL on your machine:
9
21
  ${e}
10
- `)}}function tb(e,t){(e?.stderr??process.stderr).write(t)}function tP(e,t){if(!e)return!1;let n=Date.parse(e);return!Number.isFinite(n)||n<=(t?.()??Date.now())}function tR(e){return"string"==typeof e&&e.trim().length>0}async function tU(e){await new Promise(t=>setTimeout(t,e))}let tx=new Set(["daemonAuthToken","metroBearerToken"]);function tE(e){let r=function(e){try{return c(e)}catch(n){let t=I(n);throw new S("COMMAND_FAILED",`${e.provider} connection profile returned invalid remote config.`,{generatedConfigPath:e.configPath,cause:t.message},t)}}({configPath:function(e){var r;let o=function e(t){return Array.isArray(t)?t.map(e):t&&"object"==typeof t?Object.fromEntries(Object.entries(t).filter(([,e])=>void 0!==e).sort(([e],[t])=>e.localeCompare(t)).map(([t,n])=>[t,e(n)])):t}(Object.fromEntries(Object.entries(e.profile).filter(([e])=>!tx.has(e)))),s=a.join(e.stateDir,"remote-connections","generated");t.mkdirSync(s,{recursive:!0,mode:448});let i=a.join(s,`${e.provider.replaceAll(/[^a-zA-Z0-9._-]/g,"_")||"generated"}-${(r=o,n.createHash("sha256").update(JSON.stringify(r)).digest("hex").slice(0,16))}.json`);t.writeFileSync(i,`${JSON.stringify(o,null,2)}
11
- `,{mode:384});try{t.chmodSync(i,384)}catch{}return i}({stateDir:e.stateDir,provider:e.provider,profile:e.profile}),cwd:e.cwd,env:e.env,provider:function(e){let[t="",...n]=e;return`${t.toUpperCase()}${n.join("")}`}(e.provider)});return{flags:{...e3(r.profile),...e.flags,...e.extraFlags??{},remoteConfig:r.resolvedPath},remoteConfigPath:r.resolvedPath}}async function tT(e){var t;let r=await tv({stateDir:e.stateDir,flags:e.flags,env:e.env,io:{env:e.env,fetch:e.fetchImpl}}),o=await tL({cloudBaseUrl:r.cloudBaseUrl,accessToken:r.accessToken,fetchImpl:e.fetchImpl}),a=(t={stateDir:e.stateDir,cloudBaseUrl:r.cloudBaseUrl,daemonBaseUrl:"string"==typeof o.daemonBaseUrl?o.daemonBaseUrl:"",session:e.flags.session},n.createHash("sha256").update(`${t.stateDir}\0${t.cloudBaseUrl}\0${t.daemonBaseUrl}\0${t.session??""}`).digest("hex").slice(0,16));return tE({stateDir:e.stateDir,provider:"cloud",profile:{...o,leaseProvider:o.leaseProvider??"cloud",clientId:o.clientId??a,runId:o.runId??`cloud-${a}`},cwd:e.cwd,env:e.env,flags:e.flags,extraFlags:{daemonAuthToken:r.accessToken}})}async function tL(e){let t=e.fetchImpl??fetch,n=await t(new URL("/api/control-plane/connection-profile",e.cloudBaseUrl),{method:"GET",headers:{authorization:`Bearer ${e.accessToken}`},signal:AbortSignal.timeout(15e3)});var r=await tm(n,{invalidJsonMessage:`Cloud connection profile endpoint returned invalid JSON (${n.status}).`,rejectedMessage:"Cloud connection profile endpoint rejected the request."});if(!r||"object"!=typeof r||Array.isArray(r))throw new S("COMMAND_FAILED","Cloud connection profile response is invalid.");let o=r.connection;if(!o||"object"!=typeof o)throw new S("COMMAND_FAILED","Cloud connection profile response is missing profile.");if(void 0!==o.remoteConfigProfile){var a=o.remoteConfigProfile;if(!a||"object"!=typeof a||Array.isArray(a))throw new S("COMMAND_FAILED","Cloud connection profile remoteConfigProfile is invalid.");if(0===Object.keys(a).length)throw new S("COMMAND_FAILED","Cloud connection profile remoteConfigProfile is empty.");return a}throw new S("COMMAND_FAILED","Cloud connection profile did not include remoteConfigProfile.")}function tB(e,t,n){var r;if(e.json)return void z({success:!0,data:t});let o=n?.();o&&(r=o,process.stdout.write(r.endsWith("\n")?r:`${r}
12
- `))}let tM=async({positionals:e,flags:t,client:r})=>{let o,a,s=Y(t.stateDir).baseDir,i=function(e){let t=e[0];if(void 0!==t){if(e.length>1)throw new S("INVALID_ARGS","connect accepts at most one provider positional.");if("proxy"===t)return t;throw new S("INVALID_ARGS",`Unknown connect provider: ${t}. Supported providers: proxy.`)}}(e);var l=i,d=t;if(l&&d.remoteConfig)throw new S("INVALID_ARGS","connect provider positional and --remote-config are mutually exclusive.");let u=await t$({provider:i,flags:t,stateDir:s}),f=u.flags,p=Object.values(a={leaseProvider:(o=c({configPath:u.remoteConfigPath,cwd:process.cwd(),env:process.env}).profile).leaseProvider,clientId:o.clientId,deviceKey:o.deviceKey}).some(e=>void 0!==e)?a:void 0,m=function(e){if(!e.tenant)throw new S("INVALID_ARGS","connect requires tenant in remote config or via --tenant <id>.");if(!e.runId)throw new S("INVALID_ARGS","connect requires runId in remote config or via --run-id <id>.");if(!e.daemonBaseUrl)throw new S("INVALID_ARGS","connect requires daemonBaseUrl in remote config, config, env, or --daemon-base-url.");return{tenant:e.tenant,runId:e.runId}}(f),g=function(e){let{stateDir:t,flags:r,remoteConfigPath:o}=e,a=r.session?null:eY({stateDir:t}),s=r.session??a?.session??function(e){for(let t=0;t<8;t+=1){let t=`adc-${n.randomBytes(3).toString("hex")}`;if(!eH({stateDir:e,session:t}))return t}return`adc-${Date.now().toString(36)}-${n.randomBytes(2).toString("hex")}`}(t),i=a?.session===s?a:eH({stateDir:t,session:s});return{session:s,previous:i,remoteConfigHash:eJ(o),daemon:eq(r)}}({stateDir:s,flags:f,remoteConfigPath:u.remoteConfigPath});!function(e,t){var n,r,o,a,s,i,l,c;if(!(!e||(n=e,r=t,o=n,a=r,[[o.remoteConfigPath,a.remoteConfigPath],[o.remoteConfigHash,a.remoteConfigHash],[o.session,a.session],[o.tenant,a.flags.tenant],[o.runId,a.flags.runId]].every(([e,t])=>e===t)&&(s=n,i=r,[[s.leaseBackend,i.desiredLeaseBackend],[s.platform,i.flags.platform],[s.target,i.flags.target],[s.leaseProvider,i.connection?.leaseProvider],[s.clientId,i.connection?.clientId]].every(([e,t])=>void 0===t||e===t))&&(l=n.daemon,c=r.daemon,["baseUrl","transport","serverMode"].every(e=>(l?.[e]??void 0)===(c?.[e]??void 0)))))&&!t.flags.force)throw new S("INVALID_ARGS","A different remote connection is already active for this session. Re-run connect with --force to replace it.",{session:t.session,remoteConfig:e.remoteConfigPath})}(g.previous,{flags:f,session:g.session,remoteConfigPath:u.remoteConfigPath,remoteConfigHash:g.remoteConfigHash,desiredLeaseBackend:ti(f),connection:p,daemon:g.daemon});let h=function(e){var t,n,r,o,a,s,i;let{flags:l,scope:c,connectionMetadata:d,context:u,remoteConfigPath:f}=e,p=(t=l,u.previous&&!t.force)?u.previous:null,m=new Date().toISOString(),g=(n=l,r=p,o=d,{leaseId:r?.leaseId,leaseBackend:r?.leaseBackend??ti(n),leaseProvider:o?.leaseProvider??r?.leaseProvider,clientId:o?.clientId??r?.clientId,deviceKey:r?.deviceKey??o?.deviceKey}),h=(a=l,s=p,i=m,{platform:a.platform??s?.platform,target:a.target??s?.target,runtime:s?.runtime,metro:s?.metro,connectedAt:s?.connectedAt??i});return{version:1,session:u.session,remoteConfigPath:f,remoteConfigHash:u.remoteConfigHash,daemon:u.daemon,tenant:c.tenant,runId:c.runId,...g,...h,updatedAt:m}}({flags:f,scope:m,connectionMetadata:p,context:g,remoteConfigPath:u.remoteConfigPath});eF({stateDir:s,state:h}),await tO(r,s,f,g.previous);let v=tH(h),w=function(e,t){if(!t.runtime&&(tl(e)||tq(t.remoteConfigPath)))return tF(t.remoteConfigPath)}(f,h);return tB(f,tW(h,w),()=>[`Connected remote session "${g.session}" tenant "${m.tenant}" run "${m.runId}" ${h.leaseId?`lease ${h.leaseId}`:"lease pending"}`,v?.message,w?.message].filter(e=>!!e).join("\n")),!0};async function t$(e){var t;let{provider:r,flags:o,stateDir:a}=e;return o.remoteConfig?function(e){if(!e.remoteConfig)throw new S("INVALID_ARGS","connect requires --remote-config <path>.");let t=c({configPath:e.remoteConfig,cwd:process.cwd(),env:process.env});return{flags:e,remoteConfigPath:t.resolvedPath}}(o):"proxy"===r||(t=o).daemonBaseUrl&&!t.tenant&&!t.runId&&!t.leaseId&&!t.leaseBackend&&function(e){try{return new URL(e).pathname.replace(/\/+$/,"").endsWith("/agent-device")}catch{return!1}}(t.daemonBaseUrl)?function(e){var t,r,o;let a=e.flags.daemonBaseUrl??e.env?.AGENT_DEVICE_DAEMON_BASE_URL;if(!a)throw new S("INVALID_ARGS","connect proxy requires --daemon-base-url <url> or AGENT_DEVICE_DAEMON_BASE_URL.");let s=(t=e.stateDir,r=a,o=e.flags.session,n.createHash("sha256").update(`${t}\0${r}\0${o??""}`).digest("hex").slice(0,16)),i={daemonBaseUrl:a,daemonTransport:e.flags.daemonTransport??"http",daemonServerMode:e.flags.daemonServerMode,tenant:e.flags.tenant??"proxy",sessionIsolation:e.flags.sessionIsolation??"tenant",runId:e.flags.runId??`proxy-${s}`,leaseProvider:"proxy",clientId:s,leaseBackend:e.flags.leaseBackend??ti(e.flags),platform:e.flags.platform,target:e.flags.target,device:e.flags.device,udid:e.flags.udid,serial:e.flags.serial,iosSimulatorDeviceSet:e.flags.iosSimulatorDeviceSet,androidDeviceAllowlist:e.flags.androidDeviceAllowlist,session:e.flags.session,metroProjectRoot:e.flags.metroProjectRoot,metroKind:e.flags.metroKind,metroPublicBaseUrl:e.flags.metroPublicBaseUrl,metroProxyBaseUrl:e.flags.metroProxyBaseUrl,metroPreparePort:e.flags.metroPreparePort,metroListenHost:e.flags.metroListenHost,metroStatusHost:e.flags.metroStatusHost,metroStartupTimeoutMs:e.flags.metroStartupTimeoutMs,metroProbeTimeoutMs:e.flags.metroProbeTimeoutMs,metroRuntimeFile:e.flags.metroRuntimeFile,metroNoReuseExisting:e.flags.metroNoReuseExisting,metroNoInstallDeps:e.flags.metroNoInstallDeps};return tE({stateDir:e.stateDir,provider:"proxy",profile:i,cwd:e.cwd,env:e.env,flags:e.flags,extraFlags:{daemonBaseUrl:a,daemonTransport:e.flags.daemonTransport??"http"}})}({flags:o,stateDir:a,cwd:process.cwd(),env:process.env}):await tT({flags:o,stateDir:a,cwd:process.cwd(),env:process.env})}async function tO(e,t,n,r){r&&n.force&&(await tn(r.metro),await tr({stateDir:t,state:r}),await ta(e,r))}let tK=async({flags:e,client:t})=>{let{session:n,stateDir:r,state:o}=tG(e);if(!o)return tj(e,n),!0;let a=o.session;try{await t.sessions.close({shutdown:e.shutdown})}catch{}await tn(o.metro),await tr({stateDir:r,state:o});let s=!1;if(o.leaseId)try{s=await to(t,o)}catch{}return eW({stateDir:r,session:a}),tB(e,{connected:!1,session:a,released:s},()=>`Disconnected remote session "${a}".`),!0},tV=async({positionals:e,flags:t})=>{if("status"!==e[0])throw new S("INVALID_ARGS","connection accepts only: status");let{session:n,state:r}=tG(t);if(!r)return tj(t,n),!0;let o=tH(r),a=function(e){if(!e.runtime&&tq(e.remoteConfigPath))return tF(e.remoteConfigPath)}(r);return tB(t,tW(r,a),()=>[`Connected remote session "${r.session}".`,`tenant=${r.tenant} runId=${r.runId} leaseId=${r.leaseId??"pending"} backend=${r.leaseBackend??"pending"}`,`remoteConfig=${r.remoteConfigPath}`,r.runtime?"metro=prepared":"metro=not-prepared",o?.message,a?.message].filter(e=>!!e).join("\n")),!0};function tG(e){let t=e.session??"default",n=Y(e.stateDir).baseDir;return{session:t,stateDir:n,state:eH({stateDir:n,session:t})??(e.session?null:eY({stateDir:n}))}}function tj(e,t){tB(e,{connected:!1,session:t},()=>`No remote connection for "${t}".`)}function tH(e){return e.leaseId?void 0:"proxy"===e.leaseProvider?{status:"deferred",nextSteps:["agent-device open <app-id> --relaunch","agent-device devices"],message:"Proxy lease allocation is pending; run open when ready to allocate or refresh the device lease. Devices can inspect inventory but do not allocate a proxy lease."}:{status:"deferred",nextSteps:["agent-device install-from-source <artifact-url> --platform ios|android","agent-device open <app-id> --relaunch","agent-device snapshot -i","agent-device devices"],message:"Lease allocation is pending; run install-from-source, open, snapshot, or devices when ready to allocate or refresh the lease."+(void 0===e.platform&&void 0===e.leaseBackend?" Add --platform ios|android if the profile does not set a platform.":"")}}function tF(e){let t=`agent-device metro prepare --remote-config ${e}`;return{status:"deferred",nextStep:t,message:`Metro runtime is not prepared yet; it will be prepared automatically on first open, or run "${t}" to inspect it before launch.`}}function tq(e){try{let t=c({configPath:e,cwd:process.cwd(),env:process.env}).profile;return!!(t.metroPublicBaseUrl||t.metroProxyBaseUrl||t.metroProjectRoot||t.metroKind)}catch{return!1}}function tW(e,t){let r=tH(e);return{connected:!0,session:e.session,tenant:e.tenant,runId:e.runId,leaseAllocated:!!e.leaseId,leaseId:e.leaseId,leaseBackend:e.leaseBackend,platform:e.platform,target:e.target,remoteConfig:e.remoteConfigPath,remoteConfigHash:e.remoteConfigHash,daemonBaseUrlFingerprint:function(e){if(e)return n.createHash("sha256").update(e).digest("hex").slice(0,12)}(e.daemon?.baseUrl),metro:e.metro?{prepared:!0,projectRoot:e.metro.projectRoot}:{prepared:!1},...r?{leasePreparation:r}:{},...t?{runtimePreparation:t}:{},connectedAt:e.connectedAt,updatedAt:e.updatedAt}}let tJ=async({positionals:e,flags:n})=>{let r=e[0]??"status",o=Y(n.stateDir).baseDir;if("status"===r){var a;let e,t=(e=ty({stateDir:(a={stateDir:o}).stateDir}))?{authenticated:!0,source:"cli-session",sessionId:e.id,cloudBaseUrl:e.cloudBaseUrl,workspaceId:e.workspaceId,accountId:e.accountId,name:e.name,createdAt:e.createdAt,expiresAt:e.expiresAt,expired:tP(e.expiresAt,a.now)}:{authenticated:!1,source:"none"};return tB(n,t,()=>{var e;return(e=t).authenticated?["Authenticated with cloud CLI session.",`cloud=${e.cloudBaseUrl}`,`session=${e.sessionId}`,e.workspaceId?`workspace=${e.workspaceId}`:null,e.accountId?`account=${e.accountId}`:null,e.expiresAt?`expiresAt=${e.expiresAt}`:null,e.expired?"status=expired":null].filter(e=>!!e).join("\n"):"Not authenticated."}),!0}if("login"===r){let e=await tw({stateDir:o,flags:n,commandLabel:"agent-device auth login"});return tB(n,{authenticated:!0,source:"cli-session",sessionId:e.session.id,cloudBaseUrl:e.session.cloudBaseUrl,workspaceId:e.session.workspaceId,accountId:e.session.accountId,expiresAt:e.session.expiresAt,agentTokenExpiresAt:e.expiresAt},()=>"Authenticated with cloud CLI session."),!0}if("logout"===r){let e,r=(e=tI({stateDir:o}.stateDir),!!t.existsSync(e)&&(t.rmSync(e,{force:!0}),!0));return tB(n,{authenticated:!1,removed:r},()=>r?"Removed stored cloud CLI session.":"No stored cloud CLI session."),!0}throw new S("INVALID_ARGS","auth accepts only: status, login, logout")},tz=`${ef}/`,tZ=["content-type","x-artifact-type","x-artifact-filename"],tY=["content-type","content-disposition","x-request-id"];async function tX(e,t,n){var r,o,a,s,i,l,c;let d,u,f,p=(d=new URL(e.url??"/","http://127.0.0.1").pathname)===ef?"/":d.startsWith(tz)?`/${d.slice(tz.length)}`:d;if("GET"===e.method&&"/health"===p)return void await tQ(t,n);if(r=p,o=e.method,"/rpc"===r||"/upload"===r?"POST"!==o:!r.startsWith("/artifacts/")||"GET"!==o){t.statusCode=404,t.end("Not found");return}("/rpc"===p&&(f=(await t2(e,n.maxRpcBodyBytes)).toString("utf8")),a=e,s=n.clientToken,(u=function(e,t){let n="string"==typeof e.headers.authorization?e.headers.authorization:"";if(n.toLowerCase().startsWith("bearer "))return n.slice(7);let r=e.headers["x-agent-device-token"];if("string"==typeof r)return r;if(t){let e=function(e){try{let t=JSON.parse(e);return"string"==typeof t.params?.token?t.params.token:""}catch{return""}}(t);if(e)return e}return""}(a,f)).length>0&&er(u,s))?await t1({req:e,res:t,route:p,options:n,rpcBody:f}):(i=t,l=p,c=function(e){if(!e)return null;try{return JSON.parse(e).id??null}catch{return null}}(f),(i.statusCode=401,i.setHeader("content-type","application/json"),"/rpc"===l)?i.end(JSON.stringify({jsonrpc:"2.0",id:c,error:{code:-32001,message:"Invalid proxy token",data:A(new S("UNAUTHORIZED","Invalid proxy token"))}})):i.end(JSON.stringify({ok:!1,error:"Invalid proxy token",code:"UNAUTHORIZED"})))}async function tQ(e,t){let n=await t0(t);e.statusCode=200,e.setHeader("content-type","application/json"),e.end(JSON.stringify(Z("agent-device-proxy",{upstream:n})))}async function t0(e){let t=new URL(ed(e.upstreamBaseUrl,"health")),n=await e.fetchImpl(t,{method:"GET",headers:t8({headers:{}},e.upstreamToken,"/health"),signal:AbortSignal.timeout(e.upstreamTimeoutMs)}),r=await n.text();try{return r?JSON.parse(r):{ok:n.ok,status:n.status}}catch{return{ok:n.ok,status:n.status}}}async function t1(e){var t,n,r;let a,s,c,{req:d,res:u,route:f,options:p,rpcBody:m}=e,g=(t=p.upstreamBaseUrl,n=f,r=d.url??"/",a=new URL(ed(t,n)),(s=r.indexOf("?"))>=0&&(a.search=r.slice(s)),a),h=d.method??"GET",v=t8(d,p.upstreamToken,f),w=function(e,t,n,r){if("GET"!==e.method&&"HEAD"!==e.method){var o,a;let s;return"/rpc"===t?(o=n??"",a=r,(s=JSON.parse(o)).params={...s.params??{},token:a},JSON.stringify(s)):e}}(d,f,m,p.upstreamToken),y=await p.fetchImpl(g,{method:h,headers:v,signal:AbortSignal.timeout(p.upstreamTimeoutMs),...w?{body:w,duplex:"half"}:{}});for(let e of(u.statusCode=y.status,tY)){let t=y.headers.get(e);t&&u.setHeader(e,t)}(u.hasHeader("x-request-id")||u.setHeader("x-request-id","string"==typeof(c=d.headers["x-request-id"])&&c.trim()?c.trim().slice(0,128):o()),y.body)?await l(i.fromWeb(y.body),u):u.end()}function t3(e,t){let n=e.trim();if(!n)throw new S("INVALID_ARGS",`Proxy ${t} is required.`);return n}function t8(e,t,n){let r=new Headers;for(let t of tZ){let n=e.headers[t];"string"==typeof n&&n.trim()&&r.set(t,n)}for(let[e,o]of("/rpc"!==n||r.has("content-type")||r.set("content-type","application/json"),Object.entries(ea(t))))r.set(e,o);return r}async function t2(e,t){let n=[],r=0;for await(let o of e){let e=Buffer.isBuffer(o)?o:Buffer.from(o);if((r+=e.length)>t)throw new S("INVALID_ARGS","Proxy request body is too large.");n.push(e)}return Buffer.concat(n)}let t4=async({positionals:e,flags:t})=>{if(e.length>0)throw new S("INVALID_ARGS","proxy does not accept positional arguments.");let n=await t5(t);return tB(t,n,()=>(function(e,t={}){let n=t.useColor??F(),r=t6("✓","green",n),o=t6(e.proxyBaseUrl,"cyan",n),a=t6("<tunnel URL>","cyan",n),s=t6(e.token,"yellow",n);return`${r} Proxy listening at ${o}
22
+ `)}}function r$(e,t){(e?.stderr??process.stderr).write(t)}function rb(e,t){if(!e)return!1;let r=Date.parse(e);return!Number.isFinite(r)||r<=(t?.()??Date.now())}function rC(e){return"string"==typeof e&&e.trim().length>0}async function rN(e){await new Promise(t=>setTimeout(t,e))}let rR=new Set(["daemonAuthToken","metroBearerToken"]);function rx(e){let r=function(e){try{return tL(e)}catch(r){let t=u(r);throw new f("COMMAND_FAILED",`${e.provider} connection profile returned invalid remote config.`,{generatedConfigPath:e.configPath,cause:t.message},t)}}({configPath:function(e){var r;let s=function e(t){return Array.isArray(t)?t.map(e):t&&"object"==typeof t?Object.fromEntries(Object.entries(t).filter(([,e])=>void 0!==e).sort(([e],[t])=>e.localeCompare(t)).map(([t,r])=>[t,e(r)])):t}(Object.fromEntries(Object.entries(e.profile).filter(([e])=>!rR.has(e)))),a=n.join(e.stateDir,"remote-connections","generated");t.mkdirSync(a,{recursive:!0,mode:448});let i=n.join(a,`${e.provider.replaceAll(/[^a-zA-Z0-9._-]/g,"_")||"generated"}-${(r=s,o.createHash("sha256").update(JSON.stringify(r)).digest("hex").slice(0,16))}.json`);t.writeFileSync(i,`${JSON.stringify(s,null,2)}
23
+ `,{mode:384});try{t.chmodSync(i,384)}catch{}return i}({stateDir:e.stateDir,provider:e.provider,profile:e.profile}),cwd:e.cwd,env:e.env,provider:function(e){let[t="",...r]=e;return`${t.toUpperCase()}${r.join("")}`}(e.provider)});return{flags:{...tQ(r.profile),...e.flags,...e.extraFlags??{},remoteConfig:r.resolvedPath},remoteConfigPath:r.resolvedPath}}async function rP(e){var t;let r=await rg({stateDir:e.stateDir,flags:e.flags,env:e.env,io:{env:e.env,fetch:e.fetchImpl}}),n=await rE({cloudBaseUrl:r.cloudBaseUrl,accessToken:r.accessToken,fetchImpl:e.fetchImpl}),s=(t={stateDir:e.stateDir,cloudBaseUrl:r.cloudBaseUrl,daemonBaseUrl:"string"==typeof n.daemonBaseUrl?n.daemonBaseUrl:"",session:e.flags.session},o.createHash("sha256").update(`${t.stateDir}\0${t.cloudBaseUrl}\0${t.daemonBaseUrl}\0${t.session??""}`).digest("hex").slice(0,16));return rx({stateDir:e.stateDir,provider:"cloud",profile:{...n,leaseProvider:n.leaseProvider??"cloud",clientId:n.clientId??s,runId:n.runId??`cloud-${s}`},cwd:e.cwd,env:e.env,flags:e.flags,extraFlags:{daemonAuthToken:r.accessToken}})}async function rE(e){let t=e.fetchImpl??fetch,r=await t(new URL("/api/control-plane/connection-profile",e.cloudBaseUrl),{method:"GET",headers:{authorization:`Bearer ${e.accessToken}`},signal:AbortSignal.timeout(15e3)});var n=await rf(r,{invalidJsonMessage:`Cloud connection profile endpoint returned invalid JSON (${r.status}).`,rejectedMessage:"Cloud connection profile endpoint rejected the request."});if(!n||"object"!=typeof n||Array.isArray(n))throw new f("COMMAND_FAILED","Cloud connection profile response is invalid.");let o=n.connection;if(!o||"object"!=typeof o)throw new f("COMMAND_FAILED","Cloud connection profile response is missing profile.");if(void 0!==o.remoteConfigProfile){var s=o.remoteConfigProfile;if(!s||"object"!=typeof s||Array.isArray(s))throw new f("COMMAND_FAILED","Cloud connection profile remoteConfigProfile is invalid.");if(0===Object.keys(s).length)throw new f("COMMAND_FAILED","Cloud connection profile remoteConfigProfile is empty.");return s}throw new f("COMMAND_FAILED","Cloud connection profile did not include remoteConfigProfile.")}function rT(e){return{metroProjectRoot:e.metroProjectRoot,metroKind:e.metroKind,metroPublicBaseUrl:e.metroPublicBaseUrl,metroProxyBaseUrl:e.metroProxyBaseUrl,metroPreparePort:e.metroPreparePort,metroListenHost:e.metroListenHost,metroStatusHost:e.metroStatusHost,metroStartupTimeoutMs:e.metroStartupTimeoutMs,metroProbeTimeoutMs:e.metroProbeTimeoutMs,metroRuntimeFile:e.metroRuntimeFile,metroNoReuseExisting:e.metroNoReuseExisting,metroNoInstallDeps:e.metroNoInstallDeps}}let rU=[{provider:en.browserStack,buildProfileFields:function(e){rB(e.env,"BROWSERSTACK_USERNAME","connect browserstack"),rB(e.env,"BROWSERSTACK_ACCESS_KEY","connect browserstack");let t=rM(e.flags.platform,"connect browserstack requires --platform ios|android."),r=rL(e.flags.device,"connect browserstack requires --device <name>.");return{platform:t,device:r,providerOsVersion:rL(e.flags.providerOsVersion,"connect browserstack requires --provider-os-version <version>."),providerApp:rL(e.flags.providerApp,"connect browserstack requires --provider-app <bs://app-id-or-local-path>."),providerProject:e.flags.providerProject,providerBuild:e.flags.providerBuild,providerSessionName:e.flags.providerSessionName}}},{provider:en.awsDeviceFarm,buildProfileFields:function(e){let{env:t,flags:r}=e;return{platform:rM(r.platform,"connect aws-device-farm requires --platform ios|android."),device:r.device,awsProjectArn:function(e,t,r,n){return rL(rO(e,t,r),n)}(r.awsProjectArn,t,["AGENT_DEVICE_AWS_DEVICE_FARM_PROJECT_ARN","AWS_DEVICE_FARM_PROJECT_ARN"],"connect aws-device-farm requires --aws-project-arn <arn> or AWS_DEVICE_FARM_PROJECT_ARN."),awsDeviceArn:function(e,t,r,n){return rL(rO(e,t,r),n)}(r.awsDeviceArn,t,["AGENT_DEVICE_AWS_DEVICE_FARM_DEVICE_ARN","AWS_DEVICE_FARM_DEVICE_ARN"],"connect aws-device-farm requires --aws-device-arn <arn> or AWS_DEVICE_FARM_DEVICE_ARN."),awsAppArn:rO(r.awsAppArn,t,["AGENT_DEVICE_AWS_DEVICE_FARM_APP_ARN","AWS_DEVICE_FARM_APP_ARN"]),awsRegion:rO(r.awsRegion,t,["AWS_REGION","AWS_DEFAULT_REGION"]),awsInteractionMode:r.awsInteractionMode,providerSessionName:r.providerSessionName}}}];function rM(e,t){if("android"===e||"ios"===e)return e;throw new f("INVALID_ARGS",t)}function rL(e,t){if(e)return e;throw new f("INVALID_ARGS",t)}function rB(e,t,r){let n=e?.[t];if(n)return n;throw new f("INVALID_ARGS",`${r} requires ${t} in the environment.`)}function rO(e,t,r){return e||r.map(e=>t?.[e]).find(e=>!!e)}function rV(e,t,r){var n;if(e.json)return void O({success:!0,data:t});let o=r?.();o&&(n=o,process.stdout.write(n.endsWith("\n")?n:`${n}
24
+ `))}let rj=async({positionals:e,flags:t,client:r})=>{let n,s,a=el(t.stateDir).baseDir,i=function(e){let t=e[0];if(void 0!==t){if(e.length>1)throw new f("INVALID_ARGS","connect accepts at most one provider positional.");if("cloud"===t||"proxy"===t||er(t))return t;throw new f("INVALID_ARGS",`Unknown connect provider: ${t}. Supported providers: ${["cloud","proxy",en.browserStack,en.awsDeviceFarm].join(", ")}.`)}}(e);var l=i,c=t;if(l&&c.remoteConfig)throw new f("INVALID_ARGS","connect provider positional and --remote-config are mutually exclusive.");let u=await rG({provider:i,flags:t,stateDir:a}),d=u.flags,p=Object.values(s={leaseProvider:(n=tL({configPath:u.remoteConfigPath,cwd:process.cwd(),env:process.env}).profile).leaseProvider,clientId:n.clientId,deviceKey:n.deviceKey}).some(e=>void 0!==e)?s:void 0,m=function(e,t){if(!e.tenant)throw new f("INVALID_ARGS","connect requires tenant in remote config or via --tenant <id>.");if(!e.runId)throw new f("INVALID_ARGS","connect requires runId in remote config or via --run-id <id>.");if(!e.daemonBaseUrl&&!er(t?.leaseProvider))throw new f("INVALID_ARGS","connect requires daemonBaseUrl in remote config, config, env, or --daemon-base-url.");return{tenant:e.tenant,runId:e.runId}}(d,p),g=function(e){let{stateDir:t,flags:r,remoteConfigPath:n}=e,s=r.session?null:tJ({stateDir:t}),a=r.session??s?.session??function(e){for(let t=0;t<8;t+=1){let t=`adc-${o.randomBytes(3).toString("hex")}`;if(!tj({stateDir:e,session:t}))return t}return`adc-${Date.now().toString(36)}-${o.randomBytes(2).toString("hex")}`}(t),i=s?.session===a?s:tj({stateDir:t,session:a});return{session:a,previous:i,remoteConfigHash:tH(n),daemon:tF(r)}}({stateDir:a,flags:d,remoteConfigPath:u.remoteConfigPath});!function(e,t){var r,n,o,s,a,i,l,c;if(!(!e||(r=e,n=t,o=r,s=n,[[o.remoteConfigPath,s.remoteConfigPath],[o.remoteConfigHash,s.remoteConfigHash],[o.session,s.session],[o.tenant,s.flags.tenant],[o.runId,s.flags.runId]].every(([e,t])=>e===t)&&(a=r,i=n,[[a.leaseBackend,i.desiredLeaseBackend],[a.platform,i.flags.platform],[a.target,i.flags.target],[a.leaseProvider,i.connection?.leaseProvider],[a.clientId,i.connection?.clientId]].every(([e,t])=>void 0===t||e===t))&&(l=r.daemon,c=n.daemon,["baseUrl","transport","serverMode"].every(e=>(l?.[e]??void 0)===(c?.[e]??void 0)))))&&!t.flags.force)throw new f("INVALID_ARGS","A different remote connection is already active for this session. Re-run connect with --force to replace it.",{session:t.session,remoteConfig:e.remoteConfigPath})}(g.previous,{flags:d,session:g.session,remoteConfigPath:u.remoteConfigPath,remoteConfigHash:g.remoteConfigHash,desiredLeaseBackend:rs(d),connection:p,daemon:g.daemon});let h=function(e){var t,r,n,o,s,a,i;let{flags:l,scope:c,connectionMetadata:u,context:d,remoteConfigPath:f}=e,p=(t=l,d.previous&&!t.force)?d.previous:null,m=new Date().toISOString(),g=(r=l,n=p,o=u,{leaseId:n?.leaseId,leaseBackend:n?.leaseBackend??rs(r),leaseProvider:o?.leaseProvider??n?.leaseProvider,clientId:o?.clientId??n?.clientId,deviceKey:n?.deviceKey??o?.deviceKey}),h=(s=l,a=p,i=m,{platform:s.platform??a?.platform,target:s.target??a?.target,runtime:a?.runtime,metro:a?.metro,connectedAt:a?.connectedAt??i});return{version:1,session:d.session,remoteConfigPath:f,remoteConfigHash:d.remoteConfigHash,daemon:d.daemon,tenant:c.tenant,runId:c.runId,...g,...h,updatedAt:m}}({flags:d,scope:m,connectionMetadata:p,context:g,remoteConfigPath:u.remoteConfigPath});tG({stateDir:a,state:h}),await rF(r,a,d,g.previous);let v=rJ(h),y=function(e,t){if(!t.runtime&&(ra(e)||rZ(t.remoteConfigPath)))return rz(t.remoteConfigPath)}(d,h);return rV(d,rY(h,y),()=>[`Connected remote session "${g.session}" tenant "${m.tenant}" run "${m.runId}" ${h.leaseId?`lease ${h.leaseId}`:"lease pending"}`,v?.message,y?.message].filter(e=>!!e).join("\n")),!0};async function rG(e){let{provider:t,flags:r,stateDir:n}=e;if(r.remoteConfig){var s,a,i,l,c,u,d=r;if(!d.remoteConfig)throw new f("INVALID_ARGS","connect requires --remote-config <path>.");let e=tL({configPath:d.remoteConfig,cwd:process.cwd(),env:process.env});return{flags:d,remoteConfigPath:e.resolvedPath}}if(er(t)){let e,u,d;return e=(function(e){let t=rU.find(t=>t.provider===e)?.buildProfileFields;if(t)return t;throw new f("INVALID_ARGS",`Unsupported cloud WebDriver provider "${e}".`)})((s={provider:t,flags:r,stateDir:n,cwd:process.cwd(),env:process.env}).provider)(s),a=s.provider,i=s.stateDir,l=s.flags.session,c=e.device,u=o.createHash("sha256").update(`${a}\0${i}\0${l??""}\0${c??""}`).digest("hex").slice(0,16),d={tenant:s.flags.tenant??s.provider,sessionIsolation:s.flags.sessionIsolation??"tenant",runId:s.flags.runId??`${s.provider}-${u}`,leaseProvider:s.provider,clientId:u,leaseBackend:s.flags.leaseBackend??rs(s.flags),target:s.flags.target??"mobile",session:s.flags.session,...e,...rT(s.flags)},rx({stateDir:s.stateDir,provider:s.provider,profile:d,cwd:s.cwd,env:s.env,flags:s.flags})}return"proxy"===t||!t&&(u=r).daemonBaseUrl&&!u.tenant&&!u.runId&&!u.leaseId&&!u.leaseBackend&&function(e){try{return new URL(e).pathname.replace(/\/+$/,"").endsWith("/agent-device")}catch{return!1}}(u.daemonBaseUrl)?function(e){var t,r,n;let s=e.flags.daemonBaseUrl??e.env?.AGENT_DEVICE_DAEMON_BASE_URL;if(!s)throw new f("INVALID_ARGS","connect proxy requires --daemon-base-url <url> or AGENT_DEVICE_DAEMON_BASE_URL.");let a=(t=e.stateDir,r=s,n=e.flags.session,o.createHash("sha256").update(`${t}\0${r}\0${n??""}`).digest("hex").slice(0,16)),i={daemonBaseUrl:s,daemonTransport:e.flags.daemonTransport??"http",daemonServerMode:e.flags.daemonServerMode,tenant:e.flags.tenant??"proxy",sessionIsolation:e.flags.sessionIsolation??"tenant",runId:e.flags.runId??`proxy-${a}`,leaseProvider:"proxy",clientId:a,leaseBackend:e.flags.leaseBackend??rs(e.flags),platform:e.flags.platform,target:e.flags.target,device:e.flags.device,udid:e.flags.udid,serial:e.flags.serial,iosSimulatorDeviceSet:e.flags.iosSimulatorDeviceSet,androidDeviceAllowlist:e.flags.androidDeviceAllowlist,session:e.flags.session,...rT(e.flags)};return rx({stateDir:e.stateDir,provider:"proxy",profile:i,cwd:e.cwd,env:e.env,flags:e.flags,extraFlags:{daemonBaseUrl:s,daemonTransport:e.flags.daemonTransport??"http"}})}({flags:r,stateDir:n,cwd:process.cwd(),env:process.env}):await rP({flags:r,stateDir:n,cwd:process.cwd(),env:process.env})}async function rF(e,t,r,n){n&&r.force&&(await re(n.metro),await rt({stateDir:t,state:n}),await rn(e,n))}let rK=async({flags:e,client:t})=>{let r,{session:n,stateDir:o,state:s}=rq(e);if(!s)return rW(e,n),!0;let a=s.session;try{r=(await t.sessions.close({session:a,shutdown:e.shutdown})).provider}catch{}await re(s.metro),await rt({stateDir:o,state:s});let i=!1;if(s.leaseId)try{let e=await rr(t,s);i=e.released,r??=e.provider}catch{}return tK({stateDir:o,session:a}),rV(e,{connected:!1,session:a,released:i,...r?{provider:r}:{}},()=>{var e,t,n;return e=a,[`Disconnected remote session "${e}".`,...(n=t=r,(Array.isArray(n?.warnings)?n.warnings:[]).flatMap(e=>{let t=function(e){if(!e||"object"!=typeof e||"string"!=typeof e.message||0===e.message.length)return;let t="string"==typeof e.code&&e.code.length>0?` (${e.code})`:"";return`Provider release warning${t}: ${e.message}`}(e);return t?[t]:[]})),...(t?.cloudArtifacts?.cloudArtifacts??[]).filter(e=>(e.availability??"ready")==="ready"&&e.url).slice(0,3).map(e=>`${e.name}: ${e.url}`)].join("\n")}),!0},rH=async({positionals:e,flags:t})=>{if("status"!==e[0])throw new f("INVALID_ARGS","connection accepts only: status");let{session:r,state:n}=rq(t);if(!n)return rW(t,r),!0;let o=rJ(n),s=function(e){if(!e.runtime&&rZ(e.remoteConfigPath))return rz(e.remoteConfigPath)}(n);return rV(t,rY(n,s),()=>[`Connected remote session "${n.session}".`,`tenant=${n.tenant} runId=${n.runId} leaseId=${n.leaseId??"pending"} backend=${n.leaseBackend??"pending"}`,`remoteConfig=${n.remoteConfigPath}`,n.runtime?"metro=prepared":"metro=not-prepared",o?.message,s?.message].filter(e=>!!e).join("\n")),!0};function rq(e){let t=e.session??"default",r=el(e.stateDir).baseDir;return{session:t,stateDir:r,state:tj({stateDir:r,session:t})??(e.session?null:tJ({stateDir:r}))}}function rW(e,t){rV(e,{connected:!1,session:t},()=>`No remote connection for "${t}".`)}function rJ(e){var t;if(e.leaseId)return;let r="proxy"===(t=e.leaseProvider)?"proxy":er(t)?"direct-device-provider":"remote-provider";return"proxy"===r?{status:"deferred",nextSteps:["agent-device open <app-id> --relaunch","agent-device devices"],message:"Proxy lease allocation is pending; run open when ready to allocate or refresh the device lease. Devices can inspect inventory but do not allocate a proxy lease."}:"direct-device-provider"===r?{status:"deferred",nextSteps:["agent-device open <app-id> --relaunch","agent-device snapshot -i","agent-device artifacts --json","agent-device close"],message:`Hosted ${e.leaseProvider} lease allocation is pending; run open when ready to create the provider session. After close, run "agent-device artifacts --json" to fetch provider video/log links when available.`}:{status:"deferred",nextSteps:["agent-device install-from-source <artifact-url> --platform ios|android","agent-device open <app-id> --relaunch","agent-device snapshot -i","agent-device devices"],message:"Lease allocation is pending; run install-from-source, open, snapshot, or devices when ready to allocate or refresh the lease."+(void 0===e.platform&&void 0===e.leaseBackend?" Add --platform ios|android if the profile does not set a platform.":"")}}function rz(e){let t=`agent-device metro prepare --remote-config ${e}`;return{status:"deferred",nextStep:t,message:`Metro runtime is not prepared yet; it will be prepared automatically on first open, or run "${t}" to inspect it before launch.`}}function rZ(e){try{let t=tL({configPath:e,cwd:process.cwd(),env:process.env}).profile;return!!(t.metroPublicBaseUrl||t.metroProxyBaseUrl||t.metroProjectRoot||t.metroKind)}catch{return!1}}function rY(e,t){let r=rJ(e);return{connected:!0,session:e.session,tenant:e.tenant,runId:e.runId,leaseAllocated:!!e.leaseId,leaseId:e.leaseId,leaseBackend:e.leaseBackend,leaseProvider:e.leaseProvider,platform:e.platform,target:e.target,remoteConfig:e.remoteConfigPath,remoteConfigHash:e.remoteConfigHash,daemonBaseUrlFingerprint:function(e){if(e)return o.createHash("sha256").update(e).digest("hex").slice(0,12)}(e.daemon?.baseUrl),metro:e.metro?{prepared:!0,projectRoot:e.metro.projectRoot}:{prepared:!1},...r?{leasePreparation:r}:{},...t?{runtimePreparation:t}:{},connectedAt:e.connectedAt,updatedAt:e.updatedAt}}let rX=async({positionals:e,flags:r})=>{let n=e[0]??"status",o=el(r.stateDir).baseDir;if("status"===n){var s;let e,t=(e=rv({stateDir:(s={stateDir:o}).stateDir}))?{authenticated:!0,source:"cli-session",sessionId:e.id,cloudBaseUrl:e.cloudBaseUrl,workspaceId:e.workspaceId,accountId:e.accountId,name:e.name,createdAt:e.createdAt,expiresAt:e.expiresAt,expired:rb(e.expiresAt,s.now)}:{authenticated:!1,source:"none"};return rV(r,t,()=>{var e;return(e=t).authenticated?["Authenticated with cloud CLI session.",`cloud=${e.cloudBaseUrl}`,`session=${e.sessionId}`,e.workspaceId?`workspace=${e.workspaceId}`:null,e.accountId?`account=${e.accountId}`:null,e.expiresAt?`expiresAt=${e.expiresAt}`:null,e.expired?"status=expired":null].filter(e=>!!e).join("\n"):"Not authenticated."}),!0}if("login"===n){let e=await rh({stateDir:o,flags:r,commandLabel:"agent-device auth login"});return rV(r,{authenticated:!0,source:"cli-session",sessionId:e.session.id,cloudBaseUrl:e.session.cloudBaseUrl,workspaceId:e.session.workspaceId,accountId:e.session.accountId,expiresAt:e.session.expiresAt,agentTokenExpiresAt:e.expiresAt},()=>"Authenticated with cloud CLI session."),!0}if("logout"===n){let e,n=(e=ry({stateDir:o}.stateDir),!!t.existsSync(e)&&(t.rmSync(e,{force:!0}),!0));return rV(r,{authenticated:!1,removed:n},()=>n?"Removed stored cloud CLI session.":"No stored cloud CLI session."),!0}throw new f("INVALID_ARGS","auth accepts only: status, login, logout")},rQ=`${ev}/`,r0=["content-type","content-range","x-artifact-type","x-artifact-filename","x-artifact-hash","x-artifact-hash-algorithm"],r1=["content-type","content-disposition","x-request-id"];async function r3(e,t,r){var n,o,s,a,i,l,c,u,p;let m,g,h,v=(m=new URL(e.url??"/","http://127.0.0.1").pathname)===ev?"/":m.startsWith(rQ)?`/${m.slice(rQ.length)}`:m;if("GET"===e.method&&"/health"===v)return void await r8(t,r);if(n=v,o=e.method,"/rpc"===n?"POST"!==o:(s=n,a=o,("/upload"===s||ne(s)||"/upload/finalize"===s?"POST"!==a:!s.startsWith("/upload/direct/")||"PUT"!==a)&&(!n.startsWith("/artifacts/")||"GET"!==o))){t.statusCode=404,t.end("Not found");return}("/rpc"===v&&(h=(await ei(e,r.maxRpcBodyBytes,"Proxy request body is too large.")).toString("utf8")),i=e,l=r.clientToken,(g=function(e,t){let r="string"==typeof e.headers.authorization?e.headers.authorization:"";if(r.toLowerCase().startsWith("bearer "))return r.slice(7);let n=e.headers["x-agent-device-token"];if("string"==typeof n)return n;if(t){let e=function(e){try{let t=JSON.parse(e);return"string"==typeof t.params?.token?t.params.token:""}catch{return""}}(t);if(e)return e}return""}(i,h)).length>0&&eo(g,l))?await r4({req:e,res:t,route:v,options:r,rpcBody:h}):(c=t,u=v,p=function(e){if(!e)return null;try{return JSON.parse(e).id??null}catch{return null}}(h),(c.statusCode=401,c.setHeader("content-type","application/json"),"/rpc"===u)?c.end(JSON.stringify({jsonrpc:"2.0",id:p,error:{code:-32001,message:"Invalid proxy token",data:d(new f("UNAUTHORIZED","Invalid proxy token"))}})):c.end(JSON.stringify({ok:!1,error:"Invalid proxy token",code:"UNAUTHORIZED"})))}async function r8(e,t){let r=await r2(t);e.statusCode=200,e.setHeader("content-type","application/json"),e.end(JSON.stringify(ea("agent-device-proxy",{upstream:r})))}async function r2(e){let t=new URL(eg(e.upstreamBaseUrl,"health")),r=await e.fetchImpl(t,{method:"GET",headers:nt({headers:{}},e.upstreamToken,"/health"),signal:AbortSignal.timeout(e.upstreamTimeoutMs)}),n=await r.text();try{return n?JSON.parse(n):{ok:r.ok,status:r.status}}catch{return{ok:r.ok,status:r.status}}}async function r4(e){var t,r,n;let o,s,{req:a,res:i,route:l,options:c,rpcBody:u}=e,d=(t=c.upstreamBaseUrl,r=l,n=a.url??"/",o=new URL(eg(t,r)),(s=n.indexOf("?"))>=0&&(o.search=n.slice(s)),o),f=a.method??"GET",p=nt(a,c.upstreamToken,l),m=function(e,t,r,n){if("GET"!==e.method&&"HEAD"!==e.method){var o,s;let a;return"/rpc"===t?(o=r??"",s=n,(a=JSON.parse(o)).params={...a.params??{},token:s},JSON.stringify(a)):e}}(a,l,u,c.upstreamToken),g=await c.fetchImpl(d,{method:f,headers:p,signal:AbortSignal.timeout(c.upstreamTimeoutMs),...m?{body:m,duplex:"half"}:{}});await r5({req:a,res:i,route:l,response:g,clientToken:c.clientToken})}async function r5(e){var t,r;let n,{req:o,res:s,route:i,response:l,clientToken:c}=e;(s.statusCode=l.status,function(e,t){for(let r of r1){let n=e.headers.get(r);n&&t.setHeader(r,n)}}(l,s),t=o,(r=s).hasHeader("x-request-id")||r.setHeader("x-request-id","string"==typeof(n=t.headers["x-request-id"])&&n.trim()?n.trim().slice(0,128):a()),ne(i))?await r6({req:o,res:s,response:l,clientToken:c}):await r9(l,s)}async function r6(e){let{req:t,res:r,response:n,clientToken:o}=e,s=await n.text();r.setHeader("content-type",n.headers.get("content-type")??"application/json"),r.end(function(e,t,r){let n;try{n=JSON.parse(e)}catch{return e}if(!n||"object"!=typeof n)return e;let o=n;if(!o.upload||"string"!=typeof o.upload.url)return e;let s=function(e,t){let r;try{r=new URL(e)}catch{return null}if(!r.pathname.startsWith("/upload/"))return null;let n="string"==typeof t.headers.host?t.headers.host:"";if(!n)return null;let o=new URL(t.url??"/","http://127.0.0.1").pathname,s=o.lastIndexOf("/upload/preflight"),a=s>=0?o.slice(0,s):"",i=t.headers["x-forwarded-proto"],l=Array.isArray(i)?i[0]:i,c=new URL(`${l||"http"}://${n}`);return c.pathname=`${a}${r.pathname}`,c.search=r.search,c.toString()}(o.upload.url,t);if(!s)return e;let a=o.upload.headers&&"object"==typeof o.upload.headers?{...o.upload.headers}:{};return Object.assign(a,eu(r)),JSON.stringify({...n,upload:{...o.upload,url:s,headers:a}})}(s,t,o))}async function r9(e,t){e.body?await c(l.fromWeb(e.body),t):t.end()}function r7(e,t){let r=e.trim();if(!r)throw new f("INVALID_ARGS",`Proxy ${t} is required.`);return r}function ne(e){return"/upload/preflight"===e}function nt(e,t,r){let n=new Headers;for(let t of r0){let r=e.headers[t];"string"==typeof r&&r.trim()&&n.set(t,r)}for(let[e,o]of("/rpc"!==r||n.has("content-type")||n.set("content-type","application/json"),Object.entries(eu(t))))n.set(e,o);return n}let nr=async({positionals:e,flags:t})=>{if(e.length>0)throw new f("INVALID_ARGS","proxy does not accept positional arguments.");let r=await nn(t);return rV(t,r,()=>(function(e,t={}){let r=t.useColor??U(),n=no("✓","green",r),o=no(e.proxyBaseUrl,"cyan",r),s=no("<tunnel URL>","cyan",r),a=no(e.token,"yellow",r);return`${n} Proxy listening at ${o}
13
25
 
14
26
  Provide this to the agent-device instance connecting:
15
27
 
16
- Daemon base URL: ${a}
17
- Daemon auth token: ${s}`})(n)),await new Promise(()=>{}),!0};async function t5(e){var t,n,o,a,i,l;let c,d=eu({session:"default",command:"proxy",positionals:[],flags:{stateDir:e.stateDir,daemonBaseUrl:"",daemonTransport:"http",daemonServerMode:"http"}}),u=await ei(d),f=function(e){if(!e)throw new S("COMMAND_FAILED","Local daemon HTTP endpoint is unavailable.",{hint:"Retry after cleaning daemon state, or run proxy with a fresh --state-dir."});return`http://127.0.0.1:${e}`}(u.info.httpPort),p=(t=e,t.daemonAuthToken?.trim()||r(32).toString("hex")),m=(c={upstreamBaseUrl:function(e,t){try{let t=new URL(e);if("http:"!==t.protocol&&"https:"!==t.protocol)throw Error("unsupported protocol");return t.toString().replace(/\/+$/,"")}catch(n){throw new S("INVALID_ARGS",`Invalid ${t}`,{[t]:e},n)}}((n={upstreamBaseUrl:f,upstreamToken:u.info.token,clientToken:p}).upstreamBaseUrl,"upstreamBaseUrl"),upstreamToken:t3(n.upstreamToken,"upstreamToken"),clientToken:t3(n.clientToken,"clientToken"),maxRpcBodyBytes:n.maxRpcBodyBytes??1048576,upstreamTimeoutMs:n.upstreamTimeoutMs??3e5,fetchImpl:n.fetchImpl??fetch},s.createServer((e,t)=>{tX(e,t,c).catch(e=>{!function(e,t){if(e.headersSent)return e.destroy(t instanceof Error?t:void 0);let n=A(t);e.statusCode="INVALID_ARGS"===n.code?400:500,e.setHeader("content-type","application/json"),e.end(JSON.stringify({ok:!1,error:n.message,code:n.code}))}(t,e)})})),g=e.proxyHost?.trim()||"127.0.0.1",h=e.proxyPort??0;await (o=m,a=g,i=h,new Promise((e,t)=>{o.once("error",t),o.listen(i,a,()=>{o.off("error",t),e()})}));let v=m.address();if(!v||"string"==typeof v)throw new S("COMMAND_FAILED","Proxy did not bind to a TCP address.");let w=`http://${(l=v.address).includes(":")&&!l.startsWith("[")?`[${l}]`:l}:${v.port}`;return{proxyBaseUrl:w,agentDeviceBaseUrl:ec(w),token:p,upstreamBaseUrl:f,stateDir:d.paths.baseDir}}function t6(e,t,n){return n?O(e,t,{validateStream:!1}):e}let t7=new Set(["id","text","label"]),t9=new Set(["enabled","selected"]),ne={open:function(e){var t,n,r;let o,a,s,[i,l]=e.positionals;if(!i)return{kind:"unsupported",message:"open requires an app id or URL"};if(nc(i))return{kind:"commands",commands:[{openLink:i}]};let c=(t=e,n=i,(s=(r=t,o=r.flags?.launchArgs,a={},r.flags?.relaunch===!0&&(a.stopApp=!0),r.flags?.clearAppState===!0&&(a.clearState=!0),Array.isArray(o)&&o.length>0&&(a.launchArguments=o),Object.keys(a).length>0?a:void 0))?{launchApp:{appId:n,...s}}:"launchApp");return l&&nc(l)?{kind:"config",appId:i,commands:[c,{openLink:l}]}:l?{kind:"unsupported",message:"open with a non-URL second argument is unsupported"}:{kind:"config",appId:i,commands:[c]}},click:nt,press:nt,longpress:function(e){let[t,n]=e.positionals;if(!t)return{kind:"unsupported",message:"longpress requires a target"};let r=no(t,n);return r?{kind:"commands",commands:[{longPressOn:r}],warnings:(function(e){let[t,n,r]=e.positionals,o=nd(t)&&nd(n)?r:n;return o&&nd(o)?[Number(o)]:[]})(e).map(nn)}:{kind:"unsupported",message:"longpress target is not Maestro-compatible"}},fill:function(e){let[t,n]=e.positionals;if(!t||void 0===n)return{kind:"unsupported",message:"fill requires a target and text"};let r=no(t);return r?{kind:"commands",commands:[{tapOn:r},{inputText:n}],warnings:["fill exports as tapOn + inputText; Maestro may append text instead of replacing existing field contents"]}:{kind:"unsupported",message:"fill target is not Maestro-compatible"}},type:function(e){var t;let[n]=e.positionals;if(void 0===n)return{kind:"unsupported",message:"type requires text"};let r=0!==(t=n).length&&[...t].every(e=>"\b"===e)?t.length:null;return null!==r?{kind:"commands",commands:[{eraseText:r}]}:{kind:"commands",commands:[{inputText:n}]}},keyboard:function(e){let[t]=e.positionals;return"dismiss"===t?{kind:"commands",commands:["hideKeyboard"]}:"enter"===t||"return"===t?{kind:"commands",commands:[{pressKey:"Enter"}]}:{kind:"unsupported",message:`keyboard ${t??""}`.trim()}},back:()=>({kind:"commands",commands:["back"]}),wait:function(e){let[t,n]=e.positionals;if(!t)return{kind:"unsupported",message:"wait requires a target or duration"};if(nd(t))return{kind:"commands",commands:[{waitForAnimationToEnd:{timeout:Number(t)}}],warnings:["wait <ms> exports as waitForAnimationToEnd and may return before the full duration"]};if("text"===t&&n)return{kind:"commands",commands:[{extendedWaitUntil:{visible:n,timeout:ni(e,17e3)}}]};let r=na(t);return r?{kind:"commands",commands:[{extendedWaitUntil:{visible:r,timeout:ni(e,17e3)}}]}:{kind:"unsupported",message:"wait selector is not Maestro-compatible"}},find:function(e){let[t,n,r]=e.positionals;return"text"===t&&n&&r?"exists"===r?{kind:"commands",commands:[{assertVisible:n}]}:"missing"===r||"not-exists"===r?{kind:"commands",commands:[{assertNotVisible:n}]}:{kind:"unsupported",message:`find text assertion "${r}" is unsupported`}:{kind:"unsupported",message:"only find text <query> exists|missing exports to Maestro"}},screenshot:function(e){let[t]=e.positionals;return t?{kind:"commands",commands:[{takeScreenshot:t}]}:{kind:"unsupported",message:"screenshot requires an output path"}},scroll:function(e){let[t]=e.positionals;return t&&"down"!==t?{kind:"unsupported",message:`scroll ${t} is not exported yet`}:{kind:"commands",commands:["scroll"]}},swipe:function(e){var t,n;let r,o=function(e){let[t,n,r,o,a]=e.positionals;if(nd(t)&&nd(n)&&nd(r)&&nd(o))return{start:eg(t,n),end:eg(r,o),...a&&nd(a)?{duration:Number(a)}:{}}}(e);if(!o)return{kind:"unsupported",message:"only coordinate swipe exports to Maestro"};let a=(t=e,Number.isInteger(r=t.flags?.count??1)&&r>=1?r:null);if(null===a)return{kind:"unsupported",message:"swipe count must be a positive integer"};let s=(n=e,n.flags?.pauseMs!==void 0?"swipe --pause-ms has no Maestro equivalent":n.flags?.pattern&&"one-way"!==n.flags.pattern?"swipe ping-pong pattern has no Maestro equivalent":void 0);return s?{kind:"unsupported",message:s}:{kind:"commands",commands:Array.from({length:a},()=>({swipe:o}))}}};function nt(e){var t,n,r,o,a;let s,i,[l,c]=e.positionals;if(!l)return{kind:"unsupported",message:`${e.command} requires a target`};let d=no(l,c);if(!d)return{kind:"unsupported",message:"tap target is not Maestro-compatible"};let u=(s=(n=t=e,n.flags?.jitterPx!==void 0?"tap --jitter-px has no Maestro equivalent":n.flags?.clickButton&&"primary"!==n.flags.clickButton?`tap --button ${n.flags.clickButton} has no Maestro equivalent`:void 0))?{ok:!1,message:s}:{ok:!0,options:(r=t,i={},"number"==typeof r.flags?.count&&r.flags.count>1&&(i.repeat=r.flags.count),"number"==typeof r.flags?.intervalMs&&r.flags.intervalMs>0&&(i.delay=r.flags.intervalMs),i)};return u.ok?e.flags?.doubleTap===!0?{kind:"commands",commands:[{doubleTapOn:d}],warnings:nr(e,"doubleTapOn")}:"number"==typeof e.flags?.holdMs?{kind:"commands",commands:[{longPressOn:d}],warnings:[nn(e.flags.holdMs),...nr(e,"longPressOn")]}:{kind:"commands",commands:[(o=d,0===Object.keys(a=u.options).length?{tapOn:o}:"string"==typeof o?{tapOn:{text:o,...a}}:o&&"object"==typeof o&&!Array.isArray(o)?{tapOn:{...o,...a}}:{tapOn:o})]}:{kind:"unsupported",message:u.message}}function nn(e){return`long-press duration exports as Maestro longPressOn; Maestro uses its default long-press duration instead of ${e}ms`}function nr(e,t){let n=[];return"number"==typeof e.flags?.count&&e.flags.count>1&&n.push(`tap --count ${e.flags.count} is not represented by Maestro ${t}`),"number"==typeof e.flags?.intervalMs&&e.flags.intervalMs>0&&n.push(`tap --interval-ms ${e.flags.intervalMs} is not represented by Maestro ${t}`),n}function no(e,t){return nd(e)&&nd(t)?{point:eg(e,t)}:e.startsWith("@")?null:na(e)}function na(e){let t;try{t=eD(e)}catch{return e.includes("=")||e.includes("||")?null:e}let n=function(e){if(e.length<=1)return null;let t=e.flatMap(e=>1===e.terms.length&&t7.has(e.terms[0].key)?[e.terms[0].value]:[]);if(t.length!==e.length||0===t.length)return null;let n=t[0];return"string"!=typeof n?null:t.every(e=>e===n)?n:null}(t.selectors);return null!==n?n:1!==t.selectors.length?null:function(e){let t={};for(let o of e.terms){var n,r;if(n=t,r=o,t7.has(r.key)?"string"!=typeof r.value||!!n.id||!!n.text||!!n.label||(n[r.key]=r.value,!!0):!t9.has(r.key)||"boolean"!=typeof r.value||(n[r.key]=r.value,!!0))return null}return Object.keys(t).length>0?t:null}(t.selectors[0])}function ns(e,t,n,r){for(let o of t??[])e.warnings.push({line:r,action:nl(n),message:o})}function ni(e,t){let n=e.positionals.at(-1);return n&&nd(n)?Number(n):t}function nl(e){return[e.command,...e.positionals??[]].join(" ").trim()}function nc(e){return/^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//.test(e)}function nd(e){return void 0!==e&&Number.isFinite(Number(e))}let nu=async e=>{let{positionals:t}=e;return"export"!==t[0]?function({positionals:e,flags:t}){if(e.length>1)throw new S("INVALID_ARGS","replay accepts exactly one input path: replay <path>");if(void 0!==t.replayExportFormat||void 0!==t.out)throw new S("INVALID_ARGS","replay --format/--out are only supported with replay export.");return!1}(e):await nf(e)};async function nf({positionals:e,flags:n}){let r;var o,s=e,i=n;if(s.length>2)throw new S("INVALID_ARGS","replay export accepts exactly one input path: replay export <file.ad>");if(i.replayUpdate)throw new S("INVALID_ARGS","replay export does not support --update.");if(i.replayMaestro)throw new S("INVALID_ARGS","replay export reads .ad files; omit --maestro.");if(i.replayEnv?.length)throw new S("INVALID_ARGS","replay export does not evaluate --env substitutions.");let l=i.replayExportFormat??"maestro";if("maestro"!==l)throw new S("INVALID_ARGS",`Unsupported replay export format: ${l}`);let c=e[1];if(!c)throw new S("INVALID_ARGS","replay export requires an input path.");let d=ev(c),u=function(e,t={}){var n,r,o,a;let s={config:(n=t.metadata,n?.env&&Object.keys(n.env).length>0?{env:n.env}:{}),warnings:[],unsupported:[]},i=[];for(let[n,o]of e.entries()){let e=t.actionLines?.[n]??n+1,a=(r=o,ne[r.command]?.(r)??{kind:"unsupported",message:`${r.command} has no Maestro equivalent`});switch(a.kind){case"commands":i.push(...a.commands),ns(s,a.warnings,o,e);break;case"config":(function(e,t,n,r){if(!e.config.appId){e.config.appId=t;return}e.config.appId!==t&&e.unsupported.push({line:r,action:nl(n),message:`multiple app ids cannot be represented in one Maestro config (${e.config.appId} vs ${t})`})})(s,a.appId,o,e),i.push(...a.commands),ns(s,a.warnings,o,e);break;case"unsupported":s.unsupported.push({line:e,action:nl(o),message:a.message})}}if(s.unsupported.length>0)throw new S("INVALID_ARGS",`Cannot export replay to Maestro YAML: unsupported .ad action ${s.unsupported.map(e=>`line ${e.line} (${e.action}): ${e.message}`).join("; ")}.`,{unsupported:s.unsupported});return{yaml:(o=s.config,a=i,ep(Object.keys(o).length>0?[o,a]:[a])),warnings:s.warnings}}((r=em(o=t.readFileSync(d,"utf8"))).actions,{actionLines:r.actionLines,metadata:eh(o)}),f="string"==typeof n.out?ev(n.out):void 0;for(let e of(f&&(t.mkdirSync(a.dirname(f),{recursive:!0}),t.writeFileSync(f,u.yaml)),u.warnings))process.stderr.write(`Warning: line ${e.line}: ${e.message}
18
- `);return tB(n,{format:n.replayExportFormat??"maestro",sourcePath:d,...f?{path:f}:{yaml:u.yaml},warnings:u.warnings},()=>f??u.yaml),!0}let np=$();function nm(e,t,n){let r=np[e];if(!r)throw Error(`Missing CLI reader for command: ${e}`);return r(t,n)}async function ng(e){return(await nh(e)).result}async function nh(e){let t=nm(e.command,e.positionals,e.flags),n=await eI(e.client,e.command,t);return{result:n,cliOutput:ey({name:e.command,input:t,result:n})}}let nv={connect:tM,disconnect:tK,connection:tV,auth:tJ,proxy:t4,replay:nu,screenshot:async({positionals:e,flags:t,client:n})=>{let r=await ng({client:n,command:"screenshot",positionals:e,flags:t});return tB(t,{path:r.path,...r.overlayRefs?{overlayRefs:r.overlayRefs}:{}},()=>r.overlayRefs?`Annotated ${r.overlayRefs.length} refs onto ${r.path}`:r.path),!0},diff:async({positionals:e,flags:t,client:n})=>{var r;if("snapshot"===e[0]){let r=await ng({client:n,command:"diff",positionals:e,flags:t});return tB(t,r,()=>j(r)),!0}if("screenshot"!==e[0])return!1;let o=t.baseline;if(!o||"string"!=typeof o)throw new S("INVALID_ARGS","diff screenshot requires --baseline <path>");let a=ev(o),s="string"==typeof t.out?ev(t.out):void 0,i=e[1];if(e.length>2)throw new S("INVALID_ARGS","diff screenshot accepts at most one current screenshot path");let l=eo({backend:(r=n,{platform:function(e){switch(e.platform){case"android":case"linux":case"macos":return e.platform;default:return"ios"}}(t),captureScreenshot:async(e,t,n)=>{let o=await r.capture.screenshot({path:t,session:e.session,overlayRefs:n?.overlayRefs,fullscreen:n?.fullscreen,stabilize:n?.stabilize,surface:n?.surface});return{path:o.path,...o.overlayRefs?{overlayRefs:o.overlayRefs}:{}}}}),artifacts:eA(),sessions:{get:e=>({name:e}),set:()=>{}},policy:et()}),c=await l.capture.diffScreenshot({session:t.session,baseline:{kind:"path",path:a},current:i?{kind:"path",path:ev(i)}:{kind:"live"},...s?{out:{kind:"path",path:s}}:{},threshold:function(e){if(null!=e&&""!==e)return Number(e)}(t.threshold),overlayRefs:t.overlayRefs,surface:t.surface});return tB(t,c,()=>V(c)),!0}};async function nw(e){let t={...e.flags},n=nv[e.command];return!!(n&&await n({...e,flags:t}))||!!m(e.command)&&await ny({...e,command:e.command,flags:t})}async function ny(e){let{runGenericClientBackedCommand:t}=await import("./generic.js");return await t(e)}function nI(e,t,n){return n||(e.push(t),"")}async function nA(e,t,n){let{flags:r}=t,o=function(e){if(!e?.metroProxyBaseUrl||!eV(e.leaseBackend))return null;let t=[],n={serverBaseUrl:nI(t,"metroProxyBaseUrl",e.metroProxyBaseUrl),bearerToken:nI(t,"metroBearerToken",e.metroBearerToken),tenantId:nI(t,"tenant",e.tenant),runId:nI(t,"runId",e.runId),leaseId:nI(t,"leaseId",e.leaseId)};if(t.length>0)throw new S("INVALID_ARGS",`react-devtools remote bridge requires ${t.join(", ")}.`,{missing:t});return n}(r);if(!o)return n();let a=t.stateDir??process.cwd(),s=t.session??r?.session??"default",i=r?.remoteConfig??`${o.tenantId}:${o.runId}:${o.leaseId}`;if("stop"===e[0])try{return await n()}finally{await eK({projectRoot:t.cwd??process.cwd(),stateDir:a,profileKey:i,consumerKey:s})}return await eO({projectRoot:t.cwd??process.cwd(),stateDir:a,serverBaseUrl:o.serverBaseUrl,bearerToken:o.bearerToken,bridgeScope:{tenantId:o.tenantId,runId:o.runId,leaseId:o.leaseId},session:s,profileKey:i,consumerKey:s,env:t.env??process.env}),await n()}async function nS(e,t={}){let n=t.cwd??process.cwd(),r=t.env??process.env,o=await nA(e,t,async()=>(await b("npm",["exec","--yes","--package","agent-react-devtools@0.4.0","--","agent-react-devtools",...e],{cwd:n,env:r,allowFailure:!0,onStdoutChunk:e=>{process.stdout.write(e)},onStderrChunk:e=>{process.stderr.write(e)}})).exitCode);var a,s=t.flags;return 0!==o&&"wait"===(a=e)[0]&&a.includes("--connected")&&"ios-instance"===s?.leaseBackend&&process.stderr.write("Hint: Remote iOS React DevTools connects during JavaScript startup.\nIf the app was already open before `agent-device react-devtools start`, relaunch it with `agent-device open <bundle-id> --platform ios --relaunch`, then retry `agent-device react-devtools wait --connected`.\n"),o}async function n_(e,t){var n,r,o,a,s,i,l;switch(e[0]){case"setup":{t.flags.json||process.stdout.write("Setting up managed agent-browser backend (downloads if needed)...\n");let e=await ee({stateDir:t.stateDir});return n=t.flags.json,r=e,n?z({success:!0,data:{status:nk(r)}}):process.stdout.write(`Managed web backend installed.
19
- agent-browser available at: ${r.binaryPath}
20
- `),0}case"doctor":{let e,n=await en({stateDir:t.stateDir});return o=t.flags.json,a=0===n.exitCode?"Web backend is healthy.":"Web backend doctor reported issues.",s=n,o?z({success:!0,data:"object"==typeof(l=e=(i=s).status)&&null!==l&&"socketDir"in l&&"installDir"in l&&"binaryPath"in l?{...i,status:nk(e)}:i}):process.stdout.write(`${a}
21
- `),n.exitCode}default:throw new S("INVALID_ARGS","web requires setup or doctor")}}function nk(e){let{socketDir:t,...n}=e;return n}function nD(e,t){if(void 0!==e)try{return eS.parse(e)}catch(e){throw new S("INVALID_ARGS",`Batch step ${t} runtime is invalid: ${e instanceof Error?e.message:String(e)}`)}}function nC(e,t={}){let n=nN(t),r={...e};return n.defaultPlatform&&void 0===r.platform&&(r.platform=n.defaultPlatform),r}function nN(e){var t,n,r,o;let a,s=e.env??process.env,i=e.inheritedPlatform??e.configuredPlatform??function(e){if(void 0===e)return;let t=e.trim().toLowerCase();if(t){if("ios"===t||"android"===t||"apple"===t)return t;throw new S("INVALID_ARGS",`Invalid AGENT_DEVICE_PLATFORM: ${e}. Use ios, android, or apple.`)}}(s.AGENT_DEVICE_PLATFORM),l="string"==typeof(t=e.configuredSession??s.AGENT_DEVICE_SESSION)&&t.trim().length>0;return{defaultPlatform:i,lockPolicy:(n=e.policyOverrides,r=s,o=l,(a=n?.sessionLock??n?.sessionLockConflicts??function(e){if(void 0===e)return;let t=e.trim().toLowerCase();if(t){if("reject"===t||"strip"===t)return t;throw new S("INVALID_ARGS",`Invalid session lock mode: ${e}. Use reject or strip.`)}}(r.AGENT_DEVICE_SESSION_LOCK))||(n?.sessionLocked===!0||o?"reject":void 0))}}let nb={sendToDaemon:es},nP=new Set(["launchUrl","kind","metroBearerToken","metroKind","metroListenHost","metroNoInstallDeps","metroNoReuseExisting","metroPreparePort","metroProbeTimeoutMs","metroProjectRoot","metroProxyBaseUrl","metroPublicBaseUrl","metroRuntimeFile","metroStartupTimeoutMs","metroStatusHost"]),nR=new Set(["connect","connection","close","disconnect","metro","proxy","session"]);async function nU(e,n=nb){let r=R(),o=e_(),s=function(e){try{let t=eE(e);return nx(t.command??"",t.providedFlags)}catch{return e.includes("--debug")||e.includes("-v")||e.includes("--verbose")}}(e),i=e.includes("--json"),l=function(e){for(let t=0;t<e.length;t+=1){let n=e[t];if(n.startsWith("--session=")){let e=n.slice(10).trim();return e.length>0?e:null}if("--session"===n){let n=e[t+1]?.trim();if(n&&!n.startsWith("-"))return n;break}}return null}(e)??process.env.AGENT_DEVICE_SESSION??"default";await U({session:l,requestId:r,command:e[0],debug:s},async()=>{var l,u,p,m,g,v,y,D,C,N,b,P,R,U,M,$,O;let V,G,j,F,q,Z,X;try{let n,r,o,s,i,d,h,I;l={cwd:process.cwd(),env:process.env},n=eE(e),r=l?.env??process.env,o=l?.cwd??process.cwd(),m=n.command,s=null!==m&&(u={remoteConfig:n.flags.remoteConfig,cwd:o,env:r}).remoteConfig?{...e3(c({configPath:u.remoteConfig,cwd:u.cwd,env:u.env}).profile),remoteConfig:u.remoteConfig}:{},h=eC((i=(p={command:n.command,cwd:o,cliFlags:n.flags,env:r}).env??process.env,d=eC({},function(e){let n={};for(let r of e)eC(n,function(e,n){let r,o;if(!t.existsSync(e)){if(n)throw new S("INVALID_ARGS",`Config file not found: ${e}`);return{}}try{r=t.readFileSync(e,"utf8")}catch(t){throw new S("INVALID_ARGS",`Failed to read config file: ${e}`,{cause:t instanceof Error?t.message:String(t)})}try{o=JSON.parse(r)}catch(t){throw new S("INVALID_ARGS",`Invalid JSON in config file: ${e}`,{cause:t instanceof Error?t.message:String(t)})}if(!o||"object"!=typeof o||Array.isArray(o))throw new S("INVALID_ARGS",`Config file must contain a JSON object: ${e}`);return function(e,t){let n={};for(let[r,o]of Object.entries(e)){if("installSource"===r){n.installSource=K(o,t);continue}let e=eR.get(r);if(!e)throw new S("INVALID_ARGS",`Unknown config key "${r}" in ${t}.`);if(!e.config.enabled)throw new S("INVALID_ARGS",`Unsupported config key "${r}" in ${t}.`);n[r]=f(ex(e),o,t,r)}return n}(o,`config file ${e}`)}(r.path,r.required));return n}((g=p.cwd,v=p.cliFlags.config,y=i,(I=v??y.AGENT_DEVICE_CONFIG)?[{path:(D=I,C=g,N=y,ev(D,{cwd:C,env:N})),required:!0}]:[{path:(b=y,a.join(ew("~",{env:b}),".agent-device","config.json")),required:!1},{path:a.resolve(g,"agent-device.json"),required:!1}]))),eC(d,function(e,t){var n,r,o;let a={};for(let s of eP.filter(e=>e.config.enabled&&e.supportsCommand(t))){if("installSource"===s.key)continue;let t=s.env.names.map(t=>({name:t,value:e[t]})).find(e=>"string"==typeof e.value&&e.value.trim().length>0);t&&(a[s.key]=(n=t.value,r=`environment variable ${t.name}`,o=t.name,f(ex(s),n,r,o)))}return a}(i,p.command))),s),V={...function(e,t){let n=t?.strictFlags??!0,r=[...e.warnings],o=eC({json:!1,help:!1,version:!1},t?.defaultFlags??{});eC(o,e.flags);let a=e.providedFlags.filter(t=>!eU(t.key,e.command));if(a.length>0){var s,i;let t=a.map(e=>e.token),l=(s=e.command,i=t,s?1===i.length?`Flag ${i[0]} is not supported for command ${s}.`:`Flags ${i.join(", ")} are not supported for command ${s}.`:1===i.length?`Flag ${i[0]} requires a command that supports it.`:`Flags ${i.join(", ")} require a command that supports them.`);if(n)throw new S("INVALID_ARGS",l);for(let e of(r.push(l),a))delete o[e.key]}for(let t of Object.keys(o))void 0!==o[t]&&(eU(t,e.command)||delete o[t]);if(function(e){if("back"===e.command&&!(new Set(e.providedFlags.filter(e=>"backMode"===e.key).map(e=>e.token)).size<=1))throw new S("INVALID_ARGS","back accepts only one explicit mode flag: use either --in-app or --system.")}(e),w(e.command,o),"batch"===e.command&&1!=+!!o.steps+ +!!o.stepsFile)throw new S("INVALID_ARGS","batch requires exactly one step source: --steps or --steps-file.");return function(e){if(e.flags.help)return e;if("snapshot"===e.command&&e.flags.snapshotDiff){let{snapshotDiff:t,...n}=e.flags;return{command:"diff",positionals:["snapshot",...e.positionals],flags:n,warnings:e.warnings}}return e}({command:e.command,positionals:e.positionals,flags:o,warnings:r})}(n,{strictFlags:l?.strictFlags,defaultFlags:h}),providedFlags:n.providedFlags}}catch(t){T({level:"error",phase:"cli_parse_failed",data:{error:t instanceof Error?t.message:String(t)}});let e=A(t,{diagnosticId:x().diagnosticId,logPath:E({force:!0})??void 0});i?z({success:!1,error:e}):B(e,{showDetails:s}),process.exit(1);return}for(let e of V.warnings)process.stderr.write(`Warning: ${e}
22
- `);V.flags.version&&(process.stdout.write(`${o}
23
- `),process.exit(0));let Q="help"===V.command,ee=V.flags.help;if(Q||ee){Q&&V.positionals.length>1&&(B(new S("INVALID_ARGS","help accepts at most one command.")),process.exit(1));let e=Q?V.positionals[0]:V.command;e||(process.stdout.write(`${k()}
24
- `),process.exit(0));let t=_(eM(e));t&&(process.stdout.write(t),process.exit(0)),B(new S("INVALID_ARGS",`Unknown command: ${e}`)),process.stdout.write(`${k()}
25
- `),process.exit(1)}V.command||(process.stdout.write(`${k()}
26
- `),process.exit(1));let{command:et,positionals:en}=V,er=nx(et,V.providedFlags),eo=new Set(V.providedFlags.map(e=>e.key));try{j=(G=nN({policyOverrides:V.flags,configuredPlatform:V.flags.platform,configuredSession:V.flags.session})).lockPolicy?{...V.flags}:nC(V.flags,{policyOverrides:V.flags,configuredPlatform:V.flags.platform,configuredSession:V.flags.session}),F=Y(j.stateDir),q=j.session??"default",P={command:et,explicitFlagKeys:eo,stateDir:F.baseDir,session:q,remoteConfig:j.remoteConfig,hasResolvedSession:void 0!==j.session},X=(Z="connect"===P.command||"connection"===P.command||"proxy"===P.command?null:function(e){let t=e.validateRemoteConfigHash??!0,n=e.remoteConfig?d({configPath:e.remoteConfig,cwd:e.cwd,env:e.env}):void 0,r=eH(e)??(e.allowActiveFallback?eY({stateDir:e.stateDir}):null);if(!r||n&&r.remoteConfigPath!==n)return null;if(t&&eJ(r.remoteConfigPath)!==r.remoteConfigHash)throw new S("INVALID_ARGS","Active remote connection config changed. Run agent-device connect --force to refresh it.",{remoteConfig:r.remoteConfigPath});let o=function(e,t){try{return c({configPath:e.remoteConfigPath,cwd:t.cwd,env:t.env}).profile}catch(e){if(!1===t.validateRemoteConfigHash)return{};throw e}}(r,e),a=H(r);return{runtime:r.runtime,connection:J(a),flags:{...o,remoteConfig:r.remoteConfigPath,daemonBaseUrl:r.daemon?.baseUrl??o.daemonBaseUrl,daemonAuthToken:r.daemon?.authToken??o.daemonAuthToken,daemonTransport:r.daemon?.transport??o.daemonTransport,daemonServerMode:r.daemon?.serverMode??o.daemonServerMode,...W(a),sessionIsolation:"tenant",session:r.session,platform:r.platform??o.platform,target:r.target??o.target}}}({stateDir:P.stateDir,session:P.session,remoteConfig:P.remoteConfig,cwd:process.cwd(),env:process.env,allowActiveFallback:!P.explicitFlagKeys.has("session")&&(!P.remoteConfig||"disconnect"===P.command||!P.hasResolvedSession),validateRemoteConfigHash:"disconnect"!==P.command}))?function(e,t,n){let r={...e};for(let[e,o]of Object.entries(t))void 0!==o&&(n.has(e)||(r[e]=o));return r}(j,Z.flags,eo):j}catch(t){let e=A(I(t),{diagnosticId:x().diagnosticId,logPath:E({force:!0})??void 0});V.flags.json?z({success:!1,error:e}):B(e,{showDetails:er}),process.exit(1);return}let ea=null;try{let e;if("react-devtools"===et){let e=await nS(en,{flags:X,stateDir:F.baseDir,session:X.session??q,cwd:process.cwd(),env:process.env});process.exit(e);return}if("web"===et){let e=await n_(en,{flags:X,stateDir:F.baseDir});process.exit(e);return}ek({command:et,currentVersion:o,stateDir:F.baseDir,flags:X});let a=Z?.runtime,s=Z?.connection,i=(e,t,n)=>({session:e.session,requestId:r,stateDir:e.stateDir,daemonBaseUrl:e.daemonBaseUrl,daemonAuthToken:e.daemonAuthToken,daemonTransport:e.daemonTransport,daemonServerMode:e.daemonServerMode,tenant:e.tenant,sessionIsolation:e.sessionIsolation,runId:e.runId,leaseId:e.leaseId,leaseBackend:e.leaseBackend,leaseProvider:n?.leaseProvider,clientId:n?.clientId,deviceKey:n?.deviceKey,runtime:t,lockPolicy:G.lockPolicy,lockPlatform:G.defaultPlatform,cwd:process.cwd(),debug:er});if("batch"===et){if(en.length>0)throw new S("INVALID_ARGS","batch does not accept positional arguments.");e=function(e){let n,r,o,a="";if(e.steps)a=e.steps;else if(e.stepsFile)try{a=t.readFileSync(e.stepsFile,"utf8")}catch(n){let t=n instanceof Error?n.message:String(n);throw new S("INVALID_ARGS",`Failed to read --steps-file ${e.stepsFile}: ${t}`)}var s,i=a;try{o=JSON.parse(i)}catch{throw new S("INVALID_ARGS","Batch steps must be valid JSON.")}if(!Array.isArray(o)||0===o.length)throw new S("INVALID_ARGS","Batch steps must be a non-empty JSON array.");return s=o,n=!1,r=s.map((e,t)=>{var r,o,a;let s;if(r=e,h(r)&&"input"in r&&!("positionals"in r)&&!("flags"in r))return function(e,t){let n=nD(e.runtime,t),{runtime:r,...o}=e;return{...o,...void 0===n?{}:{runtime:n}}}(e,t+1);let i=function(e,t){if(!h(e))throw new S("INVALID_ARGS",`Invalid batch step ${t}.`);var n=e,r=t;let o=Object.keys(n).filter(e=>!["command","positionals","flags","runtime"].includes(e));if(o.length>0)throw new S("INVALID_ARGS",`Batch step ${r} has unknown legacy field(s): ${o.join(", ")}.`);let a=function(e,t){let n="string"==typeof e?e.trim().toLowerCase():"";if(!n)throw new S("INVALID_ARGS",`Batch step ${t} requires command.`);if(L(n))return n;throw new S("INVALID_ARGS",`Batch step ${t} command is not available through command batch: ${String(e)}`)}(e.command,t),s=function(e,t){if(void 0!==e){if(!Array.isArray(e)||e.some(e=>"string"!=typeof e))throw new S("INVALID_ARGS",`Batch step ${t} positionals must contain only strings.`);return e}}(e.positionals,t),i=function(e,t){if(void 0!==e){if(!h(e))throw new S("INVALID_ARGS",`Batch step ${t} flags must be an object.`);return e}}(e.flags,t),l=nD(e.runtime,t);return{command:a,...void 0===s?{}:{positionals:s},...void 0===i?{}:{flags:i},...void 0===l?{}:{runtime:l}}}(e,t+1);return n=!0,o=i,s=nm(o.command,o.positionals??[],(a=o.flags,{json:!1,help:!1,version:!1,...a})),{command:o.command,input:s,...void 0===o.runtime?{}:{runtime:o.runtime}}}),n&&process.stderr.write('Warning: batch steps using positionals/flags are deprecated and will be removed in the next major version. Use {"command":"...","input":{...}} steps instead.\n'),r}(j)}if(R=et,"auth"!==R&&"connection"!==R&&"proxy"!==R&&(X=(await tg({command:et,flags:X,stateDir:F.baseDir,env:process.env})).flags),X.remoteConfig&&(U=et,!nR.has(U))){let t=el(i(X,a,s),{transport:n.sendToDaemon}),r=await e4({command:et,flags:X,client:t,runtime:a,positionals:en,batchSteps:e,forceRuntimePrepare:function(e){for(let t of nP)if(e.has(t))return!0;return!1}(eo)});X=r.flags,a=r.runtime,s=r.connection}if(M={command:et,flags:X,runtime:a,explicitFlagKeys:eo,hadConnectionDefaults:!!Z},!("open"===M.command&&!M.runtime&&!M.flags.bundleUrl&&!M.flags.metroHost&&!M.flags.metroPort&&!M.flags.remoteConfig&&!M.hadConnectionDefaults&&(($=M.explicitFlagKeys).has("daemonBaseUrl")||$.has("daemonTransport")||$.has("tenant")||$.has("sessionIsolation")||$.has("runId")||$.has("leaseId")||$.has("leaseBackend")))||process.stderr.write("Warning: open is using explicit remote daemon or tenant flags without saved Metro runtime hints. React Native apps may launch without bundle/runtime hints; prefer connect --remote-config <path> first or pass --remote-config <path> on this command.\n"),"cdp"===et){let e=await ej(en,{flags:X,runtime:a,cwd:process.cwd(),env:process.env});process.exit(e);return}let l=X.daemonBaseUrl;ea=!er||X.json||l?null:function(e){try{let n=t.existsSync(e)?t.statSync(e).size:0,r=!1,o=setInterval(()=>{if(!r&&t.existsSync(e))try{let r=t.statSync(e);if(r.size<n&&(n=0),r.size<=n)return;let o=t.openSync(e,"r");try{let e=Buffer.alloc(r.size-n);t.readSync(o,e,0,e.length,n),n=r.size,e.length>0&&process.stdout.write(e.toString("utf8"))}finally{t.closeSync(o)}}catch{}},200);return()=>{r=!0,clearInterval(o)}}catch{return null}}(F.logPath);let c=el(i(X,a,s),{transport:function(e){let{command:t,flags:n,transport:r}=e;return"test"!==t||n.json?r:async e=>await r({...e,meta:{...e.meta,requestProgress:"replay-test"}})}({command:et,flags:X,transport:n.sendToDaemon})});if("batch"===et){if(!e)throw new S("INVALID_ARGS","batch requires --steps or --steps-file.");let t=e.map((e,t)=>({...e,input:G.lockPolicy&&void 0===j.platform?{...e.input}:nC(e.input,{policyOverrides:X,configuredPlatform:X.platform,configuredSession:X.session,inheritedPlatform:X.platform})}));if(await nw({command:et,positionals:en,flags:{...X,batchSteps:t},client:c,debug:er}))return}else if("runtime"===et)throw new S("INVALID_ARGS","runtime command was removed. Use connect --remote-config <path> for remote runs, or metro prepare --remote-config <path> for inspection.");else if(await nw({command:et,positionals:en,flags:X,client:c,debug:er}))return;throw new S("INVALID_ARGS",`Unknown command: ${et}`)}catch(r){let e=I(r),n=A(e,{diagnosticId:x().diagnosticId,logPath:E({force:!0})??void 0});if("close"===et&&"COMMAND_FAILED"===(O=e).code&&(O.details?.kind==="daemon_startup_failed"||O.message.toLowerCase().includes("failed to start daemon")&&("string"==typeof O.details?.infoPath||"string"==typeof O.details?.lockPath))){X.json&&z({success:!0,data:{closed:"session",source:"no-daemon"}});return}if(X.json)z({success:!1,error:n});else if(B(n,{showDetails:er}),er)try{let e=F.logPath;if(t.existsSync(e)){let n=t.readFileSync(e,"utf8").split("\n"),r=n.slice(Math.max(0,n.length-200)).join("\n");r.trim().length>0&&process.stderr.write(`
28
+ Daemon base URL: ${s}
29
+ Daemon auth token: ${a}`})(r)),await new Promise(()=>{}),!0};async function nn(e){var t,r,n,o,a,l;let c,u=eh({session:"default",command:"proxy",positionals:[],flags:{stateDir:e.stateDir,daemonBaseUrl:"",daemonTransport:"http",daemonServerMode:"http"}}),p=await ef(u),m=function(e){if(!e)throw new f("COMMAND_FAILED","Local daemon HTTP endpoint is unavailable.",{hint:"Retry after cleaning daemon state, or run proxy with a fresh --state-dir."});return`http://127.0.0.1:${e}`}(p.info.httpPort),g=(t=e,t.daemonAuthToken?.trim()||s(32).toString("hex")),h=(c={upstreamBaseUrl:function(e,t){try{let t=new URL(e);if("http:"!==t.protocol&&"https:"!==t.protocol)throw Error("unsupported protocol");return t.toString().replace(/\/+$/,"")}catch(r){throw new f("INVALID_ARGS",`Invalid ${t}`,{[t]:e},r)}}((r={upstreamBaseUrl:m,upstreamToken:p.info.token,clientToken:g}).upstreamBaseUrl,"upstreamBaseUrl"),upstreamToken:r7(r.upstreamToken,"upstreamToken"),clientToken:r7(r.clientToken,"clientToken"),maxRpcBodyBytes:r.maxRpcBodyBytes??1048576,upstreamTimeoutMs:r.upstreamTimeoutMs??3e5,fetchImpl:r.fetchImpl??fetch},i.createServer((e,t)=>{r3(e,t,c).catch(e=>{!function(e,t){if(e.headersSent)return e.destroy(t instanceof Error?t:void 0);let r=d(t);e.statusCode="INVALID_ARGS"===r.code?400:500,e.setHeader("content-type","application/json"),e.end(JSON.stringify({ok:!1,error:r.message,code:r.code}))}(t,e)})})),v=e.proxyHost?.trim()||"127.0.0.1",y=e.proxyPort??0;await (n=h,o=v,a=y,new Promise((e,t)=>{n.once("error",t),n.listen(a,o,()=>{n.off("error",t),e()})}));let w=h.address();if(!w||"string"==typeof w)throw new f("COMMAND_FAILED","Proxy did not bind to a TCP address.");let I=`http://${(l=w.address).includes(":")&&!l.startsWith("[")?`[${l}]`:l}:${w.port}`;return{proxyBaseUrl:I,agentDeviceBaseUrl:em(I),token:g,upstreamBaseUrl:m,stateDir:u.paths.baseDir}}function no(e,t,r){return r?C(e,t,{validateStream:!1}):e}let ns=new Set(["id","text","label"]),na=new Set(["enabled","selected"]),ni={open:function(e){var t,r,n;let o,s,a,[i,l]=e.positionals;if(!i)return{kind:"unsupported",message:"open requires an app id or URL"};if(nh(i))return{kind:"commands",commands:[{openLink:i}]};let c=(t=e,r=i,(a=(n=t,o=n.flags?.launchArgs,s={},n.flags?.relaunch===!0&&(s.stopApp=!0),n.flags?.clearAppState===!0&&(s.clearState=!0),Array.isArray(o)&&o.length>0&&(s.launchArguments=o),Object.keys(s).length>0?s:void 0))?{launchApp:{appId:r,...a}}:"launchApp");return l&&nh(l)?{kind:"config",appId:i,commands:[c,{openLink:l}]}:l?{kind:"unsupported",message:"open with a non-URL second argument is unsupported"}:{kind:"config",appId:i,commands:[c]}},click:nl,press:nl,longpress:function(e){let[t,r]=e.positionals;if(!t)return{kind:"unsupported",message:"longpress requires a target"};let n=nd(t,r);return n?{kind:"commands",commands:[{longPressOn:n}],warnings:(function(e){let[t,r,n]=e.positionals,o=nv(t)&&nv(r)?n:r;return o&&nv(o)?[Number(o)]:[]})(e).map(nc)}:{kind:"unsupported",message:"longpress target is not Maestro-compatible"}},fill:function(e){let[t,r]=e.positionals;if(!t||void 0===r)return{kind:"unsupported",message:"fill requires a target and text"};let n=nd(t);return n?{kind:"commands",commands:[{tapOn:n},{inputText:r}],warnings:["fill exports as tapOn + inputText; Maestro may append text instead of replacing existing field contents"]}:{kind:"unsupported",message:"fill target is not Maestro-compatible"}},type:function(e){var t;let[r]=e.positionals;if(void 0===r)return{kind:"unsupported",message:"type requires text"};let n=0!==(t=r).length&&[...t].every(e=>"\b"===e)?t.length:null;return null!==n?{kind:"commands",commands:[{eraseText:n}]}:{kind:"commands",commands:[{inputText:r}]}},keyboard:function(e){let[t]=e.positionals;return"dismiss"===t?{kind:"commands",commands:["hideKeyboard"]}:"enter"===t||"return"===t?{kind:"commands",commands:[{pressKey:"Enter"}]}:{kind:"unsupported",message:`keyboard ${t??""}`.trim()}},back:()=>({kind:"commands",commands:["back"]}),wait:function(e){let[t,r]=e.positionals;if(!t)return{kind:"unsupported",message:"wait requires a target or duration"};if(nv(t))return{kind:"commands",commands:[{waitForAnimationToEnd:{timeout:Number(t)}}],warnings:["wait <ms> exports as waitForAnimationToEnd and may return before the full duration"]};if("text"===t&&r)return{kind:"commands",commands:[{extendedWaitUntil:{visible:r,timeout:nm(e,17e3)}}]};let n=nf(t);return n?{kind:"commands",commands:[{extendedWaitUntil:{visible:n,timeout:nm(e,17e3)}}]}:{kind:"unsupported",message:"wait selector is not Maestro-compatible"}},find:function(e){let[t,r,n]=e.positionals;return"text"===t&&r&&n?"exists"===n?{kind:"commands",commands:[{assertVisible:r}]}:"missing"===n||"not-exists"===n?{kind:"commands",commands:[{assertNotVisible:r}]}:{kind:"unsupported",message:`find text assertion "${n}" is unsupported`}:{kind:"unsupported",message:"only find text <query> exists|missing exports to Maestro"}},screenshot:function(e){let[t]=e.positionals;return t?{kind:"commands",commands:[{takeScreenshot:t}]}:{kind:"unsupported",message:"screenshot requires an output path"}},scroll:function(e){let[t]=e.positionals;return t&&"down"!==t?{kind:"unsupported",message:`scroll ${t} is not exported yet`}:{kind:"commands",commands:["scroll"]}},swipe:function(e){var t,r;let n,o=function(e){let[t,r,n,o,s]=e.positionals;if(nv(t)&&nv(r)&&nv(n)&&nv(o))return{start:eI(t,r),end:eI(n,o),...s&&nv(s)?{duration:Number(s)}:{}}}(e);if(!o)return{kind:"unsupported",message:"only coordinate swipe exports to Maestro"};let s=(t=e,Number.isInteger(n=t.flags?.count??1)&&n>=1?n:null);if(null===s)return{kind:"unsupported",message:"swipe count must be a positive integer"};let a=(r=e,r.flags?.pauseMs!==void 0?"swipe --pause-ms has no Maestro equivalent":r.flags?.pattern&&"one-way"!==r.flags.pattern?"swipe ping-pong pattern has no Maestro equivalent":void 0);return a?{kind:"unsupported",message:a}:{kind:"commands",commands:Array.from({length:s},()=>({swipe:o}))}}};function nl(e){var t,r,n,o,s;let a,i,[l,c]=e.positionals;if(!l)return{kind:"unsupported",message:`${e.command} requires a target`};let u=nd(l,c);if(!u)return{kind:"unsupported",message:"tap target is not Maestro-compatible"};let d=(a=(r=t=e,r.flags?.jitterPx!==void 0?"tap --jitter-px has no Maestro equivalent":r.flags?.clickButton&&"primary"!==r.flags.clickButton?`tap --button ${r.flags.clickButton} has no Maestro equivalent`:void 0))?{ok:!1,message:a}:{ok:!0,options:(n=t,i={},"number"==typeof n.flags?.count&&n.flags.count>1&&(i.repeat=n.flags.count),"number"==typeof n.flags?.intervalMs&&n.flags.intervalMs>0&&(i.delay=n.flags.intervalMs),i)};return d.ok?e.flags?.doubleTap===!0?{kind:"commands",commands:[{doubleTapOn:u}],warnings:nu(e,"doubleTapOn")}:"number"==typeof e.flags?.holdMs?{kind:"commands",commands:[{longPressOn:u}],warnings:[nc(e.flags.holdMs),...nu(e,"longPressOn")]}:{kind:"commands",commands:[(o=u,0===Object.keys(s=d.options).length?{tapOn:o}:"string"==typeof o?{tapOn:{text:o,...s}}:o&&"object"==typeof o&&!Array.isArray(o)?{tapOn:{...o,...s}}:{tapOn:o})]}:{kind:"unsupported",message:d.message}}function nc(e){return`long-press duration exports as Maestro longPressOn; Maestro uses its default long-press duration instead of ${e}ms`}function nu(e,t){let r=[];return"number"==typeof e.flags?.count&&e.flags.count>1&&r.push(`tap --count ${e.flags.count} is not represented by Maestro ${t}`),"number"==typeof e.flags?.intervalMs&&e.flags.intervalMs>0&&r.push(`tap --interval-ms ${e.flags.intervalMs} is not represented by Maestro ${t}`),r}function nd(e,t){return nv(e)&&nv(t)?{point:eI(e,t)}:e.startsWith("@")?null:nf(e)}function nf(e){let t;try{t=eb(e)}catch{return e.includes("=")||e.includes("||")?null:e}let r=function(e){if(e.length<=1)return null;let t=e.flatMap(e=>1===e.terms.length&&ns.has(e.terms[0].key)?[e.terms[0].value]:[]);if(t.length!==e.length||0===t.length)return null;let r=t[0];return"string"!=typeof r?null:t.every(e=>e===r)?r:null}(t.selectors);return null!==r?r:1!==t.selectors.length?null:function(e){let t={};for(let o of e.terms){var r,n;if(r=t,n=o,ns.has(n.key)?"string"!=typeof n.value||!!r.id||!!r.text||!!r.label||(r[n.key]=n.value,!!0):!na.has(n.key)||"boolean"!=typeof n.value||(r[n.key]=n.value,!!0))return null}return Object.keys(t).length>0?t:null}(t.selectors[0])}function np(e,t,r,n){for(let o of t??[])e.warnings.push({line:n,action:ng(r),message:o})}function nm(e,t){let r=e.positionals.at(-1);return r&&nv(r)?Number(r):t}function ng(e){return[e.command,...e.positionals??[]].join(" ").trim()}function nh(e){return/^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//.test(e)}function nv(e){return void 0!==e&&Number.isFinite(Number(e))}let ny=async e=>{let{positionals:t}=e;return"export"!==t[0]?function({positionals:e,flags:t}){if(e.length>1)throw new f("INVALID_ARGS","replay accepts exactly one input path: replay <path>");if(void 0!==t.replayExportFormat||void 0!==t.out)throw new f("INVALID_ARGS","replay --format/--out are only supported with replay export.");return!1}(e):await nw(e)};async function nw({positionals:e,flags:r}){let o;var s,a=e,i=r;if(a.length>2)throw new f("INVALID_ARGS","replay export accepts exactly one input path: replay export <file.ad>");if(i.replayUpdate)throw new f("INVALID_ARGS","replay export does not support --update.");if(i.replayMaestro)throw new f("INVALID_ARGS","replay export reads .ad files; omit --maestro.");if(i.replayEnv?.length)throw new f("INVALID_ARGS","replay export does not evaluate --env substitutions.");let l=i.replayExportFormat??"maestro";if("maestro"!==l)throw new f("INVALID_ARGS",`Unsupported replay export format: ${l}`);let c=e[1];if(!c)throw new f("INVALID_ARGS","replay export requires an input path.");let u=q(c),d=function(e,t={}){var r,n,o,s;let a={config:(r=t.metadata,r?.env&&Object.keys(r.env).length>0?{env:r.env}:{}),warnings:[],unsupported:[]},i=[];for(let[r,o]of e.entries()){let e=t.actionLines?.[r]??r+1,s=(n=o,ni[n.command]?.(n)??{kind:"unsupported",message:`${n.command} has no Maestro equivalent`});switch(s.kind){case"commands":i.push(...s.commands),np(a,s.warnings,o,e);break;case"config":(function(e,t,r,n){if(!e.config.appId){e.config.appId=t;return}e.config.appId!==t&&e.unsupported.push({line:n,action:ng(r),message:`multiple app ids cannot be represented in one Maestro config (${e.config.appId} vs ${t})`})})(a,s.appId,o,e),i.push(...s.commands),np(a,s.warnings,o,e);break;case"unsupported":a.unsupported.push({line:e,action:ng(o),message:s.message})}}if(a.unsupported.length>0)throw new f("INVALID_ARGS",`Cannot export replay to Maestro YAML: unsupported .ad action ${a.unsupported.map(e=>`line ${e.line} (${e.action}): ${e.message}`).join("; ")}.`,{unsupported:a.unsupported});return{yaml:(o=a.config,s=i,ey(Object.keys(o).length>0?[o,s]:[s])),warnings:a.warnings}}((o=ew(s=t.readFileSync(u,"utf8"))).actions,{actionLines:o.actionLines,metadata:eA(s)}),p="string"==typeof r.out?q(r.out):void 0;for(let e of(p&&(t.mkdirSync(n.dirname(p),{recursive:!0}),t.writeFileSync(p,d.yaml)),d.warnings))process.stderr.write(`Warning: line ${e.line}: ${e.message}
30
+ `);return rV(r,{format:r.replayExportFormat??"maestro",sourcePath:u,...p?{path:p}:{yaml:d.yaml},warnings:d.warnings},()=>p??d.yaml),!0}let nI=b();function nA(e,t,r){let n=nI[e];if(!n)throw Error(`Missing CLI reader for command: ${e}`);return n(t,r)}async function nS(e){return(await n_(e)).result}async function n_(e){let t=nA(e.command,e.positionals,e.flags),r=await e_(e.client,e.command,t);return{result:r,cliOutput:eS({name:e.command,input:t,result:r})}}let nk={connect:rj,disconnect:rK,connection:rH,auth:rX,proxy:nr,replay:ny,screenshot:async({positionals:e,flags:t,client:r})=>{let n=await nS({client:r,command:"screenshot",positionals:e,flags:t});return K(t.responseLevel)?rV(t,n,()=>JSON.stringify(n,null,2)):rV(t,{path:n.path,...n.overlayRefs?{overlayRefs:n.overlayRefs}:{}},()=>n.overlayRefs?`Annotated ${n.overlayRefs.length} refs onto ${n.path}`:n.path),!0},diff:async({positionals:e,flags:t,client:r})=>{var n;if("snapshot"===e[0]){let n=await nS({client:r,command:"diff",positionals:e,flags:t});return rV(t,n,()=>E(n)),!0}if("screenshot"!==e[0])return!1;let o=t.baseline;if(!o||"string"!=typeof o)throw new f("INVALID_ARGS","diff screenshot requires --baseline <path>");let s=q(o),a="string"==typeof t.out?q(t.out):void 0,i=e[1];if(e.length>2)throw new f("INVALID_ARGS","diff screenshot accepts at most one current screenshot path");let l=es({backend:(n=r,{platform:function(e){switch(e.platform){case"android":case"linux":case"macos":return e.platform;default:return"ios"}}(t),captureScreenshot:async(e,t,r)=>{let o=await n.capture.screenshot({path:t,session:e.session,overlayRefs:r?.overlayRefs,fullscreen:r?.fullscreen,normalizeStatusBar:r?.normalizeStatusBar,stabilize:r?.stabilize,surface:r?.surface});return{path:o.path,...o.overlayRefs?{overlayRefs:o.overlayRefs}:{}}}}),artifacts:ek(),sessions:{get:e=>({name:e}),set:()=>{}},policy:et()}),c=await l.capture.diffScreenshot({session:t.session,baseline:{kind:"path",path:s},current:i?{kind:"path",path:q(i)}:{kind:"live"},...a?{out:{kind:"path",path:a}}:{},threshold:function(e){if(null!=e&&""!==e)return Number(e)}(t.threshold),overlayRefs:t.overlayRefs,normalizeStatusBar:t.screenshotNormalizeStatusBar,surface:t.surface});return rV(t,c,()=>R(c)),!0}};async function nD(e){let t={...e.flags},r=nk[e.command];return!!(r&&await r({...e,flags:t}))||!!p(e.command)&&await n$({...e,command:e.command,flags:t})}async function n$(e){let{runGenericClientBackedCommand:t}=await import("./generic.js");return await t(e)}function nb(e,t,r){return r||(e.push(t),"")}async function nC(e,t,r){let{flags:n}=t,o=function(e){if(!e?.metroProxyBaseUrl||!tB(e.leaseBackend))return null;let t=[],r={serverBaseUrl:nb(t,"metroProxyBaseUrl",e.metroProxyBaseUrl),bearerToken:nb(t,"metroBearerToken",e.metroBearerToken),tenantId:nb(t,"tenant",e.tenant),runId:nb(t,"runId",e.runId),leaseId:nb(t,"leaseId",e.leaseId)};if(t.length>0)throw new f("INVALID_ARGS",`react-devtools remote bridge requires ${t.join(", ")}.`,{missing:t});return r}(n);if(!o)return r();let s=t.stateDir??process.cwd(),a=t.session??n?.session??"default",i=n?.remoteConfig??`${o.tenantId}:${o.runId}:${o.leaseId}`;if("stop"===e[0])try{return await r()}finally{await tP({projectRoot:t.cwd??process.cwd(),stateDir:s,profileKey:i,consumerKey:a})}return await tx({projectRoot:t.cwd??process.cwd(),stateDir:s,serverBaseUrl:o.serverBaseUrl,bearerToken:o.bearerToken,bridgeScope:{tenantId:o.tenantId,runId:o.runId,leaseId:o.leaseId},session:a,profileKey:i,consumerKey:a,env:t.env??process.env}),await r()}async function nN(e,t={}){let r=t.cwd??process.cwd(),n=t.env??process.env,o=await nC(e,t,async()=>(await J("npm",["exec","--yes","--package","agent-react-devtools@0.4.0","--","agent-react-devtools",...e],{cwd:r,env:n,allowFailure:!0,onStdoutChunk:e=>{process.stdout.write(e)},onStderrChunk:e=>{process.stderr.write(e)}})).exitCode);var s,a=t.flags;return 0!==o&&"wait"===(s=e)[0]&&s.includes("--connected")&&"ios-instance"===a?.leaseBackend&&process.stderr.write("Hint: Remote iOS React DevTools connects during JavaScript startup.\nIf the app was already open before `agent-device react-devtools start`, relaunch it with `agent-device open <bundle-id> --platform ios --relaunch`, then retry `agent-device react-devtools wait --connected`.\n"),o}async function nR(e,t){var r,n,o,s,a,i,l;switch(e[0]){case"setup":{t.flags.json||process.stdout.write("Setting up managed agent-browser backend (downloads if needed)...\n");let{setupManagedAgentBrowser:e}=await import("./8391.js"),o=await e({stateDir:t.stateDir});return r=t.flags.json,n=o,r?O({success:!0,data:{status:nx(n)}}):process.stdout.write(`Managed web backend installed.
31
+ agent-browser available at: ${n.binaryPath}
32
+ `),0}case"doctor":{let e,{doctorManagedAgentBrowser:r}=await import("./8391.js"),n=await r({stateDir:t.stateDir});return o=t.flags.json,s=0===n.exitCode?"Web backend is healthy.":"Web backend doctor reported issues.",a=n,o?O({success:!0,data:"object"==typeof(l=e=(i=a).status)&&null!==l&&"socketDir"in l&&"installDir"in l&&"binaryPath"in l?{...i,status:nx(e)}:i}):process.stdout.write(`${s}
33
+ `),n.exitCode}default:throw new f("INVALID_ARGS","web requires setup or doctor")}}function nx(e){let{socketDir:t,...r}=e;return r}function nP(e,t={}){let r=nE(t),n={...e};return r.defaultPlatform&&void 0===n.platform&&(n.platform=r.defaultPlatform),n}function nE(e){var t,r,n,o;let s,a=e.env??process.env,i=e.inheritedPlatform??e.configuredPlatform??function(e){if(void 0===e)return;let t=e.trim().toLowerCase();if(t){if("ios"===t||"android"===t||"apple"===t)return t;throw new f("INVALID_ARGS",`Invalid AGENT_DEVICE_PLATFORM: ${e}. Use ios, android, or apple.`)}}(a.AGENT_DEVICE_PLATFORM),l="string"==typeof(t=e.configuredSession??a.AGENT_DEVICE_SESSION)&&t.trim().length>0;return{defaultPlatform:i,lockPolicy:(r=e.policyOverrides,n=a,o=l,(s=r?.sessionLock??r?.sessionLockConflicts??function(e){if(void 0===e)return;let t=e.trim().toLowerCase();if(t){if("reject"===t||"strip"===t)return t;throw new f("INVALID_ARGS",`Invalid session lock mode: ${e}. Use reject or strip.`)}}(n.AGENT_DEVICE_SESSION_LOCK))||(r?.sessionLocked===!0||o?"reject":void 0))}}let nT={sendToDaemon:ed},nU=new Set(["launchUrl","kind","metroBearerToken","metroKind","metroListenHost","metroNoInstallDeps","metroNoReuseExisting","metroPreparePort","metroProbeTimeoutMs","metroProjectRoot","metroProxyBaseUrl","metroPublicBaseUrl","metroRuntimeFile","metroStartupTimeoutMs","metroStatusHost"]),nM=new Set(["connect","connection","close","disconnect","metro","proxy","session"]);async function nL(e,r=nT){let o=Z(),s=eD(),a=function(e){try{let t=eV(e);return nB(t.command??"",t.providedFlags)}catch{return e.includes("--debug")||e.includes("-v")||e.includes("--verbose")}}(e),i=e.includes("--json"),l=function(e){for(let t=0;t<e.length;t+=1){let r=e[t];if(r.startsWith("--session=")){let e=r.slice(10).trim();return e.length>0?e:null}if("--session"===r){let r=e[t+1]?.trim();if(r&&!r.startsWith("-"))return r;break}}return null}(e)??process.env.AGENT_DEVICE_SESSION??"default";await Y({session:l,requestId:o,command:e[0],debug:a},async()=>{var l,c,p,m,g,h,w,A,$,b,C,R,x,P,E,U,M;let V,j,G,F,K,H,J;try{let r,o,s,a,i,u,d,v;l={cwd:process.cwd(),env:process.env},r=eV(e),o=l?.env??process.env,s=l?.cwd??process.cwd(),m=r.command,a=null!==m&&(c={remoteConfig:r.flags.remoteConfig,cwd:s,env:o}).remoteConfig?{...tQ(tL({configPath:c.remoteConfig,cwd:c.cwd,env:c.env}).profile),remoteConfig:c.remoteConfig}:{},d=eC((i=(p={command:r.command,cwd:s,cliFlags:r.flags,env:o}).env??process.env,u=eC({},function(e){let r={};for(let n of e)eC(r,function(e,r){let n,o;if(!t.existsSync(e)){if(r)throw new f("INVALID_ARGS",`Config file not found: ${e}`);return{}}try{n=t.readFileSync(e,"utf8")}catch(t){throw new f("INVALID_ARGS",`Failed to read config file: ${e}`,{cause:t instanceof Error?t.message:String(t)})}try{o=JSON.parse(n)}catch(t){throw new f("INVALID_ARGS",`Invalid JSON in config file: ${e}`,{cause:t instanceof Error?t.message:String(t)})}if(!o||"object"!=typeof o||Array.isArray(o))throw new f("INVALID_ARGS",`Config file must contain a JSON object: ${e}`);return function(e,t){let r={};for(let[n,o]of Object.entries(e)){if("installSource"===n){r.installSource=N(o,t);continue}let e=eL.get(n);if(!e)throw new f("INVALID_ARGS",`Unknown config key "${n}" in ${t}.`);if(!e.config.enabled)throw new f("INVALID_ARGS",`Unsupported config key "${n}" in ${t}.`);r[n]=eP(eO(e),o,t,n)}return r}(o,`config file ${e}`)}(n.path,n.required));return r}((g=p.cwd,h=p.cliFlags.config,w=i,(v=h??w.AGENT_DEVICE_CONFIG)?[{path:(A=v,$=g,b=w,q(A,{cwd:$,env:b})),required:!0}]:[{path:(C=w,n.join(W("~",{env:C}),".agent-device","config.json")),required:!1},{path:n.resolve(g,"agent-device.json"),required:!1}]))),eC(u,function(e,t){var r,n,o;let s={};for(let a of eM.filter(e=>e.config.enabled&&e.supportsCommand(t))){if("installSource"===a.key)continue;let t=a.env.names.map(t=>({name:t,value:e[t]})).find(e=>"string"==typeof e.value&&e.value.trim().length>0);t&&(s[a.key]=(r=t.value,n=`environment variable ${t.name}`,o=t.name,eP(eO(a),r,n,o)))}return s}(i,p.command))),a),V={...function(e,t){let r=t?.strictFlags??!0,n=[...e.warnings],o=eC({json:!1,help:!1,version:!1},t?.defaultFlags??{});eC(o,e.flags);let s=e.providedFlags.filter(t=>!eB(t.key,e.command));if(s.length>0){var a,i;let t=s.map(e=>e.token),l=(a=e.command,i=t,a?1===i.length?`Flag ${i[0]} is not supported for command ${a}.`:`Flags ${i.join(", ")} are not supported for command ${a}.`:1===i.length?`Flag ${i[0]} requires a command that supports it.`:`Flags ${i.join(", ")} require a command that supports them.`);if(r)throw new f("INVALID_ARGS",l);for(let e of(n.push(l),s))delete o[e.key]}for(let t of Object.keys(o))void 0!==o[t]&&(eB(t,e.command)||delete o[t]);if(function(e){if("back"===e.command&&!(new Set(e.providedFlags.filter(e=>"backMode"===e.key).map(e=>e.token)).size<=1))throw new f("INVALID_ARGS","back accepts only one explicit mode flag: use either --in-app or --system.")}(e),I(e.command,o),"batch"===e.command&&1!=+!!o.steps+ +!!o.stepsFile)throw new f("INVALID_ARGS","batch requires exactly one step source: --steps or --steps-file.");return function(e){if(e.flags.help)return e;if("snapshot"===e.command&&e.flags.snapshotDiff){let{snapshotDiff:t,...r}=e.flags;return{command:"diff",positionals:["snapshot",...e.positionals],flags:r,warnings:e.warnings}}return e}({command:e.command,positionals:e.positionals,flags:o,warnings:n})}(r,{strictFlags:l?.strictFlags,defaultFlags:d}),providedFlags:r.providedFlags}}catch(t){ee({level:"error",phase:"cli_parse_failed",data:{error:t instanceof Error?t.message:String(t)}});let e=d(t,{diagnosticId:X().diagnosticId,logPath:Q({force:!0})??void 0});i?O({success:!1,error:e}):D(e,{showDetails:a}),process.exit(1);return}for(let e of V.warnings)process.stderr.write(`Warning: ${e}
34
+ `);V.flags.version&&(process.stdout.write(`${s}
35
+ `),process.exit(0));let z="help"===V.command,Z=V.flags.help;if(z||Z){z&&V.positionals.length>1&&(D(new f("INVALID_ARGS","help accepts at most one command.")),process.exit(1));let e=z?V.positionals[0]:V.command;e||(process.stdout.write(`${_()}
36
+ `),process.exit(0));let t=S(eK(e));t&&(process.stdout.write(t),process.exit(0)),D(new f("INVALID_ARGS",`Unknown command: ${e}`)),process.stdout.write(`${_()}
37
+ `),process.exit(1)}V.command||(process.stdout.write(`${_()}
38
+ `),process.exit(1));let{command:Y,positionals:et}=V,er=nB(Y,V.providedFlags),en=new Set(V.providedFlags.map(e=>e.key));try{G=(j=nE({policyOverrides:V.flags,configuredPlatform:V.flags.platform,configuredSession:V.flags.session})).lockPolicy?{...V.flags}:nP(V.flags,{policyOverrides:V.flags,configuredPlatform:V.flags.platform,configuredSession:V.flags.session}),F=el(G.stateDir),K=G.session??"default",R={command:Y,explicitFlagKeys:en,stateDir:F.baseDir,session:K,remoteConfig:G.remoteConfig,hasResolvedSession:void 0!==G.session},J=(H="connect"===R.command||"connection"===R.command||"proxy"===R.command?null:function(e){let t=e.validateRemoteConfigHash??!0,r=e.remoteConfig?tM({configPath:e.remoteConfig,cwd:e.cwd,env:e.env}):void 0,n=tj(e)??(e.allowActiveFallback?tJ({stateDir:e.stateDir}):null);if(!n||r&&n.remoteConfigPath!==r)return null;if(t&&tH(n.remoteConfigPath)!==n.remoteConfigHash)throw new f("INVALID_ARGS","Active remote connection config changed. Run agent-device connect --force to refresh it.",{remoteConfig:n.remoteConfigPath});let o=function(e,t){try{return tL({configPath:e.remoteConfigPath,cwd:t.cwd,env:t.env}).profile}catch(e){if(!1===t.validateRemoteConfigHash)return{};throw e}}(n,e),s=T(n);return{runtime:n.runtime,connection:B(s),flags:{...o,remoteConfig:n.remoteConfigPath,daemonBaseUrl:n.daemon?.baseUrl??o.daemonBaseUrl,daemonAuthToken:n.daemon?.authToken??o.daemonAuthToken,daemonTransport:n.daemon?.transport??o.daemonTransport,daemonServerMode:n.daemon?.serverMode??o.daemonServerMode,...L(s),sessionIsolation:"tenant",session:n.session,platform:n.platform??o.platform,target:n.target??o.target}}}({stateDir:R.stateDir,session:R.session,remoteConfig:R.remoteConfig,cwd:process.cwd(),env:process.env,allowActiveFallback:!R.explicitFlagKeys.has("session")&&(!R.remoteConfig||"disconnect"===R.command||!R.hasResolvedSession),validateRemoteConfigHash:"disconnect"!==R.command}))?function(e,t,r){let n={...e};for(let[e,o]of Object.entries(t))void 0!==o&&(r.has(e)||(n[e]=o));return n}(G,H.flags,en):G}catch(t){let e=d(u(t),{diagnosticId:X().diagnosticId,logPath:Q({force:!0})??void 0});V.flags.json?O({success:!1,error:e}):D(e,{showDetails:er}),process.exit(1);return}let eo=null;try{let e;if("react-devtools"===Y){let e=await nN(et,{flags:J,stateDir:F.baseDir,session:J.session??K,cwd:process.cwd(),env:process.env});process.exit(e);return}if("web"===Y){let e=await nR(et,{flags:J,stateDir:F.baseDir});process.exit(e);return}e$({command:Y,currentVersion:s,stateDir:F.baseDir,flags:J});let n=H?.runtime,a=H?.connection,i=(e,t,r)=>({session:e.session,requestId:o,stateDir:e.stateDir,daemonBaseUrl:e.daemonBaseUrl,daemonAuthToken:e.daemonAuthToken,daemonTransport:e.daemonTransport,daemonServerMode:e.daemonServerMode,tenant:e.tenant,sessionIsolation:e.sessionIsolation,runId:e.runId,leaseId:e.leaseId,leaseBackend:e.leaseBackend,leaseProvider:r?.leaseProvider,clientId:r?.clientId,deviceKey:r?.deviceKey,providerApp:e.providerApp,providerOsVersion:e.providerOsVersion,providerProject:e.providerProject,providerBuild:e.providerBuild,providerSessionName:e.providerSessionName,awsProjectArn:e.awsProjectArn,awsDeviceArn:e.awsDeviceArn,awsAppArn:e.awsAppArn,awsRegion:e.awsRegion,awsInteractionMode:e.awsInteractionMode,runtime:t,lockPolicy:j.lockPolicy,lockPlatform:j.defaultPlatform,cwd:process.cwd(),debug:er,cost:e.cost,responseLevel:e.responseLevel});if("batch"===Y){if(et.length>0)throw new f("INVALID_ARGS","batch does not accept positional arguments.");e=function(e){let r,n,o,s="";if(e.steps)s=e.steps;else if(e.stepsFile)try{s=t.readFileSync(e.stepsFile,"utf8")}catch(r){let t=r instanceof Error?r.message:String(r);throw new f("INVALID_ARGS",`Failed to read --steps-file ${e.stepsFile}: ${t}`)}var a,i=s;try{o=JSON.parse(i)}catch{throw new f("INVALID_ARGS","Batch steps must be valid JSON.")}if(!Array.isArray(o)||0===o.length)throw new f("INVALID_ARGS","Batch steps must be a non-empty JSON array.");return a=o,r=!1,n=a.map((e,t)=>{var n,o,s;let a;if(n=e,y(n)&&"input"in n&&!("positionals"in n)&&!("flags"in n))return function(e,t){let r=v(e.runtime,t),{runtime:n,...o}=e;return{...o,...void 0===r?{}:{runtime:r}}}(e,t+1);let i=function(e,t){if(!y(e))throw new f("INVALID_ARGS",`Invalid batch step ${t}.`);var r=e,n=t;let o=Object.keys(r).filter(e=>!["command","positionals","flags","runtime"].includes(e));if(o.length>0)throw new f("INVALID_ARGS",`Batch step ${n} has unknown legacy field(s): ${o.join(", ")}.`);let s=function(e,t){let r="string"==typeof e?e.trim().toLowerCase():"";if(!r)throw new f("INVALID_ARGS",`Batch step ${t} requires command.`);if(k(r))return r;throw new f("INVALID_ARGS",`Batch step ${t} command is not available through command batch: ${String(e)}`)}(e.command,t),a=function(e,t){if(void 0!==e){if(!Array.isArray(e)||e.some(e=>"string"!=typeof e))throw new f("INVALID_ARGS",`Batch step ${t} positionals must contain only strings.`);return e}}(e.positionals,t),i=function(e,t){if(void 0!==e){if(!y(e))throw new f("INVALID_ARGS",`Batch step ${t} flags must be an object.`);return e}}(e.flags,t),l=v(e.runtime,t);return{command:s,...void 0===a?{}:{positionals:a},...void 0===i?{}:{flags:i},...void 0===l?{}:{runtime:l}}}(e,t+1);return r=!0,o=i,a=nA(o.command,o.positionals??[],(s=o.flags,{json:!1,help:!1,version:!1,...s})),{command:o.command,input:a,...void 0===o.runtime?{}:{runtime:o.runtime}}}),r&&process.stderr.write('Warning: batch steps using positionals/flags are deprecated and will be removed in the next major version. Use {"command":"...","input":{...}} steps instead.\n'),n}(G)}if(x=Y,"auth"!==x&&"connection"!==x&&"proxy"!==x&&(J=(await rp({command:Y,flags:J,stateDir:F.baseDir,env:process.env})).flags),J.remoteConfig&&(P=Y,!nM.has(P))){let t=ep(i(J,n,a),{transport:nO(r.sendToDaemon)}),o=await t8({command:Y,flags:J,client:t,runtime:n,positionals:et,batchSteps:e,forceRuntimePrepare:function(e){for(let t of nU)if(e.has(t))return!0;return!1}(en)});J=o.flags,n=o.runtime,a=o.connection}if(E={command:Y,flags:J,runtime:n,explicitFlagKeys:en,hadConnectionDefaults:!!H},!("open"===E.command&&!E.runtime&&!E.flags.bundleUrl&&!E.flags.metroHost&&!E.flags.metroPort&&!E.flags.remoteConfig&&!E.hadConnectionDefaults&&((U=E.explicitFlagKeys).has("daemonBaseUrl")||U.has("daemonTransport")||U.has("tenant")||U.has("sessionIsolation")||U.has("runId")||U.has("leaseId")||U.has("leaseBackend")))||process.stderr.write("Warning: open is using explicit remote daemon or tenant flags without saved Metro runtime hints. React Native apps may launch without bundle/runtime hints; prefer connect --remote-config <path> first or pass --remote-config <path> on this command.\n"),"cdp"===Y){let e=await tV(et,{flags:J,runtime:n,cwd:process.cwd(),env:process.env});process.exit(e);return}let l=J.daemonBaseUrl;eo=!er||J.json||l?null:function(e){try{let r=t.existsSync(e)?t.statSync(e).size:0,n=!1,o=setInterval(()=>{if(!n&&t.existsSync(e))try{let n=t.statSync(e);if(n.size<r&&(r=0),n.size<=r)return;let o=t.openSync(e,"r");try{let e=Buffer.alloc(n.size-r);t.readSync(o,e,0,e.length,r),r=n.size,e.length>0&&process.stdout.write(e.toString("utf8"))}finally{t.closeSync(o)}}catch{}},200);return()=>{n=!0,clearInterval(o)}}catch{return null}}(F.logPath);let c="test"===Y?await tC({debug:er,verbose:J.verbose,json:J.json,reporter:J.reporter,reportJunit:J.reportJunit}):void 0,u=ep(i(J,n,a),{transport:function(e){let{command:t,flags:r,replayTestReporterRuntime:n,transport:o}=e;return r.json?nO(o):async e=>await nV(o,{...e,meta:{...e.meta,requestProgress:"test"===t?"replay-test":"command"}},"test"===t&&n?{onProgress:n.onProgress}:void 0)}({command:Y,flags:J,replayTestReporterRuntime:c,transport:r.sendToDaemon})});if("batch"===Y){if(!e)throw new f("INVALID_ARGS","batch requires --steps or --steps-file.");let t=e.map((e,t)=>({...e,input:j.lockPolicy&&void 0===G.platform?{...e.input}:nP(e.input,{policyOverrides:J,configuredPlatform:J.platform,configuredSession:J.session,inheritedPlatform:J.platform})}));if(await nD({command:Y,positionals:et,flags:{...J,batchSteps:t},client:u,debug:er,replayTestReporterRuntime:c}))return}else if("runtime"===Y)throw new f("INVALID_ARGS","runtime command was removed. Use connect --remote-config <path> for remote runs, or metro prepare --remote-config <path> for inspection.");else if(await nD({command:Y,positionals:et,flags:J,client:u,debug:er,replayTestReporterRuntime:c}))return;throw new f("INVALID_ARGS",`Unknown command: ${Y}`)}catch(n){let e=u(n),r=d(e,{diagnosticId:X().diagnosticId,logPath:Q({force:!0})??void 0});if("close"===Y&&"COMMAND_FAILED"===(M=e).code&&(M.details?.kind==="daemon_startup_failed"||M.message.toLowerCase().includes("failed to start daemon")&&("string"==typeof M.details?.infoPath||"string"==typeof M.details?.lockPath))){J.json&&O({success:!0,data:{closed:"session",source:"no-daemon"}});return}if(J.json)O({success:!1,error:r});else if(D(r,{showDetails:er}),er)try{let e=F.logPath;if(t.existsSync(e)){let r=t.readFileSync(e,"utf8").split("\n"),n=r.slice(Math.max(0,r.length-200)).join("\n");n.trim().length>0&&process.stderr.write(`
27
39
  [daemon log]
28
- ${r}
29
- `)}}catch{}ea&&ea(),process.exit(1)}finally{ea&&ea()}})}function nx(e,t){return t.some(t=>"verbose"===t.key&&("--debug"===t.token||"-v"===t.token||"test"!==e))}e(process.argv[1]??"").href===import.meta.url&&nU(process.argv.slice(2)).catch(e=>{B(A(I(e)),{showDetails:!0}),process.exit(1)});export{nU as runCli,nh as runCliCommandWithOutput,tB as writeCommandOutput};
40
+ ${n}
41
+ `)}}catch{}eo&&eo(),process.exit(1)}finally{eo&&eo()}})}function nB(e,t){return t.some(t=>"verbose"===t.key&&("--debug"===t.token||"-v"===t.token||"test"!==e))}function nO(e){return async t=>await nV(e,t)}async function nV(e,t,r){return await e(t,r)}e(process.argv[1]??"").href===import.meta.url&&nL(process.argv.slice(2)).catch(e=>{D(d(u(e)),{showDetails:!0}),process.exit(1)});export{tb as renderReplayTestResponse,nL as runCli,n_ as runCliCommandWithOutput,rV as writeCommandOutput};