agent-device 0.21.2 → 0.21.3

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 (74) hide show
  1. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.2.apk → agent-device-android-ime-helper-0.21.3.apk} +0 -0
  2. package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.3.apk.sha256 +1 -0
  3. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.2.manifest.json → agent-device-android-ime-helper-0.21.3.manifest.json} +4 -4
  4. package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.21.2.apk → agent-device-android-snapshot-helper-0.21.3.apk} +0 -0
  5. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.3.apk.sha256 +1 -0
  6. package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.21.2.manifest.json → agent-device-android-snapshot-helper-0.21.3.manifest.json} +7 -7
  7. package/dist/src/agent-device-client.js +1 -1
  8. package/dist/src/app-launch.js +1 -1
  9. package/dist/src/auth.js +1 -1
  10. package/dist/src/back-mode.js +1 -1
  11. package/dist/src/cli.js +2 -2
  12. package/dist/src/client-types.d.ts +1 -1
  13. package/dist/src/command-schema.js +1 -1
  14. package/dist/src/config.js +1 -1
  15. package/dist/src/connection-runtime.js +1 -1
  16. package/dist/src/connection.js +1 -1
  17. package/dist/src/daemon-client-lifecycle.js +1 -1
  18. package/dist/src/daemon-registration.js +1 -1
  19. package/dist/src/daemon-resolution.js +1 -0
  20. package/dist/src/daemon.js +1 -1
  21. package/dist/src/device-claim-rule.js +1 -1
  22. package/dist/src/harmonyos.js +1 -1
  23. package/dist/src/human-control-contract.js +1 -1
  24. package/dist/src/human-control.js +1 -1
  25. package/dist/src/interaction.js +1 -1
  26. package/dist/src/interactor.js +1 -1
  27. package/dist/src/interactors.js +1 -1
  28. package/dist/src/internal/bin.js +1 -1
  29. package/dist/src/internal/daemon.js +2 -2
  30. package/dist/src/lease-scope.js +1 -1
  31. package/dist/src/mechanics.js +16 -16
  32. package/dist/src/perf-runtime-plan.js +1 -1
  33. package/dist/src/physical-device-control.js +1 -1
  34. package/dist/src/platform-request-scope.js +1 -1
  35. package/dist/src/platform-runtime-host.js +1 -1
  36. package/dist/src/platform-runtime-operation-host.js +1 -1
  37. package/dist/src/platform-runtime-screen-recording-finalizer-host.js +1 -1
  38. package/dist/src/platform-runtime-screen-recording-harmony-host.js +1 -1
  39. package/dist/src/platform-runtime.js +1 -1
  40. package/dist/src/provider-webdriver.js +1 -1
  41. package/dist/src/record-runtime.js +1 -1
  42. package/dist/src/register-builtins.js +1 -1
  43. package/dist/src/registry.js +3 -3
  44. package/dist/src/request-providers.js +1 -1
  45. package/dist/src/runner-cache-metadata.js +2 -2
  46. package/dist/src/runner-client.js +1 -1
  47. package/dist/src/runner-disposal.js +1 -1
  48. package/dist/src/runtime.js +1 -1
  49. package/dist/src/runtime2.js +1 -1
  50. package/dist/src/runtime4.js +5 -5
  51. package/dist/src/runtime6.js +1 -1
  52. package/dist/src/runtime9.js +1 -1
  53. package/dist/src/screen-recording-resource-recovery.js +1 -1
  54. package/dist/src/screen-recording-runtime.js +1 -1
  55. package/dist/src/screenshot-runtime.js +1 -1
  56. package/dist/src/sdk-batch.js +2 -2
  57. package/dist/src/sdk-remote-config.d.ts +1 -0
  58. package/dist/src/sdk-remote-config.js +1 -1
  59. package/dist/src/selector-runtime.js +1 -1
  60. package/dist/src/session-routing.js +1 -1
  61. package/dist/src/session-snapshot.js +1 -1
  62. package/dist/src/session2.js +5 -5
  63. package/dist/src/simulator.js +1 -1
  64. package/dist/src/snapshot-runtime-binding.js +1 -1
  65. package/dist/src/snapshot-runtime.js +1 -1
  66. package/dist/src/snapshot4.js +1 -1
  67. package/dist/src/src3.js +1 -1
  68. package/dist/src/src4.js +1 -1
  69. package/package.json +1 -1
  70. package/server.json +2 -2
  71. package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.2.apk.sha256 +0 -1
  72. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.2.apk.sha256 +0 -1
  73. package/dist/src/config2.js +0 -1
  74. package/dist/src/provider-device-runtime.js +0 -1
@@ -0,0 +1 @@
1
+ 94e386014aafa5af78801fc0ff83e0eb0c8ce1734fbc121d6b126007e99db7ac agent-device-android-ime-helper-0.21.3.apk
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "android-ime-helper",
3
- "version": "0.21.2",
4
- "assetName": "agent-device-android-ime-helper-0.21.2.apk",
5
- "sha256": "17a3645b2baca245adaa37e025a89eb35da7c5c6d53ae2d2d84862474f402cf0",
3
+ "version": "0.21.3",
4
+ "assetName": "agent-device-android-ime-helper-0.21.3.apk",
5
+ "sha256": "94e386014aafa5af78801fc0ff83e0eb0c8ce1734fbc121d6b126007e99db7ac",
6
6
  "packageName": "com.callstack.agentdevice.imehelper",
7
- "versionCode": 21002,
7
+ "versionCode": 21003,
8
8
  "serviceComponent": "com.callstack.agentdevice.imehelper/.TestInputMethodService",
9
9
  "broadcastProtocol": "android-ime-helper-v1"
10
10
  }
@@ -0,0 +1 @@
1
+ 5faa8e4e6d581c94614fde709406868c3fa7858519766fdfaa773709cbba7434 agent-device-android-snapshot-helper-0.21.3.apk
@@ -1,17 +1,17 @@
1
1
  {
2
2
  "name": "android-snapshot-helper",
3
- "version": "0.21.2",
4
- "releaseTag": "v0.21.2",
5
- "assetName": "agent-device-android-snapshot-helper-0.21.2.apk",
3
+ "version": "0.21.3",
4
+ "releaseTag": "v0.21.3",
5
+ "assetName": "agent-device-android-snapshot-helper-0.21.3.apk",
6
6
  "apkUrl": null,
7
- "sha256": "ee5d763221ede67f2b6e33e56d3487f3c05aab65a9a6999e456b273c7ccfecec",
8
- "checksumName": "agent-device-android-snapshot-helper-0.21.2.apk.sha256",
7
+ "sha256": "5faa8e4e6d581c94614fde709406868c3fa7858519766fdfaa773709cbba7434",
8
+ "checksumName": "agent-device-android-snapshot-helper-0.21.3.apk.sha256",
9
9
  "packageName": "com.callstack.agentdevice.snapshothelper",
10
- "versionCode": 21002,
10
+ "versionCode": 21003,
11
11
  "instrumentationRunner": "com.callstack.agentdevice.snapshothelper/.SnapshotInstrumentation",
12
12
  "minSdk": 23,
13
13
  "targetSdk": 36,
14
14
  "outputFormat": "uiautomator-xml",
15
15
  "statusProtocol": "android-snapshot-helper-v1",
16
- "installArgs": ["install", "-r", "-t"]
16
+ "installArgs": ["install", "-r"]
17
17
  }
@@ -1,3 +1,3 @@
1
- import{r as e}from"./rolldown-runtime.js";import{B as t,C as n,L as r,a as i,o as a}from"./sdk-contracts.js";import"./capture.js";import{n as o}from"./snapshot-capture-annotations.js";import{C as s,D as c,S as l,T as u,b as d,g as f,h as p,w as m,x as h,y as g}from"./sdk-batch-runner.js";import{n as _}from"./snapshot-diagnostics.js";import{c as v,m as y,p as ee,s as te}from"./sdk-device.js";import{f as ne,i as b}from"./lease-scope.js";import{tn as x,w as S}from"./sdk-batch.js";import{n as C,t as w}from"./catalog.js";import{T as re,i as ie,m as ae,w as oe}from"./registry.js";import{c as T,n as se,r as ce}from"./diagnostics.js";import{t as E}from"./command-metadata.js";import"./diagnostics2.js";import{a as le,c as ue,i as de,l as fe,n as pe,o as me,r as he,s as ge,t as _e}from"./daemon-client-lifecycle.js";import{n as D}from"./config.js";import{r as ve}from"./session-paths.js";import{n as ye,t as be}from"./client-metro.js";import{t as xe}from"./screenshot-result.js";import O from"node:path";import k from"node:fs";function A(e){let t=e.appId??e.bundleId??e.packageName;return{session:e.session,appId:t,appBundleId:e.bundleId,package:e.packageName}}function j(e,t,n){return{deviceId:t,deviceName:n,...y(e)?{serial:t}:e===`ios`?{udid:t}:{}}}function M(e,t){let n=h(e,`bundleId`),r=h(e,`package`);return{app:u(e,`app`),appPath:u(e,`appPath`),platform:m(e,`platform`),appId:n??r,bundleId:n,package:r,identifiers:A({session:t,bundleId:n,packageName:r})}}function Se(e,t){let r=h(e,`bundleId`),i=h(e,`packageName`),a=r??i??h(e,`appId`),o=h(e,`launchTarget`)??i??r??a;if(!o)throw new n(`COMMAND_FAILED`,`Daemon response is missing "launchTarget".`,{response:e});return{appName:h(e,`appName`),appId:a,bundleId:r,packageName:i,launchTarget:o,installablePath:h(e,`installablePath`),archivePath:h(e,`archivePath`),materializationId:h(e,`materializationId`),materializationExpiresAt:h(e,`materializationExpiresAt`),identifiers:A({session:t,bundleId:r,packageName:i,appId:a})}}function Ce(e){return{released:e.released===!0,materializationId:u(e,`materializationId`),identifiers:{}}}function N(e){let{record:t,platform:n,id:r,name:i,target:a}=F(e,`name`),o=P(t);return{platform:n,target:a,kind:l(t,`kind`),id:r,name:i,booted:typeof t.booted==`boolean`?t.booted:void 0,...v(n)&&o?{appleOs:o}:{},identifiers:j(n,r,i),...we(t),...I(n,r)}}function we(e){let t=e.claimedBy;if(!t||typeof t!=`object`||Array.isArray(t))return{};let n=t,r=n.session,i=n.workspace;return typeof r!=`string`||typeof i!=`string`?{}:{claimedBy:{session:r,workspace:i}}}function Te(e){let{record:t,platform:n,id:r,name:i,target:a}=F(e,`name`),o=u(t,`device`),c=P(t),l={session:i,...j(n,r,o)};return{name:i,address:h(t,`address`),createdAt:s(t,`createdAt`),sessionStateDir:h(t,`sessionStateDir`),runnerLogPath:h(t,`runnerLogPath`),device:{platform:n,target:a,id:r,name:o,...c?{appleOs:c}:{},identifiers:l,...I(n,r,{simulatorSetPath:d(t,`ios_simulator_device_set`)})},identifiers:l}}function P(e){let t=e.appleOs;return te(t)?t:void 0}function F(e,t){let n=p(e);return{record:n,platform:m(n,`platform`),id:u(n,`id`),name:u(n,t),target:g(n,`target`)}}function I(e,t,n={}){if(e===`ios`)return{ios:{udid:t,...n.simulatorSetPath===void 0?{}:{simulatorSetPath:n.simulatorSetPath}}};if(!y(e))return{};let r=n.serial??t;return e===`android`?{android:{serial:r}}:e===`harmonyos`?{harmonyos:{serial:r}}:{vega:{serial:r}}}function Ee(e){if(!f(e))return;let t=e.platform,n=h(e,`metroHost`),r=typeof e.metroPort==`number`?e.metroPort:void 0,i=h(e,`bundleUrl`),o=h(e,`launchUrl`);return{platform:a(t)?t:void 0,metroHost:n,metroPort:r,bundleUrl:i,launchUrl:o}}function De(e){let t=e.platform,n=h(e,`id`),r=h(e,`device`);if(!ee(t)||!n||!r)return;let i=g(e,`target`),a=y(t)?h(e,`serial`)??n:void 0;return{platform:t,target:i,id:n,name:r,identifiers:{...j(t,n,r),...a?{serial:a}:{}},...I(t,t===`ios`?h(e,`device_udid`)??n:n,{simulatorSetPath:d(e,`ios_simulator_device_set`),serial:a})}}const Oe=[`explicit-selector`,`existing-session`,`single-booted-local`,`single-bootable-local`,`single-app-installed-local`,`preferred-local`,`single-provider-device`],ke=[`session`,`local`,`provider`];function Ae(e){if(!f(e))return;let{reason:t,source:n,candidateCount:r,bootOccurred:i}=e;if(!(!Oe.includes(t)||!ke.includes(n)||typeof r!=`number`||!Number.isInteger(r)||r<0||typeof i!=`boolean`))return{reason:t,source:n,candidateCount:r,bootOccurred:i}}function je(e){if(f(e)&&typeof e.durationMs==`number`&&typeof e.measuredAt==`string`&&typeof e.method==`string`)return{durationMs:e.durationMs,measuredAt:e.measuredAt,method:e.method,appTarget:h(e,`appTarget`),appBundleId:h(e,`appBundleId`)}}function L(e){if(!f(e)||typeof e.success!=`boolean`||typeof e.exitCode!=`number`||typeof e.stdout!=`string`||typeof e.stderr!=`string`)return;let t=R(e.error);return{success:e.success,exitCode:e.exitCode,stdout:e.stdout,stderr:e.stderr,...t?{error:t}:{}}}const Me=[`hint`,`diagnosticId`,`logPath`,`supportedOn`];function R(e){if(!f(e)||typeof e.code!=`string`||typeof e.message!=`string`)return;let t={code:e.code,message:e.message};Object.assign(t,Ne(e.cause));for(let n of Me){let r=e[n];typeof r==`string`&&(t[n]=r)}return f(e.details)&&(t.details=e.details),typeof e.retriable==`boolean`&&(t.retriable=e.retriable),t}function Ne(e){let n=t(e);return n?{cause:n}:void 0}function Pe(e){let t=R(e.initialSnapshotError);return{...e.snapshot&&typeof e.snapshot==`object`?{snapshot:e.snapshot}:{},...t?{initialSnapshotError:t}:{}}}function Fe(e){return Array.isArray(e)?e:[]}function Ie(e){let t=b(e);return c({requestId:e.requestId,cwd:e.cwd,sessionExplicit:e.session!==void 0,debug:e.debug,includeCost:e.cost,responseLevel:e.responseLevel,lockPolicy:e.lockPolicy,lockPlatform:e.lockPlatform,...ne(t),sessionIsolation:e.sessionIsolation,installSource:e.installSource,retainMaterializedPaths:e.retainMaterializedPaths,materializedPathRetentionMs:e.materializedPathRetentionMs,materializationId:e.materializationId})}function z(e){return e??`default`}const B={...ie(),batch:ae(Le)};async function Le(e,t,r){let i=B[e];if(!i)throw Error(`Missing daemon writer for batch command: ${e}`);let a=E(e);if(!a)throw Error(`Missing command metadata for batch command: ${e}`);try{return await V(i,a,a.readInput(t))}catch(t){let i=t instanceof Error?t.message:String(t);throw new n(`INVALID_ARGS`,`Batch step ${r} ${e} input is invalid: ${i}`,void 0,t)}}async function Re(e,t){let n=B[e];if(!n)throw Error(`Missing daemon writer for command: ${e}`);return await V(n,E(e),t)}async function V(e,t,n){let r=await e(n);return{...r,...t?{metadataFlags:re(t,r.options)}:{}}}async function H(e,t={}){let n=e.meta?.requestId??se(),r=!!(e.meta?.debug||e.flags?.verbose),i=e.flags,{daemonAuthToken:a,...o}=i??{},s=i?{...e,flags:o}:e,c=ge(s,t.authToken??a),l=x(S(s.command),s),u=await T(`daemon_startup`,async()=>await de(c),{requestId:n,session:e.session}),d=u.info,f=await fe(s,d);Ke(s.command);let p=ze(s,f,d.token,n,r);return ce({level:`info`,phase:`daemon_request_prepare`,data:{requestId:n,command:s.command,session:s.session}}),await Ue(s,u,c,async()=>Ge(We(await T(`daemon_request`,async()=>await ue(d,p,c.transportPreference,c.paths,l,t.onProgress?{onProgress:t.onProgress}:void 0),{requestId:n,command:e.command}),c),s,c))}function ze(e,t,n,r,i){return{...e,positionals:t.positionals,flags:t.flags,token:n,meta:Be(e,t,r,i)}}function Be(e,t,n,r){let i=e.meta??{};return{...i,requestId:n,debug:r,...Ve(i,e.flags),...He(t)}}function Ve(e,t){return{includeCost:e.includeCost,cwd:e.cwd,sessionExplicit:e.sessionExplicit,tenantId:e.tenantId??t?.tenant,runId:e.runId??t?.runId,leaseId:e.leaseId??t?.leaseId,sessionIsolation:e.sessionIsolation??t?.sessionIsolation,lockPolicy:e.lockPolicy,lockPlatform:e.lockPlatform}}function He(e){return{...e.uploadedArtifactId?{uploadedArtifactId:e.uploadedArtifactId}:{},...e.clientArtifactPaths?{clientArtifactPaths:e.clientArtifactPaths}:{},...e.installSource?{installSource:e.installSource}:{}}}async function Ue(e,t,r,i){let a,o=!1,s;try{a=await i()}catch(e){o=!0,s=e}let c=await he(e,t,r,a);if(o)throw s;if(!c)throw new n(`COMMAND_FAILED`,`Daemon request produced no response after cleanup`);return c}function We(e,t){return e.ok||!t.ownedStateDir||!me(e)?e:pe(e,t.paths.baseDir)}function Ge(e,t,n){return!e.ok||!le(t,e)?e:_e(e,n.ownedStateDir?n.paths.baseDir:void 0)}function Ke(e){!qe(e)||process.stderr.isTTY!==!0||process.env.CI||process.stderr.write(e===C.reinstall?`Reinstalling...
1
+ import{r as e}from"./rolldown-runtime.js";import{B as t,C as n,L as r,a as i,o as a}from"./sdk-contracts.js";import"./capture.js";import{n as o}from"./snapshot-capture-annotations.js";import{C as s,D as c,S as l,T as u,b as d,g as f,h as p,w as m,x as h,y as g}from"./sdk-batch-runner.js";import{n as _}from"./snapshot-diagnostics.js";import{c as v,m as y,p as ee,s as te}from"./sdk-device.js";import{f as ne,i as b}from"./lease-scope.js";import{tn as x,w as S}from"./sdk-batch.js";import{n as C,t as w}from"./catalog.js";import{T as re,i as ie,m as ae,w as oe}from"./registry.js";import{c as T,n as se,r as ce}from"./diagnostics.js";import{t as E}from"./command-metadata.js";import"./diagnostics2.js";import{a as le,c as ue,i as de,l as fe,n as pe,o as me,r as he,s as ge,t as _e}from"./daemon-client-lifecycle.js";import{t as D}from"./daemon-resolution.js";import{r as ve}from"./session-paths.js";import{n as ye,t as be}from"./client-metro.js";import{t as xe}from"./screenshot-result.js";import O from"node:path";import k from"node:fs";function A(e){let t=e.appId??e.bundleId??e.packageName;return{session:e.session,appId:t,appBundleId:e.bundleId,package:e.packageName}}function j(e,t,n){return{deviceId:t,deviceName:n,...y(e)?{serial:t}:e===`ios`?{udid:t}:{}}}function M(e,t){let n=h(e,`bundleId`),r=h(e,`package`);return{app:u(e,`app`),appPath:u(e,`appPath`),platform:m(e,`platform`),appId:n??r,bundleId:n,package:r,identifiers:A({session:t,bundleId:n,packageName:r})}}function Se(e,t){let r=h(e,`bundleId`),i=h(e,`packageName`),a=r??i??h(e,`appId`),o=h(e,`launchTarget`)??i??r??a;if(!o)throw new n(`COMMAND_FAILED`,`Daemon response is missing "launchTarget".`,{response:e});return{appName:h(e,`appName`),appId:a,bundleId:r,packageName:i,launchTarget:o,installablePath:h(e,`installablePath`),archivePath:h(e,`archivePath`),materializationId:h(e,`materializationId`),materializationExpiresAt:h(e,`materializationExpiresAt`),identifiers:A({session:t,bundleId:r,packageName:i,appId:a})}}function Ce(e){return{released:e.released===!0,materializationId:u(e,`materializationId`),identifiers:{}}}function N(e){let{record:t,platform:n,id:r,name:i,target:a}=F(e,`name`),o=P(t);return{platform:n,target:a,kind:l(t,`kind`),id:r,name:i,booted:typeof t.booted==`boolean`?t.booted:void 0,...v(n)&&o?{appleOs:o}:{},identifiers:j(n,r,i),...we(t),...I(n,r)}}function we(e){let t=e.claimedBy;if(!t||typeof t!=`object`||Array.isArray(t))return{};let n=t,r=n.session,i=n.workspace;return typeof r!=`string`||typeof i!=`string`?{}:{claimedBy:{session:r,workspace:i}}}function Te(e){let{record:t,platform:n,id:r,name:i,target:a}=F(e,`name`),o=u(t,`device`),c=P(t),l={session:i,...j(n,r,o)};return{name:i,address:h(t,`address`),createdAt:s(t,`createdAt`),sessionStateDir:h(t,`sessionStateDir`),runnerLogPath:h(t,`runnerLogPath`),device:{platform:n,target:a,id:r,name:o,...c?{appleOs:c}:{},identifiers:l,...I(n,r,{simulatorSetPath:d(t,`ios_simulator_device_set`)})},identifiers:l}}function P(e){let t=e.appleOs;return te(t)?t:void 0}function F(e,t){let n=p(e);return{record:n,platform:m(n,`platform`),id:u(n,`id`),name:u(n,t),target:g(n,`target`)}}function I(e,t,n={}){if(e===`ios`)return{ios:{udid:t,...n.simulatorSetPath===void 0?{}:{simulatorSetPath:n.simulatorSetPath}}};if(!y(e))return{};let r=n.serial??t;return e===`android`?{android:{serial:r}}:e===`harmonyos`?{harmonyos:{serial:r}}:{vega:{serial:r}}}function Ee(e){if(!f(e))return;let t=e.platform,n=h(e,`metroHost`),r=typeof e.metroPort==`number`?e.metroPort:void 0,i=h(e,`bundleUrl`),o=h(e,`launchUrl`);return{platform:a(t)?t:void 0,metroHost:n,metroPort:r,bundleUrl:i,launchUrl:o}}function De(e){let t=e.platform,n=h(e,`id`),r=h(e,`device`);if(!ee(t)||!n||!r)return;let i=g(e,`target`),a=y(t)?h(e,`serial`)??n:void 0;return{platform:t,target:i,id:n,name:r,identifiers:{...j(t,n,r),...a?{serial:a}:{}},...I(t,t===`ios`?h(e,`device_udid`)??n:n,{simulatorSetPath:d(e,`ios_simulator_device_set`),serial:a})}}const Oe=[`explicit-selector`,`existing-session`,`single-booted-local`,`single-bootable-local`,`single-app-installed-local`,`preferred-local`,`single-provider-device`],ke=[`session`,`local`,`provider`];function Ae(e){if(!f(e))return;let{reason:t,source:n,candidateCount:r,bootOccurred:i}=e;if(!(!Oe.includes(t)||!ke.includes(n)||typeof r!=`number`||!Number.isInteger(r)||r<0||typeof i!=`boolean`))return{reason:t,source:n,candidateCount:r,bootOccurred:i}}function je(e){if(f(e)&&typeof e.durationMs==`number`&&typeof e.measuredAt==`string`&&typeof e.method==`string`)return{durationMs:e.durationMs,measuredAt:e.measuredAt,method:e.method,appTarget:h(e,`appTarget`),appBundleId:h(e,`appBundleId`)}}function L(e){if(!f(e)||typeof e.success!=`boolean`||typeof e.exitCode!=`number`||typeof e.stdout!=`string`||typeof e.stderr!=`string`)return;let t=R(e.error);return{success:e.success,exitCode:e.exitCode,stdout:e.stdout,stderr:e.stderr,...t?{error:t}:{}}}const Me=[`hint`,`diagnosticId`,`logPath`,`supportedOn`];function R(e){if(!f(e)||typeof e.code!=`string`||typeof e.message!=`string`)return;let t={code:e.code,message:e.message};Object.assign(t,Ne(e.cause));for(let n of Me){let r=e[n];typeof r==`string`&&(t[n]=r)}return f(e.details)&&(t.details=e.details),typeof e.retriable==`boolean`&&(t.retriable=e.retriable),t}function Ne(e){let n=t(e);return n?{cause:n}:void 0}function Pe(e){let t=R(e.initialSnapshotError);return{...e.snapshot&&typeof e.snapshot==`object`?{snapshot:e.snapshot}:{},...t?{initialSnapshotError:t}:{}}}function Fe(e){return Array.isArray(e)?e:[]}function Ie(e){let t=b(e);return c({requestId:e.requestId,cwd:e.cwd,sessionExplicit:e.session!==void 0,debug:e.debug,includeCost:e.cost,responseLevel:e.responseLevel,lockPolicy:e.lockPolicy,lockPlatform:e.lockPlatform,...ne(t),sessionIsolation:e.sessionIsolation,installSource:e.installSource,retainMaterializedPaths:e.retainMaterializedPaths,materializedPathRetentionMs:e.materializedPathRetentionMs,materializationId:e.materializationId})}function z(e){return e??`default`}const B={...ie(),batch:ae(Le)};async function Le(e,t,r){let i=B[e];if(!i)throw Error(`Missing daemon writer for batch command: ${e}`);let a=E(e);if(!a)throw Error(`Missing command metadata for batch command: ${e}`);try{return await V(i,a,a.readInput(t))}catch(t){let i=t instanceof Error?t.message:String(t);throw new n(`INVALID_ARGS`,`Batch step ${r} ${e} input is invalid: ${i}`,void 0,t)}}async function Re(e,t){let n=B[e];if(!n)throw Error(`Missing daemon writer for command: ${e}`);return await V(n,E(e),t)}async function V(e,t,n){let r=await e(n);return{...r,...t?{metadataFlags:re(t,r.options)}:{}}}async function H(e,t={}){let n=e.meta?.requestId??se(),r=!!(e.meta?.debug||e.flags?.verbose),i=e.flags,{daemonAuthToken:a,...o}=i??{},s=i?{...e,flags:o}:e,c=ge(s,t.authToken??a),l=x(S(s.command),s),u=await T(`daemon_startup`,async()=>await de(c),{requestId:n,session:e.session}),d=u.info,f=await fe(s,d);Ke(s.command);let p=ze(s,f,d.token,n,r);return ce({level:`info`,phase:`daemon_request_prepare`,data:{requestId:n,command:s.command,session:s.session}}),await Ue(s,u,c,async()=>Ge(We(await T(`daemon_request`,async()=>await ue(d,p,c.transportPreference,c.paths,l,t.onProgress?{onProgress:t.onProgress}:void 0),{requestId:n,command:e.command}),c),s,c))}function ze(e,t,n,r,i){return{...e,positionals:t.positionals,flags:t.flags,token:n,meta:Be(e,t,r,i)}}function Be(e,t,n,r){let i=e.meta??{};return{...i,requestId:n,debug:r,...Ve(i,e.flags),...He(t)}}function Ve(e,t){return{includeCost:e.includeCost,cwd:e.cwd,sessionExplicit:e.sessionExplicit,tenantId:e.tenantId??t?.tenant,runId:e.runId??t?.runId,leaseId:e.leaseId??t?.leaseId,sessionIsolation:e.sessionIsolation??t?.sessionIsolation,lockPolicy:e.lockPolicy,lockPlatform:e.lockPlatform}}function He(e){return{...e.uploadedArtifactId?{uploadedArtifactId:e.uploadedArtifactId}:{},...e.clientArtifactPaths?{clientArtifactPaths:e.clientArtifactPaths}:{},...e.installSource?{installSource:e.installSource}:{}}}async function Ue(e,t,r,i){let a,o=!1,s;try{a=await i()}catch(e){o=!0,s=e}let c=await he(e,t,r,a);if(o)throw s;if(!c)throw new n(`COMMAND_FAILED`,`Daemon request produced no response after cleanup`);return c}function We(e,t){return e.ok||!t.ownedStateDir||!me(e)?e:pe(e,t.paths.baseDir)}function Ge(e,t,n){return!e.ok||!le(t,e)?e:_e(e,n.ownedStateDir?n.paths.baseDir:void 0)}function Ke(e){!qe(e)||process.stderr.isTTY!==!0||process.env.CI||process.stderr.write(e===C.reinstall?`Reinstalling...
2
2
  `:`Installing...
3
3
  `)}function qe(e){return e===C.install||e===C.reinstall||e===w.installSource}function U(e,t){return O.join(e,`metro-sessions`,`${ve(t)}.json`)}function W(e){let t=U(e.stateDir,e.session);k.mkdirSync(O.dirname(t),{recursive:!0}),k.writeFileSync(t,`${JSON.stringify(e.hints,null,2)}\n`,`utf8`)}function Je(e){let t=U(e.stateDir,e.session),n;try{n=k.readFileSync(t,`utf8`)}catch{return}let r;try{r=JSON.parse(n)}catch{return}if(!r||typeof r!=`object`||Array.isArray(r))return;let i=r,a={};return typeof i.metroHost==`string`&&i.metroHost&&(a.metroHost=i.metroHost),typeof i.metroPort==`number`&&Number.isInteger(i.metroPort)&&(a.metroPort=i.metroPort),typeof i.bundleUrl==`string`&&i.bundleUrl&&(a.bundleUrl=i.bundleUrl),Object.keys(a).length>0?a:void 0}function G(e){k.rmSync(U(e.stateDir,e.session),{force:!0})}function Ye(e){let t=async(t,n)=>await e(w.humanControl,t,n);return{allocate:async t=>q(await e(w.leaseAllocate,[],{...t,leaseId:void 0})),heartbeat:async t=>q(await e(w.leaseHeartbeat,[],t)),release:async t=>{let n=await e(w.leaseRelease,[],t);return{released:n.released===!0,provider:f(n.provider)?n.provider:void 0}},humanControl:{list:async e=>{let r=await t([`list`],e);if(!Array.isArray(r.holds))throw new n(`COMMAND_FAILED`,`Daemon did not return human-control holds.`);return r.holds.map(K)},put:async(e,n={},r)=>K((await t([`put`,e,JSON.stringify(n)],r)).hold),remove:async(e,n)=>(await t([`remove`,e],n)).released===!0}}}function K(e){if(!f(e)||!f(e.scope)||e.state!==`active`&&e.state!==`activating`||typeof e.createdAt!=`number`||typeof e.updatedAt!=`number`)throw new n(`COMMAND_FAILED`,`Daemon returned an invalid human-control hold.`);return{id:u(e,`id`),scope:{backend:u(e.scope,`backend`),leaseProvider:h(e.scope,`leaseProvider`),deviceKey:u(e.scope,`deviceKey`)},state:e.state,reason:h(e,`reason`),createdAt:e.createdAt,updatedAt:e.updatedAt,...typeof e.expiresAt==`number`?{expiresAt:e.expiresAt}:{}}}function q(e){let t=e.lease;if(!f(t))throw Error(`Invalid lease response from daemon`);return{leaseId:u(t,`leaseId`),tenantId:u(t,`tenantId`),runId:u(t,`runId`),backend:u(t,`backend`),leaseProvider:h(t,`leaseProvider`),clientId:h(t,`clientId`),deviceKey:h(t,`deviceKey`),createdAt:typeof t.createdAt==`number`?t.createdAt:void 0,heartbeatAt:typeof t.heartbeatAt==`number`?t.heartbeatAt:void 0,expiresAt:typeof t.expiresAt==`number`?t.expiresAt:void 0}}var Xe=e({createAgentDeviceClient:()=>J});function J(e={},t={}){let a=t.transport??H,o=t=>i(t.responseLevel??e.responseLevel),s=async(t,n=[],i={},o,s)=>{let c=Q(e,i),l={session:z(c.session),command:t,positionals:n,...s?{input:s}:{},flags:oe(c,o),runtime:c.runtime,meta:Ie(c)},u=await a(l,{authToken:c.daemonAuthToken});return u.ok||r(u.error),u.data??{}},c=async(e={})=>{let t=await s(w.sessionList,[],e);return(Array.isArray(t.sessions)?t.sessions:[]).map(Te)},l=async(e,t={})=>{let n=await Re(e,t);return await s(n.command,n.positionals,n.options,n.metadataFlags,n.input)},d=(t={})=>z(Q(e,t).session);return{command:{wait:async e=>await l(`wait`,e),alert:async(e={})=>await l(`alert`,e),appState:async(e={})=>await l(`appstate`,e),back:async(e={})=>await l(`back`,e),home:async(e={})=>await l(`home`,e),orientation:async e=>await l(`orientation`,e),appSwitcher:async(e={})=>await l(`app-switcher`,e),keyboard:async(e={})=>await l(`keyboard`,e),clipboard:async e=>await l(`clipboard`,e),tvRemote:async e=>await l(`tv-remote`,e),reactNative:async e=>await l(`react-native`,e),doctor:async(e={})=>await l(`doctor`,e),prepare:async e=>await l(`prepare`,e),viewport:async e=>await l(`viewport`,e)},devices:{list:async(e={})=>{let t=await l(`devices`,e);return(Array.isArray(t.devices)?t.devices:[]).map(N)},capabilities:async(e={})=>{let t=await l(`capabilities`,e),n=Array.isArray(t.availableCommands)?t.availableCommands.filter(e=>typeof e==`string`):[];return{device:N(t.device),availableCommands:n}},boot:async(e={})=>await l(`boot`,e),shutdown:async(e={})=>await l(`shutdown`,e)},sessions:{list:async(e={})=>await c(e),stateDir:async(t={})=>{let n=Q(e,t);return D(n.stateDir??process.env.AGENT_DEVICE_STATE_DIR).baseDir},close:async(t={})=>{let n=d(t);try{let e=await l(`close`,t);return{session:n,shutdown:L(e.shutdown),provider:Z(e.provider),savedScript:h(e,`savedScript`),identifiers:{session:n}}}finally{lt(e,t)}},saveScript:async(e={})=>{let t=await s(w.sessionSaveScript,e.path===void 0?[]:[e.path],e,{force:e.force}),r=t.actionCount;if(typeof r!=`number`||!Number.isInteger(r)||r<0)throw new n(`COMMAND_FAILED`,`Daemon returned an invalid saved-script action count.`);let i=u(t,`session`);return{session:i,savedScript:u(t,`savedScript`),actionCount:r,identifiers:{session:i}}},artifacts:async(e={})=>await l(`artifacts`,e)},apps:{install:async e=>M(await l(`install`,e),d(e)),reinstall:async e=>M(await l(`reinstall`,e),d(e)),installFromSource:async e=>Se(await l(`install-from-source`,e),d(e)),list:async(e={})=>{let t=await l(`apps`,e);return Array.isArray(t.apps)?t.apps.filter(e=>typeof e==`string`):[]},open:async t=>{let n=d(t),r=await l(`open`,t);ct({config:e,options:t,runtime:Q(e,t).runtime,sessionReused:r.sessionReused===!0});let i=De(r),a=h(r,`appBundleId`),o=a,s=Array.isArray(r.warnings)?r.warnings.filter(e=>typeof e==`string`):[];return{session:n,...s.length>0?{warnings:s}:{},sessionStateDir:h(r,`sessionStateDir`),runnerLogPath:h(r,`runnerLogPath`),requestLogPath:h(r,`requestLogPath`),eventLogPath:h(r,`eventLogPath`),appName:h(r,`appName`),appBundleId:a,appId:o,selection:Ae(r.selection),startup:je(r.startup),runtime:Ee(r.runtime),device:i,...Pe(r),identifiers:{session:n,deviceId:i?.id,deviceName:i?.name,udid:i?.ios?.udid,serial:i?.android?.serial,appId:o,appBundleId:a}}},close:async(e={})=>{let t=d(e),n=await l(`close`,e);return{session:t,closedApp:e.app,shutdown:L(n.shutdown),savedScript:h(n,`savedScript`),identifiers:{session:t}}},push:async e=>await l(`push`,e),triggerEvent:async e=>await l(`trigger-app-event`,e)},materializations:{release:async e=>Ce(await s(w.releaseMaterializedPaths,[],{...e,materializationId:e.materializationId}))},leases:Ye(s),metro:{prepare:async t=>{let n=await be({projectRoot:t.projectRoot??e.cwd,kind:t.kind,publicBaseUrl:t.publicBaseUrl,proxyBaseUrl:t.proxyBaseUrl,proxyBearerToken:t.bearerToken,bridgeScope:t.bridgeScope,launchUrl:t.launchUrl,companionProfileKey:t.companionProfileKey,companionConsumerKey:t.companionConsumerKey,metroPort:t.port,listenHost:t.listenHost,statusHost:t.statusHost,startupTimeoutMs:t.startupTimeoutMs,probeTimeoutMs:t.probeTimeoutMs,reuseExisting:t.reuseExisting,installDependenciesIfNeeded:t.installDependenciesIfNeeded,runtimeFilePath:t.runtimeFilePath,logPath:t.logPath});return at(e,n),n},reload:async(t={})=>await ye({metroHost:t.metroHost,metroPort:t.metroPort,bundleUrl:t.bundleUrl,runtime:e.runtime??ot(e),timeoutMs:t.timeoutMs})},capture:{snapshot:async(e={})=>{let t=d(e),n=await l(`snapshot`,e);return o(e)?n:rt(n,t)},screenshot:async(e={})=>{let t=d(e),n=await l(`screenshot`,e);return o(e)?n:xe(n,t)},diff:async e=>await l(`diff`,e)},interactions:{click:async e=>await l(`click`,e),press:async e=>await l(`press`,e),longPress:async e=>await l(`longpress`,e),hover:async e=>await l(`hover`,e),swipe:async e=>await l(`swipe`,e),pan:async e=>await l(`gesture`,Ze(e)),drag:async e=>await l(`gesture`,Qe(e)),fling:async e=>await l(`gesture`,Y(e)),swipeGesture:async e=>await l(`gesture`,$e(e)),focus:async e=>await l(`focus`,e),type:async e=>await l(`type`,e),fill:async e=>await l(`fill`,e),scroll:async e=>await l(`scroll`,e),pinch:async e=>await l(`gesture`,et(e)),rotateGesture:async e=>await l(`gesture`,tt(e)),transformGesture:async e=>await l(`gesture`,nt(e)),get:async e=>await l(`get`,e),is:async e=>await l(`is`,e),find:async e=>await l(`find`,e)},replay:{run:async e=>await l(`replay`,e),test:async e=>await l(`test`,e)},batch:{run:async e=>await l(`batch`,e)},observability:{perf:async e=>await l(`perf`,e),logs:async(e={})=>await l(`logs`,e),events:async(e={})=>await l(`events`,e),network:async(e={})=>await l(`network`,e),audio:async(e={})=>await l(`audio`,e)},debug:{symbols:async t=>{let{symbolicateCrashArtifact:n}=await import(`./debug-symbols-facade.js`);return n({cwd:t.cwd??e.cwd,...t})}},recording:{record:async e=>await l(`record`,e),trace:async e=>await l(`trace`,e)},settings:{update:async e=>await l(`settings`,e)}}}function Ze(e){let{x:t,y:n,dx:r,dy:i,...a}=e;return{...a,kind:`pan`,origin:{x:t,y:n},delta:{x:r,y:i}}}function Qe(e){return{...e,kind:`drag`}}function Y(e){let{x:t,y:n,...r}=e;return{...r,kind:`fling`,origin:{x:t,y:n}}}function $e(e){return{...e,kind:`swipe`}}function et(e){let{x:t,y:n,...r}=e;return X(t,n,`pinch`),{...r,kind:`pinch`,...t===void 0&&n===void 0?{}:{origin:{x:t,y:n}}}}function tt(e){let{x:t,y:n,...r}=e;return X(t,n,`rotate`),{...r,kind:`rotate`,...t===void 0&&n===void 0?{}:{origin:{x:t,y:n}}}}function nt(e){let{x:t,y:n,dx:r,dy:i,...a}=e;return{...a,kind:`transform`,origin:{x:t,y:n},delta:{x:r,y:i}}}function X(e,t,r){if(e===void 0!=(t===void 0))throw new n(`INVALID_ARGS`,`gesture ${r} center requires both x and y`)}function rt(e,t){let n=h(e,`appBundleId`);return{nodes:Fe(e.nodes),...typeof e.truncated==`boolean`?{truncated:e.truncated}:{},appName:h(e,`appName`),appBundleId:n,...it(e),identifiers:{session:t,appId:n,appBundleId:n}}}function it(e){let t=Z(e.visibility),n=Z(e.unchanged),r=_(e.snapshotDiagnostics);return{...t?{visibility:t}:{},...o(e),...n?{unchanged:n}:{},...r?{snapshotDiagnostics:r}:{},...typeof e.fallbackScreenshotPath==`string`?{fallbackScreenshotPath:e.fallbackScreenshotPath}:{},...typeof e.refsGeneration==`number`?{refsGeneration:e.refsGeneration}:{}}}function Z(e){return f(e)?e:void 0}function Q(e,t){return{...e,...t}}function $(e,t={}){let n=Q(e,t);return{stateDir:D(n.stateDir??process.env.AGENT_DEVICE_STATE_DIR).baseDir,session:z(n.session)}}function at(e,t){try{let n=new URL(t.statusUrl),r=Number.parseInt(n.port,10);if(!n.hostname||!Number.isInteger(r))return;let i=t.bridge?void 0:t.iosRuntime.bundleUrl??t.androidRuntime.bundleUrl;W({...$(e),hints:{metroHost:n.hostname,metroPort:r,bundleUrl:i}})}catch{}}function ot(e){try{return Je($(e))}catch{return}}function st(e){if(!e)return;let{metroHost:t,metroPort:n,bundleUrl:r}=e;if(t!==void 0||n!==void 0||r!==void 0)return{metroHost:t,metroPort:n,bundleUrl:r}}function ct(e){try{let t=$(e.config,e.options),n=st(e.runtime);if(n){W({...t,hints:n});return}e.sessionReused||G(t)}catch{}}function lt(e,t){try{G($(e,t))}catch{}}export{J as n,H as r,Xe as t};
@@ -1,2 +1,2 @@
1
- import{C as e}from"./sdk-contracts.js";import{a as t,i as n,r}from"./sdk-batch-runner.js";import{l as i,u as a}from"./sdk-device.js";import{n as o,t as s}from"./launch-console.js";import"./observability.js";import{r as c}from"./diagnostics.js";import{n as l}from"./exec.js";import"./diagnostics2.js";import"./command.js";import{i as u,n as d}from"./retry.js";import{D as f,o as p}from"./host-file.js";import{f as m,t as h}from"./config2.js";import{a as g,o as _}from"./tool-provider.js";import{t as v}from"./physical-device-control.js";import{t as y}from"./simctl.js";import{n as b,r as x}from"./apps-simctl.js";import{m as S}from"./runner-client.js";import{t as C}from"./simulator.js";import{a as w,l as T,u as E}from"./app-resolution.js";import D from"node:path";function O(t){if(!(t instanceof e)||t.code!==`COMMAND_FAILED`)return!1;let n=t.details??{};if(n.exitCode!==4)return!1;let r=String(n.stderr??``).toLowerCase();return r.includes(`fbsopenapplicationserviceerrordomain`)&&r.includes(`the request to open`)}async function k(e,t){let n=await _(y(e,[`get_app_container`,e.id,t]),{allowFailure:!0});if(n.exitCode!==0)return{installed:!1};let r=n.stdout.trim();if(!r)return{installed:!1};let i=await g(`plutil`,[`-extract`,`CFBundleExecutable`,`raw`,`-o`,`-`,`${r}/Info.plist`],{allowFailure:!0});if(i.exitCode!==0||!i.stdout.trim())return{installed:!0};let a=`${r}/${i.stdout.trim()}`,o=await g(`otool`,[`-l`,a],{allowFailure:!0});if(o.exitCode!==0)return{installed:!0};let s=o.stdout.toLowerCase();return{installed:!0,simulatorCompatible:s.includes(`iossimulator`)||s.includes(`platform 7`)}}function A(e){return e.installed?e.simulatorCompatible===!1?`ARCH_MISMATCH`:`PERSISTENT_LAUNCH_FAIL`:`APP_NOT_INSTALLED`}function j(e){switch(e){case`ARCH_MISMATCH`:return`The app binary was not built for the simulator platform. Rebuild with a simulator destination or use a physical device.`;case`APP_NOT_INSTALLED`:return`The app bundle is not installed on this simulator. Run install before open.`;case`PERSISTENT_LAUNCH_FAIL`:return`The simulator repeatedly refused to launch the app. Inspect crash logs in Console.app or ~/Library/Logs/DiagnosticReports/ and consider reinstalling the app.`;default:return`The simulator failed to launch the app. Retry with --debug and inspect diagnostics log for details.`}}const M=25e3;async function N(c,l,u){let d=u?.launchConsole?.trim(),f=u?.launchArgs;if(d&&(!i(c)||c.kind!==`simulator`))throw new e(`UNSUPPORTED_OPERATION`,o);if(a(c)){if(f&&f.length>0)throw new e(`UNSUPPORTED_OPERATION`,`--launch-args is not supported on macOS; launch arguments are currently iOS-only.`);await E(c,l,u);return}let p=u?.url?.trim();if(p){if(d)throw new e(`INVALID_ARGS`,s);if(!r(p))throw new e(`INVALID_ARGS`,`open <app> <url> requires a valid URL target`);if(c.kind===`simulator`){let e=!!f||n(p);if(u?.terminateRunningApp||e){let t=u?.appBundleId??await w(c,l);e?await z(c,t,{...f?{launchArgs:f}:{},...u?.terminateRunningApp?{terminateRunningApp:!0}:{}}):await R(c,t)}await P(c,p,void 0);return}let i=u?.appBundleId??await w(c,l),a=t(i,p);if(!a)throw new e(`INVALID_ARGS`,`Deep link open on iOS devices requires an active app bundle ID. Open the app first, then open the URL.`);await W(c,a,{payloadUrl:p,launchArgs:f,runnerOptions:u?.runnerOptions});return}let m=l.trim();if(r(m)){if(d)throw new e(`INVALID_ARGS`,s);if(c.kind===`simulator`){await P(c,m,f);return}let n=t(u?.appBundleId,m);if(!n)throw new e(`INVALID_ARGS`,`Deep link open on iOS devices requires an active app bundle ID. Open the app first, then open the URL.`);await W(c,n,{payloadUrl:m,launchArgs:f,runnerOptions:u?.runnerOptions});return}let h=u?.appBundleId??await w(c,l);if(c.kind===`simulator`){await z(c,h,{...d?{launchConsole:d}:{},...f?{launchArgs:f}:{},...u?.terminateRunningApp?{terminateRunningApp:!0}:{}});return}await W(c,h,{launchArgs:f,runnerOptions:u?.runnerOptions})}async function P(t,n,r){if(r&&r.length>0)throw new e(`INVALID_ARGS`,`--launch-args is not supported with iOS simulator URL opens (simctl openurl ignores launch args). Launch the app first with --launch-args, then issue the URL open in a separate call.`);await C(t),await b(t,[`openurl`,t.id,n])}async function F(e){a(e)||e.kind===`simulator`&&await C(e)}async function I(e,t,n){if(a(e)){await T(e,t);return}let r=await w(e,t);if(e.kind===`simulator`){await R(e,r);return}await L(r),await v(e).terminateApp(e,r,{runnerOptions:n,runRunnerCommand:S})}async function L(t){let{isIosSystemSurfaceHost:n,iosSystemSurfaceOpenRefusal:r}=await import(`./ios-system-surface.js`).then(e=>e.i);if(n(t))throw new e(`UNSUPPORTED_OPERATION`,r(t),{reason:`system-surface-host-not-openable`,appBundleId:t})}async function R(t,n){await L(n),await C(t);let r=x(t,[`terminate`,t.id,n]),i=await _(r,{allowFailure:!0,timeoutMs:m});if(i.exitCode!==0&&!i.stderr.toLowerCase().includes(`found nothing to terminate`))throw new e(`COMMAND_FAILED`,`xcrun exited with code ${i.exitCode}`,l(i,{cmd:`xcrun`,args:r}))}async function z(t,n,r){await L(n),await C(t);let i=0,a=d.fromTimeoutMs(h);try{await u(async({deadline:i})=>{if(i?.isExpired())throw new e(`COMMAND_FAILED`,`App launch deadline exceeded`,{timeoutMs:h});let a=x(t,B(t.id,n,r)),o=r?.launchConsole?await V(a,r.launchConsole):await _(a,{allowFailure:!0});if(o.exitCode!==0)throw new e(`COMMAND_FAILED`,`xcrun exited with code ${o.exitCode}`,l(o,{cmd:`xcrun`,args:a}))},{maxAttempts:10,baseDelayMs:1e3,maxDelayMs:5e3,jitter:.2,shouldRetry(e){return O(e)?(i+=1,i<3):!1}},{deadline:a})}catch(e){if(O(e)){let r=e,i=A(await k(t,n));r.details={...r.details,hint:j(i)}}throw e}}function B(e,t,n){let r=[`launch`];return n?.launchConsole&&r.push(`--console-pty`),n?.terminateRunningApp&&r.push(`--terminate-running-process`),r.push(e,t),n?.launchArgs&&n.launchArgs.length>0&&r.push(...n.launchArgs),r}async function V(t,n){await p(D.dirname(n));try{let e=await _(t,{allowFailure:!0,timeoutMs:M});return await H(n,e.stdout,e.stderr),e}catch(t){let r=(t instanceof e?t:void 0)?.details;if(r?.timeoutMs===M){let e=typeof r.stdout==`string`?r.stdout:``,t=typeof r.stderr==`string`?r.stderr:``;return await H(n,e,t),c({level:`warn`,phase:`ios_simulator_launch_console_capture_timeout`,data:{timeoutMs:M,logPath:n,stdoutBytes:Buffer.byteLength(e),stderrBytes:Buffer.byteLength(t)}}),{stdout:e,stderr:t,exitCode:0}}throw t}}async function H(e,t,n){await f(e,U(t,n))}function U(e,t){return!e||!t||e.endsWith(`
1
+ import{C as e}from"./sdk-contracts.js";import{a as t,i as n,r}from"./sdk-batch-runner.js";import{l as i,u as a}from"./sdk-device.js";import{n as o,t as s}from"./launch-console.js";import"./observability.js";import{r as c}from"./diagnostics.js";import{n as l}from"./exec.js";import"./diagnostics2.js";import"./command.js";import{i as u,n as d}from"./retry.js";import{D as f,o as p}from"./host-file.js";import{f as m,t as h}from"./config.js";import{a as g,o as _}from"./tool-provider.js";import{t as v}from"./physical-device-control.js";import{t as y}from"./simctl.js";import{n as b,r as x}from"./apps-simctl.js";import{m as S}from"./runner-client.js";import{t as C}from"./simulator.js";import{a as w,l as T,u as E}from"./app-resolution.js";import D from"node:path";function O(t){if(!(t instanceof e)||t.code!==`COMMAND_FAILED`)return!1;let n=t.details??{};if(n.exitCode!==4)return!1;let r=String(n.stderr??``).toLowerCase();return r.includes(`fbsopenapplicationserviceerrordomain`)&&r.includes(`the request to open`)}async function k(e,t){let n=await _(y(e,[`get_app_container`,e.id,t]),{allowFailure:!0});if(n.exitCode!==0)return{installed:!1};let r=n.stdout.trim();if(!r)return{installed:!1};let i=await g(`plutil`,[`-extract`,`CFBundleExecutable`,`raw`,`-o`,`-`,`${r}/Info.plist`],{allowFailure:!0});if(i.exitCode!==0||!i.stdout.trim())return{installed:!0};let a=`${r}/${i.stdout.trim()}`,o=await g(`otool`,[`-l`,a],{allowFailure:!0});if(o.exitCode!==0)return{installed:!0};let s=o.stdout.toLowerCase();return{installed:!0,simulatorCompatible:s.includes(`iossimulator`)||s.includes(`platform 7`)}}function A(e){return e.installed?e.simulatorCompatible===!1?`ARCH_MISMATCH`:`PERSISTENT_LAUNCH_FAIL`:`APP_NOT_INSTALLED`}function j(e){switch(e){case`ARCH_MISMATCH`:return`The app binary was not built for the simulator platform. Rebuild with a simulator destination or use a physical device.`;case`APP_NOT_INSTALLED`:return`The app bundle is not installed on this simulator. Run install before open.`;case`PERSISTENT_LAUNCH_FAIL`:return`The simulator repeatedly refused to launch the app. Inspect crash logs in Console.app or ~/Library/Logs/DiagnosticReports/ and consider reinstalling the app.`;default:return`The simulator failed to launch the app. Retry with --debug and inspect diagnostics log for details.`}}const M=25e3;async function N(c,l,u){let d=u?.launchConsole?.trim(),f=u?.launchArgs;if(d&&(!i(c)||c.kind!==`simulator`))throw new e(`UNSUPPORTED_OPERATION`,o);if(a(c)){if(f&&f.length>0)throw new e(`UNSUPPORTED_OPERATION`,`--launch-args is not supported on macOS; launch arguments are currently iOS-only.`);await E(c,l,u);return}let p=u?.url?.trim();if(p){if(d)throw new e(`INVALID_ARGS`,s);if(!r(p))throw new e(`INVALID_ARGS`,`open <app> <url> requires a valid URL target`);if(c.kind===`simulator`){let e=!!f||n(p);if(u?.terminateRunningApp||e){let t=u?.appBundleId??await w(c,l);e?await z(c,t,{...f?{launchArgs:f}:{},...u?.terminateRunningApp?{terminateRunningApp:!0}:{}}):await R(c,t)}await P(c,p,void 0);return}let i=u?.appBundleId??await w(c,l),a=t(i,p);if(!a)throw new e(`INVALID_ARGS`,`Deep link open on iOS devices requires an active app bundle ID. Open the app first, then open the URL.`);await W(c,a,{payloadUrl:p,launchArgs:f,runnerOptions:u?.runnerOptions});return}let m=l.trim();if(r(m)){if(d)throw new e(`INVALID_ARGS`,s);if(c.kind===`simulator`){await P(c,m,f);return}let n=t(u?.appBundleId,m);if(!n)throw new e(`INVALID_ARGS`,`Deep link open on iOS devices requires an active app bundle ID. Open the app first, then open the URL.`);await W(c,n,{payloadUrl:m,launchArgs:f,runnerOptions:u?.runnerOptions});return}let h=u?.appBundleId??await w(c,l);if(c.kind===`simulator`){await z(c,h,{...d?{launchConsole:d}:{},...f?{launchArgs:f}:{},...u?.terminateRunningApp?{terminateRunningApp:!0}:{}});return}await W(c,h,{launchArgs:f,runnerOptions:u?.runnerOptions})}async function P(t,n,r){if(r&&r.length>0)throw new e(`INVALID_ARGS`,`--launch-args is not supported with iOS simulator URL opens (simctl openurl ignores launch args). Launch the app first with --launch-args, then issue the URL open in a separate call.`);await C(t),await b(t,[`openurl`,t.id,n])}async function F(e){a(e)||e.kind===`simulator`&&await C(e)}async function I(e,t,n){if(a(e)){await T(e,t);return}let r=await w(e,t);if(e.kind===`simulator`){await R(e,r);return}await L(r),await v(e).terminateApp(e,r,{runnerOptions:n,runRunnerCommand:S})}async function L(t){let{isIosSystemSurfaceHost:n,iosSystemSurfaceOpenRefusal:r}=await import(`./ios-system-surface.js`).then(e=>e.i);if(n(t))throw new e(`UNSUPPORTED_OPERATION`,r(t),{reason:`system-surface-host-not-openable`,appBundleId:t})}async function R(t,n){await L(n),await C(t);let r=x(t,[`terminate`,t.id,n]),i=await _(r,{allowFailure:!0,timeoutMs:m});if(i.exitCode!==0&&!i.stderr.toLowerCase().includes(`found nothing to terminate`))throw new e(`COMMAND_FAILED`,`xcrun exited with code ${i.exitCode}`,l(i,{cmd:`xcrun`,args:r}))}async function z(t,n,r){await L(n),await C(t);let i=0,a=d.fromTimeoutMs(h);try{await u(async({deadline:i})=>{if(i?.isExpired())throw new e(`COMMAND_FAILED`,`App launch deadline exceeded`,{timeoutMs:h});let a=x(t,B(t.id,n,r)),o=r?.launchConsole?await V(a,r.launchConsole):await _(a,{allowFailure:!0});if(o.exitCode!==0)throw new e(`COMMAND_FAILED`,`xcrun exited with code ${o.exitCode}`,l(o,{cmd:`xcrun`,args:a}))},{maxAttempts:10,baseDelayMs:1e3,maxDelayMs:5e3,jitter:.2,shouldRetry(e){return O(e)?(i+=1,i<3):!1}},{deadline:a})}catch(e){if(O(e)){let r=e,i=A(await k(t,n));r.details={...r.details,hint:j(i)}}throw e}}function B(e,t,n){let r=[`launch`];return n?.launchConsole&&r.push(`--console-pty`),n?.terminateRunningApp&&r.push(`--terminate-running-process`),r.push(e,t),n?.launchArgs&&n.launchArgs.length>0&&r.push(...n.launchArgs),r}async function V(t,n){await p(D.dirname(n));try{let e=await _(t,{allowFailure:!0,timeoutMs:M});return await H(n,e.stdout,e.stderr),e}catch(t){let r=(t instanceof e?t:void 0)?.details;if(r?.timeoutMs===M){let e=typeof r.stdout==`string`?r.stdout:``,t=typeof r.stderr==`string`?r.stderr:``;return await H(n,e,t),c({level:`warn`,phase:`ios_simulator_launch_console_capture_timeout`,data:{timeoutMs:M,logPath:n,stdoutBytes:Buffer.byteLength(e),stderrBytes:Buffer.byteLength(t)}}),{stdout:e,stderr:t,exitCode:0}}throw t}}async function H(e,t,n){await f(e,U(t,n))}function U(e,t){return!e||!t||e.endsWith(`
2
2
  `)||e.endsWith(`\r`)?`${e}${t}`:`${e}\n${t}`}async function W(e,t,n){await L(t),await v(e).launchApp(e,t,{...n,runRunnerCommand:S})}export{N as n,F as r,I as t};
package/dist/src/auth.js CHANGED
@@ -1,2 +1,2 @@
1
- import{C as e}from"./sdk-contracts.js";import{n as t}from"./config.js";import{a as n,n as r,t as i}from"./auth-session.js";import{t as a}from"./shared.js";const o=async({positionals:o,flags:c})=>{let l=o[0]??`status`,u=t(c.stateDir).baseDir;if(l===`status`){let e=n({stateDir:u});return await a(c,e,()=>s(e)),!0}if(l===`login`){let e=await i({stateDir:u,flags:c,commandLabel:`agent-device auth login`}),t={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};return await a(c,t,()=>`Authenticated with cloud CLI session.`),!0}if(l===`logout`){let e=r({stateDir:u});return await a(c,{authenticated:!1,removed:e},()=>e?`Removed stored cloud CLI session.`:`No stored cloud CLI session.`),!0}throw new e(`INVALID_ARGS`,`auth accepts only: status, login, logout`)};function s(e){return e.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(`
1
+ import{C as e}from"./sdk-contracts.js";import{t}from"./daemon-resolution.js";import{a as n,n as r,t as i}from"./auth-session.js";import{t as a}from"./shared.js";const o=async({positionals:o,flags:c})=>{let l=o[0]??`status`,u=t(c.stateDir).baseDir;if(l===`status`){let e=n({stateDir:u});return await a(c,e,()=>s(e)),!0}if(l===`login`){let e=await i({stateDir:u,flags:c,commandLabel:`agent-device auth login`}),t={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};return await a(c,t,()=>`Authenticated with cloud CLI session.`),!0}if(l===`logout`){let e=r({stateDir:u});return await a(c,{authenticated:!1,removed:e},()=>e?`Removed stored cloud CLI session.`:`No stored cloud CLI session.`),!0}throw new e(`INVALID_ARGS`,`auth accepts only: status, login, logout`)};function s(e){return e.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(`
2
2
  `):`Not authenticated.`}export{o as authCommand};
@@ -1 +1 @@
1
- import{n as e}from"./sdk-contracts.js";import{a as t}from"./capture.js";import{r as n}from"./sdk-device.js";import{c as r}from"./sdk-remote-config.js";import{t as i}from"./session.js";import{c as a}from"./observability.js";const o=[`app`,`device`,`system`];function s(e){return o.some(t=>t===e)}function c(e){return e===`device`||e===`system`}const l=[{key:`count`,names:[`--count`],type:`int`,min:1,max:200,usageLabel:`--count <n>`,usageDescription:`Repeat count for press/swipe series`,projectConfig:!0,recorded:!0},{key:`pointerCount`,names:[`--pointer-count`],type:`int`,min:1,max:2,usageLabel:`--pointer-count <1|2>`,usageDescription:`Gesture pan: number of touch pointers (default 1)`,projectConfig:!0,recorded:!0},{key:`fps`,names:[`--fps`],type:`int`,min:1,max:120,usageLabel:`--fps <n>`,usageDescription:`Record: target frames per second (iOS physical device runner)`,projectConfig:!0,recorded:!0},{key:`quality`,names:[`--quality`],type:`string`,usageLabel:`--quality <medium|high>`,usageDescription:`Record: output quality preset; Android maps this to screenrecord bitrate, Apple targets use it for export/encoding. Legacy numeric values 5-7 map to medium; 8-10 map to high`,projectConfig:!0,recorded:!0},{key:`hideTouches`,names:[`--hide-touches`],type:`boolean`,usageLabel:`--hide-touches`,usageDescription:`Record: skip touch-overlay post-processing for faster raw benchmark videos`,projectConfig:!0,recorded:!0},{key:`recordingScope`,names:[`--scope`],type:`enum`,enumValues:o,usageLabel:`--scope <app|device|system>`,usageDescription:`Record: app requires an active app session; device/system records the whole screen`,projectConfig:!0,recorded:!1},{key:`intervalMs`,names:[`--interval-ms`],type:`int`,min:0,max:1e4,usageLabel:`--interval-ms <ms>`,usageDescription:`Delay between press iterations`,projectConfig:!0,recorded:!0},{key:`delayMs`,names:[`--delay-ms`],type:`int`,min:0,max:1e4,usageLabel:`--delay-ms <ms>`,usageDescription:`Delay between typed characters`,projectConfig:!0,recorded:!0},{key:`recordAs`,names:[`--record-as`],type:`string`,usageLabel:`--record-as <VAR>`,usageDescription:"Fill: send the live text but publish ${VAR} in an armed .ad recording",projectConfig:!0,recorded:!1},{key:`durationMs`,names:[`--duration-ms`],type:`int`,min:0,max:1e4,usageLabel:`--duration-ms <ms>`,usageDescription:`Scroll: pace the gesture over this duration when supported`,projectConfig:!0,recorded:!1},{key:`holdMs`,names:[`--hold-ms`],type:`int`,min:0,max:1e4,usageLabel:`--hold-ms <ms>`,usageDescription:`Press hold duration for each iteration`,projectConfig:!0,recorded:!0},{key:`jitterPx`,names:[`--jitter-px`],type:`int`,min:0,max:100,usageLabel:`--jitter-px <n>`,usageDescription:`Deterministic coordinate jitter radius for press`,projectConfig:!0,recorded:!0},{key:`pixels`,names:[`--pixels`],type:`int`,min:1,max:1e5,usageLabel:`--pixels <n>`,usageDescription:`Scroll: explicit gesture distance in pixels`,projectConfig:!0,recorded:!1},{key:`until`,names:[`--until`],type:`string`,usageLabel:`--until <selector>`,usageDescription:`Scroll: repeat passes until the selector is visible on screen`,projectConfig:!0,recorded:!1},{key:`doubleTap`,names:[`--double-tap`],type:`boolean`,usageLabel:`--double-tap`,usageDescription:`Use double-tap gesture per press iteration`,projectConfig:!0,recorded:!0},{key:`verify`,names:[`--verify`],type:`boolean`,usageLabel:`--verify`,usageDescription:`Capture cheap post-action evidence (AX digest, node counts, changedFromBefore) instead of a follow-up snapshot`,projectConfig:!0,recorded:!1},{key:`settle`,names:[`--settle`],type:`boolean`,usageLabel:`--settle`,usageDescription:`After the action, wait for the UI to go quiet and return the settled diff vs the pre-action tree in the same response (best-effort; never fails the action)`,projectConfig:!0,recorded:!1},{key:`settleQuietMs`,names:[`--settle-quiet`],type:`int`,min:0,usageLabel:`--settle-quiet <ms>`,usageDescription:`Settle: quiet window the UI must hold to count as settled (default 500ms)`,projectConfig:!0,recorded:!1},{key:`clickButton`,names:[`--button`],type:`enum`,enumValues:[`primary`,`secondary`,`middle`],usageLabel:`--button primary|secondary|middle`,usageDescription:`Click: choose mouse button (middle reserved for future macOS support)`,projectConfig:!0,recorded:!0},{key:`backMode`,names:[`--in-app`],type:`enum`,enumValues:[`in-app`,`system`],setValue:`in-app`,usageLabel:`--in-app`,usageDescription:`Back: use app-provided back UI when available`,projectConfig:!0,recorded:!1},{key:`backMode`,names:[`--system`],type:`enum`,enumValues:[`in-app`,`system`],setValue:`system`,usageLabel:`--system`,usageDescription:`Back: use system back input or gesture when available`,projectConfig:!0,recorded:!1},{key:`pauseMs`,names:[`--pause-ms`],type:`int`,min:0,max:1e4,usageLabel:`--pause-ms <ms>`,usageDescription:`Delay between swipe iterations`,projectConfig:!0,recorded:!0},{key:`pattern`,names:[`--pattern`],type:`enum`,enumValues:[`one-way`,`ping-pong`],usageLabel:`--pattern one-way|ping-pong`,usageDescription:`Swipe repeat pattern`,projectConfig:!0,recorded:!0},{key:`verbose`,names:[`--debug`,`--verbose`,`-v`],type:`boolean`,usageLabel:`--debug, --verbose, -v`,usageDescription:`Enable debug diagnostics; test --verbose prints per-test step timings without debug logs`,projectConfig:!0,recorded:!0},{key:`cost`,names:[`--cost`],type:`boolean`,usageLabel:`--cost`,usageDescription:`Include per-command wall-clock latency (cost.wallClockMs) in the response`,projectConfig:!0,recorded:!1},{key:`responseLevel`,names:[`--level`],type:`enum`,enumValues:e,usageLabel:`--level digest|default|full`,usageDescription:`Response detail level: digest (token-cheap), default (today), or full. Default keeps the wire shape unchanged.`,projectConfig:!0,recorded:!1},{key:`json`,names:[`--json`],type:`boolean`,usageLabel:`--json`,usageDescription:`JSON output`,projectConfig:!0,recorded:!1},{key:`help`,names:[`--help`,`-h`],type:`boolean`,usageLabel:`--help, -h`,usageDescription:`Print help and exit`,projectConfig:!1,recorded:!1},{key:`version`,names:[`--version`,`-V`],type:`boolean`,usageLabel:`--version, -V`,usageDescription:`Print version and exit`,projectConfig:!1,recorded:!1},{key:`snapshotDiff`,names:[`--diff`],type:`boolean`,usageLabel:`--diff`,usageDescription:`Snapshot: show structural diff against the previous session baseline`,projectConfig:!0,recorded:!1},{key:`saveScript`,names:[`--save-script`],type:`booleanOrString`,usageLabel:`--save-script [path]`,usageDescription:`Arm evidence capture on open, publish the armed recording on close; close --save-script alone (without an armed open) is rejected — start with open --save-script, or use session save-script mid-session. Optional custom output path.`,projectConfig:!1,recorded:!0},{key:`networkInclude`,names:[`--include`],type:`enum`,enumValues:[`summary`,`headers`,`body`,`all`],usageLabel:`--include summary|headers|body|all`,usageDescription:`Network: include headers, bodies, or both in output`,projectConfig:!0,recorded:!1},{key:`shutdown`,names:[`--shutdown`],type:`boolean`,usageLabel:`--shutdown`,usageDescription:`close: shutdown associated simulator/emulator after ending session`,projectConfig:!0,recorded:!1},{key:`relaunch`,names:[`--relaunch`],type:`boolean`,usageLabel:`--relaunch`,usageDescription:`open: terminate app process before launching it`,projectConfig:!0,recorded:!0},{key:`foreground`,names:[`--foreground`],type:`boolean`,usageLabel:`--foreground`,usageDescription:`open: keep normal app/device selection and return an initial snapshot; without an app, resolve the sole running app on the sole booted iOS simulator`,inputDescription:`Include an initial interactive snapshot in a fresh open response. With no app argument, discover the sole running app on the sole booted iOS simulator; ambiguous environments fail closed.`,projectConfig:!1,recorded:!1},{key:`restart`,names:[`--restart`],type:`boolean`,usageLabel:`--restart`,usageDescription:`logs clear: stop active stream, clear logs, then start streaming again`,projectConfig:!0,recorded:!1},{key:`retainPaths`,names:[`--retain-paths`],type:`boolean`,usageLabel:`--retain-paths`,usageDescription:`install-from-source: keep materialized artifact paths after install`,projectConfig:!0,recorded:!1},{key:`retentionMs`,names:[`--retention-ms`],type:`int`,min:1,usageLabel:`--retention-ms <ms>`,usageDescription:`install-from-source: retention TTL for materialized artifact paths`,projectConfig:!0,recorded:!1},{key:`noRecord`,names:[`--no-record`],type:`boolean`,usageLabel:`--no-record`,usageDescription:`Do not record this action`,projectConfig:!0,recorded:!0},{key:`record`,names:[`--record`],type:`boolean`,usageLabel:`--record`,usageHidden:!0,usageDescription:`Force-record this action even though its command is observation-only and would otherwise be excluded from a repair-armed heal by default (mutually exclusive with --no-record)`,projectConfig:!0,recorded:!0}],u=[{key:`config`,names:[`--config`],type:`string`,usageLabel:`--config <path>`,usageDescription:`Load CLI defaults from a specific config file (required for connection/provider defaults outside user config)`,projectConfig:!1,recorded:!1},{key:`remoteConfig`,names:[`--remote-config`],type:`string`,usageLabel:`--remote-config <path>`,usageDescription:`Load remote host + Metro workflow settings from a specific profile file`,projectConfig:!1,recorded:!1},{key:`stateDir`,names:[`--state-dir`],type:`string`,usageLabel:`--state-dir <path>`,usageDescription:`Daemon state directory (defaults to ~/.agent-device for packages, or a worktree-scoped dev dir from source)`,projectConfig:!1,recorded:!1},{key:`daemonBaseUrl`,names:[`--daemon-base-url`],type:`string`,usageLabel:`--daemon-base-url <url>`,usageDescription:`Explicit remote HTTP daemon base URL (skip local daemon discovery/startup)`,projectConfig:!1,recorded:!1},{key:`daemonAuthToken`,names:[`--daemon-auth-token`],type:`string`,usageLabel:`--daemon-auth-token <token>`,usageDescription:`Remote HTTP daemon or proxy auth token (sent as request token and bearer header)`,projectConfig:!1,recorded:!1},{key:`daemonTransport`,names:[`--daemon-transport`],type:`enum`,enumValues:[`auto`,`socket`,`http`],usageLabel:`--daemon-transport auto|socket|http`,usageDescription:`Daemon client transport preference`,projectConfig:!1,recorded:!1},{key:`daemonServerMode`,names:[`--daemon-server-mode`],type:`enum`,enumValues:[`socket`,`http`,`dual`],usageLabel:`--daemon-server-mode socket|http|dual`,usageDescription:`Daemon server mode used when spawning daemon`,projectConfig:!1,recorded:!1},{key:`proxyHost`,names:[`--host`],type:`string`,usageLabel:`--host <host>`,usageDescription:`Proxy: host interface to bind (default: 127.0.0.1)`,projectConfig:!1,recorded:!1},{key:`proxyPort`,names:[`--port`],type:`int`,min:1,max:65535,usageLabel:`--port <port>`,usageDescription:`Proxy: TCP port to bind (default: 0, choose a free port)`,projectConfig:!1,recorded:!1},{key:`tenant`,names:[`--tenant`],type:`string`,usageLabel:`--tenant <id>`,usageDescription:`Tenant scope identifier for isolated daemon sessions`,projectConfig:!1,recorded:!1},{key:`sessionIsolation`,names:[`--session-isolation`],type:`enum`,enumValues:[`none`,`tenant`],usageLabel:`--session-isolation none|tenant`,usageDescription:`Session isolation strategy (tenant prefixes session namespace)`,projectConfig:!1,recorded:!1},{key:`runId`,names:[`--run-id`],type:`string`,usageLabel:`--run-id <id>`,usageDescription:`Run identifier used for tenant lease admission checks`,projectConfig:!1,recorded:!1},{key:`leaseId`,names:[`--lease-id`],type:`string`,usageLabel:`--lease-id <id>`,usageDescription:`Lease identifier bound to tenant/run admission scope`,projectConfig:!1,recorded:!1},{key:`leaseBackend`,names:[`--lease-backend`],type:`enum`,enumValues:[`ios-simulator`,`ios-instance`,`android-instance`,`harmonyos-instance`],usageLabel:`--lease-backend ios-simulator|ios-instance|android-instance|harmonyos-instance`,usageDescription:`Lease backend for remote tenant connection admission`,projectConfig:!1,recorded:!1},{key:`provider`,names:[`--provider`],type:`string`,usageLabel:`--provider <name>`,usageDescription:`Cloud provider name for provider-scoped commands`,projectConfig:!1,recorded:!1},{key:`providerSessionId`,names:[`--provider-session`],type:`string`,usageLabel:`--provider-session <id>`,usageDescription:`Cloud provider session id or ARN`,projectConfig:!1,recorded:!1},{key:`providerApp`,names:[`--provider-app`],type:`string`,usageLabel:`--provider-app <ref-or-path>`,usageDescription:`Cloud provider app reference or local app path used when creating hosted WebDriver sessions`,projectConfig:!1,recorded:!1},{key:`providerOsVersion`,names:[`--provider-os-version`,`--os-version`],type:`string`,usageLabel:`--provider-os-version <version>`,usageDescription:`Hosted cloud provider OS version, for example 17 or 14.0`,projectConfig:!1,recorded:!1},{key:`providerProject`,names:[`--provider-project`],type:`string`,usageLabel:`--provider-project <name>`,usageDescription:`Hosted cloud provider project label`,projectConfig:!1,recorded:!1},{key:`providerBuild`,names:[`--provider-build`],type:`string`,usageLabel:`--provider-build <name>`,usageDescription:`Hosted cloud provider build label`,projectConfig:!1,recorded:!1},{key:`providerSessionName`,names:[`--provider-session-name`],type:`string`,usageLabel:`--provider-session-name <name>`,usageDescription:`Hosted cloud provider session label`,projectConfig:!1,recorded:!1},{key:`providerDeviceOrientation`,names:[`--provider-device-orientation`,`--device-orientation`],type:`enum`,enumValues:r,usageLabel:`--provider-device-orientation portrait|landscape`,usageDescription:`Screen orientation a hosted cloud provider session starts in. Set this rather than rotating after launch: a session that boots landscape renders login webviews landscape`,projectConfig:!1,recorded:!1},{key:`providerGeoLocation`,names:[`--provider-geo-location`,`--geo-location`],type:`string`,usageLabel:`--provider-geo-location <country>`,usageDescription:`Hosted cloud provider IP geolocation country code, for example US`,projectConfig:!1,recorded:!1},{key:`providerTimezone`,names:[`--provider-timezone`,`--timezone`],type:`string`,usageLabel:`--provider-timezone <zone>`,usageDescription:`Hosted cloud provider device time zone, for example New_York`,projectConfig:!1,recorded:!1},{key:`providerLanguage`,names:[`--provider-language`,`--language`],type:`string`,usageLabel:`--provider-language <language>`,usageDescription:`Hosted cloud provider app language, for example Fr`,projectConfig:!1,recorded:!1},{key:`providerLocale`,names:[`--provider-locale`,`--locale`],type:`string`,usageLabel:`--provider-locale <locale>`,usageDescription:`Hosted cloud provider device locale, for example Fr`,projectConfig:!1,recorded:!1},{key:`providerNetworkProfile`,names:[`--provider-network-profile`,`--network-profile`],type:`string`,usageLabel:`--provider-network-profile <profile>`,usageDescription:`Hosted cloud provider named network condition profile, for example 4g-lte-advanced-good. Mutually exclusive with --provider-custom-network`,projectConfig:!1,recorded:!1},{key:`providerCustomNetwork`,names:[`--provider-custom-network`,`--custom-network`],type:`string`,usageLabel:`--provider-custom-network <shape>`,usageDescription:`Hosted cloud provider custom network shape. Mutually exclusive with --provider-network-profile`,projectConfig:!1,recorded:!1},{key:`providerNoResignApp`,names:[`--provider-no-resign-app`],type:`boolean`,usageLabel:`--provider-no-resign-app`,usageDescription:`iOS only: keep an Enterprise-signed app as uploaded instead of letting the provider re-sign it, which strips entitlements such as push notifications`,projectConfig:!1,recorded:!1},{key:`awsProjectArn`,names:[`--aws-project-arn`],type:`string`,usageLabel:`--aws-project-arn <arn>`,usageDescription:`AWS Device Farm project ARN for hosted WebDriver sessions`,projectConfig:!1,recorded:!1},{key:`awsDeviceArn`,names:[`--aws-device-arn`],type:`string`,usageLabel:`--aws-device-arn <arn>`,usageDescription:`AWS Device Farm device ARN for hosted WebDriver sessions`,projectConfig:!1,recorded:!1},{key:`awsAppArn`,names:[`--aws-app-arn`],type:`string`,usageLabel:`--aws-app-arn <arn>`,usageDescription:`AWS Device Farm app ARN attached to hosted remote access sessions`,projectConfig:!1,recorded:!1},{key:`awsRegion`,names:[`--aws-region`],type:`string`,usageLabel:`--aws-region <region>`,usageDescription:`AWS region for Device Farm API calls`,projectConfig:!1,recorded:!1},{key:`awsInteractionMode`,names:[`--aws-interaction-mode`],type:`enum`,enumValues:[`INTERACTIVE`,`NO_VIDEO`,`VIDEO_ONLY`],usageLabel:`--aws-interaction-mode INTERACTIVE|NO_VIDEO|VIDEO_ONLY`,usageDescription:`AWS Device Farm remote access interaction mode`,projectConfig:!1,recorded:!1},{key:`force`,names:[`--force`,`--overwrite`],type:`boolean`,usageLabel:`--force, --overwrite`,usageDescription:`Force replacement of existing state (connect: replace an active connection; --save-script: overwrite an existing target instead of refusing)`,projectConfig:!0,recorded:!0},{key:`clean`,names:[`--clean`],type:`boolean`,usageLabel:`--clean`,usageDescription:`Daemon stop: remove retained runner processes and leases after stopping`,projectConfig:!0,recorded:!1},{key:`noLogin`,names:[`--no-login`],type:`boolean`,usageLabel:`--no-login`,usageDescription:`Connect: fail instead of starting implicit cloud login`,projectConfig:!0,recorded:!1},{key:`sessionLock`,names:[`--session-lock`],type:`enum`,enumValues:[`reject`,`strip`],usageLabel:`--session-lock reject|strip`,usageDescription:`Lock bound-session device routing for this CLI invocation and nested batch steps; strip drops conflicting platform/scope selectors only, and a selector naming a different device always fails`,projectConfig:!0,recorded:!1}],d=[{key:`platform`,names:[`--platform`],type:`enum`,enumValues:n,usageLabel:`--platform ${n.join(`|`)}`,usageDescription:"Platform to target (`apple` aliases the Apple automation backend)",projectConfig:!0,recorded:!0},{key:`target`,names:[`--target`],type:`enum`,enumValues:[`mobile`,`tv`,`desktop`],usageLabel:`--target mobile|tv|desktop`,usageDescription:`Device target class to match`,projectConfig:!0,recorded:!1},{key:`device`,names:[`--device`],type:`string`,usageLabel:`--device <name>`,usageDescription:`Device name to target (a UDID belongs in --udid, a serial in --serial)`,projectConfig:!0,recorded:!0},{key:`udid`,names:[`--udid`],type:`string`,usageLabel:`--udid <udid>`,usageDescription:`Apple device or simulator UDID; the only selector that pins one device when several share a --device name`,projectConfig:!0,recorded:!0},{key:`serial`,names:[`--serial`],type:`string`,usageLabel:`--serial <serial>`,usageDescription:`Android, HarmonyOS, or Vega VVD serial`,projectConfig:!0,recorded:!0},{key:`stale`,names:[`--stale`],type:`boolean`,usageLabel:`--stale`,usageDescription:`Device status: show only claims with a provably stale owner`,projectConfig:!0,recorded:!1},{key:`surface`,names:[`--surface`],type:`enum`,enumValues:i,usageLabel:`--surface app|frontmost-app|desktop|menubar`,usageDescription:`macOS session surface for open (defaults to app)`,projectConfig:!0,recorded:!1},{key:`headless`,names:[`--headless`],type:`boolean`,usageLabel:`--headless`,usageDescription:`Boot: launch Android emulator without a GUI window`,projectConfig:!0,recorded:!1},{key:`targetApp`,names:[`--app`,`--target-app`],type:`string`,usageLabel:`--app <id-or-name>`,usageDescription:`Doctor: verify an installed target app without opening a session`,projectConfig:!1,recorded:!1},{key:`metroHost`,names:[`--metro-host`],type:`string`,usageLabel:`--metro-host <host>`,usageDescription:`Session-scoped Metro/debug host hint`,projectConfig:!1,recorded:!0},{key:`metroPort`,names:[`--metro-port`],type:`int`,min:1,max:65535,usageLabel:`--metro-port <port>`,usageDescription:`Session-scoped Metro/debug port hint; on an emulator/simulator the host defaults to the loopback alias, physical devices still need --metro-host`,projectConfig:!1,recorded:!0},{key:`metroProjectRoot`,names:[`--project-root`],type:`string`,usageLabel:`--project-root <path>`,usageDescription:`metro prepare: React Native project root (default: cwd)`,projectConfig:!1,recorded:!1},{key:`kind`,names:[`--kind`],type:`enum`,enumValues:[`auto`,`react-native`,`expo`,`repack`,...a],usageLabel:`--kind <kind>`,usageDescription:`Kind selector for commands that support it, such as metro prepare or perf artifact collectors`,projectConfig:!0,recorded:!1},{key:`perfTemplate`,names:[`--template`],type:`string`,usageLabel:`--template <name>`,usageDescription:`Perf xctrace template name, for example Time Profiler`,projectConfig:!0,recorded:!1},{key:`metroKind`,names:[`--metro-kind`],type:`enum`,enumValues:[`auto`,`react-native`,`expo`,`repack`],usageLabel:`--metro-kind auto|react-native|expo|repack`,usageDescription:`metro prepare: detect or force the React Native dev-server launcher kind`,projectConfig:!1,recorded:!1},{key:`metroPublicBaseUrl`,names:[`--public-base-url`],type:`string`,usageLabel:`--public-base-url <url>`,usageDescription:`metro prepare: public base URL used for direct dev-server bundle hints`,projectConfig:!1,recorded:!1},{key:`metroProxyBaseUrl`,names:[`--proxy-base-url`],type:`string`,usageLabel:`--proxy-base-url <url>`,usageDescription:`metro prepare: optional bridge origin for remote dev-server access`,projectConfig:!1,recorded:!1},{key:`metroBearerToken`,names:[`--bearer-token`],type:`string`,usageLabel:`--bearer-token <token>`,usageDescription:`metro prepare: host bridge bearer token (or AGENT_DEVICE_METRO_BEARER_TOKEN; falls back to AGENT_DEVICE_DAEMON_AUTH_TOKEN)`,projectConfig:!1,recorded:!1},{key:`metroPreparePort`,names:[`--port`],type:`int`,min:1,max:65535,usageLabel:`--port <port>`,usageDescription:`metro prepare: local dev-server port (default: 8081)`,projectConfig:!1,recorded:!1},{key:`metroListenHost`,names:[`--listen-host`],type:`string`,usageLabel:`--listen-host <host>`,usageDescription:`metro prepare: host dev server listens on (default: 0.0.0.0)`,projectConfig:!1,recorded:!1},{key:`metroStatusHost`,names:[`--status-host`],type:`string`,usageLabel:`--status-host <host>`,usageDescription:`metro prepare: host used for local dev-server /status polling (default: 127.0.0.1)`,projectConfig:!1,recorded:!1},{key:`metroStartupTimeoutMs`,names:[`--startup-timeout-ms`],type:`int`,min:1,usageLabel:`--startup-timeout-ms <ms>`,usageDescription:`metro prepare: timeout while waiting for the dev server to become ready`,projectConfig:!1,recorded:!1},{key:`metroProbeTimeoutMs`,names:[`--probe-timeout-ms`],type:`int`,min:1,usageLabel:`--probe-timeout-ms <ms>`,usageDescription:`metro prepare: timeout for /status and proxy bridge calls`,projectConfig:!1,recorded:!1},{key:`metroRuntimeFile`,names:[`--runtime-file`],type:`string`,usageLabel:`--runtime-file <path>`,usageDescription:`metro prepare: optional file path to persist the JSON result`,projectConfig:!1,recorded:!1},{key:`metroNoReuseExisting`,names:[`--no-reuse-existing`],type:`boolean`,usageLabel:`--no-reuse-existing`,usageDescription:`metro prepare: always start a fresh Metro process`,projectConfig:!1,recorded:!1},{key:`metroNoInstallDeps`,names:[`--no-install-deps`],type:`boolean`,usageLabel:`--no-install-deps`,usageDescription:`metro prepare: skip package-manager install when node_modules is missing`,projectConfig:!1,recorded:!1},{key:`bundleUrl`,names:[`--bundle-url`],type:`string`,usageLabel:`--bundle-url <url>`,usageDescription:`Session-scoped bundle URL hint`,projectConfig:!1,recorded:!0},{key:`launchUrl`,names:[`--launch-url`],type:`string`,usageLabel:`--launch-url <url>`,usageDescription:`Session-scoped deep link / launch URL hint`,projectConfig:!0,recorded:!0},{key:`iosSimulatorDeviceSet`,names:[`--ios-simulator-device-set`],type:`string`,usageLabel:`--ios-simulator-device-set <path>`,usageDescription:`Scope iOS simulator discovery/commands to this simulator device set`,projectConfig:!1,recorded:!1},{key:`iosXctestrunFile`,names:[`--ios-xctestrun-file`],type:`string`,usageLabel:`--ios-xctestrun-file <path>`,usageDescription:`Use an externally built iOS XCTest runner .xctestrun artifact`,projectConfig:!1,recorded:!1},{key:`iosXctestDerivedDataPath`,names:[`--ios-xctest-derived-data-path`],type:`string`,usageLabel:`--ios-xctest-derived-data-path <path>`,usageDescription:`Derived data path for external iOS XCTest runner execution`,projectConfig:!1,recorded:!1},{key:`iosXctestEnvDir`,names:[`--ios-xctest-env-dir`],type:`string`,usageLabel:`--ios-xctest-env-dir <path>`,usageDescription:`Writable directory for per-session iOS XCTest runner env overlays`,projectConfig:!1,recorded:!1},{key:`deviceHub`,names:[`--device-hub`],type:`boolean`,usageLabel:`--device-hub`,usageDescription:`open: use Xcode Device Hub when surfacing Apple simulators`,projectConfig:!0,recorded:!1},{key:`testIme`,names:[`--test-ime`],type:`boolean`,usageLabel:`--test-ime`,usageDescription:`open: activate the headless Android test IME for deterministic Unicode text entry (default on for emulators; opt-in on real devices)`,projectConfig:!0,recorded:!1},{key:`testIme`,names:[`--no-test-ime`],type:`boolean`,setValue:!1,usageLabel:`--no-test-ime`,usageDescription:`open: keep the real Android keyboard even on emulators (opt out of the headless test IME)`,projectConfig:!0,recorded:!1},{key:`androidDeviceAllowlist`,names:[`--android-device-allowlist`],type:`string`,usageLabel:`--android-device-allowlist <serials>`,usageDescription:`Comma/space separated Android serial allowlist for discovery/selection`,projectConfig:!1,recorded:!1},{key:`remote`,names:[`--remote`],type:`boolean`,usageLabel:`--remote`,usageDescription:`Doctor: check remote connection setup instead of local device inventory`,projectConfig:!0,recorded:!1},{key:`activity`,names:[`--activity`],type:`string`,usageLabel:`--activity <component>`,usageDescription:`Android app launch activity (package/Activity); not for URL opens`,projectConfig:!0,recorded:!1},{key:`launchConsole`,names:[`--launch-console`],type:`string`,usageLabel:`--launch-console <path>`,usageDescription:`open: capture the initial iOS simulator launch console window to a file`,projectConfig:!1,recorded:!1},{key:`launchArgs`,names:[`--launch-args`],type:`string`,multiple:!0,usageLabel:`--launch-args <arg>`,usageDescription:`open: repeatable launch argument forwarded verbatim to the platform launch command (iOS app process args; Android adb shell am start args). Linux and macOS reject the flag.`,projectConfig:!0,recorded:!1},{key:`header`,names:[`--header`],type:`string`,multiple:!0,usageLabel:`--header <name:value>`,usageDescription:`install-from-source: repeatable HTTP header for URL downloads`,projectConfig:!1,recorded:!1},{key:`githubActionsArtifact`,names:[`--github-actions-artifact`],type:`string`,usageLabel:`--github-actions-artifact <owner/repo:artifact>`,usageDescription:`install-from-source: GitHub Actions artifact resolved by a remote daemon`,projectConfig:!1,recorded:!1},{key:`installSource`,names:[],type:`string`,projectConfig:!1,recorded:!1},{key:`session`,names:[`--session`],type:`string`,usageLabel:`--session <name>`,usageDescription:`Named session`,projectConfig:!0,recorded:!1}],f=[{key:`replayUpdate`,names:[`--update`,`-u`],type:`boolean`,usageLabel:`--update, -u`,usageDescription:`Replay: retired as a rewrite (ADR 0012) — never edits the .ad file; every divergence already carries ranked selector suggestions, --update or not`,projectConfig:!0,recorded:!1},{key:`replayFrom`,names:[`--from`],type:`int`,min:1,usageLabel:`--from <n>`,usageDescription:`Replay: resume at 1-based plan step n, skipping 1..n-1 without executing them (requires --plan-digest; see a divergence report's resume field). replay only, not test`,projectConfig:!0,recorded:!1},{key:`replayPlanDigest`,names:[`--plan-digest`],type:`string`,usageLabel:`--plan-digest <sha256>`,usageDescription:`Replay: the plan digest a --from resume must match (from a prior divergence report); mismatch, edits, or include/platform-expansion changes fail INVALID_ARGS before any action`,projectConfig:!0,recorded:!1},{key:`replayKeepSession`,names:[`--keep-session`],type:`boolean`,usageLabel:`--keep-session`,usageDescription:`Replay: leave the session active by suppressing exactly an authored terminal close in a native .ad script; replay only, not test or Maestro YAML`,projectConfig:!0,recorded:!1},{key:`replayMaestro`,names:[`--maestro`],type:`boolean`,usageLabel:`--maestro`,usageDescription:`Replay: treat input as a supported Maestro YAML subset; unsupported syntax fails loudly. See agent-device help maestro for commands and boundaries`,projectConfig:!0,recorded:!1},{key:`replayEnv`,names:[`-e`,`--env`],type:`string`,multiple:!0,usageLabel:`-e KEY=VALUE, --env KEY=VALUE`,usageDescription:"Replay/Test: inject or override a ${KEY} variable for the script (repeatable)",projectConfig:!1,recorded:!1},{key:`failFast`,names:[`--fail-fast`],type:`boolean`,usageLabel:`--fail-fast`,usageDescription:`Test: stop the suite after the first failing script; with sharding, each shard stops independently`,projectConfig:!0,recorded:!1},{key:`timeoutMs`,names:[`--timeout`],type:`int`,min:1,usageLabel:`--timeout <ms>`,usageDescription:`Open/Prepare: startup budget covering the Simulator boot (and runner preparation for prepare). Replay/Snapshot/Test: maximum wall-clock time for the command or attempt. With --settle: the settle-wait deadline (default 10s)`,projectConfig:!0,recorded:!1},{key:`retries`,names:[`--retries`],type:`int`,min:0,max:3,usageLabel:`--retries <n>`,usageDescription:`Test: retry each failed script up to n additional times`,projectConfig:!0,recorded:!1},{key:`recordVideo`,names:[`--record-video`],type:`boolean`,usageLabel:`--record-video`,usageDescription:`Test: record each replay attempt to recording.mp4 in its attempt artifacts`,projectConfig:!0,recorded:!1},{key:`artifactsDir`,names:[`--artifacts-dir`],type:`string`,usageLabel:`--artifacts-dir <path>`,usageDescription:`Test: root directory for suite artifacts`,projectConfig:!1,recorded:!1},{key:`reporter`,names:[`--reporter`],type:`string`,multiple:!0,usageLabel:`--reporter <name-or-path>`,usageDescription:`Test: add a replay suite reporter; use default, junit:<path>, or a custom reporter path (repeatable)`,projectConfig:!1,recorded:!1},{key:`reportJunit`,names:[`--report-junit`],type:`string`,usageLabel:`--report-junit <path>`,usageDescription:`Test: compatibility alias for --reporter junit:<path>`,projectConfig:!1,recorded:!1},{key:`shardAll`,names:[`--shard-all`],type:`int`,min:1,usageLabel:`--shard-all <n>`,usageDescription:`Test: run the full suite on each of n devices; combine with --device id1,id2 for explicit connected devices; AD_SHARD_INDEX is zero-based`,projectConfig:!0,recorded:!1},{key:`shardSplit`,names:[`--shard-split`],type:`int`,min:1,usageLabel:`--shard-split <n>`,usageDescription:`Test: split runnable suite entries across n devices; AD_SHARD_INDEX is zero-based`,projectConfig:!0,recorded:!1},{key:`steps`,names:[`--steps`],type:`string`,usageLabel:`--steps <json>`,usageDescription:`Batch: JSON array of {"command","input"} steps`,projectConfig:!1,recorded:!1},{key:`stepsFile`,names:[`--steps-file`],type:`string`,usageLabel:`--steps-file <path>`,usageDescription:`Batch: read steps JSON from file`,projectConfig:!1,recorded:!1},{key:`batchOnError`,names:[`--on-error`],type:`enum`,enumValues:[`stop`],usageLabel:`--on-error stop`,usageDescription:`Batch: stop when a step fails`,projectConfig:!0,recorded:!1},{key:`batchMaxSteps`,names:[`--max-steps`],type:`int`,min:1,max:1e3,usageLabel:`--max-steps <n>`,usageDescription:`Batch: maximum number of allowed steps`,projectConfig:!0,recorded:!1},{key:`appsFilter`,names:[`--all`],type:`enum`,enumValues:[`user-installed`,`all`],setValue:`all`,usageLabel:`--all`,usageDescription:`Apps: include system/OEM apps`,projectConfig:!0,recorded:!1},{key:`snapshotInteractiveOnly`,names:[`-i`],type:`boolean`,usageLabel:`-i`,usageDescription:`Snapshot: interactive elements only`,projectConfig:!0,recorded:!0},{key:`snapshotDepth`,names:[`--depth`,`-d`],type:`int`,min:0,usageLabel:`--depth, -d <depth>`,usageDescription:`Snapshot: limit snapshot depth`,projectConfig:!0,recorded:!0},{key:`snapshotScope`,names:[`--scope`,`-s`],type:`string`,usageLabel:`--scope, -s <scope>`,usageDescription:`Snapshot: scope snapshot to label/identifier`,projectConfig:!0,recorded:!0},{key:`snapshotRaw`,names:[`--raw`],type:`boolean`,usageLabel:`--raw`,usageDescription:`Snapshot: raw node output`,projectConfig:!0,recorded:!0},{key:`snapshotCustomActions`,names:[`--actions`],type:`boolean`,usageLabel:`--actions`,usageDescription:`Snapshot: name the affordances merged inside an element (iOS sim); not directly invokable — reach them via the detail screen, labeled children, or coordinates`,inputDescription:`Name the affordances an element merged away (iOS UIAccessibilityCustomAction, React Native accessibilityActions) — a card whose reply/options controls are not separate elements still lists them here. The names are for PLANNING, not invocation: there is no API to trigger them, so reach the affordance through the element detail screen, through the same control exposed as a labeled element elsewhere, or by coordinates from its rect. iOS simulator only; costs one accessibility round trip per merged element.`,projectConfig:!0,recorded:!0},{key:`snapshotForceFull`,names:[`--force-full`],type:`boolean`,usageLabel:`--force-full`,usageDescription:`Snapshot: re-emit the full tree even when unchanged`,projectConfig:!0,recorded:!1},{key:`findFirst`,names:[`--first`],type:`boolean`,usageLabel:`--first`,usageDescription:`Find: pick the first match when ambiguous`,projectConfig:!0,recorded:!1},{key:`findLast`,names:[`--last`],type:`boolean`,usageLabel:`--last`,usageDescription:`Find: pick the last match when ambiguous`,projectConfig:!0,recorded:!1},{key:`out`,names:[`--out`],type:`string`,usageLabel:`--out <path>`,usageDescription:`Output path`,projectConfig:!1,recorded:!0},{key:`artifact`,names:[`--artifact`],type:`string`,usageLabel:`--artifact <path>`,usageDescription:`Debug symbols: Apple crash artifact path (.ips, .crash, or .log)`,projectConfig:!1,recorded:!1},{key:`dsym`,names:[`--dsym`],type:`string`,usageLabel:`--dsym <path>`,usageDescription:`Debug symbols: matching .dSYM bundle path`,projectConfig:!1,recorded:!1},{key:`searchPath`,names:[`--search-path`],type:`string`,usageLabel:`--search-path <dir>`,usageDescription:`Debug symbols: directory to scan for matching .dSYM bundles`,projectConfig:!1,recorded:!1},{key:`overlayRefs`,names:[`--overlay-refs`],type:`boolean`,usageLabel:`--overlay-refs`,usageDescription:`Screenshot: draw current snapshot refs and target rectangles onto the saved PNG; diff screenshot: also write a separate current-screen overlay guide`,projectConfig:!0,recorded:!1},...t,{key:`baseline`,names:[`--baseline`,`-b`],type:`string`,usageLabel:`--baseline, -b <path>`,usageDescription:`Diff screenshot: path to baseline image file`,projectConfig:!0,recorded:!1},{key:`threshold`,names:[`--threshold`],type:`string`,usageLabel:`--threshold <0-1>`,usageDescription:`Diff screenshot: color distance threshold (default 0.1)`,projectConfig:!0,recorded:!1}],p=[...u,...d,...l,...f],m=new Map;for(let e of p)for(let t of e.names)m.set(t,e);function h(e){return m.get(e)}function g(){return p}function _(e){return p.filter(t=>t.key===e)}function v(){return new Set(p.filter(e=>e.projectConfig).map(e=>e.key))}function y(){return new Set(p.filter(e=>e.recorded).map(e=>e.key))}const b=[`in-app`,`system`];export{v as a,s as c,_ as i,c as l,h as n,y as o,g as r,o as s,b as t};
1
+ import{n as e}from"./sdk-contracts.js";import{a as t}from"./capture.js";import{r as n}from"./sdk-device.js";import{c as r}from"./sdk-remote-config.js";import{t as i}from"./session.js";import{c as a}from"./observability.js";const o=[`app`,`device`,`system`];function s(e){return o.some(t=>t===e)}function c(e){return e===`device`||e===`system`}const l=[{key:`count`,names:[`--count`],type:`int`,min:1,max:200,usageLabel:`--count <n>`,usageDescription:`Repeat count for press/swipe series`,projectConfig:!0,recorded:!0},{key:`pointerCount`,names:[`--pointer-count`],type:`int`,min:1,max:2,usageLabel:`--pointer-count <1|2>`,usageDescription:`Gesture pan: number of touch pointers (default 1)`,projectConfig:!0,recorded:!0},{key:`fps`,names:[`--fps`],type:`int`,min:1,max:120,usageLabel:`--fps <n>`,usageDescription:`Record: target frames per second (iOS physical device runner)`,projectConfig:!0,recorded:!0},{key:`quality`,names:[`--quality`],type:`string`,usageLabel:`--quality <medium|high>`,usageDescription:`Record: output quality preset; Android maps this to screenrecord bitrate, Apple targets use it for export/encoding. Legacy numeric values 5-7 map to medium; 8-10 map to high`,projectConfig:!0,recorded:!0},{key:`hideTouches`,names:[`--hide-touches`],type:`boolean`,usageLabel:`--hide-touches`,usageDescription:`Record: skip touch-overlay post-processing for faster raw benchmark videos`,projectConfig:!0,recorded:!0},{key:`recordingScope`,names:[`--scope`],type:`enum`,enumValues:o,usageLabel:`--scope <app|device|system>`,usageDescription:`Record: app requires an active app session; device/system records the whole screen`,projectConfig:!0,recorded:!1},{key:`intervalMs`,names:[`--interval-ms`],type:`int`,min:0,max:1e4,usageLabel:`--interval-ms <ms>`,usageDescription:`Delay between press iterations`,projectConfig:!0,recorded:!0},{key:`delayMs`,names:[`--delay-ms`],type:`int`,min:0,max:1e4,usageLabel:`--delay-ms <ms>`,usageDescription:`Delay between typed characters`,projectConfig:!0,recorded:!0},{key:`recordAs`,names:[`--record-as`],type:`string`,usageLabel:`--record-as <VAR>`,usageDescription:"Fill: send the live text but publish ${VAR} in an armed .ad recording",projectConfig:!0,recorded:!1},{key:`durationMs`,names:[`--duration-ms`],type:`int`,min:0,max:1e4,usageLabel:`--duration-ms <ms>`,usageDescription:`Scroll: pace the gesture over this duration when supported`,projectConfig:!0,recorded:!1},{key:`holdMs`,names:[`--hold-ms`],type:`int`,min:0,max:1e4,usageLabel:`--hold-ms <ms>`,usageDescription:`Press hold duration for each iteration`,projectConfig:!0,recorded:!0},{key:`jitterPx`,names:[`--jitter-px`],type:`int`,min:0,max:100,usageLabel:`--jitter-px <n>`,usageDescription:`Deterministic coordinate jitter radius for press`,projectConfig:!0,recorded:!0},{key:`pixels`,names:[`--pixels`],type:`int`,min:1,max:1e5,usageLabel:`--pixels <n>`,usageDescription:`Scroll: explicit gesture distance in pixels`,projectConfig:!0,recorded:!1},{key:`until`,names:[`--until`],type:`string`,usageLabel:`--until <selector>`,usageDescription:`Scroll: repeat passes until the selector is visible on screen`,projectConfig:!0,recorded:!1},{key:`doubleTap`,names:[`--double-tap`],type:`boolean`,usageLabel:`--double-tap`,usageDescription:`Use double-tap gesture per press iteration`,projectConfig:!0,recorded:!0},{key:`verify`,names:[`--verify`],type:`boolean`,usageLabel:`--verify`,usageDescription:`Capture cheap post-action evidence (AX digest, node counts, changedFromBefore) instead of a follow-up snapshot`,projectConfig:!0,recorded:!1},{key:`settle`,names:[`--settle`],type:`boolean`,usageLabel:`--settle`,usageDescription:`After the action, wait for the UI to go quiet and return the settled diff vs the pre-action tree in the same response (best-effort; never fails the action)`,projectConfig:!0,recorded:!1},{key:`settleQuietMs`,names:[`--settle-quiet`],type:`int`,min:0,usageLabel:`--settle-quiet <ms>`,usageDescription:`Settle: quiet window the UI must hold to count as settled (default 500ms)`,projectConfig:!0,recorded:!1},{key:`clickButton`,names:[`--button`],type:`enum`,enumValues:[`primary`,`secondary`,`middle`],usageLabel:`--button primary|secondary|middle`,usageDescription:`Click: choose mouse button (middle reserved for future macOS support)`,projectConfig:!0,recorded:!0},{key:`backMode`,names:[`--in-app`],type:`enum`,enumValues:[`in-app`,`system`],setValue:`in-app`,usageLabel:`--in-app`,usageDescription:`Back: use app-provided back UI when available`,projectConfig:!0,recorded:!1},{key:`backMode`,names:[`--system`],type:`enum`,enumValues:[`in-app`,`system`],setValue:`system`,usageLabel:`--system`,usageDescription:`Back: use system back input or gesture when available`,projectConfig:!0,recorded:!1},{key:`pauseMs`,names:[`--pause-ms`],type:`int`,min:0,max:1e4,usageLabel:`--pause-ms <ms>`,usageDescription:`Delay between swipe iterations`,projectConfig:!0,recorded:!0},{key:`pattern`,names:[`--pattern`],type:`enum`,enumValues:[`one-way`,`ping-pong`],usageLabel:`--pattern one-way|ping-pong`,usageDescription:`Swipe repeat pattern`,projectConfig:!0,recorded:!0},{key:`verbose`,names:[`--debug`,`--verbose`,`-v`],type:`boolean`,usageLabel:`--debug, --verbose, -v`,usageDescription:`Enable debug diagnostics; test --verbose prints per-test step timings without debug logs`,projectConfig:!0,recorded:!0},{key:`cost`,names:[`--cost`],type:`boolean`,usageLabel:`--cost`,usageDescription:`Include per-command wall-clock latency (cost.wallClockMs) in the response`,projectConfig:!0,recorded:!1},{key:`responseLevel`,names:[`--level`],type:`enum`,enumValues:e,usageLabel:`--level digest|default|full`,usageDescription:`Response detail level: digest (token-cheap), default (today), or full. Default keeps the wire shape unchanged.`,projectConfig:!0,recorded:!1},{key:`json`,names:[`--json`],type:`boolean`,usageLabel:`--json`,usageDescription:`JSON output`,projectConfig:!0,recorded:!1},{key:`help`,names:[`--help`,`-h`],type:`boolean`,usageLabel:`--help, -h`,usageDescription:`Print help and exit`,projectConfig:!1,recorded:!1},{key:`version`,names:[`--version`,`-V`],type:`boolean`,usageLabel:`--version, -V`,usageDescription:`Print version and exit`,projectConfig:!1,recorded:!1},{key:`snapshotDiff`,names:[`--diff`],type:`boolean`,usageLabel:`--diff`,usageDescription:`Snapshot: show structural diff against the previous session baseline`,projectConfig:!0,recorded:!1},{key:`saveScript`,names:[`--save-script`],type:`booleanOrString`,usageLabel:`--save-script [path]`,usageDescription:`Arm evidence capture on open, publish the armed recording on close; close --save-script alone (without an armed open) is rejected — start with open --save-script, or use session save-script mid-session. Optional custom output path.`,projectConfig:!1,recorded:!0},{key:`networkInclude`,names:[`--include`],type:`enum`,enumValues:[`summary`,`headers`,`body`,`all`],usageLabel:`--include summary|headers|body|all`,usageDescription:`Network: include headers, bodies, or both in output`,projectConfig:!0,recorded:!1},{key:`shutdown`,names:[`--shutdown`],type:`boolean`,usageLabel:`--shutdown`,usageDescription:`close: shutdown associated simulator/emulator after ending session`,projectConfig:!0,recorded:!1},{key:`relaunch`,names:[`--relaunch`],type:`boolean`,usageLabel:`--relaunch`,usageDescription:`open: terminate app process before launching it`,projectConfig:!0,recorded:!0},{key:`foreground`,names:[`--foreground`],type:`boolean`,usageLabel:`--foreground`,usageDescription:`open: keep normal app/device selection and return an initial snapshot; without an app, resolve the sole running app on the sole booted iOS simulator`,inputDescription:`Include an initial interactive snapshot in a fresh open response. With no app argument, discover the sole running app on the sole booted iOS simulator; ambiguous environments fail closed.`,projectConfig:!1,recorded:!1},{key:`restart`,names:[`--restart`],type:`boolean`,usageLabel:`--restart`,usageDescription:`logs clear: stop active stream, clear logs, then start streaming again`,projectConfig:!0,recorded:!1},{key:`retainPaths`,names:[`--retain-paths`],type:`boolean`,usageLabel:`--retain-paths`,usageDescription:`install-from-source: keep materialized artifact paths after install`,projectConfig:!0,recorded:!1},{key:`retentionMs`,names:[`--retention-ms`],type:`int`,min:1,usageLabel:`--retention-ms <ms>`,usageDescription:`install-from-source: retention TTL for materialized artifact paths`,projectConfig:!0,recorded:!1},{key:`noRecord`,names:[`--no-record`],type:`boolean`,usageLabel:`--no-record`,usageDescription:`Do not record this action`,projectConfig:!0,recorded:!0},{key:`record`,names:[`--record`],type:`boolean`,usageLabel:`--record`,usageHidden:!0,usageDescription:`Force-record this action even though its command is observation-only and would otherwise be excluded from a repair-armed heal by default (mutually exclusive with --no-record)`,projectConfig:!0,recorded:!0}],u=[{key:`config`,names:[`--config`],type:`string`,usageLabel:`--config <path>`,usageDescription:`Load CLI defaults from a specific config file (required for connection/provider defaults outside user config)`,projectConfig:!1,recorded:!1},{key:`remoteConfig`,names:[`--remote-config`],type:`string`,usageLabel:`--remote-config <path>`,usageDescription:`Load remote host + Metro workflow settings from a specific profile file`,projectConfig:!1,recorded:!1},{key:`stateDir`,names:[`--state-dir`],type:`string`,usageLabel:`--state-dir <path>`,usageDescription:`Daemon state directory (defaults to ~/.agent-device for packages, or a worktree-scoped dev dir from source)`,projectConfig:!1,recorded:!1},{key:`daemonBaseUrl`,names:[`--daemon-base-url`],type:`string`,usageLabel:`--daemon-base-url <url>`,usageDescription:`Explicit remote HTTP daemon base URL (skip local daemon discovery/startup)`,projectConfig:!1,recorded:!1},{key:`daemonAuthToken`,names:[`--daemon-auth-token`],type:`string`,usageLabel:`--daemon-auth-token <token>`,usageDescription:`Remote HTTP daemon or proxy auth token (sent as request token and bearer header)`,projectConfig:!1,recorded:!1},{key:`daemonTransport`,names:[`--daemon-transport`],type:`enum`,enumValues:[`auto`,`socket`,`http`],usageLabel:`--daemon-transport auto|socket|http`,usageDescription:`Daemon client transport preference`,projectConfig:!1,recorded:!1},{key:`daemonServerMode`,names:[`--daemon-server-mode`],type:`enum`,enumValues:[`socket`,`http`,`dual`],usageLabel:`--daemon-server-mode socket|http|dual`,usageDescription:`Daemon server mode used when spawning daemon`,projectConfig:!1,recorded:!1},{key:`proxyHost`,names:[`--host`],type:`string`,usageLabel:`--host <host>`,usageDescription:`Proxy: host interface to bind (default: 127.0.0.1)`,projectConfig:!1,recorded:!1},{key:`proxyPort`,names:[`--port`],type:`int`,min:1,max:65535,usageLabel:`--port <port>`,usageDescription:`Proxy: TCP port to bind (default: 0, choose a free port)`,projectConfig:!1,recorded:!1},{key:`tenant`,names:[`--tenant`],type:`string`,usageLabel:`--tenant <id>`,usageDescription:`Tenant scope identifier for isolated daemon sessions`,projectConfig:!1,recorded:!1},{key:`sessionIsolation`,names:[`--session-isolation`],type:`enum`,enumValues:[`none`,`tenant`],usageLabel:`--session-isolation none|tenant`,usageDescription:`Session isolation strategy (tenant prefixes session namespace)`,projectConfig:!1,recorded:!1},{key:`runId`,names:[`--run-id`],type:`string`,usageLabel:`--run-id <id>`,usageDescription:`Run identifier used for tenant lease admission checks`,projectConfig:!1,recorded:!1},{key:`leaseId`,names:[`--lease-id`],type:`string`,usageLabel:`--lease-id <id>`,usageDescription:`Lease identifier bound to tenant/run admission scope`,projectConfig:!1,recorded:!1},{key:`leaseBackend`,names:[`--lease-backend`],type:`enum`,enumValues:[`ios-simulator`,`ios-instance`,`android-instance`,`harmonyos-instance`],usageLabel:`--lease-backend ios-simulator|ios-instance|android-instance|harmonyos-instance`,usageDescription:`Lease backend for remote tenant connection admission`,projectConfig:!1,recorded:!1},{key:`provider`,names:[`--provider`],type:`string`,usageLabel:`--provider <name>`,usageDescription:`Cloud provider name for provider-scoped commands`,projectConfig:!1,recorded:!1},{key:`providerSessionId`,names:[`--provider-session`],type:`string`,usageLabel:`--provider-session <id>`,usageDescription:`Cloud provider session id or ARN`,projectConfig:!1,recorded:!1},{key:`providerApp`,names:[`--provider-app`],type:`string`,usageLabel:`--provider-app <ref-or-path>`,usageDescription:`Cloud provider app reference or local app path used when creating hosted WebDriver sessions`,projectConfig:!1,recorded:!1},{key:`providerOsVersion`,names:[`--provider-os-version`,`--os-version`],type:`string`,usageLabel:`--provider-os-version <version>`,usageDescription:`Hosted cloud provider OS version, for example 17 or 14.0`,projectConfig:!1,recorded:!1},{key:`providerProject`,names:[`--provider-project`],type:`string`,usageLabel:`--provider-project <name>`,usageDescription:`Hosted cloud provider project label`,projectConfig:!1,recorded:!1},{key:`providerBuild`,names:[`--provider-build`],type:`string`,usageLabel:`--provider-build <name>`,usageDescription:`Hosted cloud provider build label`,projectConfig:!1,recorded:!1},{key:`providerSessionName`,names:[`--provider-session-name`],type:`string`,usageLabel:`--provider-session-name <name>`,usageDescription:`Hosted cloud provider session label`,projectConfig:!1,recorded:!1},{key:`providerDeviceOrientation`,names:[`--provider-device-orientation`,`--device-orientation`],type:`enum`,enumValues:r,usageLabel:`--provider-device-orientation portrait|landscape`,usageDescription:`Screen orientation a hosted cloud provider session starts in. Set this rather than rotating after launch: a session that boots landscape renders login webviews landscape`,projectConfig:!1,recorded:!1},{key:`providerGeoLocation`,names:[`--provider-geo-location`,`--geo-location`],type:`string`,usageLabel:`--provider-geo-location <country>`,usageDescription:`Hosted cloud provider IP geolocation country code, for example US`,projectConfig:!1,recorded:!1},{key:`providerTimezone`,names:[`--provider-timezone`,`--timezone`],type:`string`,usageLabel:`--provider-timezone <zone>`,usageDescription:`Hosted cloud provider device time zone, for example New_York`,projectConfig:!1,recorded:!1},{key:`providerAppiumVersion`,names:[`--provider-appium-version`,`--appium-version`],type:`string`,usageLabel:`--provider-appium-version <version>`,usageDescription:`Hosted cloud provider Appium server version, for example 3.2.0. Without it BrowserStack falls back to its default (Appium 1.x)`,projectConfig:!1,recorded:!1},{key:`providerLanguage`,names:[`--provider-language`,`--language`],type:`string`,usageLabel:`--provider-language <language>`,usageDescription:`Hosted cloud provider app language, for example Fr`,projectConfig:!1,recorded:!1},{key:`providerLocale`,names:[`--provider-locale`,`--locale`],type:`string`,usageLabel:`--provider-locale <locale>`,usageDescription:`Hosted cloud provider device locale, for example Fr`,projectConfig:!1,recorded:!1},{key:`providerNetworkProfile`,names:[`--provider-network-profile`,`--network-profile`],type:`string`,usageLabel:`--provider-network-profile <profile>`,usageDescription:`Hosted cloud provider named network condition profile, for example 4g-lte-advanced-good. Mutually exclusive with --provider-custom-network`,projectConfig:!1,recorded:!1},{key:`providerCustomNetwork`,names:[`--provider-custom-network`,`--custom-network`],type:`string`,usageLabel:`--provider-custom-network <shape>`,usageDescription:`Hosted cloud provider custom network shape. Mutually exclusive with --provider-network-profile`,projectConfig:!1,recorded:!1},{key:`providerNoResignApp`,names:[`--provider-no-resign-app`],type:`boolean`,usageLabel:`--provider-no-resign-app`,usageDescription:`iOS only: keep an Enterprise-signed app as uploaded instead of letting the provider re-sign it, which strips entitlements such as push notifications`,projectConfig:!1,recorded:!1},{key:`awsProjectArn`,names:[`--aws-project-arn`],type:`string`,usageLabel:`--aws-project-arn <arn>`,usageDescription:`AWS Device Farm project ARN for hosted WebDriver sessions`,projectConfig:!1,recorded:!1},{key:`awsDeviceArn`,names:[`--aws-device-arn`],type:`string`,usageLabel:`--aws-device-arn <arn>`,usageDescription:`AWS Device Farm device ARN for hosted WebDriver sessions`,projectConfig:!1,recorded:!1},{key:`awsAppArn`,names:[`--aws-app-arn`],type:`string`,usageLabel:`--aws-app-arn <arn>`,usageDescription:`AWS Device Farm app ARN attached to hosted remote access sessions`,projectConfig:!1,recorded:!1},{key:`awsRegion`,names:[`--aws-region`],type:`string`,usageLabel:`--aws-region <region>`,usageDescription:`AWS region for Device Farm API calls`,projectConfig:!1,recorded:!1},{key:`awsInteractionMode`,names:[`--aws-interaction-mode`],type:`enum`,enumValues:[`INTERACTIVE`,`NO_VIDEO`,`VIDEO_ONLY`],usageLabel:`--aws-interaction-mode INTERACTIVE|NO_VIDEO|VIDEO_ONLY`,usageDescription:`AWS Device Farm remote access interaction mode`,projectConfig:!1,recorded:!1},{key:`force`,names:[`--force`,`--overwrite`],type:`boolean`,usageLabel:`--force, --overwrite`,usageDescription:`Force replacement of existing state (connect: replace an active connection; --save-script: overwrite an existing target instead of refusing)`,projectConfig:!0,recorded:!0},{key:`clean`,names:[`--clean`],type:`boolean`,usageLabel:`--clean`,usageDescription:`Daemon stop: remove retained runner processes and leases after stopping`,projectConfig:!0,recorded:!1},{key:`noLogin`,names:[`--no-login`],type:`boolean`,usageLabel:`--no-login`,usageDescription:`Connect: fail instead of starting implicit cloud login`,projectConfig:!0,recorded:!1},{key:`sessionLock`,names:[`--session-lock`],type:`enum`,enumValues:[`reject`,`strip`],usageLabel:`--session-lock reject|strip`,usageDescription:`Lock bound-session device routing for this CLI invocation and nested batch steps; strip drops conflicting platform/scope selectors only, and a selector naming a different device always fails`,projectConfig:!0,recorded:!1}],d=[{key:`platform`,names:[`--platform`],type:`enum`,enumValues:n,usageLabel:`--platform ${n.join(`|`)}`,usageDescription:"Platform to target (`apple` aliases the Apple automation backend)",projectConfig:!0,recorded:!0},{key:`target`,names:[`--target`],type:`enum`,enumValues:[`mobile`,`tv`,`desktop`],usageLabel:`--target mobile|tv|desktop`,usageDescription:`Device target class to match`,projectConfig:!0,recorded:!1},{key:`device`,names:[`--device`],type:`string`,usageLabel:`--device <name>`,usageDescription:`Device name to target (a UDID belongs in --udid, a serial in --serial)`,projectConfig:!0,recorded:!0},{key:`udid`,names:[`--udid`],type:`string`,usageLabel:`--udid <udid>`,usageDescription:`Apple device or simulator UDID; the only selector that pins one device when several share a --device name`,projectConfig:!0,recorded:!0},{key:`serial`,names:[`--serial`],type:`string`,usageLabel:`--serial <serial>`,usageDescription:`Android, HarmonyOS, or Vega VVD serial`,projectConfig:!0,recorded:!0},{key:`stale`,names:[`--stale`],type:`boolean`,usageLabel:`--stale`,usageDescription:`Device status: show only claims with a provably stale owner`,projectConfig:!0,recorded:!1},{key:`surface`,names:[`--surface`],type:`enum`,enumValues:i,usageLabel:`--surface app|frontmost-app|desktop|menubar`,usageDescription:`macOS session surface for open (defaults to app)`,projectConfig:!0,recorded:!1},{key:`headless`,names:[`--headless`],type:`boolean`,usageLabel:`--headless`,usageDescription:`Boot: launch Android emulator without a GUI window`,projectConfig:!0,recorded:!1},{key:`targetApp`,names:[`--app`,`--target-app`],type:`string`,usageLabel:`--app <id-or-name>`,usageDescription:`Doctor: verify an installed target app without opening a session`,projectConfig:!1,recorded:!1},{key:`metroHost`,names:[`--metro-host`],type:`string`,usageLabel:`--metro-host <host>`,usageDescription:`Session-scoped Metro/debug host hint`,projectConfig:!1,recorded:!0},{key:`metroPort`,names:[`--metro-port`],type:`int`,min:1,max:65535,usageLabel:`--metro-port <port>`,usageDescription:`Session-scoped Metro/debug port hint; on an emulator/simulator the host defaults to the loopback alias, physical devices still need --metro-host`,projectConfig:!1,recorded:!0},{key:`metroProjectRoot`,names:[`--project-root`],type:`string`,usageLabel:`--project-root <path>`,usageDescription:`metro prepare: React Native project root (default: cwd)`,projectConfig:!1,recorded:!1},{key:`kind`,names:[`--kind`],type:`enum`,enumValues:[`auto`,`react-native`,`expo`,`repack`,...a],usageLabel:`--kind <kind>`,usageDescription:`Kind selector for commands that support it, such as metro prepare or perf artifact collectors`,projectConfig:!0,recorded:!1},{key:`perfTemplate`,names:[`--template`],type:`string`,usageLabel:`--template <name>`,usageDescription:`Perf xctrace template name, for example Time Profiler`,projectConfig:!0,recorded:!1},{key:`metroKind`,names:[`--metro-kind`],type:`enum`,enumValues:[`auto`,`react-native`,`expo`,`repack`],usageLabel:`--metro-kind auto|react-native|expo|repack`,usageDescription:`metro prepare: detect or force the React Native dev-server launcher kind`,projectConfig:!1,recorded:!1},{key:`metroPublicBaseUrl`,names:[`--public-base-url`],type:`string`,usageLabel:`--public-base-url <url>`,usageDescription:`metro prepare: public base URL used for direct dev-server bundle hints`,projectConfig:!1,recorded:!1},{key:`metroProxyBaseUrl`,names:[`--proxy-base-url`],type:`string`,usageLabel:`--proxy-base-url <url>`,usageDescription:`metro prepare: optional bridge origin for remote dev-server access`,projectConfig:!1,recorded:!1},{key:`metroBearerToken`,names:[`--bearer-token`],type:`string`,usageLabel:`--bearer-token <token>`,usageDescription:`metro prepare: host bridge bearer token (or AGENT_DEVICE_METRO_BEARER_TOKEN; falls back to AGENT_DEVICE_DAEMON_AUTH_TOKEN)`,projectConfig:!1,recorded:!1},{key:`metroPreparePort`,names:[`--port`],type:`int`,min:1,max:65535,usageLabel:`--port <port>`,usageDescription:`metro prepare: local dev-server port (default: 8081)`,projectConfig:!1,recorded:!1},{key:`metroListenHost`,names:[`--listen-host`],type:`string`,usageLabel:`--listen-host <host>`,usageDescription:`metro prepare: host dev server listens on (default: 0.0.0.0)`,projectConfig:!1,recorded:!1},{key:`metroStatusHost`,names:[`--status-host`],type:`string`,usageLabel:`--status-host <host>`,usageDescription:`metro prepare: host used for local dev-server /status polling (default: 127.0.0.1)`,projectConfig:!1,recorded:!1},{key:`metroStartupTimeoutMs`,names:[`--startup-timeout-ms`],type:`int`,min:1,usageLabel:`--startup-timeout-ms <ms>`,usageDescription:`metro prepare: timeout while waiting for the dev server to become ready`,projectConfig:!1,recorded:!1},{key:`metroProbeTimeoutMs`,names:[`--probe-timeout-ms`],type:`int`,min:1,usageLabel:`--probe-timeout-ms <ms>`,usageDescription:`metro prepare: timeout for /status and proxy bridge calls`,projectConfig:!1,recorded:!1},{key:`metroRuntimeFile`,names:[`--runtime-file`],type:`string`,usageLabel:`--runtime-file <path>`,usageDescription:`metro prepare: optional file path to persist the JSON result`,projectConfig:!1,recorded:!1},{key:`metroNoReuseExisting`,names:[`--no-reuse-existing`],type:`boolean`,usageLabel:`--no-reuse-existing`,usageDescription:`metro prepare: always start a fresh Metro process`,projectConfig:!1,recorded:!1},{key:`metroNoInstallDeps`,names:[`--no-install-deps`],type:`boolean`,usageLabel:`--no-install-deps`,usageDescription:`metro prepare: skip package-manager install when node_modules is missing`,projectConfig:!1,recorded:!1},{key:`bundleUrl`,names:[`--bundle-url`],type:`string`,usageLabel:`--bundle-url <url>`,usageDescription:`Session-scoped bundle URL hint`,projectConfig:!1,recorded:!0},{key:`launchUrl`,names:[`--launch-url`],type:`string`,usageLabel:`--launch-url <url>`,usageDescription:`Session-scoped deep link / launch URL hint`,projectConfig:!0,recorded:!0},{key:`iosSimulatorDeviceSet`,names:[`--ios-simulator-device-set`],type:`string`,usageLabel:`--ios-simulator-device-set <path>`,usageDescription:`Scope iOS simulator discovery/commands to this simulator device set`,projectConfig:!1,recorded:!1},{key:`iosXctestrunFile`,names:[`--ios-xctestrun-file`],type:`string`,usageLabel:`--ios-xctestrun-file <path>`,usageDescription:`Use an externally built iOS XCTest runner .xctestrun artifact`,projectConfig:!1,recorded:!1},{key:`iosXctestDerivedDataPath`,names:[`--ios-xctest-derived-data-path`],type:`string`,usageLabel:`--ios-xctest-derived-data-path <path>`,usageDescription:`Derived data path for external iOS XCTest runner execution`,projectConfig:!1,recorded:!1},{key:`iosXctestEnvDir`,names:[`--ios-xctest-env-dir`],type:`string`,usageLabel:`--ios-xctest-env-dir <path>`,usageDescription:`Writable directory for per-session iOS XCTest runner env overlays`,projectConfig:!1,recorded:!1},{key:`deviceHub`,names:[`--device-hub`],type:`boolean`,usageLabel:`--device-hub`,usageDescription:`open: use Xcode Device Hub when surfacing Apple simulators`,projectConfig:!0,recorded:!1},{key:`testIme`,names:[`--test-ime`],type:`boolean`,usageLabel:`--test-ime`,usageDescription:`open: activate the headless Android test IME for deterministic Unicode text entry (default on for emulators; opt-in on real devices)`,projectConfig:!0,recorded:!1},{key:`testIme`,names:[`--no-test-ime`],type:`boolean`,setValue:!1,usageLabel:`--no-test-ime`,usageDescription:`open: keep the real Android keyboard even on emulators (opt out of the headless test IME)`,projectConfig:!0,recorded:!1},{key:`androidDeviceAllowlist`,names:[`--android-device-allowlist`],type:`string`,usageLabel:`--android-device-allowlist <serials>`,usageDescription:`Comma/space separated Android serial allowlist for discovery/selection`,projectConfig:!1,recorded:!1},{key:`remote`,names:[`--remote`],type:`boolean`,usageLabel:`--remote`,usageDescription:`Doctor: check remote connection setup instead of local device inventory`,projectConfig:!0,recorded:!1},{key:`activity`,names:[`--activity`],type:`string`,usageLabel:`--activity <component>`,usageDescription:`Android app launch activity (package/Activity); not for URL opens`,projectConfig:!0,recorded:!1},{key:`launchConsole`,names:[`--launch-console`],type:`string`,usageLabel:`--launch-console <path>`,usageDescription:`open: capture the initial iOS simulator launch console window to a file`,projectConfig:!1,recorded:!1},{key:`launchArgs`,names:[`--launch-args`],type:`string`,multiple:!0,usageLabel:`--launch-args <arg>`,usageDescription:`open: repeatable launch argument forwarded verbatim to the platform launch command (iOS app process args; Android adb shell am start args). Linux and macOS reject the flag.`,projectConfig:!0,recorded:!1},{key:`header`,names:[`--header`],type:`string`,multiple:!0,usageLabel:`--header <name:value>`,usageDescription:`install-from-source: repeatable HTTP header for URL downloads`,projectConfig:!1,recorded:!1},{key:`githubActionsArtifact`,names:[`--github-actions-artifact`],type:`string`,usageLabel:`--github-actions-artifact <owner/repo:artifact>`,usageDescription:`install-from-source: GitHub Actions artifact resolved by a remote daemon`,projectConfig:!1,recorded:!1},{key:`installSource`,names:[],type:`string`,projectConfig:!1,recorded:!1},{key:`session`,names:[`--session`],type:`string`,usageLabel:`--session <name>`,usageDescription:`Named session (implicit default is scoped to this workspace + platform)`,projectConfig:!0,recorded:!1}],f=[{key:`replayUpdate`,names:[`--update`,`-u`],type:`boolean`,usageLabel:`--update, -u`,usageDescription:`Replay: retired as a rewrite (ADR 0012) — never edits the .ad file; every divergence already carries ranked selector suggestions, --update or not`,projectConfig:!0,recorded:!1},{key:`replayFrom`,names:[`--from`],type:`int`,min:1,usageLabel:`--from <n>`,usageDescription:`Replay: resume at 1-based plan step n, skipping 1..n-1 without executing them (requires --plan-digest; see a divergence report's resume field). replay only, not test`,projectConfig:!0,recorded:!1},{key:`replayPlanDigest`,names:[`--plan-digest`],type:`string`,usageLabel:`--plan-digest <sha256>`,usageDescription:`Replay: the plan digest a --from resume must match (from a prior divergence report); mismatch, edits, or include/platform-expansion changes fail INVALID_ARGS before any action`,projectConfig:!0,recorded:!1},{key:`replayKeepSession`,names:[`--keep-session`],type:`boolean`,usageLabel:`--keep-session`,usageDescription:`Replay: leave the session active by suppressing exactly an authored terminal close in a native .ad script; replay only, not test or Maestro YAML`,projectConfig:!0,recorded:!1},{key:`replayMaestro`,names:[`--maestro`],type:`boolean`,usageLabel:`--maestro`,usageDescription:`Replay: treat input as a supported Maestro YAML subset; unsupported syntax fails loudly. See agent-device help maestro for commands and boundaries`,projectConfig:!0,recorded:!1},{key:`replayEnv`,names:[`-e`,`--env`],type:`string`,multiple:!0,usageLabel:`-e KEY=VALUE, --env KEY=VALUE`,usageDescription:"Replay/Test: inject or override a ${KEY} variable for the script (repeatable)",projectConfig:!1,recorded:!1},{key:`failFast`,names:[`--fail-fast`],type:`boolean`,usageLabel:`--fail-fast`,usageDescription:`Test: stop the suite after the first failing script; with sharding, each shard stops independently`,projectConfig:!0,recorded:!1},{key:`timeoutMs`,names:[`--timeout`],type:`int`,min:1,usageLabel:`--timeout <ms>`,usageDescription:`Open/Prepare: startup budget covering the Simulator boot (and runner preparation for prepare). Replay/Snapshot/Test: maximum wall-clock time for the command or attempt. With --settle: the settle-wait deadline (default 10s)`,projectConfig:!0,recorded:!1},{key:`retries`,names:[`--retries`],type:`int`,min:0,max:3,usageLabel:`--retries <n>`,usageDescription:`Test: retry each failed script up to n additional times`,projectConfig:!0,recorded:!1},{key:`recordVideo`,names:[`--record-video`],type:`boolean`,usageLabel:`--record-video`,usageDescription:`Test: record each replay attempt to recording.mp4 in its attempt artifacts`,projectConfig:!0,recorded:!1},{key:`artifactsDir`,names:[`--artifacts-dir`],type:`string`,usageLabel:`--artifacts-dir <path>`,usageDescription:`Test: root directory for suite artifacts`,projectConfig:!1,recorded:!1},{key:`reporter`,names:[`--reporter`],type:`string`,multiple:!0,usageLabel:`--reporter <name-or-path>`,usageDescription:`Test: add a replay suite reporter; use default, junit:<path>, or a custom reporter path (repeatable)`,projectConfig:!1,recorded:!1},{key:`reportJunit`,names:[`--report-junit`],type:`string`,usageLabel:`--report-junit <path>`,usageDescription:`Test: compatibility alias for --reporter junit:<path>`,projectConfig:!1,recorded:!1},{key:`shardAll`,names:[`--shard-all`],type:`int`,min:1,usageLabel:`--shard-all <n>`,usageDescription:`Test: run the full suite on each of n devices; combine with --device id1,id2 for explicit connected devices; AD_SHARD_INDEX is zero-based`,projectConfig:!0,recorded:!1},{key:`shardSplit`,names:[`--shard-split`],type:`int`,min:1,usageLabel:`--shard-split <n>`,usageDescription:`Test: split runnable suite entries across n devices; AD_SHARD_INDEX is zero-based`,projectConfig:!0,recorded:!1},{key:`steps`,names:[`--steps`],type:`string`,usageLabel:`--steps <json>`,usageDescription:`Batch: JSON array of {"command","input"} steps`,projectConfig:!1,recorded:!1},{key:`stepsFile`,names:[`--steps-file`],type:`string`,usageLabel:`--steps-file <path>`,usageDescription:`Batch: read steps JSON from file`,projectConfig:!1,recorded:!1},{key:`batchOnError`,names:[`--on-error`],type:`enum`,enumValues:[`stop`],usageLabel:`--on-error stop`,usageDescription:`Batch: stop when a step fails`,projectConfig:!0,recorded:!1},{key:`batchMaxSteps`,names:[`--max-steps`],type:`int`,min:1,max:1e3,usageLabel:`--max-steps <n>`,usageDescription:`Batch: maximum number of allowed steps`,projectConfig:!0,recorded:!1},{key:`appsFilter`,names:[`--all`],type:`enum`,enumValues:[`user-installed`,`all`],setValue:`all`,usageLabel:`--all`,usageDescription:`Apps: include system/OEM apps`,projectConfig:!0,recorded:!1},{key:`snapshotInteractiveOnly`,names:[`-i`],type:`boolean`,usageLabel:`-i`,usageDescription:`Snapshot: interactive elements only`,projectConfig:!0,recorded:!0},{key:`snapshotDepth`,names:[`--depth`,`-d`],type:`int`,min:0,usageLabel:`--depth, -d <depth>`,usageDescription:`Snapshot: limit snapshot depth`,projectConfig:!0,recorded:!0},{key:`snapshotScope`,names:[`--scope`,`-s`],type:`string`,usageLabel:`--scope, -s <scope>`,usageDescription:`Snapshot: scope snapshot to label/identifier`,projectConfig:!0,recorded:!0},{key:`snapshotRaw`,names:[`--raw`],type:`boolean`,usageLabel:`--raw`,usageDescription:`Snapshot: raw node output`,projectConfig:!0,recorded:!0},{key:`snapshotCustomActions`,names:[`--actions`],type:`boolean`,usageLabel:`--actions`,usageDescription:`Snapshot: name the affordances merged inside an element (iOS sim); not directly invokable — reach them via the detail screen, labeled children, or coordinates`,inputDescription:`Name the affordances an element merged away (iOS UIAccessibilityCustomAction, React Native accessibilityActions) — a card whose reply/options controls are not separate elements still lists them here. The names are for PLANNING, not invocation: there is no API to trigger them, so reach the affordance through the element detail screen, through the same control exposed as a labeled element elsewhere, or by coordinates from its rect. iOS simulator only; costs one accessibility round trip per merged element.`,projectConfig:!0,recorded:!0},{key:`snapshotForceFull`,names:[`--force-full`],type:`boolean`,usageLabel:`--force-full`,usageDescription:`Snapshot: re-emit the full tree even when unchanged`,projectConfig:!0,recorded:!1},{key:`findFirst`,names:[`--first`],type:`boolean`,usageLabel:`--first`,usageDescription:`Find: pick the first match when ambiguous`,projectConfig:!0,recorded:!1},{key:`findLast`,names:[`--last`],type:`boolean`,usageLabel:`--last`,usageDescription:`Find: pick the last match when ambiguous`,projectConfig:!0,recorded:!1},{key:`out`,names:[`--out`],type:`string`,usageLabel:`--out <path>`,usageDescription:`Output path`,projectConfig:!1,recorded:!0},{key:`artifact`,names:[`--artifact`],type:`string`,usageLabel:`--artifact <path>`,usageDescription:`Debug symbols: Apple crash artifact path (.ips, .crash, or .log)`,projectConfig:!1,recorded:!1},{key:`dsym`,names:[`--dsym`],type:`string`,usageLabel:`--dsym <path>`,usageDescription:`Debug symbols: matching .dSYM bundle path`,projectConfig:!1,recorded:!1},{key:`searchPath`,names:[`--search-path`],type:`string`,usageLabel:`--search-path <dir>`,usageDescription:`Debug symbols: directory to scan for matching .dSYM bundles`,projectConfig:!1,recorded:!1},{key:`overlayRefs`,names:[`--overlay-refs`],type:`boolean`,usageLabel:`--overlay-refs`,usageDescription:`Screenshot: draw current snapshot refs and target rectangles onto the saved PNG; diff screenshot: also write a separate current-screen overlay guide`,projectConfig:!0,recorded:!1},...t,{key:`baseline`,names:[`--baseline`,`-b`],type:`string`,usageLabel:`--baseline, -b <path>`,usageDescription:`Diff screenshot: path to baseline image file`,projectConfig:!0,recorded:!1},{key:`threshold`,names:[`--threshold`],type:`string`,usageLabel:`--threshold <0-1>`,usageDescription:`Diff screenshot: color distance threshold (default 0.1)`,projectConfig:!0,recorded:!1}],p=[...u,...d,...l,...f],m=new Map;for(let e of p)for(let t of e.names)m.set(t,e);function h(e){return m.get(e)}function g(){return p}function _(e){return p.filter(t=>t.key===e)}function v(){return new Set(p.filter(e=>e.projectConfig).map(e=>e.key))}function y(){return new Set(p.filter(e=>e.recorded).map(e=>e.key))}const b=[`in-app`,`system`];export{v as a,s as c,_ as i,c as l,h as n,y as o,g as r,o as s,b as t};
package/dist/src/cli.js CHANGED
@@ -1,5 +1,5 @@
1
- import{C as e,L as t,M as n,w as r}from"./sdk-contracts.js";import{t as i}from"./capture.js";import{d as a,l as o,o as s,u as c}from"./sdk-batch-runner.js";import{n as l,r as u}from"./agent-device-client.js";import{s as d,t as f,u as p}from"./sdk-batch.js";import{n as m,r as h}from"./back-mode.js";import{i as g,r as _,t as v}from"./catalog.js";import{x as ee}from"./registry.js";import{a as y,i as b,l as x,n as te,o as ne,r as S}from"./diagnostics.js";import{f as re}from"./exec.js";import{n as ie}from"./command-metadata.js";import"./diagnostics2.js";import"./command.js";import{r as ae}from"./version.js";import{n as oe}from"./config.js";import{t as se}from"./session-artifact-paths.js";import{r as ce,t as le}from"./command-schema.js";import{n as C,r as w,t as ue}from"./cli-config.js";import{t as de}from"./update-check.js";import{n as fe,r as pe,t as me}from"./cli-command-aliases.js";import{exitAfterFlush as T}from"./process-exit.js";import{D as he,E as ge,O as _e,d as ve,k as ye,m as be,n as xe,w as Se}from"./connection-runtime.js";import{i as Ce}from"./auth-session.js";import E from"node:fs";import{pathToFileURL as D}from"node:url";const O=`open <app> --relaunch`,k={start:{command:`open`,example:O},restart:{command:`open`,example:O},touch:{command:`press`,example:`press`},input:{command:`fill`,example:`fill`},settext:{command:`fill`,example:`fill`},entertext:{command:`fill`,example:`fill`},screencap:{command:`screenshot`,example:`screenshot`},capture:{command:`screenshot`,example:`screenshot`},dismiss:{command:`keyboard`,example:`keyboard dismiss`},"get-text":{command:`get`,example:`get text`},gettext:{command:`get`,example:`get text`},get_text:{command:`get`,example:`get text`},"open-url":{command:`open`,example:`open <url>`},"close-session":{command:`close`,example:`close`}};function A(e){if(e.length<=2)return[];let t=g(),n=t.filter(t=>t.startsWith(e));if(n.length>0)return n.sort((e,t)=>e.length-t.length||e.localeCompare(t)).slice(0,3);let r=we(e),i=t.map(t=>({name:t,distance:Te(e,t)})).filter(e=>e.distance<=r);if(i.length===0)return[];let a=Math.min(...i.map(e=>e.distance));return i.filter(e=>e.distance===a).sort((e,t)=>e.name.localeCompare(t.name)).slice(0,3).map(e=>e.name)}function we(e){return e.length<4?1:e.length<=6?2:3}function Te(e,t){return e===t?0:e.startsWith(t)||t.startsWith(e)?Math.abs(e.length-t.length):Ee(e,t)}function Ee(e,t){let n=e.length+1,r=t.length+1,i=Array.from({length:n},()=>Array(r).fill(0));for(let e=0;e<n;e+=1)i[e][0]=e;for(let e=0;e<r;e+=1)i[0][e]=e;for(let a=1;a<n;a+=1)for(let n=1;n<r;n+=1){let r=e[a-1]===t[n-1]?0:1;i[a][n]=Math.min(i[a-1][n]+1,i[a][n-1]+1,i[a-1][n-1]+r)}return i[n-1][r-1]}function j(e){let t=e.toLowerCase(),n=k[t]?.example;if(n)return n;let r=A(t);if(r.length!==0)return r.length===1?r[0]:`one of: ${r.join(`, `)}`}const De=new Set([`--bundle-id`,`--bundleid`,`--bundle`,`--package`,`--package-name`,`--packagename`,`--app-id`,`--appid`,`--pkg`]),Oe=new Set([`--session-locked`,`--session-lock-conflicts`]);function ke(e){return De.has(e.toLowerCase())?`Unknown flag: ${e}. The app or bundle id is a positional argument, e.g. ${O}.`:Oe.has(e.toLowerCase())?`Unknown flag: ${e}. Use --session-lock reject|strip instead.`:e.toLowerCase()===i.cliToken?`Unknown flag: ${e}. ${i.migration.screenshot}. ${i.migration.record}.`:`Unknown flag: ${e}`}function M(t){let n={json:!1,help:!1,version:!1},r=null,i=null,a=[],o=[],s=[],c=!0;for(let o=0;o<t.length;o+=1){let l=t[o];if(c&&l===`--`){c=!1;continue}if(!c){r?a.push(l):(i=l,r=L(l));continue}if(Ne(r)){a.push(l);continue}let u=l.startsWith(`--`),d=l.startsWith(`-`)&&l.length>1;if(!u&&!d){r?a.push(l):(i=l,r=L(l));continue}let[f,p]=u?N(l):[l,void 0];if(je(r,f))continue;let m=Pe(f,r);if(Me(r,m)){a.push(l);continue}if(!m){if(ze(r,a,l)){r?a.push(l):r=l;continue}throw new e(`INVALID_ARGS`,ke(f))}let h=Le(m,f,p,t[o+1]);h.consumeNext&&(o+=1);let g=n[m.key];if(m.multiple){let e=Array.isArray(g)?[...g,h.value]:g===void 0?[h.value]:[g,h.value];n[m.key]=e}else n[m.key]=h.value;s.push({key:m.key,token:f})}return Ae(i,n),{command:r,positionals:a,flags:n,warnings:o,providedFlags:s}}function Ae(e,t){if(e)for(let n of me(e)?.impliedFlags??[])t[n]=!0}function je(e,t){return t===`-c`&&(e===`snapshot`||e===`diff`)}function Me(e,t){return e===`react-devtools`?!t||!w(t.key,e):!1}function Ne(e){return e===`cdp`}function Pe(e,t){let n=h().filter(t=>t.names.includes(e));if(n.length<=1)return n[0]??m(e);if(t){let e=n.find(e=>w(e.key,t));if(e)return e}return m(e)}function Fe(t,n){let r=n?.strictFlags??!0,i=[...t.warnings],a=C({json:!1,help:!1,version:!1},n?.defaultFlags??{});if(C(a,t.flags),t.command&&!_(t.command)&&!a.help){let n=j(t.command),r=n?`Unknown command: ${t.command}. Did you mean ${n}?`:`Unknown command: ${t.command}`;throw new e(`INVALID_ARGS`,r)}let o=t.providedFlags.filter(e=>!w(e.key,t.command));if(o.length>0){let n=o.map(e=>e.token),s=He(t.command,n);if(r)throw new e(`INVALID_ARGS`,s);i.push(s);for(let e of o)delete a[e.key]}for(let e of Object.keys(a))a[e]!==void 0&&(w(e,t.command)||delete a[e]);Ie(t),p(t.command,a);let s=Ve({command:t.command,positionals:t.positionals,flags:a,warnings:i});if(le(s.command,s.positionals),s.command===`batch`&&+!!a.steps+ +!!a.stepsFile!=1)throw new e(`INVALID_ARGS`,`batch requires exactly one step source: --steps or --steps-file.`);return s}function Ie(t){if(t.command!==`back`)return;let n=t.providedFlags.filter(e=>e.key===`backMode`);if(!(new Set(n.map(e=>e.token)).size<=1))throw new e(`INVALID_ARGS`,`back accepts only one explicit mode flag: use either --in-app or --system.`)}function N(e){let t=e.indexOf(`=`);return t===-1?[e,void 0]:[e.slice(0,t),e.slice(t+1)]}function Le(t,n,r,i){if(t.setValue!==void 0){if(r!==void 0)throw new e(`INVALID_ARGS`,`Flag ${n} does not take a value.`);return{value:t.setValue,consumeNext:!1}}if(t.type===`boolean`){if(r!==void 0)throw new e(`INVALID_ARGS`,`Flag ${n} does not take a value.`);return{value:!0,consumeNext:!1}}if(t.type===`booleanOrString`){if(r!==void 0){if(r.trim().length===0)throw new e(`INVALID_ARGS`,`Flag ${n} requires a non-empty value when provided.`);return{value:r,consumeNext:!1}}return i===void 0||F(i)?{value:!0,consumeNext:!1}:Re(i)?{value:i,consumeNext:!0}:{value:!0,consumeNext:!1}}let a=r??i;if(a===void 0||r===void 0&&F(a))throw new e(`INVALID_ARGS`,`Flag ${n} requires a value.`);if(t.type===`string`)return{value:a,consumeNext:r===void 0};if(t.type===`enum`){if(!t.enumValues?.includes(a))throw new e(`INVALID_ARGS`,`Invalid ${P(n)}: ${a}`);return{value:a,consumeNext:r===void 0}}let o=Number(a);if(!Number.isFinite(o)||typeof t.min==`number`&&o<t.min||typeof t.max==`number`&&o>t.max)throw new e(`INVALID_ARGS`,`Invalid ${P(n)}: ${a}`);return{value:t.type===`int`?Math.floor(o):o,consumeNext:r===void 0}}function P(e){return e.replace(/^-+/,``)}function F(e){if(!e.startsWith(`-`)||e===`-`)return!1;let[t]=e.startsWith(`--`)?N(e):[e,void 0];return m(t)!==void 0}function Re(e){let t=e.trim();return!t||/^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//.test(t)?!1:!!(t.startsWith(`./`)||t.startsWith(`../`)||t.startsWith(`~/`)||t.startsWith(`/`)||t.includes(`/`)||t.includes(`\\`))}function ze(e,t,n){if(!Be(n)||!e)return!1;let r=ce(e);if(!r||r.allowsExtraPositionals)return!0;let i=r.positionalArgs??[];return i.length===0?!1:t.length<i.length||i.some(e=>e.includes(`?`))}function Be(e){return/^-\d+(\.\d+)?$/.test(e)}function Ve(e){if(e.flags.help)return e;if(e.command===`snapshot`&&e.flags.snapshotDiff){let{snapshotDiff:t,...n}=e.flags;return{command:`diff`,positionals:[`snapshot`,...e.positionals],flags:n,warnings:e.warnings}}return e}function He(e,t){return e?t.length===1?`Flag ${t[0]} is not supported for command ${e}.`:`Flags ${t.join(`, `)} are not supported for command ${e}.`:t.length===1?`Flag ${t[0]} requires a command that supports it.`:`Flags ${t.join(`, `)} require a command that supports them.`}async function I(){let{buildUsageText:e}=await import(`./cli-help.js`).then(e=>e.n);return e()}async function Ue(e){let{buildCommandUsageText:t}=await import(`./cli-help.js`).then(e=>e.n);return t(L(e))}function L(t){let n=pe(t);if(n)throw new e(`INVALID_ARGS`,n);return fe(t)}function We(){return{renderedToStderr:!1}}function Ge(e){return t=>{t.type===`command`&&(e.renderedToStderr=!0,process.stderr.write(`${t.message}\n`))}}function Ke(e){return ie(e)}const qe={connect:async()=>(await import(`./connection.js`)).connectCommand,disconnect:async()=>(await import(`./connection.js`)).disconnectCommand,connection:async()=>(await import(`./connection.js`)).connectionCommand,auth:async()=>(await import(`./auth.js`)).authCommand,daemon:async()=>(await import(`./daemon.js`)).daemonCommand,device:async()=>(await import(`./device2.js`)).deviceCommand,proxy:async()=>(await import(`./proxy.js`)).proxyCommand,takeover:async()=>(await import(`./takeover.js`)).takeoverCommand,replay:async()=>(await import(`./replay.js`)).replayCommand,screenshot:async()=>(await import(`./screenshot3.js`)).screenshotCommand,diff:async()=>(await import(`./screenshot3.js`)).diffCommand};async function R(e){let t={...e.flags},n=qe[e.command];return n&&await(await n())({...e,flags:t})?!0:Ke(e.command)?await Je({...e,command:e.command,flags:t}):!1}async function Je(e){let{runGenericClientBackedCommand:t}=await import(`./generic.js`);return await t(e)}function Ye(e){return[`exec`,`--yes`,`--package`,`agent-react-devtools@0.5.0`,`--`,`agent-react-devtools`,...e]}function Xe(e){return e===`ios-instance`}function Ze(e){return e[0]===`wait`&&e.includes(`--connected`)}function Qe(e,t,n){n===0||!Ze(e)||!Xe(t?.leaseBackend)||process.stderr.write([`Hint: Remote iOS React DevTools connects during JavaScript startup.`,"If 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`.",``].join(`
1
+ import{C as e,L as t,M as n,w as r}from"./sdk-contracts.js";import{t as i}from"./capture.js";import{d as a,l as o,o as s,u as c}from"./sdk-batch-runner.js";import{n as l,r as u}from"./agent-device-client.js";import{s as d,t as f,u as p}from"./sdk-batch.js";import{n as m,r as h}from"./back-mode.js";import{i as g,r as _,t as v}from"./catalog.js";import{x as ee}from"./registry.js";import{a as y,i as b,l as x,n as te,o as ne,r as S}from"./diagnostics.js";import{f as re}from"./exec.js";import{n as ie}from"./command-metadata.js";import"./diagnostics2.js";import"./command.js";import{r as ae}from"./version.js";import{t as oe}from"./daemon-resolution.js";import{t as se}from"./session-artifact-paths.js";import{r as ce,t as le}from"./command-schema.js";import{n as C,r as w,t as ue}from"./cli-config.js";import{t as de}from"./update-check.js";import{n as fe,r as pe,t as me}from"./cli-command-aliases.js";import{exitAfterFlush as T}from"./process-exit.js";import{D as he,E as ge,O as _e,d as ve,k as ye,m as be,n as xe,w as Se}from"./connection-runtime.js";import{i as Ce}from"./auth-session.js";import E from"node:fs";import{pathToFileURL as D}from"node:url";const O=`open <app> --relaunch`,k={start:{command:`open`,example:O},restart:{command:`open`,example:O},touch:{command:`press`,example:`press`},input:{command:`fill`,example:`fill`},settext:{command:`fill`,example:`fill`},entertext:{command:`fill`,example:`fill`},screencap:{command:`screenshot`,example:`screenshot`},capture:{command:`screenshot`,example:`screenshot`},dismiss:{command:`keyboard`,example:`keyboard dismiss`},"get-text":{command:`get`,example:`get text`},gettext:{command:`get`,example:`get text`},get_text:{command:`get`,example:`get text`},"open-url":{command:`open`,example:`open <url>`},"close-session":{command:`close`,example:`close`}};function A(e){if(e.length<=2)return[];let t=g(),n=t.filter(t=>t.startsWith(e));if(n.length>0)return n.sort((e,t)=>e.length-t.length||e.localeCompare(t)).slice(0,3);let r=we(e),i=t.map(t=>({name:t,distance:Te(e,t)})).filter(e=>e.distance<=r);if(i.length===0)return[];let a=Math.min(...i.map(e=>e.distance));return i.filter(e=>e.distance===a).sort((e,t)=>e.name.localeCompare(t.name)).slice(0,3).map(e=>e.name)}function we(e){return e.length<4?1:e.length<=6?2:3}function Te(e,t){return e===t?0:e.startsWith(t)||t.startsWith(e)?Math.abs(e.length-t.length):Ee(e,t)}function Ee(e,t){let n=e.length+1,r=t.length+1,i=Array.from({length:n},()=>Array(r).fill(0));for(let e=0;e<n;e+=1)i[e][0]=e;for(let e=0;e<r;e+=1)i[0][e]=e;for(let a=1;a<n;a+=1)for(let n=1;n<r;n+=1){let r=e[a-1]===t[n-1]?0:1;i[a][n]=Math.min(i[a-1][n]+1,i[a][n-1]+1,i[a-1][n-1]+r)}return i[n-1][r-1]}function j(e){let t=e.toLowerCase(),n=k[t]?.example;if(n)return n;let r=A(t);if(r.length!==0)return r.length===1?r[0]:`one of: ${r.join(`, `)}`}const De=new Set([`--bundle-id`,`--bundleid`,`--bundle`,`--package`,`--package-name`,`--packagename`,`--app-id`,`--appid`,`--pkg`]),Oe=new Set([`--session-locked`,`--session-lock-conflicts`]);function ke(e){return De.has(e.toLowerCase())?`Unknown flag: ${e}. The app or bundle id is a positional argument, e.g. ${O}.`:Oe.has(e.toLowerCase())?`Unknown flag: ${e}. Use --session-lock reject|strip instead.`:e.toLowerCase()===i.cliToken?`Unknown flag: ${e}. ${i.migration.screenshot}. ${i.migration.record}.`:`Unknown flag: ${e}`}function M(t){let n={json:!1,help:!1,version:!1},r=null,i=null,a=[],o=[],s=[],c=!0;for(let o=0;o<t.length;o+=1){let l=t[o];if(c&&l===`--`){c=!1;continue}if(!c){r?a.push(l):(i=l,r=L(l));continue}if(Ne(r)){a.push(l);continue}let u=l.startsWith(`--`),d=l.startsWith(`-`)&&l.length>1;if(!u&&!d){r?a.push(l):(i=l,r=L(l));continue}let[f,p]=u?N(l):[l,void 0];if(je(r,f))continue;let m=Pe(f,r);if(Me(r,m)){a.push(l);continue}if(!m){if(ze(r,a,l)){r?a.push(l):r=l;continue}throw new e(`INVALID_ARGS`,ke(f))}let h=Le(m,f,p,t[o+1]);h.consumeNext&&(o+=1);let g=n[m.key];if(m.multiple){let e=Array.isArray(g)?[...g,h.value]:g===void 0?[h.value]:[g,h.value];n[m.key]=e}else n[m.key]=h.value;s.push({key:m.key,token:f})}return Ae(i,n),{command:r,positionals:a,flags:n,warnings:o,providedFlags:s}}function Ae(e,t){if(e)for(let n of me(e)?.impliedFlags??[])t[n]=!0}function je(e,t){return t===`-c`&&(e===`snapshot`||e===`diff`)}function Me(e,t){return e===`react-devtools`?!t||!w(t.key,e):!1}function Ne(e){return e===`cdp`}function Pe(e,t){let n=h().filter(t=>t.names.includes(e));if(n.length<=1)return n[0]??m(e);if(t){let e=n.find(e=>w(e.key,t));if(e)return e}return m(e)}function Fe(t,n){let r=n?.strictFlags??!0,i=[...t.warnings],a=C({json:!1,help:!1,version:!1},n?.defaultFlags??{});if(C(a,t.flags),t.command&&!_(t.command)&&!a.help){let n=j(t.command),r=n?`Unknown command: ${t.command}. Did you mean ${n}?`:`Unknown command: ${t.command}`;throw new e(`INVALID_ARGS`,r)}let o=t.providedFlags.filter(e=>!w(e.key,t.command));if(o.length>0){let n=o.map(e=>e.token),s=He(t.command,n);if(r)throw new e(`INVALID_ARGS`,s);i.push(s);for(let e of o)delete a[e.key]}for(let e of Object.keys(a))a[e]!==void 0&&(w(e,t.command)||delete a[e]);Ie(t),p(t.command,a);let s=Ve({command:t.command,positionals:t.positionals,flags:a,warnings:i});if(le(s.command,s.positionals),s.command===`batch`&&+!!a.steps+ +!!a.stepsFile!=1)throw new e(`INVALID_ARGS`,`batch requires exactly one step source: --steps or --steps-file.`);return s}function Ie(t){if(t.command!==`back`)return;let n=t.providedFlags.filter(e=>e.key===`backMode`);if(!(new Set(n.map(e=>e.token)).size<=1))throw new e(`INVALID_ARGS`,`back accepts only one explicit mode flag: use either --in-app or --system.`)}function N(e){let t=e.indexOf(`=`);return t===-1?[e,void 0]:[e.slice(0,t),e.slice(t+1)]}function Le(t,n,r,i){if(t.setValue!==void 0){if(r!==void 0)throw new e(`INVALID_ARGS`,`Flag ${n} does not take a value.`);return{value:t.setValue,consumeNext:!1}}if(t.type===`boolean`){if(r!==void 0)throw new e(`INVALID_ARGS`,`Flag ${n} does not take a value.`);return{value:!0,consumeNext:!1}}if(t.type===`booleanOrString`){if(r!==void 0){if(r.trim().length===0)throw new e(`INVALID_ARGS`,`Flag ${n} requires a non-empty value when provided.`);return{value:r,consumeNext:!1}}return i===void 0||F(i)?{value:!0,consumeNext:!1}:Re(i)?{value:i,consumeNext:!0}:{value:!0,consumeNext:!1}}let a=r??i;if(a===void 0||r===void 0&&F(a))throw new e(`INVALID_ARGS`,`Flag ${n} requires a value.`);if(t.type===`string`)return{value:a,consumeNext:r===void 0};if(t.type===`enum`){if(!t.enumValues?.includes(a))throw new e(`INVALID_ARGS`,`Invalid ${P(n)}: ${a}`);return{value:a,consumeNext:r===void 0}}let o=Number(a);if(!Number.isFinite(o)||typeof t.min==`number`&&o<t.min||typeof t.max==`number`&&o>t.max)throw new e(`INVALID_ARGS`,`Invalid ${P(n)}: ${a}`);return{value:t.type===`int`?Math.floor(o):o,consumeNext:r===void 0}}function P(e){return e.replace(/^-+/,``)}function F(e){if(!e.startsWith(`-`)||e===`-`)return!1;let[t]=e.startsWith(`--`)?N(e):[e,void 0];return m(t)!==void 0}function Re(e){let t=e.trim();return!t||/^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//.test(t)?!1:!!(t.startsWith(`./`)||t.startsWith(`../`)||t.startsWith(`~/`)||t.startsWith(`/`)||t.includes(`/`)||t.includes(`\\`))}function ze(e,t,n){if(!Be(n)||!e)return!1;let r=ce(e);if(!r||r.allowsExtraPositionals)return!0;let i=r.positionalArgs??[];return i.length===0?!1:t.length<i.length||i.some(e=>e.includes(`?`))}function Be(e){return/^-\d+(\.\d+)?$/.test(e)}function Ve(e){if(e.flags.help)return e;if(e.command===`snapshot`&&e.flags.snapshotDiff){let{snapshotDiff:t,...n}=e.flags;return{command:`diff`,positionals:[`snapshot`,...e.positionals],flags:n,warnings:e.warnings}}return e}function He(e,t){return e?t.length===1?`Flag ${t[0]} is not supported for command ${e}.`:`Flags ${t.join(`, `)} are not supported for command ${e}.`:t.length===1?`Flag ${t[0]} requires a command that supports it.`:`Flags ${t.join(`, `)} require a command that supports them.`}async function I(){let{buildUsageText:e}=await import(`./cli-help.js`).then(e=>e.n);return e()}async function Ue(e){let{buildCommandUsageText:t}=await import(`./cli-help.js`).then(e=>e.n);return t(L(e))}function L(t){let n=pe(t);if(n)throw new e(`INVALID_ARGS`,n);return fe(t)}function We(){return{renderedToStderr:!1}}function Ge(e){return t=>{t.type===`command`&&(e.renderedToStderr=!0,process.stderr.write(`${t.message}\n`))}}function Ke(e){return ie(e)}const qe={connect:async()=>(await import(`./connection.js`)).connectCommand,disconnect:async()=>(await import(`./connection.js`)).disconnectCommand,connection:async()=>(await import(`./connection.js`)).connectionCommand,auth:async()=>(await import(`./auth.js`)).authCommand,daemon:async()=>(await import(`./daemon.js`)).daemonCommand,device:async()=>(await import(`./device2.js`)).deviceCommand,proxy:async()=>(await import(`./proxy.js`)).proxyCommand,takeover:async()=>(await import(`./takeover.js`)).takeoverCommand,replay:async()=>(await import(`./replay.js`)).replayCommand,screenshot:async()=>(await import(`./screenshot3.js`)).screenshotCommand,diff:async()=>(await import(`./screenshot3.js`)).diffCommand};async function R(e){let t={...e.flags},n=qe[e.command];return n&&await(await n())({...e,flags:t})?!0:Ke(e.command)?await Je({...e,command:e.command,flags:t}):!1}async function Je(e){let{runGenericClientBackedCommand:t}=await import(`./generic.js`);return await t(e)}function Ye(e){return[`exec`,`--yes`,`--package`,`agent-react-devtools@0.5.0`,`--`,`agent-react-devtools`,...e]}function Xe(e){return e===`ios-instance`}function Ze(e){return e[0]===`wait`&&e.includes(`--connected`)}function Qe(e,t,n){n===0||!Ze(e)||!Xe(t?.leaseBackend)||process.stderr.write([`Hint: Remote iOS React DevTools connects during JavaScript startup.`,"If 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`.",``].join(`
2
2
  `))}function z(e,t,n){return n||(e.push(t),``)}function B(t){if(!t?.metroProxyBaseUrl||!he(t.leaseBackend))return null;let n=[],r={serverBaseUrl:z(n,`metroProxyBaseUrl`,t.metroProxyBaseUrl),bearerToken:z(n,`metroBearerToken`,t.metroBearerToken),tenantId:z(n,`tenant`,t.tenant),runId:z(n,`runId`,t.runId),leaseId:z(n,`leaseId`,t.leaseId)};if(n.length>0)throw new e(`INVALID_ARGS`,`react-devtools remote bridge requires ${n.join(`, `)}.`,{missing:n});return r}async function $e(e,t,n){let{flags:r}=t,i=B(r);if(!i)return n();let a=t.stateDir??process.cwd(),o=t.session??r?.session??`default`,s=r?.remoteConfig??`${i.tenantId}:${i.runId}:${i.leaseId}`;if(e[0]===`stop`)try{return await n()}finally{await ye({projectRoot:t.cwd??process.cwd(),stateDir:a,profileKey:s,consumerKey:o})}return await _e({projectRoot:t.cwd??process.cwd(),stateDir:a,serverBaseUrl:i.serverBaseUrl,bearerToken:i.bearerToken,bridgeScope:{tenantId:i.tenantId,runId:i.runId,leaseId:i.leaseId},session:o,profileKey:s,consumerKey:o,env:t.env??process.env}),await n()}function et(e,t){if(e[0]!==`start`)return!1;let{flags:n}=t;return n?ve(n.leaseProvider).supportsDirectPortReverse&&n.leaseBackend===`android-instance`&&n.metroProxyBaseUrl===void 0&&t.configureDirectPortReverse!==void 0:!1}async function tt(e,t={}){let n=t.cwd??process.cwd(),r=t.env??process.env,i=await $e(e,t,async()=>(et(e,t)&&await t.configureDirectPortReverse?.(),(await re(`npm`,Ye(e),{cwd:n,env:r,allowFailure:!0,onStdoutChunk:e=>{process.stdout.write(e)},onStderrChunk:e=>{process.stderr.write(e)}})).exitCode));return Qe(e,t.flags,i),i}const V=`${s} Run agent-device help batch for the commands batch accepts and for runnable step examples.`,nt=`${f} Run agent-device help batch for the commands batch accepts and for runnable step examples.`;function rt(t){let n;try{n=JSON.parse(t)}catch{throw new e(`INVALID_ARGS`,`Batch steps must be valid JSON.`)}if(!Array.isArray(n)||n.length===0)throw new e(`INVALID_ARGS`,`Batch steps must be a non-empty JSON array.`);return n.map((e,t)=>it(e,t+1))}function it(t,n){let r=a(t,n,V),i=[`positionals`,`flags`].filter(e=>e in r);if(i.length>0){let t=i.map(e=>`"${e}"`).join(`, `);throw new e(`INVALID_ARGS`,`Batch step ${n} uses removed field(s): ${t}. Use {"command":"...","input":{...}}. Example: {"command":"open","input":{"app":"settings","platform":"ios"}}.`,{hint:V})}ee(r,[`command`,`input`,`runtime`],`Batch step ${n}`,V);let s=o(r.runtime,n);return{command:d(r.command,n,nt),input:c(r,n,V),...s===void 0?{}:{runtime:s}}}function H(e,t={}){let n=U(t),r={...e};return n.defaultPlatform&&r.platform===void 0&&(r.platform=n.defaultPlatform),r}function U(e){let t=e.env??process.env,n=e.inheritedPlatform??e.configuredPlatform??ot(t.AGENT_DEVICE_PLATFORM),r=ct(e.configuredSession??t.AGENT_DEVICE_SESSION);return{defaultPlatform:n,lockPolicy:at(e.policyOverrides,t,r)}}function at(e,t,n){let r=e?.sessionLock??st(t.AGENT_DEVICE_SESSION_LOCK);if(r)return r;if(n)return`reject`}function ot(t){if(t===void 0)return;let n=t.trim().toLowerCase();if(n){if(n===`ios`||n===`android`||n===`apple`)return n;throw new e(`INVALID_ARGS`,`Invalid AGENT_DEVICE_PLATFORM: ${t}. Use ios, android, or apple.`)}}function st(t){if(t===void 0)return;let n=t.trim().toLowerCase();if(n){if(n===`reject`||n===`strip`)return n;throw new e(`INVALID_ARGS`,`Invalid session lock mode: ${t}. Use reject or strip.`)}}function ct(e){return typeof e==`string`&&e.trim().length>0}function lt(e,t){let n=M(e),r=t?.env??process.env,i=t?.cwd??process.cwd(),a=ut(n.command)?be({remoteConfig:n.flags.remoteConfig,cwd:i,env:r}):{},o=C(ue({command:n.command,cwd:i,cliFlags:n.flags,env:r}),a);return{...Fe(n,{strictFlags:t?.strictFlags,defaultFlags:o}),providedFlags:n.providedFlags}}function ut(e){return e!==null}v.runtime;async function dt(e){let{command:t,request:n,transport:r,transportOptions:i}=e;return await r({...n,command:t},i)}const W=(e,t={})=>import(`./error.js`).then(({printHumanError:n})=>n(e,t)),G=e=>import(`./json.js`).then(({printJson:t})=>t(e)),ft={sendToDaemon:u},pt=new Set([`launchUrl`,`kind`,`metroBearerToken`,`metroKind`,`metroListenHost`,`metroNoInstallDeps`,`metroNoReuseExisting`,`metroPreparePort`,`metroProbeTimeoutMs`,`metroProjectRoot`,`metroProxyBaseUrl`,`metroPublicBaseUrl`,`metroRuntimeFile`,`metroStartupTimeoutMs`,`metroStatusHost`]),mt=new Set([`connect`,`connection`,`close`,`daemon`,`device`,`disconnect`,`metro`,`proxy`,`session`,`takeover`]);async function K(e,t=ft){let n=te(),r=ae(),i=wt(e),a=e.includes(`--json`),o=Lt(e)??process.env.AGENT_DEVICE_SESSION??`default`;await x({session:o,requestId:n,command:e[0],debug:i},async()=>{let{parsed:o,command:s,positionals:c}=await ht(e,{version:r,jsonRequested:a,debugEnabled:i}),u=Z(s,o.providedFlags),d=await gt(o,{command:s,positionals:c,requestId:n,debugOutputEnabled:u});q(d.effectiveFlags);let f=null;try{if(s===`react-devtools`){await T(await _t(d,t));return}if(s===`web`){let{runWebCommand:e}=await import(`./web.js`);await T(await e(c,{flags:d.effectiveFlags,stateDir:d.daemonPaths.baseDir}));return}if(de({command:s,currentVersion:r,stateDir:d.daemonPaths.baseDir,flags:d.effectiveFlags}),await vt(d,t),q(d.effectiveFlags),s===`cdp`){await T(await ge(c,{flags:d.effectiveFlags,runtime:d.resolvedRuntime,cwd:process.cwd(),env:process.env}));return}f=yt(d);let e=await bt(d),n=We();await xt(d,l(J(d),{transport:It({command:s,flags:d.effectiveFlags,replayTestReporterRuntime:e,commandProgress:n,transport:t.sendToDaemon})}),e,n)}catch(e){await St(e,d,f)}finally{f&&f()}})}function q(e){e.daemonAuthToken&&ne(e.daemonAuthToken)}async function ht(t,r){let i;try{i=lt(t,{cwd:process.cwd(),env:process.env})}catch(e){S({level:`error`,phase:`cli_parse_failed`,data:{error:e instanceof Error?e.message:String(e)}});let t=n(e,{diagnosticId:y().diagnosticId,logPath:b({force:!0})?.path});return r.jsonRequested?await G({success:!1,error:t}):await W(t,{showDetails:r.debugEnabled}),T(1)}for(let e of i.warnings)process.stderr.write(`Warning: ${e}\n`);if(i.flags.version)return process.stdout.write(`${r.version}\n`),T(0);let a=i.command===`help`,o=i.flags.help;if(a||o){if(a&&i.positionals.length>1)return await W(new e(`INVALID_ARGS`,`help accepts at most one command.`)),T(1);let t=a?i.positionals[0]:i.command;if(!t)return process.stdout.write(`${await I()}\n`),T(0);let n=await Ue(t);return n?(process.stdout.write(n),T(0)):(await W(new e(`INVALID_ARGS`,Tt(t))),process.stdout.write(`${await I()}\n`),T(1))}return i.command?{parsed:i,command:i.command,positionals:i.positionals}:(process.stdout.write(`${await I()}\n`),T(1))}async function gt(e,t){let i=new Set(e.providedFlags.map(e=>e.key));try{let n=U({policyOverrides:e.flags,configuredPlatform:e.flags.platform,configuredSession:e.flags.session}),r=n.lockPolicy?{...e.flags}:H(e.flags,{policyOverrides:e.flags,configuredPlatform:e.flags.platform,configuredSession:e.flags.session}),a=oe(r.stateDir),o=r.session??`default`,s=kt({command:t.command,explicitFlagKeys:i,stateDir:a.baseDir,session:o,remoteConfig:r.remoteConfig,hasResolvedSession:r.session!==void 0}),c=s?Pt(r,s.flags,i):r;return{...t,binding:n,flags:r,daemonPaths:a,sessionName:o,connectionDefaults:s,explicitFlagKeys:i,effectiveFlags:c,resolvedRuntime:s?.runtime,connectionMetadata:s?.connection,parsedBatchSteps:void 0}}catch(i){let a=r(i),o=n(a,{diagnosticId:y().diagnosticId,logPath:b({force:!0})?.path});return e.flags.json?await G({success:!1,error:o}):await W(o,{showDetails:t.debugOutputEnabled}),T(1)}}async function _t(e,n){let{daemonAuthToken:r,...i}=e.effectiveFlags;return await tt(e.positionals,{flags:{...i,leaseProvider:e.connectionDefaults?.connection?.leaseProvider},stateDir:e.daemonPaths.baseDir,session:e.effectiveFlags.session??e.sessionName,cwd:process.cwd(),env:process.env,configureDirectPortReverse:async()=>{let a=await dt({route:`react-devtools`,command:v.runtime,request:{positionals:[`port-reverse`],flags:{...i,leaseProvider:e.connectionDefaults?.connection?.leaseProvider,devicePort:8097,hostPort:8097,portReverseName:`react-devtools`},session:e.effectiveFlags.session??e.sessionName},transport:n.sendToDaemon,transportOptions:{authToken:r}});a.ok||t(a.error)}})}async function vt(t,n){if(t.command===`batch`){if(t.positionals.length>0)throw new e(`INVALID_ARGS`,`batch does not accept positional arguments.`);t.parsedBatchSteps=Dt(t.flags)}if(jt(t.command)&&(t.effectiveFlags=(await Ce({command:t.command,flags:t.effectiveFlags,stateDir:t.daemonPaths.baseDir,env:process.env})).flags),t.effectiveFlags.remoteConfig&&At(t.command)){let e=l(J(t),{transport:Q(n.sendToDaemon)}),r=await xe({command:t.command,flags:t.effectiveFlags,client:e,runtime:t.resolvedRuntime,positionals:t.positionals,batchSteps:t.parsedBatchSteps,forceRuntimePrepare:Ft(t.explicitFlagKeys)});t.effectiveFlags=r.flags,t.resolvedRuntime=r.runtime,t.connectionMetadata=r.connection}Mt({command:t.command,flags:t.effectiveFlags,runtime:t.resolvedRuntime,explicitFlagKeys:t.explicitFlagKeys,hadConnectionDefaults:!!t.connectionDefaults})&&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.
3
- `)}function J(e){let t=e.effectiveFlags,n=e.connectionMetadata;return{session:t.session,requestId:e.requestId,stateDir:t.stateDir,daemonBaseUrl:t.daemonBaseUrl,daemonAuthToken:t.daemonAuthToken,daemonTransport:t.daemonTransport,daemonServerMode:t.daemonServerMode,tenant:t.tenant,sessionIsolation:t.sessionIsolation,runId:t.runId,leaseId:t.leaseId,leaseBackend:t.leaseBackend,leaseProvider:n?.leaseProvider,clientId:n?.clientId,deviceKey:n?.deviceKey,providerApp:t.providerApp,providerOsVersion:t.providerOsVersion,providerProject:t.providerProject,providerBuild:t.providerBuild,providerSessionName:t.providerSessionName,providerDeviceOrientation:t.providerDeviceOrientation,providerGeoLocation:t.providerGeoLocation,providerTimezone:t.providerTimezone,providerLanguage:t.providerLanguage,providerLocale:t.providerLocale,providerNetworkProfile:t.providerNetworkProfile,providerCustomNetwork:t.providerCustomNetwork,providerNoResignApp:t.providerNoResignApp,awsProjectArn:t.awsProjectArn,awsDeviceArn:t.awsDeviceArn,awsAppArn:t.awsAppArn,awsRegion:t.awsRegion,awsInteractionMode:t.awsInteractionMode,runtime:e.resolvedRuntime,lockPolicy:e.binding.lockPolicy,lockPlatform:e.binding.defaultPlatform,cwd:process.cwd(),debug:e.debugOutputEnabled,cost:t.cost,responseLevel:t.responseLevel}}function yt(e){let t=e.effectiveFlags.daemonBaseUrl;return e.debugOutputEnabled&&!e.effectiveFlags.json&&!t?Rt(e.daemonPaths.logPath):null}async function bt(e){if(e.command!==`test`)return;let{createReplayTestReporterRuntime:t}=await import(`./reporting.js`);return t({debug:e.debugOutputEnabled,verbose:e.effectiveFlags.verbose,json:e.effectiveFlags.json,reporter:e.effectiveFlags.reporter,reportJunit:e.effectiveFlags.reportJunit})}async function xt(t,n,r,i){let{command:a,positionals:o,effectiveFlags:s}=t;if(a===`batch`){if(!t.parsedBatchSteps)throw new e(`INVALID_ARGS`,`batch requires --steps or --steps-file.`);let c=t.parsedBatchSteps.map((e,n)=>({...e,input:t.binding.lockPolicy&&t.flags.platform===void 0?{...e.input}:H(e.input,{policyOverrides:s,configuredPlatform:s.platform,configuredSession:s.session,inheritedPlatform:s.platform})}));if(await R({command:a,positionals:o,flags:{...s,batchSteps:c},client:n,debug:t.debugOutputEnabled,replayTestReporterRuntime:r,commandProgress:i}))return}else if(a===`runtime`)throw new e(`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 R({command:a,positionals:o,flags:s,client:n,debug:t.debugOutputEnabled,replayTestReporterRuntime:r,commandProgress:i}))return;throw new e(`INVALID_ARGS`,Et(a))}async function St(e,t,i){let a=r(e),o=n(a,{diagnosticId:y().diagnosticId,logPath:b({force:!0})?.path});if(t.command===`close`&&Ot(a)){t.effectiveFlags.json&&await G({success:!0,data:{closed:`session`,source:`no-daemon`}});return}t.effectiveFlags.json?await G({success:!1,error:o}):(await W(o,{showDetails:t.debugOutputEnabled}),t.debugOutputEnabled&&Ct(t,o)),i&&i(),await T(1)}const Y=64e3;function Ct(e,t){if(!e.effectiveFlags.daemonBaseUrl){X(`daemon log`,e.daemonPaths.logPath);return}let n=t.diagnosticsRecord;n&&X(`remote diagnostics`,se(e.daemonPaths.baseDir,n))}function X(e,t){try{if(E.existsSync(t)){let n=E.readFileSync(t,`utf8`).split(`
3
+ `)}function J(e){let t=e.effectiveFlags,n=e.connectionMetadata;return{session:t.session,requestId:e.requestId,stateDir:t.stateDir,daemonBaseUrl:t.daemonBaseUrl,daemonAuthToken:t.daemonAuthToken,daemonTransport:t.daemonTransport,daemonServerMode:t.daemonServerMode,tenant:t.tenant,sessionIsolation:t.sessionIsolation,runId:t.runId,leaseId:t.leaseId,leaseBackend:t.leaseBackend,leaseProvider:n?.leaseProvider,clientId:n?.clientId,deviceKey:n?.deviceKey,providerApp:t.providerApp,providerOsVersion:t.providerOsVersion,providerProject:t.providerProject,providerBuild:t.providerBuild,providerSessionName:t.providerSessionName,providerDeviceOrientation:t.providerDeviceOrientation,providerGeoLocation:t.providerGeoLocation,providerTimezone:t.providerTimezone,providerAppiumVersion:t.providerAppiumVersion,providerLanguage:t.providerLanguage,providerLocale:t.providerLocale,providerNetworkProfile:t.providerNetworkProfile,providerCustomNetwork:t.providerCustomNetwork,providerNoResignApp:t.providerNoResignApp,awsProjectArn:t.awsProjectArn,awsDeviceArn:t.awsDeviceArn,awsAppArn:t.awsAppArn,awsRegion:t.awsRegion,awsInteractionMode:t.awsInteractionMode,runtime:e.resolvedRuntime,lockPolicy:e.binding.lockPolicy,lockPlatform:e.binding.defaultPlatform,cwd:process.cwd(),debug:e.debugOutputEnabled,cost:t.cost,responseLevel:t.responseLevel}}function yt(e){let t=e.effectiveFlags.daemonBaseUrl;return e.debugOutputEnabled&&!e.effectiveFlags.json&&!t?Rt(e.daemonPaths.logPath):null}async function bt(e){if(e.command!==`test`)return;let{createReplayTestReporterRuntime:t}=await import(`./reporting.js`);return t({debug:e.debugOutputEnabled,verbose:e.effectiveFlags.verbose,json:e.effectiveFlags.json,reporter:e.effectiveFlags.reporter,reportJunit:e.effectiveFlags.reportJunit})}async function xt(t,n,r,i){let{command:a,positionals:o,effectiveFlags:s}=t;if(a===`batch`){if(!t.parsedBatchSteps)throw new e(`INVALID_ARGS`,`batch requires --steps or --steps-file.`);let c=t.parsedBatchSteps.map((e,n)=>({...e,input:t.binding.lockPolicy&&t.flags.platform===void 0?{...e.input}:H(e.input,{policyOverrides:s,configuredPlatform:s.platform,configuredSession:s.session,inheritedPlatform:s.platform})}));if(await R({command:a,positionals:o,flags:{...s,batchSteps:c},client:n,debug:t.debugOutputEnabled,replayTestReporterRuntime:r,commandProgress:i}))return}else if(a===`runtime`)throw new e(`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 R({command:a,positionals:o,flags:s,client:n,debug:t.debugOutputEnabled,replayTestReporterRuntime:r,commandProgress:i}))return;throw new e(`INVALID_ARGS`,Et(a))}async function St(e,t,i){let a=r(e),o=n(a,{diagnosticId:y().diagnosticId,logPath:b({force:!0})?.path});if(t.command===`close`&&Ot(a)){t.effectiveFlags.json&&await G({success:!0,data:{closed:`session`,source:`no-daemon`}});return}t.effectiveFlags.json?await G({success:!1,error:o}):(await W(o,{showDetails:t.debugOutputEnabled}),t.debugOutputEnabled&&Ct(t,o)),i&&i(),await T(1)}const Y=64e3;function Ct(e,t){if(!e.effectiveFlags.daemonBaseUrl){X(`daemon log`,e.daemonPaths.logPath);return}let n=t.diagnosticsRecord;n&&X(`remote diagnostics`,se(e.daemonPaths.baseDir,n))}function X(e,t){try{if(E.existsSync(t)){let n=E.readFileSync(t,`utf8`).split(`
4
4
  `),r=n.slice(Math.max(0,n.length-200)).join(`
5
5
  `);r.length>Y&&(r=r.slice(r.length-Y)),r.trim().length>0&&process.stderr.write(`\n[${e}]\n${r}\n`)}}catch{}}function wt(e){try{let t=M(e);return Z(t.command??``,t.providedFlags)}catch{return e.includes(`--debug`)||e.includes(`-v`)||e.includes(`--verbose`)}}function Tt(e){let t=j(e);return t?`Unknown command: ${e}. Did you mean ${t}?`:`Unknown command: ${e}`}function Et(e){return _(e)?(S({level:`error`,phase:`cli_known_command_unhandled`,data:{command:e}}),`Command is registered but no CLI handler accepted it: ${e}`):`Unknown command: ${e}`}function Z(e,t){return t.some(t=>t.key===`verbose`&&(t.token===`--debug`||t.token===`-v`||e!==`test`))}function Dt(t){let n=``;if(t.steps)n=t.steps;else if(t.stepsFile)try{n=E.readFileSync(t.stepsFile,`utf8`)}catch(n){let r=n instanceof Error?n.message:String(n);throw new e(`INVALID_ARGS`,`Failed to read --steps-file ${t.stepsFile}: ${r}`)}return rt(n)}function Ot(e){return e.code===`COMMAND_FAILED`?e.details?.kind===`daemon_startup_failed`?!0:e.message.toLowerCase().includes(`failed to start daemon`)?typeof e.details?.infoPath==`string`||typeof e.details?.lockPath==`string`:!1:!1}function kt(e){return e.command===`connect`||e.command===`connection`||e.command===`daemon`||e.command===`proxy`?null:Se({stateDir:e.stateDir,session:e.session,remoteConfig:e.remoteConfig,cwd:process.cwd(),env:process.env,allowActiveFallback:!e.explicitFlagKeys.has(`session`)&&(!e.remoteConfig||e.command===`disconnect`||!e.hasResolvedSession),validateRemoteConfigHash:e.command!==`disconnect`})}function At(e){return!mt.has(e)}function jt(e){return e!==`auth`&&e!==`connection`&&e!==`daemon`&&e!==`device`&&e!==`proxy`}function Mt(e){return e.command!==`open`||e.runtime||e.flags.bundleUrl||e.flags.metroHost||e.flags.metroPort||e.flags.remoteConfig||e.hadConnectionDefaults?!1:Nt(e.explicitFlagKeys)}function Nt(e){return e.has(`daemonBaseUrl`)||e.has(`daemonTransport`)||e.has(`tenant`)||e.has(`sessionIsolation`)||e.has(`runId`)||e.has(`leaseId`)||e.has(`leaseBackend`)}function Pt(e,t,n){let r={...e};for(let[e,i]of Object.entries(t))i!==void 0&&(n.has(e)||(r[e]=i));return r}function Ft(e){for(let t of pt)if(e.has(t))return!0;return!1}function It(e){let{command:t,flags:n,replayTestReporterRuntime:r,transport:i}=e;if(n.json)return Q(i);let a=t===`test`&&r?r.onProgress:Ge(e.commandProgress);return async(e,n)=>{let r={...n,onProgress:a};return await $(i,{...e,meta:{...e.meta,requestProgress:t===`test`?`replay-test`:`command`}},r)}}function Q(e){return async(t,n)=>await $(e,t,n)}async function $(e,t,n){return await e(t,n)}function Lt(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(n===`--session`){let n=e[t+1]?.trim();return n&&!n.startsWith(`-`)?n:null}}return null}D(process.argv[1]??``).href===import.meta.url&&K(process.argv.slice(2)).catch(async e=>{let t=r(e);await W(n(t),{showDetails:!0}),await T(1)});function Rt(e){try{let t=E.existsSync(e)?E.statSync(e).size:0,n=!1,r=setInterval(()=>{if(!n&&E.existsSync(e))try{let n=E.statSync(e);if(n.size<t&&(t=0),n.size<=t)return;let r=E.openSync(e,`r`);try{let e=Buffer.alloc(n.size-t);E.readSync(r,e,0,e.length,t),t=n.size,e.length>0&&process.stdout.write(e.toString(`utf8`))}finally{E.closeSync(r)}}catch{}},200);return()=>{n=!0,clearInterval(r)}}catch{return null}}export{K as runCli};
@@ -42,7 +42,7 @@ type AgentDeviceClientConfig = RemoteConnectionProfileFields & CloudProviderProf
42
42
  iosXctestDerivedDataPath?: string;
43
43
  iosXctestEnvDir?: string;
44
44
  };
45
- type AgentDeviceRequestOverrides = Pick<AgentDeviceClientConfig, 'session' | 'lockPolicy' | 'lockPlatform' | 'requestId' | 'daemonBaseUrl' | 'daemonAuthToken' | 'daemonTransport' | 'daemonServerMode' | 'tenant' | 'sessionIsolation' | 'runId' | 'leaseId' | 'leaseBackend' | 'leaseProvider' | 'deviceKey' | 'clientId' | 'providerApp' | 'providerOsVersion' | 'providerProject' | 'providerBuild' | 'providerSessionName' | 'providerDeviceOrientation' | 'providerGeoLocation' | 'providerTimezone' | 'providerLanguage' | 'providerLocale' | 'providerNetworkProfile' | 'providerCustomNetwork' | 'providerNoResignApp' | 'awsProjectArn' | 'awsDeviceArn' | 'awsAppArn' | 'awsRegion' | 'awsInteractionMode' | 'leaseTtlMs' | 'cwd' | 'debug' | 'cost' | 'responseLevel' | 'iosXctestrunFile' | 'iosXctestDerivedDataPath' | 'iosXctestEnvDir'>;
45
+ type AgentDeviceRequestOverrides = Pick<AgentDeviceClientConfig, 'session' | 'lockPolicy' | 'lockPlatform' | 'requestId' | 'daemonBaseUrl' | 'daemonAuthToken' | 'daemonTransport' | 'daemonServerMode' | 'tenant' | 'sessionIsolation' | 'runId' | 'leaseId' | 'leaseBackend' | 'leaseProvider' | 'deviceKey' | 'clientId' | 'providerApp' | 'providerOsVersion' | 'providerProject' | 'providerBuild' | 'providerSessionName' | 'providerDeviceOrientation' | 'providerGeoLocation' | 'providerTimezone' | 'providerAppiumVersion' | 'providerLanguage' | 'providerLocale' | 'providerNetworkProfile' | 'providerCustomNetwork' | 'providerNoResignApp' | 'awsProjectArn' | 'awsDeviceArn' | 'awsAppArn' | 'awsRegion' | 'awsInteractionMode' | 'leaseTtlMs' | 'cwd' | 'debug' | 'cost' | 'responseLevel' | 'iosXctestrunFile' | 'iosXctestDerivedDataPath' | 'iosXctestEnvDir'>;
46
46
  type AgentDeviceIdentifiers = {
47
47
  session?: string;
48
48
  deviceId?: string;
@@ -1,4 +1,4 @@
1
- import{C as e}from"./sdk-contracts.js";import{p as t,r as n,u as r}from"./registry.js";import{r as i}from"./command-metadata.js";const a={cdp:{text:{summary:`Inspect CDP targets, JS heap, and leaks`,description:`Run CDP commands for React Native diagnostics, JS heap usage, heap snapshots, and leak analysis`},usageOverride:`cdp [...args]`,listUsageOverride:`cdp`,positionalArgs:[`args?`],allowsExtraPositionals:!0,supportedFlags:r},auth:{text:{summary:`Manage cloud login state`,description:`Manage cloud login state used by remote daemon and cloud device workflows.`},usageOverride:`auth status|login|logout`,listUsageOverride:`auth`,positionalArgs:[`status|login|logout`],supportedFlags:[`remoteConfig`,`stateDir`]},daemon:{text:{summary:`Stop a local daemon and clean up resources`,description:`Stop a local daemon after verifying its PID/start-time identity. Use --clean to remove retained Apple runner processes and leases owned by that daemon.`},usageOverride:`daemon stop [--state-dir <path>]`,listUsageOverride:`daemon stop`,positionalArgs:[`stop`],allowedFlags:[`clean`],supportedFlags:[`stateDir`]},device:{text:{summary:`Inspect and recover enforced local device ownership without a daemon`,description:`Inspect enforced host-local device ownership claims without starting or contacting a daemon; status --stale only inspects proven-stale claims. release --stale settles a provably dead owner through exact-owner resource reconciliation and clears its claim last — live and uncertain owners always fail closed. Automatic reclamation still occurs during open and daemon startup.`},usageOverride:`device status|release [--platform <platform>] [--udid <udid>] [--serial <serial>]`,listUsageOverride:`device status`,positionalArgs:[`status|release`],allowedFlags:[`stale`],supportedFlags:[`platform`,`device`,`udid`,`serial`]},connect:{text:{summary:`Configure remote or provider state`,description:`Configure remote access without allocating a device. Direct providers validate credentials/resources before saving state and print the exact device/app preparation needed before open. AGENT_DEVICE_CLOUD_BASE_URL is the bridge/control-plane API origin; use AGENT_DEVICE_DAEMON_AUTH_TOKEN=adc_live_... for CI/service-token automation.`},usageOverride:`connect [cloud|proxy|limrun|browserstack|aws-device-farm] [--remote-config <path>] [--daemon-base-url <url>] [--tenant <id>] [--run-id <id>] [--lease-id <id>] [--lease-backend <backend>] [--force] [--no-login]`,usageFlags:[],listUsageOverride:`connect`,positionalArgs:[`provider?`],allowedFlags:`remoteConfig.daemonBaseUrl.tenant.runId.leaseId.leaseBackend.providerApp.providerOsVersion.providerProject.providerBuild.providerSessionName.providerDeviceOrientation.providerGeoLocation.providerTimezone.providerLanguage.providerLocale.providerNetworkProfile.providerCustomNetwork.providerNoResignApp.awsProjectArn.awsDeviceArn.awsAppArn.awsRegion.awsInteractionMode.force.noLogin`.split(`.`),supportedFlags:[`stateDir`,`daemonAuthToken`,`session`,`platform`,`device`,...t,`launchUrl`]},connection:{text:{summary:`Inspect the saved remote connection`,description:`Inspect active remote connection state`},usageOverride:`connection status`,listUsageOverride:`connection`,positionalArgs:[`status`],supportedFlags:[`remoteConfig`,`stateDir`,`session`]},disconnect:{text:{summary:`Clear remote connection state and release leases`,description:`Disconnect remote daemon state, stop owned Metro companion, and release lease`},listUsageOverride:`disconnect`,allowedFlags:[`shutdown`],supportedFlags:[`remoteConfig`,`stateDir`,`session`]},mcp:{text:{summary:`Start MCP server`,description:`Start the official stdio MCP server. It exposes structured command tools backed by the agent-device client.`}},proxy:{text:{summary:`Expose a local daemon through an HTTP tunnel`,description:`Expose the local daemon HTTP contract through a tunnel-friendly reverse proxy.
1
+ import{C as e}from"./sdk-contracts.js";import{p as t,r as n,u as r}from"./registry.js";import{r as i}from"./command-metadata.js";const a={cdp:{text:{summary:`Inspect CDP targets, JS heap, and leaks`,description:`Run CDP commands for React Native diagnostics, JS heap usage, heap snapshots, and leak analysis`},usageOverride:`cdp [...args]`,listUsageOverride:`cdp`,positionalArgs:[`args?`],allowsExtraPositionals:!0,supportedFlags:r},auth:{text:{summary:`Manage cloud login state`,description:`Manage cloud login state used by remote daemon and cloud device workflows.`},usageOverride:`auth status|login|logout`,listUsageOverride:`auth`,positionalArgs:[`status|login|logout`],supportedFlags:[`remoteConfig`,`stateDir`]},daemon:{text:{summary:`Stop a local daemon and clean up resources`,description:`Stop a local daemon after verifying its PID/start-time identity. Use --clean to remove retained Apple runner processes and leases owned by that daemon.`},usageOverride:`daemon stop [--state-dir <path>]`,listUsageOverride:`daemon stop`,positionalArgs:[`stop`],allowedFlags:[`clean`],supportedFlags:[`stateDir`]},device:{text:{summary:`Inspect and recover enforced local device ownership without a daemon`,description:`Inspect enforced host-local device ownership claims without starting or contacting a daemon; status --stale only inspects proven-stale claims. release --stale settles a provably dead owner through exact-owner resource reconciliation and clears its claim last — live and uncertain owners always fail closed. Automatic reclamation still occurs during open and daemon startup.`},usageOverride:`device status|release [--platform <platform>] [--udid <udid>] [--serial <serial>]`,listUsageOverride:`device status`,positionalArgs:[`status|release`],allowedFlags:[`stale`],supportedFlags:[`platform`,`device`,`udid`,`serial`]},connect:{text:{summary:`Configure remote or provider state`,description:`Configure remote access without allocating a device. Direct providers validate credentials/resources before saving state and print the exact device/app preparation needed before open. AGENT_DEVICE_CLOUD_BASE_URL is the bridge/control-plane API origin; use AGENT_DEVICE_DAEMON_AUTH_TOKEN=adc_live_... for CI/service-token automation.`},usageOverride:`connect [cloud|proxy|limrun|browserstack|aws-device-farm] [--remote-config <path>] [--daemon-base-url <url>] [--tenant <id>] [--run-id <id>] [--lease-id <id>] [--lease-backend <backend>] [--force] [--no-login]`,usageFlags:[],listUsageOverride:`connect`,positionalArgs:[`provider?`],allowedFlags:`remoteConfig.daemonBaseUrl.tenant.runId.leaseId.leaseBackend.providerApp.providerOsVersion.providerProject.providerBuild.providerSessionName.providerDeviceOrientation.providerGeoLocation.providerTimezone.providerAppiumVersion.providerLanguage.providerLocale.providerNetworkProfile.providerCustomNetwork.providerNoResignApp.awsProjectArn.awsDeviceArn.awsAppArn.awsRegion.awsInteractionMode.force.noLogin`.split(`.`),supportedFlags:[`stateDir`,`daemonAuthToken`,`session`,`platform`,`device`,...t,`launchUrl`]},connection:{text:{summary:`Inspect the saved remote connection`,description:`Inspect active remote connection state`},usageOverride:`connection status`,listUsageOverride:`connection`,positionalArgs:[`status`],supportedFlags:[`remoteConfig`,`stateDir`,`session`]},disconnect:{text:{summary:`Clear remote connection state and release leases`,description:`Disconnect remote daemon state, stop owned Metro companion, and release lease`},listUsageOverride:`disconnect`,allowedFlags:[`shutdown`],supportedFlags:[`remoteConfig`,`stateDir`,`session`]},mcp:{text:{summary:`Start MCP server`,description:`Start the official stdio MCP server. It exposes structured command tools backed by the agent-device client.`}},proxy:{text:{summary:`Expose a local daemon through an HTTP tunnel`,description:`Expose the local daemon HTTP contract through a tunnel-friendly reverse proxy.
2
2
 
3
3
  Run this on the host that has access to simulators/devices, expose the printed local proxy URL through a tunnel, then point another machine at the tunnel URL with connect proxy.
4
4
 
@@ -1 +1 @@
1
- import{n as e,t}from"./path-resolution.js";import"./file.js";import{a as n,n as r}from"./version.js";import i from"node:path";import a from"node:fs";import o from"node:crypto";function s(e,t={}){let n=c(e,t);return{baseDir:n,infoPath:i.join(n,`daemon.json`),lockPath:i.join(n,`daemon.lock`),logPath:i.join(n,`daemon.log`),allocationsDir:i.join(n,`allocations`),sessionsDir:i.join(n,`sessions`)}}function c(t,n){let r=(t??``).trim();return r?e(r,{env:n.env}):l(n)}function l(e={}){let a=i.join(t(`~`,{env:e.env}),`.agent-device`),o=e.projectRoot??r();return n(o)?i.join(a,`dev`,u(o)):a}function u(e){let t=d(e),n=i.basename(t).replaceAll(/[^a-zA-Z0-9._-]+/g,`-`),r=o.createHash(`sha1`).update(t).digest(`hex`).slice(0,12);return`${n||`agent-device`}-${r}`}function d(e){try{return a.realpathSync.native(e)}catch{return i.resolve(e)}}function f(e){let t=(e??``).trim().toLowerCase();return t===`http`?`http`:t===`dual`?`dual`:`socket`}function p(e){let t=(e??``).trim().toLowerCase();return t===`auto`?`auto`:t===`socket`?`socket`:t===`http`?`http`:`auto`}function m(e){return(e??``).trim().toLowerCase()===`tenant`?`tenant`:`none`}function h(e){if(!e)return;let t=e.trim();if(t&&/^[a-zA-Z0-9._-]{1,128}$/.test(t))return t}export{m as a,p as i,s as n,f as r,h as t};
1
+ const e=18e4,t=6e4,n=6e4,r=2e4,i=12e4,a=1e4,o=15e3,s=2e4,c=15e3,l=2e4,u=1e3,d=5e3;export{l as a,u as c,s as d,o as f,i,d as l,e as n,t as o,r,a as s,n as t,c as u};
@@ -1 +1 @@
1
- import{C as e,o as t}from"./sdk-contracts.js";import{a as n,l as r,v as i,x as a}from"./sdk-device.js";import{c as o,i as s,s as c}from"./lease-scope.js";import{n as l,t as u}from"./catalog.js";import{t as d}from"./sdk-remote-config.js";import{t as f}from"./prepare-kind.js";import{r as p}from"./diagnostics.js";import{O as m}from"./owner-identity.js";import{f as h}from"./exec.js";import"./file.js";import"./diagnostics2.js";import"./command.js";import{n as ee}from"./config.js";import{_ as g}from"./base-url.js";import{i as _,r as v}from"./client-metro-companion.js";import{n as y}from"./metro2.js";import{n as te,r as b,t as ne}from"./remote-config2.js";import{n as x,t as S}from"./providers.js";import C from"node:path";import w from"node:fs";import T from"node:crypto";const E={slug:`react-devtools-companion`,runArg:g,displayName:`React DevTools companion`};async function re(e){return await v({...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 D(e){return await _({...e,definition:E})}function O(e){return e===`android-instance`||e===`ios-instance`}function ie(e){return[`exec`,`--yes`,`--package`,`agent-cdp@1.6.1`,`--`,`agent-cdp`,...e]}function ae(e){return e.some(e=>e===`--url`||e.startsWith(`--url=`))}function k(e){return e[0]===`target`&&(e[1]===`list`||e[1]===`select`)&&!ae(e)}function oe(e){let t=new URL(e);t.search=``,t.hash=``;let n=t.pathname.replace(/\/+$/,``);return t.pathname=n.endsWith(`/index.bundle`)?n.slice(0,-13)||`/`:n||`/`,t.toString().replace(/\/+$/,``)}function se(e){let t=e?.metroPublicBaseUrl?.trim();return t?oe(t):null}function ce(t,n={}){if(!k(t)||!n.flags?.metroProxyBaseUrl||!O(n.flags.leaseBackend))return t;let r=se(n.flags);if(!r)throw new e(`INVALID_ARGS`,`cdp remote bridge target discovery requires a React Native dev-server public base URL.`,{hint:`Include metroPublicBaseUrl in the remote config so cdp can reach the local or tunneled Metro/Re.Pack CDP endpoint without bridge proxy authentication.`});return[...t,`--url`,r]}async function le(e,t={}){let n=ce(e,t);return(await h(`npm`,ie(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 A(e){let t=L(e);if(!w.existsSync(t))return null;let n;try{n=JSON.parse(w.readFileSync(t,`utf8`))}catch(t){return H(e,t),null}return ge(n)?n:(H(e),null)}function j(e){let t=L({stateDir:e.stateDir,session:e.state.session});w.mkdirSync(C.dirname(t),{recursive:!0}),V(t,e.state),V(R(e.stateDir),{session:e.state.session})}function M(e){return{baseUrl:me(e.daemonBaseUrl),transport:e.daemonTransport,serverMode:e.daemonServerMode}}function N(e){w.rmSync(L(e),{force:!0});let t=R(e.stateDir);B(e.stateDir)===e.session&&w.rmSync(t,{force:!0})}function ue(t){let n=t.validateRemoteConfigHash??!0,r=t.remoteConfig?te({configPath:t.remoteConfig,cwd:t.cwd,env:t.env}):void 0,i=A(t)??(t.allowActiveFallback?z({stateDir:t.stateDir}):null);if(!i||r&&i.remoteConfigPath!==r)return null;if(n&&I(i.remoteConfigPath)!==i.remoteConfigHash)throw new e(`INVALID_ARGS`,`Active remote connection config changed. Run agent-device connect --force to refresh it.`,{remoteConfig:i.remoteConfigPath});let a=pe(i,t),l=s(i);return{runtime:i.runtime,connection:o(l),flags:{...a,remoteConfig:i.remoteConfigPath,daemonBaseUrl:i.daemon?.baseUrl??a.daemonBaseUrl,daemonAuthToken:a.daemonAuthToken,daemonTransport:i.daemon?.transport??a.daemonTransport,daemonServerMode:i.daemon?.serverMode??a.daemonServerMode,...c(l),sessionIsolation:`tenant`,session:i.session,platform:i.platform??a.platform,target:i.target??a.target}}}function P(e){return o(s(e))}function F(e,t){return{leaseProvider:e.leaseProvider??t.leaseProvider,clientId:e.clientId??t.clientId,deviceKey:e.deviceKey??t.deviceKey}}function de(e,t){return!t||(t.leaseProvider===void 0||e.leaseProvider===t.leaseProvider)&&(t.clientId===void 0||e.clientId===t.clientId)}function I(t){try{return T.createHash(`sha256`).update(w.readFileSync(t)).digest(`hex`)}catch(n){throw new e(`INVALID_ARGS`,`Remote config file not found: ${t}`,{cause:n instanceof Error?n.message:String(n)})}}function L(e){return C.join(e.stateDir,`remote-connections`,`${he(e.session)}.json`)}function R(e){return C.join(e,`remote-connections`,`.active-session.json`)}function z(e){let t=B(e.stateDir);return t?A({stateDir:e.stateDir,session:t}):null}function B(e){let t=R(e);if(w.existsSync(t))try{let e=JSON.parse(w.readFileSync(t,`utf8`));return typeof e.session==`string`?e.session:void 0}catch{return}}function fe(e){if(e)return T.createHash(`sha256`).update(e).digest(`hex`).slice(0,12)}function pe(e,t){try{return b({configPath:e.remoteConfigPath,cwd:t.cwd,env:t.env}).profile}catch(e){if(t.validateRemoteConfigHash===!1)return{};throw e}}function V(e,t){m({destination:e,contents:`${JSON.stringify(t,null,2)}\n`,mode:384})}function me(e){if(!e)return;let t=new URL(e);t.username=``,t.password=``;for(let e of Array.from(t.searchParams.keys()))/(auth|key|password|secret|token)/i.test(e)&&t.searchParams.delete(e);return t.toString().replace(/\/+$/,``)}function H(e,t){p({level:`warn`,phase:`remote_connection_state_invalid`,data:{session:e.session,cause:t instanceof Error?t.message:t?String(t):void 0}}),N(e)}function he(e){let t=e.replaceAll(/[^a-zA-Z0-9._-]/g,`_`);return t?t===e?t:`${t}-${T.createHash(`sha256`).update(e).digest(`hex`).slice(0,8)}`:`default`}function ge(e){if(!e||typeof e!=`object`||Array.isArray(e))return!1;let t=e;return t.version===1&&_e(t,[`session`,`remoteConfigPath`,`remoteConfigHash`,`tenant`,`runId`,`connectedAt`,`updatedAt`])&&ve(t,[`leaseId`,`leaseBackend`,`leaseProvider`,`deviceKey`,`clientId`])&&ye(t.daemon)}function _e(e,t){return t.every(t=>typeof e[t]==`string`)}function ve(e,t){return t.every(t=>e[t]===void 0||typeof e[t]==`string`)}function ye(e){return e===void 0?!0:!e||typeof e!=`object`||Array.isArray(e)?!1:be(e)}function be(e){let t=e;return(t.baseUrl===void 0||typeof t.baseUrl==`string`)&&(t.authToken===void 0||typeof t.authToken==`string`)&&(t.transport===void 0||typeof t.transport==`string`)&&(t.serverMode===void 0||typeof t.serverMode==`string`)}const xe=d.map(e=>e.key);function U(e){let t={};for(let n of xe){let r=e[n];r!==void 0&&(t[n]=r)}return t}function Se(e){return e.remoteConfig?{...U(b({configPath:e.remoteConfig,cwd:e.cwd,env:e.env}).profile),remoteConfig:e.remoteConfig}:{}}function Ce(e){return e===`cloud`||e===`proxy`||W(e)}function W(e){return e===`limrun`||x(e)}function we(){return[`cloud`,`proxy`,S.browserStack,S.awsDeviceFarm,`limrun`].join(`, `)}function G(e){let t=W(e),n=x(e);return{leaseKind:e===`proxy`?`proxy`:t?`direct-device-provider`:`remote-provider`,requiresAppAttachment:e===S.awsDeviceFarm,requiresRemoteDaemon:!t,supportsArtifacts:n,supportsDeferredAppSelection:e===`limrun`,supportsDirectPortReverse:e===`limrun`,usesCloudWebDriverLease:n}}function K(e){return{providerDeviceOrientation:e.providerDeviceOrientation,providerGeoLocation:e.providerGeoLocation,providerTimezone:e.providerTimezone,providerLanguage:e.providerLanguage,providerLocale:e.providerLocale,providerNetworkProfile:e.providerNetworkProfile,providerCustomNetwork:e.providerCustomNetwork,providerNoResignApp:e.providerNoResignApp}}function Te(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,launchUrl:e.launchUrl}}const q=new Set([`artifacts`,`connect`,`connection`,`close`,`disconnect`,`metro`,`session`]),J=new Set([`open`]),Ee=new Set([l.open,l.install,l.reinstall,u.installSource]);async function De(t){let{command:n,flags:r,client:i}=t;if(!r.remoteConfig)return{flags:r,runtime:t.runtime};let a=ee(r.stateDir).baseDir,o=b({configPath:r.remoteConfig,cwd:process.cwd(),env:process.env}),s={...U(o.profile),...r,remoteConfig:o.resolvedPath},c=A({stateDir:a,session:s.session??`default`});if(c&&c.remoteConfigPath!==o.resolvedPath)throw new e(`INVALID_ARGS`,`A different remote connection is already active for this session. Run connect --force or disconnect before using a different --remote-config.`,{session:c.session,activeRemoteConfig:c.remoteConfigPath,requestedRemoteConfig:o.resolvedPath});let u=c??Qe(s,o.resolvedPath,o.profile),d={...s,session:u.session},f=G(u.leaseProvider).supportsDeferredAppSelection,p=f&&n===l.open?t.positionals?.[0]:void 0;f&&delete d.providerApp;let m=Ze(u.runtime,d.platform)??t.runtime,h=u,g=!c,_,v=Fe(h);if(v.shouldAllocate(n)){let e=await Me({command:n,client:i,state:u,nextState:h,nextFlags:d,initialApp:p,policy:v});h=e.state,g||=e.changed,_=e.acquiredLeaseForCleanup}let y=await Oe({command:n,flags:d,client:i,state:u,nextState:h,runtime:m,positionals:t.positionals,batchSteps:t.batchSteps,forceRuntimePrepare:t.forceRuntimePrepare});return h=y.state,m=y.runtime,g||=y.changed,await je({changed:g,stateDir:a,state:h,client:i,acquiredLeaseForCleanup:_,preparedMetroCleanupOnFailure:y.preparedMetroCleanupOnFailure,metroCleanupToStop:y.metroCleanupToStop}),{flags:{...d,session:h.session,leaseId:h.leaseId,leaseBackend:h.leaseBackend,platform:h.platform??d.platform,target:h.target??d.target},runtime:m,connection:P(h)}}async function Oe(t){let{command:n,flags:r,state:i,client:a}=t,o=ke(t.nextState,r),s=t.runtime;if(!Je(n,r,t.batchSteps,t.positionals)||!$(r)||!Ae(t.forceRuntimePrepare,s,r.platform))return{state:o,runtime:s,changed:!1};if(!o.leaseId)throw new e(`INVALID_ARGS`,`${n} requires a resolved remote lease before Metro runtime can be prepared.`);let c=await Be(r,a,i.remoteConfigPath,i.session,{tenantId:i.tenant,runId:i.runId,leaseId:o.leaseId}),l=!Xe(o.metro,c.cleanup);return o={...o,runtime:c.runtime,metro:c.cleanup,updatedAt:new Date().toISOString()},{state:o,runtime:c.runtime,changed:!0,metroCleanupToStop:l?t.nextState.metro:void 0,preparedMetroCleanupOnFailure:l?c.cleanup:void 0}}function ke(e,t){return e.leaseId||!t.leaseId?e:{...e,leaseId:t.leaseId,leaseBackend:t.leaseBackend}}function Ae(e,t,n){return e===!0||!t||!Ye(t,n)}async function je(e){if(e.changed)try{j({stateDir:e.stateDir,state:e.state})}catch(t){throw await Y(e.preparedMetroCleanupOnFailure),await Ke(e.client,e.state,e.acquiredLeaseForCleanup),t}await Y(e.metroCleanupToStop)}async function Me(e){let{command:t,client:n,state:r,nextFlags:i,policy:a}=e,o=r.leaseBackend??Q(i),s=e.nextState,c=await a.resolveLeaseState({command:t,client:n,state:s,flags:i,leaseBackend:o});s=c.state,c.device&&tt(i,c.device);let l=s.leaseBackend??o??qe(i,t);at(r,i,l);let u=await $e(n,s,l,a,i,e.initialApp),d=u.lease;return i.leaseId=d.leaseId,i.leaseBackend=l,i.platform=s.platform??i.platform,i.target=s.target??i.target,Ne(s,d,l)?{state:s,changed:!1,acquiredLeaseForCleanup:u.acquired?d:void 0}:{state:Pe(s,d,l,i),changed:!0,acquiredLeaseForCleanup:u.acquired?d:void 0}}function Ne(e,t,n){return e.leaseId===t.leaseId&&e.leaseBackend===n&&e.deviceKey===(t.deviceKey??e.deviceKey)}function Pe(e,t,n,r){let i=F(t,e);return{...e,leaseId:t.leaseId,leaseBackend:n,...i,platform:e.platform??r.platform,target:e.target??r.target,updatedAt:new Date().toISOString()}}function Fe(e){let t=G(e.leaseProvider);return t.leaseKind===`proxy`?Re:t.supportsDeferredAppSelection?Ie:t.usesCloudWebDriverLease?ze:Le}const Ie={shouldAllocate:e=>e!==l.apps&&!q.has(e),ttlMs:()=>void 0,resolveLeaseState:async e=>({state:e.state})},Le={shouldAllocate:e=>!q.has(e),ttlMs:()=>void 0,resolveLeaseState:async e=>({state:e.state})},Re={shouldAllocate:e=>e!==`devices`&&!q.has(e),ttlMs:()=>3e5,resolveLeaseState:et},ze={shouldAllocate:e=>!q.has(e),ttlMs:()=>6e5,resolveLeaseState:async e=>({state:e.state})};async function Be(t,n,r,i,a){if(!t.metroProjectRoot&&!t.metroPublicBaseUrl&&!t.metroProxyBaseUrl)return{};if(t.platform!==`ios`&&t.platform!==`android`)throw new e(`INVALID_ARGS`,`Deferred Metro preparation requires platform "ios" or "android".`);if(!t.metroPublicBaseUrl&&!t.metroProxyBaseUrl)throw new e(`INVALID_ARGS`,`Deferred Metro preparation requires metroPublicBaseUrl or metroProxyBaseUrl when Metro settings are provided.`);let o=await n.metro.prepare({projectRoot:t.metroProjectRoot,kind:f(t.metroKind),publicBaseUrl:t.metroPublicBaseUrl,proxyBaseUrl:t.metroProxyBaseUrl,bearerToken:t.metroBearerToken,bridgeScope:a,launchUrl:t.launchUrl,companionProfileKey:r,companionConsumerKey:i,port:t.metroPreparePort,listenHost:t.metroListenHost,statusHost:t.metroStatusHost,startupTimeoutMs:t.metroStartupTimeoutMs,probeTimeoutMs:t.metroProbeTimeoutMs,reuseExisting:!t.metroNoReuseExisting&&void 0,installDependenciesIfNeeded:!t.metroNoInstallDeps&&void 0,runtimeFilePath:t.metroRuntimeFile});return{runtime:t.platform===`ios`?o.iosRuntime:o.androidRuntime,cleanup:t.metroProxyBaseUrl?{projectRoot:o.projectRoot,profileKey:r,consumerKey:i}:void 0}}async function Y(e){if(e)try{await y(e)}catch{}}async function Ve(e){try{await D({projectRoot:process.cwd(),stateDir:e.stateDir,profileKey:e.state.remoteConfigPath,consumerKey:e.state.session})}catch{}}async function X(e,t,n){return t.leaseId?await e.leases.release({tenant:t.tenant,runId:t.runId,leaseId:t.leaseId,leaseBackend:t.leaseBackend,daemonBaseUrl:t.daemon?.baseUrl,daemonAuthToken:n,daemonTransport:t.daemon?.transport,daemonServerMode:t.daemon?.serverMode,...P(t)}):{released:!1}}function He(e){let t=Ue(e.previous,e.cwd,e.env);return t?{canAuthenticate:!0,daemonAuthToken:t}:e.previous.daemon?.baseUrl===e.nextDaemonBaseUrl?{canAuthenticate:!0,daemonAuthToken:e.ambientDaemonAuthToken}:{canAuthenticate:!1}}function Ue(e,t,n){try{let{profile:r}=ne({configPath:e.remoteConfigPath,cwd:t,env:n});return r.daemonAuthToken&&We(e,r.daemonBaseUrl)?r.daemonAuthToken:void 0}catch{return}}function We(e,t){let n=M({daemonBaseUrl:t})?.baseUrl;return n!==void 0&&n===e.daemon?.baseUrl}async function Ge(e,t,n){if(!t.leaseId)return;let r=He({previous:t,nextDaemonBaseUrl:n.nextDaemonBaseUrl,ambientDaemonAuthToken:n.ambientDaemonAuthToken,cwd:n.cwd,env:n.env});if(!r.canAuthenticate)return Z(t,`no credential known to belong to that endpoint was available`);try{await X(e,t,r.daemonAuthToken);return}catch{return Z(t,`the release request failed`)}}function Z(e,t){return{status:`unreleased`,message:`Could not release the previous lease ${e.leaseId} (tenant ${e.tenant}, run ${e.runId}) at ${e.daemon?.baseUrl??`its daemon`}: ${t}. It was left in place — release it manually if it is still active.`}}async function Ke(e,t,n){if(n)try{let r=F(t,n);await e.leases.release({tenant:t.tenant,runId:t.runId,leaseId:n.leaseId,leaseBackend:t.leaseBackend??n.backend,...r})}catch{}}function Q(e){if(e.leaseBackend)return e.leaseBackend;if(e.platform===`android`)return`android-instance`;if(e.platform===`ios`)return`ios-instance`;if(e.platform===`harmonyos`)return`harmonyos-instance`}function qe(t,n){let r=Q(t);if(r)return r;throw new e(`INVALID_ARGS`,`${n} requires --platform ios|android|harmonyos or --lease-backend when the remote connection has not resolved a lease yet.`)}function Je(e,t,n,r=[]){return e===`cdp`?k(r)&&!!t.metroPublicBaseUrl:J.has(e)?!0:e!==`batch`||!n?!1:n.some(e=>{let t=e.command.trim().toLowerCase();return J.has(t)&&e.runtime===void 0})}function $(e){let t=e.metroKind;return!!(e.metroPublicBaseUrl||e.metroProxyBaseUrl||e.metroProjectRoot||t)}function Ye(e,n){return!e.platform||!n||!t(n)||e.platform===n}function Xe(e,t){return e?.projectRoot===t?.projectRoot&&e?.profileKey===t?.profileKey&&e?.consumerKey===t?.consumerKey}function Ze(e,t){if(e)return Ye(e,t)?e:void 0}function Qe(t,n,r={}){if(!t.tenant)throw new e(`INVALID_ARGS`,`remote command requires tenant in remote config or via --tenant <id>.`);if(!t.runId)throw new e(`INVALID_ARGS`,`remote command requires runId in remote config or via --run-id <id>.`);if(!t.daemonBaseUrl&&G(r.leaseProvider).requiresRemoteDaemon)throw new e(`INVALID_ARGS`,`remote command requires daemonBaseUrl in remote config, config, env, or --daemon-base-url.`);let i=new Date().toISOString();return{version:1,session:t.session??`default`,remoteConfigPath:n,remoteConfigHash:I(n),daemon:M(t),tenant:t.tenant,runId:t.runId,leaseId:t.leaseId,leaseBackend:t.leaseBackend??Q(t),leaseProvider:r.leaseProvider,clientId:r.clientId,deviceKey:r.deviceKey,platform:t.platform,target:t.target,connectedAt:i,updatedAt:i}}async function $e(e,t,n,r,i,a){let o=P(t);if(t.leaseId&&t.leaseBackend===n){let i=await ot(e,t.leaseId,{tenant:t.tenant,runId:t.runId,leaseBackend:n,...o,ttlMs:r.ttlMs(t)});if(i)return{lease:i,acquired:!1}}return{lease:await e.leases.allocate({tenant:t.tenant,runId:t.runId,leaseBackend:n,...o,ttlMs:r.ttlMs(t),platform:t.platform??i.platform,target:t.target??i.target,device:i.device,udid:i.udid,serial:i.serial,providerApp:a??i.providerApp,providerOsVersion:i.providerOsVersion,providerProject:i.providerProject,providerBuild:i.providerBuild,providerSessionName:i.providerSessionName,...K(i),awsProjectArn:i.awsProjectArn,awsDeviceArn:i.awsDeviceArn,awsAppArn:i.awsAppArn,awsRegion:i.awsRegion,awsInteractionMode:i.awsInteractionMode}),acquired:!0}}async function et(t){if(!Ee.has(t.command)){if(t.state.leaseId&&t.state.deviceKey)return{state:t.state};throw new e(`INVALID_ARGS`,`No active proxy device lease for this session; run open first.`)}let n=await nt(t.client,t.flags),r=rt(n);return{state:{...t.state,deviceKey:r,leaseBackend:t.state.leaseBackend??t.leaseBackend??it(n),platform:t.state.platform??n.platform,target:t.state.target??n.target,updatedAt:new Date().toISOString()},device:n}}function tt(e,t){if(e.platform=t.platform,e.target=t.target??e.target,r(t)){e.udid=t.id;return}(t.platform===`android`||t.platform===`harmonyos`)&&(e.serial=t.id)}async function nt(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 a(r.map(e=>({...n(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})}function rt(e){return`${i(e)}:${e.target??`mobile`}:${e.id}`}function it(e){if(r(e))return`ios-instance`;if(e.platform===`android`)return`android-instance`;if(e.platform===`harmonyos`)return`harmonyos-instance`}function at(t,n,r){if(t.leaseBackend&&t.leaseBackend!==r)throw new e(`INVALID_ARGS`,`Active remote connection is already bound to a different lease backend. Re-run connect --force to replace it.`,{session:t.session,leaseBackend:t.leaseBackend});if(t.platform&&n.platform&&t.platform!==n.platform)throw new e(`INVALID_ARGS`,`Active remote connection is already bound to a different platform. Re-run connect --force to replace it.`,{session:t.session,platform:t.platform});if(t.target&&n.target&&t.target!==n.target)throw new e(`INVALID_ARGS`,`Active remote connection is already bound to a different target. Re-run connect --force to replace it.`,{session:t.session,target:t.target})}async function ot(e,t,n){try{return await e.leases.heartbeat({...n,leaseId:t})}catch(e){if(st(e))return;throw e}}function st(t){return!(t instanceof e)||t.code!==`UNAUTHORIZED`?!1:t.details?.reason===`LEASE_NOT_FOUND`||t.details?.reason===`LEASE_EXPIRED`||t.details?.reason===`LEASE_REVOKED`}export{N as C,O as D,le as E,re as O,de as S,j as T,fe as _,Q as a,z as b,K as c,G as d,Ce as f,P as g,M as h,X as i,D as k,Te as l,Se as m,De as n,Y as o,U as p,Ge as r,Ve as s,$ as t,we as u,I as v,ue as w,A as x,F as y};
1
+ import{C as e,o as t}from"./sdk-contracts.js";import{a as n,l as r,v as i,x as a}from"./sdk-device.js";import{c as o,i as s,s as c}from"./lease-scope.js";import{n as l,t as u}from"./catalog.js";import{t as d}from"./sdk-remote-config.js";import{t as f}from"./prepare-kind.js";import{r as p}from"./diagnostics.js";import{O as m}from"./owner-identity.js";import{f as h}from"./exec.js";import"./file.js";import"./diagnostics2.js";import"./command.js";import{t as ee}from"./daemon-resolution.js";import{_ as g}from"./base-url.js";import{i as _,r as v}from"./client-metro-companion.js";import{n as y}from"./metro2.js";import{n as te,r as b,t as ne}from"./remote-config2.js";import{n as x,t as S}from"./providers.js";import C from"node:path";import w from"node:fs";import T from"node:crypto";const E={slug:`react-devtools-companion`,runArg:g,displayName:`React DevTools companion`};async function re(e){return await v({...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 D(e){return await _({...e,definition:E})}function O(e){return e===`android-instance`||e===`ios-instance`}function ie(e){return[`exec`,`--yes`,`--package`,`agent-cdp@1.6.1`,`--`,`agent-cdp`,...e]}function ae(e){return e.some(e=>e===`--url`||e.startsWith(`--url=`))}function k(e){return e[0]===`target`&&(e[1]===`list`||e[1]===`select`)&&!ae(e)}function oe(e){let t=new URL(e);t.search=``,t.hash=``;let n=t.pathname.replace(/\/+$/,``);return t.pathname=n.endsWith(`/index.bundle`)?n.slice(0,-13)||`/`:n||`/`,t.toString().replace(/\/+$/,``)}function se(e){let t=e?.metroPublicBaseUrl?.trim();return t?oe(t):null}function ce(t,n={}){if(!k(t)||!n.flags?.metroProxyBaseUrl||!O(n.flags.leaseBackend))return t;let r=se(n.flags);if(!r)throw new e(`INVALID_ARGS`,`cdp remote bridge target discovery requires a React Native dev-server public base URL.`,{hint:`Include metroPublicBaseUrl in the remote config so cdp can reach the local or tunneled Metro/Re.Pack CDP endpoint without bridge proxy authentication.`});return[...t,`--url`,r]}async function le(e,t={}){let n=ce(e,t);return(await h(`npm`,ie(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 A(e){let t=L(e);if(!w.existsSync(t))return null;let n;try{n=JSON.parse(w.readFileSync(t,`utf8`))}catch(t){return H(e,t),null}return ge(n)?n:(H(e),null)}function j(e){let t=L({stateDir:e.stateDir,session:e.state.session});w.mkdirSync(C.dirname(t),{recursive:!0}),V(t,e.state),V(R(e.stateDir),{session:e.state.session})}function M(e){return{baseUrl:me(e.daemonBaseUrl),transport:e.daemonTransport,serverMode:e.daemonServerMode}}function N(e){w.rmSync(L(e),{force:!0});let t=R(e.stateDir);B(e.stateDir)===e.session&&w.rmSync(t,{force:!0})}function ue(t){let n=t.validateRemoteConfigHash??!0,r=t.remoteConfig?te({configPath:t.remoteConfig,cwd:t.cwd,env:t.env}):void 0,i=A(t)??(t.allowActiveFallback?z({stateDir:t.stateDir}):null);if(!i||r&&i.remoteConfigPath!==r)return null;if(n&&I(i.remoteConfigPath)!==i.remoteConfigHash)throw new e(`INVALID_ARGS`,`Active remote connection config changed. Run agent-device connect --force to refresh it.`,{remoteConfig:i.remoteConfigPath});let a=pe(i,t),l=s(i);return{runtime:i.runtime,connection:o(l),flags:{...a,remoteConfig:i.remoteConfigPath,daemonBaseUrl:i.daemon?.baseUrl??a.daemonBaseUrl,daemonAuthToken:a.daemonAuthToken,daemonTransport:i.daemon?.transport??a.daemonTransport,daemonServerMode:i.daemon?.serverMode??a.daemonServerMode,...c(l),sessionIsolation:`tenant`,session:i.session,platform:i.platform??a.platform,target:i.target??a.target}}}function P(e){return o(s(e))}function F(e,t){return{leaseProvider:e.leaseProvider??t.leaseProvider,clientId:e.clientId??t.clientId,deviceKey:e.deviceKey??t.deviceKey}}function de(e,t){return!t||(t.leaseProvider===void 0||e.leaseProvider===t.leaseProvider)&&(t.clientId===void 0||e.clientId===t.clientId)}function I(t){try{return T.createHash(`sha256`).update(w.readFileSync(t)).digest(`hex`)}catch(n){throw new e(`INVALID_ARGS`,`Remote config file not found: ${t}`,{cause:n instanceof Error?n.message:String(n)})}}function L(e){return C.join(e.stateDir,`remote-connections`,`${he(e.session)}.json`)}function R(e){return C.join(e,`remote-connections`,`.active-session.json`)}function z(e){let t=B(e.stateDir);return t?A({stateDir:e.stateDir,session:t}):null}function B(e){let t=R(e);if(w.existsSync(t))try{let e=JSON.parse(w.readFileSync(t,`utf8`));return typeof e.session==`string`?e.session:void 0}catch{return}}function fe(e){if(e)return T.createHash(`sha256`).update(e).digest(`hex`).slice(0,12)}function pe(e,t){try{return b({configPath:e.remoteConfigPath,cwd:t.cwd,env:t.env}).profile}catch(e){if(t.validateRemoteConfigHash===!1)return{};throw e}}function V(e,t){m({destination:e,contents:`${JSON.stringify(t,null,2)}\n`,mode:384})}function me(e){if(!e)return;let t=new URL(e);t.username=``,t.password=``;for(let e of Array.from(t.searchParams.keys()))/(auth|key|password|secret|token)/i.test(e)&&t.searchParams.delete(e);return t.toString().replace(/\/+$/,``)}function H(e,t){p({level:`warn`,phase:`remote_connection_state_invalid`,data:{session:e.session,cause:t instanceof Error?t.message:t?String(t):void 0}}),N(e)}function he(e){let t=e.replaceAll(/[^a-zA-Z0-9._-]/g,`_`);return t?t===e?t:`${t}-${T.createHash(`sha256`).update(e).digest(`hex`).slice(0,8)}`:`default`}function ge(e){if(!e||typeof e!=`object`||Array.isArray(e))return!1;let t=e;return t.version===1&&_e(t,[`session`,`remoteConfigPath`,`remoteConfigHash`,`tenant`,`runId`,`connectedAt`,`updatedAt`])&&ve(t,[`leaseId`,`leaseBackend`,`leaseProvider`,`deviceKey`,`clientId`])&&ye(t.daemon)}function _e(e,t){return t.every(t=>typeof e[t]==`string`)}function ve(e,t){return t.every(t=>e[t]===void 0||typeof e[t]==`string`)}function ye(e){return e===void 0?!0:!e||typeof e!=`object`||Array.isArray(e)?!1:be(e)}function be(e){let t=e;return(t.baseUrl===void 0||typeof t.baseUrl==`string`)&&(t.authToken===void 0||typeof t.authToken==`string`)&&(t.transport===void 0||typeof t.transport==`string`)&&(t.serverMode===void 0||typeof t.serverMode==`string`)}const xe=d.map(e=>e.key);function U(e){let t={};for(let n of xe){let r=e[n];r!==void 0&&(t[n]=r)}return t}function Se(e){return e.remoteConfig?{...U(b({configPath:e.remoteConfig,cwd:e.cwd,env:e.env}).profile),remoteConfig:e.remoteConfig}:{}}function Ce(e){return e===`cloud`||e===`proxy`||W(e)}function W(e){return e===`limrun`||x(e)}function we(){return[`cloud`,`proxy`,S.browserStack,S.awsDeviceFarm,`limrun`].join(`, `)}function G(e){let t=W(e),n=x(e);return{leaseKind:e===`proxy`?`proxy`:t?`direct-device-provider`:`remote-provider`,requiresAppAttachment:e===S.awsDeviceFarm,requiresRemoteDaemon:!t,supportsArtifacts:n,supportsDeferredAppSelection:e===`limrun`,supportsDirectPortReverse:e===`limrun`,usesCloudWebDriverLease:n}}function K(e){return{providerDeviceOrientation:e.providerDeviceOrientation,providerGeoLocation:e.providerGeoLocation,providerTimezone:e.providerTimezone,providerAppiumVersion:e.providerAppiumVersion,providerLanguage:e.providerLanguage,providerLocale:e.providerLocale,providerNetworkProfile:e.providerNetworkProfile,providerCustomNetwork:e.providerCustomNetwork,providerNoResignApp:e.providerNoResignApp}}function Te(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,launchUrl:e.launchUrl}}const q=new Set([`artifacts`,`connect`,`connection`,`close`,`disconnect`,`metro`,`session`]),J=new Set([`open`]),Ee=new Set([l.open,l.install,l.reinstall,u.installSource]);async function De(t){let{command:n,flags:r,client:i}=t;if(!r.remoteConfig)return{flags:r,runtime:t.runtime};let a=ee(r.stateDir).baseDir,o=b({configPath:r.remoteConfig,cwd:process.cwd(),env:process.env}),s={...U(o.profile),...r,remoteConfig:o.resolvedPath},c=A({stateDir:a,session:s.session??`default`});if(c&&c.remoteConfigPath!==o.resolvedPath)throw new e(`INVALID_ARGS`,`A different remote connection is already active for this session. Run connect --force or disconnect before using a different --remote-config.`,{session:c.session,activeRemoteConfig:c.remoteConfigPath,requestedRemoteConfig:o.resolvedPath});let u=c??Qe(s,o.resolvedPath,o.profile),d={...s,session:u.session},f=G(u.leaseProvider).supportsDeferredAppSelection,p=f&&n===l.open?t.positionals?.[0]:void 0;f&&delete d.providerApp;let m=Ze(u.runtime,d.platform)??t.runtime,h=u,g=!c,_,v=Fe(h);if(v.shouldAllocate(n)){let e=await Me({command:n,client:i,state:u,nextState:h,nextFlags:d,initialApp:p,policy:v});h=e.state,g||=e.changed,_=e.acquiredLeaseForCleanup}let y=await Oe({command:n,flags:d,client:i,state:u,nextState:h,runtime:m,positionals:t.positionals,batchSteps:t.batchSteps,forceRuntimePrepare:t.forceRuntimePrepare});return h=y.state,m=y.runtime,g||=y.changed,await je({changed:g,stateDir:a,state:h,client:i,acquiredLeaseForCleanup:_,preparedMetroCleanupOnFailure:y.preparedMetroCleanupOnFailure,metroCleanupToStop:y.metroCleanupToStop}),{flags:{...d,session:h.session,leaseId:h.leaseId,leaseBackend:h.leaseBackend,platform:h.platform??d.platform,target:h.target??d.target},runtime:m,connection:P(h)}}async function Oe(t){let{command:n,flags:r,state:i,client:a}=t,o=ke(t.nextState,r),s=t.runtime;if(!Je(n,r,t.batchSteps,t.positionals)||!$(r)||!Ae(t.forceRuntimePrepare,s,r.platform))return{state:o,runtime:s,changed:!1};if(!o.leaseId)throw new e(`INVALID_ARGS`,`${n} requires a resolved remote lease before Metro runtime can be prepared.`);let c=await Be(r,a,i.remoteConfigPath,i.session,{tenantId:i.tenant,runId:i.runId,leaseId:o.leaseId}),l=!Xe(o.metro,c.cleanup);return o={...o,runtime:c.runtime,metro:c.cleanup,updatedAt:new Date().toISOString()},{state:o,runtime:c.runtime,changed:!0,metroCleanupToStop:l?t.nextState.metro:void 0,preparedMetroCleanupOnFailure:l?c.cleanup:void 0}}function ke(e,t){return e.leaseId||!t.leaseId?e:{...e,leaseId:t.leaseId,leaseBackend:t.leaseBackend}}function Ae(e,t,n){return e===!0||!t||!Ye(t,n)}async function je(e){if(e.changed)try{j({stateDir:e.stateDir,state:e.state})}catch(t){throw await Y(e.preparedMetroCleanupOnFailure),await Ke(e.client,e.state,e.acquiredLeaseForCleanup),t}await Y(e.metroCleanupToStop)}async function Me(e){let{command:t,client:n,state:r,nextFlags:i,policy:a}=e,o=r.leaseBackend??Q(i),s=e.nextState,c=await a.resolveLeaseState({command:t,client:n,state:s,flags:i,leaseBackend:o});s=c.state,c.device&&tt(i,c.device);let l=s.leaseBackend??o??qe(i,t);at(r,i,l);let u=await $e(n,s,l,a,i,e.initialApp),d=u.lease;return i.leaseId=d.leaseId,i.leaseBackend=l,i.platform=s.platform??i.platform,i.target=s.target??i.target,Ne(s,d,l)?{state:s,changed:!1,acquiredLeaseForCleanup:u.acquired?d:void 0}:{state:Pe(s,d,l,i),changed:!0,acquiredLeaseForCleanup:u.acquired?d:void 0}}function Ne(e,t,n){return e.leaseId===t.leaseId&&e.leaseBackend===n&&e.deviceKey===(t.deviceKey??e.deviceKey)}function Pe(e,t,n,r){let i=F(t,e);return{...e,leaseId:t.leaseId,leaseBackend:n,...i,platform:e.platform??r.platform,target:e.target??r.target,updatedAt:new Date().toISOString()}}function Fe(e){let t=G(e.leaseProvider);return t.leaseKind===`proxy`?Re:t.supportsDeferredAppSelection?Ie:t.usesCloudWebDriverLease?ze:Le}const Ie={shouldAllocate:e=>e!==l.apps&&!q.has(e),ttlMs:()=>void 0,resolveLeaseState:async e=>({state:e.state})},Le={shouldAllocate:e=>!q.has(e),ttlMs:()=>void 0,resolveLeaseState:async e=>({state:e.state})},Re={shouldAllocate:e=>e!==`devices`&&!q.has(e),ttlMs:()=>3e5,resolveLeaseState:et},ze={shouldAllocate:e=>!q.has(e),ttlMs:()=>6e5,resolveLeaseState:async e=>({state:e.state})};async function Be(t,n,r,i,a){if(!t.metroProjectRoot&&!t.metroPublicBaseUrl&&!t.metroProxyBaseUrl)return{};if(t.platform!==`ios`&&t.platform!==`android`)throw new e(`INVALID_ARGS`,`Deferred Metro preparation requires platform "ios" or "android".`);if(!t.metroPublicBaseUrl&&!t.metroProxyBaseUrl)throw new e(`INVALID_ARGS`,`Deferred Metro preparation requires metroPublicBaseUrl or metroProxyBaseUrl when Metro settings are provided.`);let o=await n.metro.prepare({projectRoot:t.metroProjectRoot,kind:f(t.metroKind),publicBaseUrl:t.metroPublicBaseUrl,proxyBaseUrl:t.metroProxyBaseUrl,bearerToken:t.metroBearerToken,bridgeScope:a,launchUrl:t.launchUrl,companionProfileKey:r,companionConsumerKey:i,port:t.metroPreparePort,listenHost:t.metroListenHost,statusHost:t.metroStatusHost,startupTimeoutMs:t.metroStartupTimeoutMs,probeTimeoutMs:t.metroProbeTimeoutMs,reuseExisting:!t.metroNoReuseExisting&&void 0,installDependenciesIfNeeded:!t.metroNoInstallDeps&&void 0,runtimeFilePath:t.metroRuntimeFile});return{runtime:t.platform===`ios`?o.iosRuntime:o.androidRuntime,cleanup:t.metroProxyBaseUrl?{projectRoot:o.projectRoot,profileKey:r,consumerKey:i}:void 0}}async function Y(e){if(e)try{await y(e)}catch{}}async function Ve(e){try{await D({projectRoot:process.cwd(),stateDir:e.stateDir,profileKey:e.state.remoteConfigPath,consumerKey:e.state.session})}catch{}}async function X(e,t,n){return t.leaseId?await e.leases.release({tenant:t.tenant,runId:t.runId,leaseId:t.leaseId,leaseBackend:t.leaseBackend,daemonBaseUrl:t.daemon?.baseUrl,daemonAuthToken:n,daemonTransport:t.daemon?.transport,daemonServerMode:t.daemon?.serverMode,...P(t)}):{released:!1}}function He(e){let t=Ue(e.previous,e.cwd,e.env);return t?{canAuthenticate:!0,daemonAuthToken:t}:e.previous.daemon?.baseUrl===e.nextDaemonBaseUrl?{canAuthenticate:!0,daemonAuthToken:e.ambientDaemonAuthToken}:{canAuthenticate:!1}}function Ue(e,t,n){try{let{profile:r}=ne({configPath:e.remoteConfigPath,cwd:t,env:n});return r.daemonAuthToken&&We(e,r.daemonBaseUrl)?r.daemonAuthToken:void 0}catch{return}}function We(e,t){let n=M({daemonBaseUrl:t})?.baseUrl;return n!==void 0&&n===e.daemon?.baseUrl}async function Ge(e,t,n){if(!t.leaseId)return;let r=He({previous:t,nextDaemonBaseUrl:n.nextDaemonBaseUrl,ambientDaemonAuthToken:n.ambientDaemonAuthToken,cwd:n.cwd,env:n.env});if(!r.canAuthenticate)return Z(t,`no credential known to belong to that endpoint was available`);try{await X(e,t,r.daemonAuthToken);return}catch{return Z(t,`the release request failed`)}}function Z(e,t){return{status:`unreleased`,message:`Could not release the previous lease ${e.leaseId} (tenant ${e.tenant}, run ${e.runId}) at ${e.daemon?.baseUrl??`its daemon`}: ${t}. It was left in place — release it manually if it is still active.`}}async function Ke(e,t,n){if(n)try{let r=F(t,n);await e.leases.release({tenant:t.tenant,runId:t.runId,leaseId:n.leaseId,leaseBackend:t.leaseBackend??n.backend,...r})}catch{}}function Q(e){if(e.leaseBackend)return e.leaseBackend;if(e.platform===`android`)return`android-instance`;if(e.platform===`ios`)return`ios-instance`;if(e.platform===`harmonyos`)return`harmonyos-instance`}function qe(t,n){let r=Q(t);if(r)return r;throw new e(`INVALID_ARGS`,`${n} requires --platform ios|android|harmonyos or --lease-backend when the remote connection has not resolved a lease yet.`)}function Je(e,t,n,r=[]){return e===`cdp`?k(r)&&!!t.metroPublicBaseUrl:J.has(e)?!0:e!==`batch`||!n?!1:n.some(e=>{let t=e.command.trim().toLowerCase();return J.has(t)&&e.runtime===void 0})}function $(e){let t=e.metroKind;return!!(e.metroPublicBaseUrl||e.metroProxyBaseUrl||e.metroProjectRoot||t)}function Ye(e,n){return!e.platform||!n||!t(n)||e.platform===n}function Xe(e,t){return e?.projectRoot===t?.projectRoot&&e?.profileKey===t?.profileKey&&e?.consumerKey===t?.consumerKey}function Ze(e,t){if(e)return Ye(e,t)?e:void 0}function Qe(t,n,r={}){if(!t.tenant)throw new e(`INVALID_ARGS`,`remote command requires tenant in remote config or via --tenant <id>.`);if(!t.runId)throw new e(`INVALID_ARGS`,`remote command requires runId in remote config or via --run-id <id>.`);if(!t.daemonBaseUrl&&G(r.leaseProvider).requiresRemoteDaemon)throw new e(`INVALID_ARGS`,`remote command requires daemonBaseUrl in remote config, config, env, or --daemon-base-url.`);let i=new Date().toISOString();return{version:1,session:t.session??`default`,remoteConfigPath:n,remoteConfigHash:I(n),daemon:M(t),tenant:t.tenant,runId:t.runId,leaseId:t.leaseId,leaseBackend:t.leaseBackend??Q(t),leaseProvider:r.leaseProvider,clientId:r.clientId,deviceKey:r.deviceKey,platform:t.platform,target:t.target,connectedAt:i,updatedAt:i}}async function $e(e,t,n,r,i,a){let o=P(t);if(t.leaseId&&t.leaseBackend===n){let i=await ot(e,t.leaseId,{tenant:t.tenant,runId:t.runId,leaseBackend:n,...o,ttlMs:r.ttlMs(t)});if(i)return{lease:i,acquired:!1}}return{lease:await e.leases.allocate({tenant:t.tenant,runId:t.runId,leaseBackend:n,...o,ttlMs:r.ttlMs(t),platform:t.platform??i.platform,target:t.target??i.target,device:i.device,udid:i.udid,serial:i.serial,providerApp:a??i.providerApp,providerOsVersion:i.providerOsVersion,providerProject:i.providerProject,providerBuild:i.providerBuild,providerSessionName:i.providerSessionName,...K(i),awsProjectArn:i.awsProjectArn,awsDeviceArn:i.awsDeviceArn,awsAppArn:i.awsAppArn,awsRegion:i.awsRegion,awsInteractionMode:i.awsInteractionMode}),acquired:!0}}async function et(t){if(!Ee.has(t.command)){if(t.state.leaseId&&t.state.deviceKey)return{state:t.state};throw new e(`INVALID_ARGS`,`No active proxy device lease for this session; run open first.`)}let n=await nt(t.client,t.flags),r=rt(n);return{state:{...t.state,deviceKey:r,leaseBackend:t.state.leaseBackend??t.leaseBackend??it(n),platform:t.state.platform??n.platform,target:t.state.target??n.target,updatedAt:new Date().toISOString()},device:n}}function tt(e,t){if(e.platform=t.platform,e.target=t.target??e.target,r(t)){e.udid=t.id;return}(t.platform===`android`||t.platform===`harmonyos`)&&(e.serial=t.id)}async function nt(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 a(r.map(e=>({...n(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})}function rt(e){return`${i(e)}:${e.target??`mobile`}:${e.id}`}function it(e){if(r(e))return`ios-instance`;if(e.platform===`android`)return`android-instance`;if(e.platform===`harmonyos`)return`harmonyos-instance`}function at(t,n,r){if(t.leaseBackend&&t.leaseBackend!==r)throw new e(`INVALID_ARGS`,`Active remote connection is already bound to a different lease backend. Re-run connect --force to replace it.`,{session:t.session,leaseBackend:t.leaseBackend});if(t.platform&&n.platform&&t.platform!==n.platform)throw new e(`INVALID_ARGS`,`Active remote connection is already bound to a different platform. Re-run connect --force to replace it.`,{session:t.session,platform:t.platform});if(t.target&&n.target&&t.target!==n.target)throw new e(`INVALID_ARGS`,`Active remote connection is already bound to a different target. Re-run connect --force to replace it.`,{session:t.session,target:t.target})}async function ot(e,t,n){try{return await e.leases.heartbeat({...n,leaseId:t})}catch(e){if(st(e))return;throw e}}function st(t){return!(t instanceof e)||t.code!==`UNAUTHORIZED`?!1:t.details?.reason===`LEASE_NOT_FOUND`||t.details?.reason===`LEASE_EXPIRED`||t.details?.reason===`LEASE_REVOKED`}export{N as C,O as D,le as E,re as O,de as S,j as T,fe as _,Q as a,z as b,K as c,G as d,Ce as f,P as g,M as h,X as i,D as k,Te as l,Se as m,De as n,Y as o,U as p,Ge as r,Ve as s,$ as t,we as u,I as v,ue as w,A as x,F as y};