agent-device 0.20.1 → 0.20.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/README.md +0 -2
  2. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.20.1.apk → agent-device-android-ime-helper-0.20.2.apk} +0 -0
  3. package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.2.apk.sha256 +1 -0
  4. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.20.1.manifest.json → agent-device-android-ime-helper-0.20.2.manifest.json} +4 -4
  5. package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.20.1.apk → agent-device-android-snapshot-helper-0.20.2.apk} +0 -0
  6. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.2.apk.sha256 +1 -0
  7. package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.20.1.manifest.json → agent-device-android-snapshot-helper-0.20.2.manifest.json} +6 -6
  8. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Alert.swift +2 -0
  9. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +1 -35
  10. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +0 -32
  11. package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Orientation.swift +92 -0
  12. package/dist/src/agent-device-client.js +2 -2
  13. package/dist/src/android.js +1 -1
  14. package/dist/src/app-lifecycle.js +5 -5
  15. package/dist/src/app-log-request-scope.js +1 -1
  16. package/dist/src/app-resolution.js +1 -1
  17. package/dist/src/apps.js +5 -5
  18. package/dist/src/cli-config.js +1 -1
  19. package/dist/src/cli-help.js +6 -6
  20. package/dist/src/cli-runner.js +1 -1
  21. package/dist/src/cli.js +14 -14
  22. package/dist/src/click-button.d.ts +5 -0
  23. package/dist/src/client-metro.js +1 -0
  24. package/dist/src/command-schema.js +3 -3
  25. package/dist/src/context.js +1 -1
  26. package/dist/src/contracts.d.ts +1 -1
  27. package/dist/src/device-input-state.js +1 -1
  28. package/dist/src/device.js +9 -0
  29. package/dist/src/devices2.js +1 -1
  30. package/dist/src/find.js +1 -1
  31. package/dist/src/generic.js +1 -1
  32. package/dist/src/gesture-plan-types.js +1 -0
  33. package/dist/src/gesture-plan.js +1 -0
  34. package/dist/src/index.d.ts +1174 -1413
  35. package/dist/src/input-actions.js +4 -4
  36. package/dist/src/install-artifact.js +5 -1
  37. package/dist/src/install-artifact2.js +1 -0
  38. package/dist/src/interaction-snapshot.js +1 -1
  39. package/dist/src/interaction.d.ts +3 -6
  40. package/dist/src/interaction.js +1 -1
  41. package/dist/src/interactor.js +2 -2
  42. package/dist/src/interactor2.js +1 -1
  43. package/dist/src/internal/bin.js +1 -1
  44. package/dist/src/internal/daemon.js +14 -22
  45. package/dist/src/lease-context.js +1 -1
  46. package/dist/src/lease.js +1 -1
  47. package/dist/src/limrun.d.ts +361 -0
  48. package/dist/src/limrun.js +1 -0
  49. package/dist/src/linux.js +1 -1
  50. package/dist/src/logcat.js +1 -5
  51. package/dist/src/metro.d.ts +71 -2
  52. package/dist/src/metro.js +1 -1
  53. package/dist/src/metro2.js +1 -1
  54. package/dist/src/notifications.js +1 -1
  55. package/dist/src/physical-device-control.js +1 -0
  56. package/dist/src/plist.js +1 -0
  57. package/dist/src/react-native.js +1 -1
  58. package/dist/src/recording-export-quality.js +13 -13
  59. package/dist/src/register-builtins.js +1 -1
  60. package/dist/src/registry.js +18 -18
  61. package/dist/src/remote-config.d.ts +5 -2
  62. package/dist/src/remote-config.js +1 -1
  63. package/dist/src/remote-config2.js +1 -0
  64. package/dist/src/reporting.js +8 -8
  65. package/dist/src/runner-client.js +1 -1
  66. package/dist/src/runner-disposal.js +1 -2
  67. package/dist/src/runner-lease.js +1 -1
  68. package/dist/src/runtime-transport.js +1 -1
  69. package/dist/src/runtime.js +3 -3
  70. package/dist/src/runtime2.js +1 -1
  71. package/dist/src/sdk-android-adb.d.ts +4 -2
  72. package/dist/src/sdk-batch-runner.d.ts +13 -3
  73. package/dist/src/sdk-batch-runner.js +1 -1
  74. package/dist/src/sdk-contracts.d.ts +28 -2
  75. package/dist/src/sdk-contracts.js +2 -2
  76. package/dist/src/sdk-finders.d.ts +1 -1
  77. package/dist/src/sdk-remote-config.d.ts +119 -4
  78. package/dist/src/selector-runtime.js +1 -1
  79. package/dist/src/selector-vocabulary.js +1 -1
  80. package/dist/src/selectors.d.ts +1 -1
  81. package/dist/src/server.js +2 -2
  82. package/dist/src/session-target-evidence.js +1 -1
  83. package/dist/src/session.js +8 -8
  84. package/dist/src/simulator.js +1 -1
  85. package/dist/src/snapshot-diagnostics.js +4 -4
  86. package/dist/src/snapshot2.js +1 -1
  87. package/dist/src/tool-provider.js +3 -3
  88. package/dist/src/tool-provider2.js +1 -1
  89. package/dist/src/tool-provider3.js +1 -1
  90. package/dist/src/tv-remote.d.ts +213 -0
  91. package/dist/src/xml.js +2 -0
  92. package/package.json +37 -17
  93. package/server.json +2 -2
  94. package/smithery.yaml +1 -1
  95. package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.1.apk.sha256 +0 -1
  96. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.1.apk.sha256 +0 -1
  97. package/dist/src/android-system-chrome.js +0 -1
  98. package/dist/src/client-metro-companion.js +0 -1
  99. package/dist/src/metro-types.d.ts +0 -52
  100. package/dist/src/project-runtime.js +0 -1
  101. package/dist/src/scoped-provider.js +0 -1
  102. package/dist/src/simctl.js +0 -1
  103. package/dist/src/snapshot-quality.js +0 -1
@@ -1,7 +1,7 @@
1
- import{t as e}from"./rolldown-runtime.js";import{_ as t}from"./sdk-contracts.js";import{_ as n,a as r,c as i,i as a,n as o,v as s,w as c}from"./sdk-android-adb.js";import{t as l}from"./timeouts.js";import{d as u,i as d,l as f,s as p,u as ee}from"./logcat.js";import{promises as m}from"node:fs";import te from"node:os";import h from"node:path";const ne=[`mCurrentFocus=Window{`,`mFocusedApp=AppWindowToken{`,`mResumedActivity:`,`ResumedActivity:`],re=/\bApplication Not Responding:\s*([A-Za-z0-9_.]+)/i,ie=/([^{}]*\bis(?:n't| not)\s+responding[^{}]*)/i,ae=/\b([A-Za-z][A-Za-z0-9_]*(?:\.[A-Za-z0-9_]+)+)\b/;function g(e){let t=new Set;for(let n of e.split(`
1
+ import{t as e}from"./rolldown-runtime.js";import{_ as t}from"./sdk-contracts.js";import{_ as n,a as r,c as i,i as a,n as o,v as s,w as c}from"./sdk-android-adb.js";import{t as l}from"./timeouts.js";import{a as u,c as ee,l as d,n as f,s as p}from"./install-artifact.js";import{promises as m}from"node:fs";import te from"node:os";import h from"node:path";const ne=[`mCurrentFocus=Window{`,`mFocusedApp=AppWindowToken{`,`mResumedActivity:`,`ResumedActivity:`],re=/\bApplication Not Responding:\s*([A-Za-z0-9_.]+)/i,ie=/([^{}]*\bis(?:n't| not)\s+responding[^{}]*)/i,ae=/\b([A-Za-z][A-Za-z0-9_]*(?:\.[A-Za-z0-9_]+)+)\b/;function g(e){let t=new Set;for(let n of e.split(`
2
2
  `)){let e=n.trim();if(!e)continue;let r=e.split(/\s+/)[0]??``;if(!r.includes(`/`))continue;let i=r.split(`/`)[0]??``;i.includes(`.`)&&i&&t.add(i)}return Array.from(t)}function _(e){return e.split(`
3
3
  `).map(e=>{let t=e.trim();return t.startsWith(`package:`)?t.slice(8):t}).filter(Boolean)}function v(e){return y(e,e=>ce(e))}function oe(e){return y(e,(e,t)=>se(e,t))}function y(e,t){let n=e.split(`
4
- `);for(let e of ne)for(let r of n){let n=r.indexOf(e);if(n===-1)continue;let i=r.trim(),a=t(r.slice(n+e.length),i);if(a)return a}return null}function se(e,t){let n=e.split(`}`)[0]?.trim()??e.trim(),r=re.exec(n);if(r){let e=r[1];return{package:e,focusedWindow:`Application Not Responding: ${e}`,raw:t}}let i=ie.exec(n);if(!i)return null;let a=i[1];if(a===void 0)return null;let o=a.trim().replace(/\s+/g,` `),s=ae.exec(o)?.[1];return{...s?{package:s}:{},focusedWindow:o,raw:t}}function ce(e){for(let t of e.trim().split(/\s+/)){let e=t.indexOf(`/`);if(e<=0)continue;let n=b(t.slice(0,e),!1),r=b(t.slice(e+1),!0);if(n&&r&&n.length===e)return{package:n,activity:r}}return null}function b(e,t){let n=0;for(;n<e.length&&le(e[n],t);)n+=1;return e.slice(0,n)}function le(e,t){if(!e)return!1;let n=e.charCodeAt(0);return n>=48&&n<=57||n>=65&&n<=90||n>=97&&n<=122||e===`_`||e===`.`||t&&e===`$`}const ue=/\.(?:apk|aab)$/i,de=/^[A-Za-z_][\w]*(\.[A-Za-z_][\w]*)+$/;function x(e){let t=e.trim();return t.length===0?`other`:ue.test(t)?t.includes(`/`)||t.includes(`\\`)||t.startsWith(`.`)||t.startsWith(`~`)||!S(t)?`binary`:`package`:S(t)?`package`:`other`}function S(e){return de.test(e)}function fe(e){return`Android runtime hints require an installed package name, not "${e}". Install or reinstall the app first, then relaunch by package.`}var pe=e({closeAndroidApp:()=>K,getAndroidAppState:()=>N,getAndroidBlockingDialogFocus:()=>P,inferAndroidAppName:()=>M,installAndroidApp:()=>He,installAndroidInstallablePath:()=>Q,installAndroidInstallablePathAndResolvePackageName:()=>$,isAmStartError:()=>U,listAndroidApps:()=>A,openAndroidApp:()=>R,openAndroidDevice:()=>G,parseAndroidLaunchComponent:()=>W,reinstallAndroidApp:()=>Ue,resolveAndroidApp:()=>k});const me={settings:{type:`intent`,value:`android.settings.SETTINGS`}},C=`android.intent.category.LAUNCHER`,w=`android.intent.category.LEANBACK_LAUNCHER`,T=`android.intent.category.DEFAULT`,E=`Run agent-device apps --platform android to discover the installed package name, then retry open with that exact package.`,he=new Set([`localhost`,`127.0.0.1`,`::1`,`[::1]`]),D=ee();function O(e){return{platform:`android`,deviceId:e.id,variant:e.target??``}}async function k(e,n){let r=n.trim();if(x(r)===`package`)return{type:`package`,value:r};let i=me[r.toLowerCase()];if(i)return i;let a=O(e),o=D.get(a,r);if(o)return o;let s=(await p(e,[`shell`,`pm`,`list`,`packages`])).stdout.split(`
5
- `).map(e=>e.replace(`package:`,``).trim()).filter(Boolean).filter(e=>e.toLowerCase().includes(r.toLowerCase())),c=s[0];if(c!==void 0&&s.length===1)return D.set(a,r,{type:`package`,value:c});throw s.length>1?new t(`INVALID_ARGS`,`Multiple packages matched "${n}"`,{matches:s,hint:`Run agent-device apps --platform android to see the exact installed package names before retrying open.`}):new t(`APP_NOT_INSTALLED`,`No package found matching "${n}"`,{hint:E})}async function A(e,t){let n=await ge(e);return(t===`user-installed`?(await ve(e)).filter(e=>n.has(e)):Array.from(n)).sort((e,t)=>e.localeCompare(t)).map(e=>({package:e,name:M(e)}))}async function ge(e){let t=new Set;for(let n of j(e,{includeFallbackWhenUnknown:!0})){let r=await p(e,[`shell`,`cmd`,`package`,`query-activities`,`--brief`,`-a`,`android.intent.action.MAIN`,`-c`,n],{allowFailure:!0});if(!(r.exitCode!==0||r.stdout.trim().length===0))for(let e of g(r.stdout))t.add(e)}return t}function _e(e){return j(e)[0]??C}function j(e,t={}){return e.target===`tv`?[w]:e.target===`mobile`?[C]:t.includeFallbackWhenUnknown?[C,w]:[C]}async function ve(e){return _((await p(e,[`shell`,`pm`,`list`,`packages`,`-3`])).stdout)}function M(e){let t=new Set([`com`,`android`,`google`,`app`,`apps`,`service`,`services`,`mobile`,`client`]),n=e.split(`.`).flatMap(e=>e.split(/[_-]+/)).map(e=>e.trim().toLowerCase()).filter(e=>e.length>0),r=n[n.length-1]??e;for(let e=n.length-1;e>=0;--e){let i=n[e];if(i&&!t.has(i)){r=i;break}}return r.split(/[^a-z0-9]+/i).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(` `)}async function N(e){return await F(e,[[`shell`,`dumpsys`,`window`,`windows`],[`shell`,`dumpsys`,`window`]])||await F(e,[[`shell`,`dumpsys`,`activity`,`activities`],[`shell`,`dumpsys`,`activity`]])||{}}async function P(e){return await ye(e,[[`shell`,`dumpsys`,`window`,`windows`],[`shell`,`dumpsys`,`window`]])}async function F(e,t){for(let n of t){let t=v((await p(e,n,{allowFailure:!0})).stdout??``);if(t)return t}return null}async function ye(e,t){for(let n of t){let t=oe((await p(e,n,{allowFailure:!0})).stdout??``);if(t)return t}return null}function be(e){let t;try{t=new URL(e)}catch{return null}let n=t.hostname.toLowerCase();if(!he.has(n)||!t.port)return null;let r=Number(t.port);return Number.isInteger(r)?`tcp:${r}`:null}async function I(e,n){let r=be(n);if(!r)return;let o=a(i(e));try{await o.ensure({local:r,remote:r})}catch(e){let n={localPort:r.replace(`tcp:`,``),operation:`adb reverse ${r} ${r}`};throw e instanceof t&&Object.assign(n,{hint:e.details?.hint,diagnosticId:e.details?.diagnosticId,logPath:e.details?.logPath}),new t(`COMMAND_FAILED`,`Failed to ensure Android port reverse ${r} before opening localhost URL`,n,e)}}function xe(e){return/^[A-Za-z0-9_@%+=:,./-]+$/.test(e)?e:`'${e.replace(/'/g,`'\\''`)}'`}function L(e){return(e.launchArgs??[]).map(xe)}async function R(e,t,n){e.booted||await f(e.id);let r=Oe(n),i=r.activity,a=t.trim();if(u(a)){await Se(e,a,r);return}if(r.url!==void 0){await Ce(e,t,r);return}let o=await k(e,t),s=_e(e);if(o.type===`intent`){await we(e,o.value,r);return}if(i){await Te(e,o.value,i,s,r);return}await Ee(e,o.value,s,r)}async function Se(e,n,r){if(r.activity)throw new t(`INVALID_ARGS`,`Activity override is not supported when opening a deep link URL`);await I(e,n),await p(e,[`shell`,`am`,`start`,`-W`,`-a`,`android.intent.action.VIEW`,`-d`,n,...ke(r.appBundleId),...L(r)])}async function Ce(e,n,r){if(r.activity)throw new t(`INVALID_ARGS`,`Activity override is not supported when opening an app-bound deep link URL`);let i=r.url?.trim()??``;if(!u(i))throw new t(`INVALID_ARGS`,`Android app-bound open requires a valid URL target`);await I(e,i),await p(e,[`shell`,`am`,`start`,`-W`,`-a`,`android.intent.action.VIEW`,`-d`,i,`-p`,await De(e,n,`app-bound open`),...L(r)])}async function we(e,n,r){if(r.activity)throw new t(`INVALID_ARGS`,`Activity override requires a package name, not an intent`);await p(e,[`shell`,`am`,`start`,`-W`,`-a`,n,...L(r)])}async function Te(e,t,n,r,i){let a=n.includes(`/`)?n:`${t}/${n.startsWith(`.`)?n:`.${n}`}`;try{await p(e,z(a,r,i))}catch(n){throw await Ae(e,t,n),n}}async function Ee(e,t,n,r){let i=await p(e,[`shell`,`am`,`start`,`-W`,`-a`,`android.intent.action.MAIN`,`-c`,T,`-c`,n,`-p`,t,...L(r)],{allowFailure:!0});if(i.exitCode===0&&!U(i.stdout,i.stderr))return;let a=await je(e,t);if(!a)throw await V(e,t)?o(`Failed to launch ${t}`,i):B(t);await p(e,z(a,n,r))}function z(e,t,n){return[`shell`,`am`,`start`,`-W`,`-a`,`android.intent.action.MAIN`,`-c`,T,`-c`,t,`-n`,e,...L(n)]}async function De(e,n,r){let i=await k(e,n);if(i.type===`intent`)throw new t(`INVALID_ARGS`,`Android ${r} requires a package name, not an intent`);return i.value}function Oe(e){return typeof e==`string`?{activity:e}:e??{}}function ke(e){let t=e?.trim();return t?[`-p`,t]:[]}function B(e){return new t(`APP_NOT_INSTALLED`,`No package found matching "${e}"`,{package:e,hint:E})}async function V(e,t){let n=await p(e,[`shell`,`pm`,`path`,t],{allowFailure:!0}),r=`${n.stdout}\n${n.stderr}`;return n.exitCode===0&&/\bpackage:/i.test(r)?!0:(H(r),!1)}async function Ae(e,n,r){if(H(r instanceof t?`${String(r.details?.stdout??``)}\n${String(r.details?.stderr??``)}`:``)||!await V(e,n))throw B(n)}function H(e){return/\bunknown package\b/i.test(e)||/\bpackage .* (?:was|is) not found\b/i.test(e)||/\bpackage .* does not exist\b/i.test(e)||/\bcould not find package\b/i.test(e)}async function je(e,t){let n=Array.from(new Set(j(e,{includeFallbackWhenUnknown:!0})));for(let r of n){let n=await p(e,[`shell`,`cmd`,`package`,`resolve-activity`,`--brief`,`-a`,`android.intent.action.MAIN`,`-c`,r,t],{allowFailure:!0});if(n.exitCode!==0)continue;let i=W(n.stdout);if(i)return i}return null}function U(e,t){let n=`${e}\n${t}`;return/Error:.*(?:Activity not started|unable to resolve Intent)/i.test(n)}function W(e){let t=e.split(`
6
- `).map(e=>e.trim()).filter(Boolean);for(let e=t.length-1;e>=0;--e){let n=t[e];if(n===void 0||!n.includes(`/`))continue;let r=n.split(/\s+/)[0];if(r!==void 0)return r}return null}async function G(e){e.booted||await f(e.id)}async function K(e,n){if(n.trim().toLowerCase()===`settings`){await p(e,[`shell`,`am`,`force-stop`,`com.android.settings`]),await q(e,`com.android.settings`);return}let r=await k(e,n);if(r.type===`intent`)throw new t(`INVALID_ARGS`,`Close requires a package name, not an intent`);await p(e,[`shell`,`am`,`force-stop`,r.value]),await q(e,r.value)}async function q(e,t){await Me(e,t),await Pe(e,t)}async function Me(e,t){let n=Date.now()+2e3;for(;Date.now()<n;){if((await Ne(e))?.package!==t)return;await l(50)}}async function Ne(e){for(let t of[[`shell`,`dumpsys`,`window`,`windows`],[`shell`,`dumpsys`,`window`],[`shell`,`dumpsys`,`activity`,`activities`],[`shell`,`dumpsys`,`activity`]]){let n=v((await p(e,t,{allowFailure:!0})).stdout??``);if(n)return n}return null}async function Pe(e,t){let n=Date.now()+2e3;for(;Date.now()<n;){if(!await J(e,t)&&(await l(150),!await J(e,t)))return;await l(50)}}async function J(e,t){return((await p(e,[`shell`,`pidof`,t],{allowFailure:!0})).stdout??``).trim().length>0}async function Fe(e,n){let r=await k(e,n);if(r.type===`intent`)throw new t(`INVALID_ARGS`,`App uninstall requires a package name, not an intent`);let i=await p(e,[`uninstall`,r.value],{allowFailure:!0});if(i.exitCode!==0){let e=`${i.stdout}\n${i.stderr}`.toLowerCase();if(!e.includes(`unknown package`)&&!e.includes(`not installed`))throw o(`adb uninstall failed for ${r.value}`,i)}return{package:r.value}}let Y=null;function Ie(){return`${process.env.PATH??``}::${process.env.AGENT_DEVICE_BUNDLETOOL_JAR??``}`}async function Le(){let e=Ie();if(Y?.key===e)return Y.invocation;if(await c(`bundletool`)){let t={cmd:`bundletool`,prefixArgs:[]};return Y={key:e,invocation:t},t}let r=await n(process.env.AGENT_DEVICE_BUNDLETOOL_JAR,`AGENT_DEVICE_BUNDLETOOL_JAR`);if(!r)throw new t(`TOOL_MISSING`,`bundletool not found in PATH. Install bundletool or set AGENT_DEVICE_BUNDLETOOL_JAR to a bundletool-all.jar path.`);let i={cmd:`java`,prefixArgs:[`-jar`,r]};return Y={key:e,invocation:i},i}async function X(e){let t=await Le();await s(t.cmd,[...t.prefixArgs,...e])}function Re(e){return h.extname(e).toLowerCase()===`.aab`}async function ze(e,t){let n=i(e),r=`universal`;if(n.installBundle){await n.installBundle(t,{mode:r});return}let a=await m.mkdtemp(h.join(te.tmpdir(),`agent-device-aab-`)),o=h.join(a,`bundle.apks`);try{await X([`build-apks`,`--bundle`,t,`--output`,o,`--mode`,r]),await X([`install-apks`,`--apks`,o,`--device-id`,e.id])}finally{await m.rm(a,{recursive:!0,force:!0})}}async function Be(e,t){if(Re(t)){await ze(e,t);return}await r(t,{device:e,replace:!0})}async function Z(e){let t=await p(e,[`shell`,`pm`,`list`,`packages`]);return new Set(t.stdout.split(`
7
- `).map(e=>e.replace(`package:`,``).trim()).filter(Boolean))}async function Ve(e,t){let n=await Z(e),r=Array.from(n).filter(e=>!t.has(e));if(r.length===1)return r[0]}async function Q(e,t){await D.invalidateWhile(O(e),async()=>{e.booted||await f(e.id),await Be(e,t)})}async function $(e,t,n){let r=n?void 0:await Z(e);return await Q(e,t),n??(r?await Ve(e,r):void 0)}async function He(e,t){e.booted||await f(e.id);let n=await d({kind:`path`,path:t});try{let t=await $(e,n.installablePath,n.packageName),r=t?M(t):void 0;return{archivePath:n.archivePath,installablePath:n.installablePath,packageName:t,appName:r,launchTarget:t}}finally{await n.cleanup()}}async function Ue(e,t,n){return await D.invalidateWhile(O(e),async()=>{e.booted||await f(e.id);let{package:r}=await Fe(e,t),i=await d({kind:`path`,path:n},{resolveIdentity:!1});try{await Q(e,i.installablePath)}finally{await i.cleanup()}return{package:r}})}export{M as a,R as c,k as d,x as f,_ as g,g as h,P as i,G as l,v as m,K as n,U as o,fe as p,N as r,A as s,pe as t,W as u};
4
+ `);for(let e of ne)for(let r of n){let n=r.indexOf(e);if(n===-1)continue;let i=r.trim(),a=t(r.slice(n+e.length),i);if(a)return a}return null}function se(e,t){let n=e.split(`}`)[0]?.trim()??e.trim(),r=re.exec(n);if(r){let e=r[1];return{package:e,focusedWindow:`Application Not Responding: ${e}`,raw:t}}let i=ie.exec(n);if(!i)return null;let a=i[1];if(a===void 0)return null;let o=a.trim().replace(/\s+/g,` `),s=ae.exec(o)?.[1];return{...s?{package:s}:{},focusedWindow:o,raw:t}}function ce(e){for(let t of e.trim().split(/\s+/)){let e=t.indexOf(`/`);if(e<=0)continue;let n=b(t.slice(0,e),!1),r=b(t.slice(e+1),!0);if(n&&r&&n.length===e)return{package:n,activity:r}}return null}function b(e,t){let n=0;for(;n<e.length&&le(e[n],t);)n+=1;return e.slice(0,n)}function le(e,t){if(!e)return!1;let n=e.charCodeAt(0);return n>=48&&n<=57||n>=65&&n<=90||n>=97&&n<=122||e===`_`||e===`.`||t&&e===`$`}const ue=/\.(?:apk|aab)$/i,de=/^[A-Za-z_][\w]*(\.[A-Za-z_][\w]*)+$/;function x(e){let t=e.trim();return t.length===0?`other`:ue.test(t)?t.includes(`/`)||t.includes(`\\`)||t.startsWith(`.`)||t.startsWith(`~`)||!S(t)?`binary`:`package`:S(t)?`package`:`other`}function S(e){return de.test(e)}function fe(e){return`Android runtime hints require an installed package name, not "${e}". Install or reinstall the app first, then relaunch by package.`}var pe=e({closeAndroidApp:()=>K,getAndroidAppState:()=>N,getAndroidBlockingDialogFocus:()=>P,inferAndroidAppName:()=>M,installAndroidApp:()=>He,installAndroidInstallablePath:()=>Q,installAndroidInstallablePathAndResolvePackageName:()=>$,isAmStartError:()=>U,listAndroidApps:()=>A,openAndroidApp:()=>R,openAndroidDevice:()=>G,parseAndroidLaunchComponent:()=>W,reinstallAndroidApp:()=>Ue,resolveAndroidApp:()=>k});const me={settings:{type:`intent`,value:`android.settings.SETTINGS`}},C=`android.intent.category.LAUNCHER`,w=`android.intent.category.LEANBACK_LAUNCHER`,T=`android.intent.category.DEFAULT`,E=`Run agent-device apps --platform android to discover the installed package name, then retry open with that exact package.`,he=new Set([`localhost`,`127.0.0.1`,`::1`,`[::1]`]),D=ee();function O(e){return{platform:`android`,deviceId:e.id,variant:e.target??``}}async function k(e,n){let r=n.trim();if(x(r)===`package`)return{type:`package`,value:r};let i=me[r.toLowerCase()];if(i)return i;let a=O(e),o=D.get(a,r);if(o)return o;let s=(await u(e,[`shell`,`pm`,`list`,`packages`])).stdout.split(`
5
+ `).map(e=>e.replace(`package:`,``).trim()).filter(Boolean).filter(e=>e.toLowerCase().includes(r.toLowerCase())),c=s[0];if(c!==void 0&&s.length===1)return D.set(a,r,{type:`package`,value:c});throw s.length>1?new t(`INVALID_ARGS`,`Multiple packages matched "${n}"`,{matches:s,hint:`Run agent-device apps --platform android to see the exact installed package names before retrying open.`}):new t(`APP_NOT_INSTALLED`,`No package found matching "${n}"`,{hint:E})}async function A(e,t){let n=await ge(e);return(t===`user-installed`?(await ve(e)).filter(e=>n.has(e)):Array.from(n)).sort((e,t)=>e.localeCompare(t)).map(e=>({package:e,name:M(e)}))}async function ge(e){let t=new Set;for(let n of j(e,{includeFallbackWhenUnknown:!0})){let r=await u(e,[`shell`,`cmd`,`package`,`query-activities`,`--brief`,`-a`,`android.intent.action.MAIN`,`-c`,n],{allowFailure:!0});if(!(r.exitCode!==0||r.stdout.trim().length===0))for(let e of g(r.stdout))t.add(e)}return t}function _e(e){return j(e)[0]??C}function j(e,t={}){return e.target===`tv`?[w]:e.target===`mobile`?[C]:t.includeFallbackWhenUnknown?[C,w]:[C]}async function ve(e){return _((await u(e,[`shell`,`pm`,`list`,`packages`,`-3`])).stdout)}function M(e){let t=new Set([`com`,`android`,`google`,`app`,`apps`,`service`,`services`,`mobile`,`client`]),n=e.split(`.`).flatMap(e=>e.split(/[_-]+/)).map(e=>e.trim().toLowerCase()).filter(e=>e.length>0),r=n[n.length-1]??e;for(let e=n.length-1;e>=0;--e){let i=n[e];if(i&&!t.has(i)){r=i;break}}return r.split(/[^a-z0-9]+/i).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(` `)}async function N(e){return await F(e,[[`shell`,`dumpsys`,`window`,`windows`],[`shell`,`dumpsys`,`window`]])||await F(e,[[`shell`,`dumpsys`,`activity`,`activities`],[`shell`,`dumpsys`,`activity`]])||{}}async function P(e){return await ye(e,[[`shell`,`dumpsys`,`window`,`windows`],[`shell`,`dumpsys`,`window`]])}async function F(e,t){for(let n of t){let t=v((await u(e,n,{allowFailure:!0})).stdout??``);if(t)return t}return null}async function ye(e,t){for(let n of t){let t=oe((await u(e,n,{allowFailure:!0})).stdout??``);if(t)return t}return null}function be(e){let t;try{t=new URL(e)}catch{return null}let n=t.hostname.toLowerCase();if(!he.has(n)||!t.port)return null;let r=Number(t.port);return Number.isInteger(r)?`tcp:${r}`:null}async function I(e,n){let r=be(n);if(!r)return;let o=a(i(e));try{await o.ensure({local:r,remote:r})}catch(e){let n={localPort:r.replace(`tcp:`,``),operation:`adb reverse ${r} ${r}`};throw e instanceof t&&Object.assign(n,{hint:e.details?.hint,diagnosticId:e.details?.diagnosticId,logPath:e.details?.logPath}),new t(`COMMAND_FAILED`,`Failed to ensure Android port reverse ${r} before opening localhost URL`,n,e)}}function xe(e){return/^[A-Za-z0-9_@%+=:,./-]+$/.test(e)?e:`'${e.replace(/'/g,`'\\''`)}'`}function L(e){return(e.launchArgs??[]).map(xe)}async function R(e,t,n){e.booted||await p(e.id);let r=Oe(n),i=r.activity,a=t.trim();if(d(a)){await Se(e,a,r);return}if(r.url!==void 0){await Ce(e,t,r);return}let o=await k(e,t),s=_e(e);if(o.type===`intent`){await we(e,o.value,r);return}if(i){await Te(e,o.value,i,s,r);return}await Ee(e,o.value,s,r)}async function Se(e,n,r){if(r.activity)throw new t(`INVALID_ARGS`,`Activity override is not supported when opening a deep link URL`);await I(e,n),await u(e,[`shell`,`am`,`start`,`-W`,`-a`,`android.intent.action.VIEW`,`-d`,n,...ke(r.appBundleId),...L(r)])}async function Ce(e,n,r){if(r.activity)throw new t(`INVALID_ARGS`,`Activity override is not supported when opening an app-bound deep link URL`);let i=r.url?.trim()??``;if(!d(i))throw new t(`INVALID_ARGS`,`Android app-bound open requires a valid URL target`);await I(e,i),await u(e,[`shell`,`am`,`start`,`-W`,`-a`,`android.intent.action.VIEW`,`-d`,i,`-p`,await De(e,n,`app-bound open`),...L(r)])}async function we(e,n,r){if(r.activity)throw new t(`INVALID_ARGS`,`Activity override requires a package name, not an intent`);await u(e,[`shell`,`am`,`start`,`-W`,`-a`,n,...L(r)])}async function Te(e,t,n,r,i){let a=n.includes(`/`)?n:`${t}/${n.startsWith(`.`)?n:`.${n}`}`;try{await u(e,z(a,r,i))}catch(n){throw await Ae(e,t,n),n}}async function Ee(e,t,n,r){let i=await u(e,[`shell`,`am`,`start`,`-W`,`-a`,`android.intent.action.MAIN`,`-c`,T,`-c`,n,`-p`,t,...L(r)],{allowFailure:!0});if(i.exitCode===0&&!U(i.stdout,i.stderr))return;let a=await je(e,t);if(!a)throw await V(e,t)?o(`Failed to launch ${t}`,i):B(t);await u(e,z(a,n,r))}function z(e,t,n){return[`shell`,`am`,`start`,`-W`,`-a`,`android.intent.action.MAIN`,`-c`,T,`-c`,t,`-n`,e,...L(n)]}async function De(e,n,r){let i=await k(e,n);if(i.type===`intent`)throw new t(`INVALID_ARGS`,`Android ${r} requires a package name, not an intent`);return i.value}function Oe(e){return typeof e==`string`?{activity:e}:e??{}}function ke(e){let t=e?.trim();return t?[`-p`,t]:[]}function B(e){return new t(`APP_NOT_INSTALLED`,`No package found matching "${e}"`,{package:e,hint:E})}async function V(e,t){let n=await u(e,[`shell`,`pm`,`path`,t],{allowFailure:!0}),r=`${n.stdout}\n${n.stderr}`;return n.exitCode===0&&/\bpackage:/i.test(r)?!0:(H(r),!1)}async function Ae(e,n,r){if(H(r instanceof t?`${String(r.details?.stdout??``)}\n${String(r.details?.stderr??``)}`:``)||!await V(e,n))throw B(n)}function H(e){return/\bunknown package\b/i.test(e)||/\bpackage .* (?:was|is) not found\b/i.test(e)||/\bpackage .* does not exist\b/i.test(e)||/\bcould not find package\b/i.test(e)}async function je(e,t){let n=Array.from(new Set(j(e,{includeFallbackWhenUnknown:!0})));for(let r of n){let n=await u(e,[`shell`,`cmd`,`package`,`resolve-activity`,`--brief`,`-a`,`android.intent.action.MAIN`,`-c`,r,t],{allowFailure:!0});if(n.exitCode!==0)continue;let i=W(n.stdout);if(i)return i}return null}function U(e,t){let n=`${e}\n${t}`;return/Error:.*(?:Activity not started|unable to resolve Intent)/i.test(n)}function W(e){let t=e.split(`
6
+ `).map(e=>e.trim()).filter(Boolean);for(let e=t.length-1;e>=0;--e){let n=t[e];if(n===void 0||!n.includes(`/`))continue;let r=n.split(/\s+/)[0];if(r!==void 0)return r}return null}async function G(e){e.booted||await p(e.id)}async function K(e,n){if(n.trim().toLowerCase()===`settings`){await u(e,[`shell`,`am`,`force-stop`,`com.android.settings`]),await q(e,`com.android.settings`);return}let r=await k(e,n);if(r.type===`intent`)throw new t(`INVALID_ARGS`,`Close requires a package name, not an intent`);await u(e,[`shell`,`am`,`force-stop`,r.value]),await q(e,r.value)}async function q(e,t){await Me(e,t),await Pe(e,t)}async function Me(e,t){let n=Date.now()+2e3;for(;Date.now()<n;){if((await Ne(e))?.package!==t)return;await l(50)}}async function Ne(e){for(let t of[[`shell`,`dumpsys`,`window`,`windows`],[`shell`,`dumpsys`,`window`],[`shell`,`dumpsys`,`activity`,`activities`],[`shell`,`dumpsys`,`activity`]]){let n=v((await u(e,t,{allowFailure:!0})).stdout??``);if(n)return n}return null}async function Pe(e,t){let n=Date.now()+2e3;for(;Date.now()<n;){if(!await J(e,t)&&(await l(150),!await J(e,t)))return;await l(50)}}async function J(e,t){return((await u(e,[`shell`,`pidof`,t],{allowFailure:!0})).stdout??``).trim().length>0}async function Fe(e,n){let r=await k(e,n);if(r.type===`intent`)throw new t(`INVALID_ARGS`,`App uninstall requires a package name, not an intent`);let i=await u(e,[`uninstall`,r.value],{allowFailure:!0});if(i.exitCode!==0){let e=`${i.stdout}\n${i.stderr}`.toLowerCase();if(!e.includes(`unknown package`)&&!e.includes(`not installed`))throw o(`adb uninstall failed for ${r.value}`,i)}return{package:r.value}}let Y=null;function Ie(){return`${process.env.PATH??``}::${process.env.AGENT_DEVICE_BUNDLETOOL_JAR??``}`}async function Le(){let e=Ie();if(Y?.key===e)return Y.invocation;if(await c(`bundletool`)){let t={cmd:`bundletool`,prefixArgs:[]};return Y={key:e,invocation:t},t}let r=await n(process.env.AGENT_DEVICE_BUNDLETOOL_JAR,`AGENT_DEVICE_BUNDLETOOL_JAR`);if(!r)throw new t(`TOOL_MISSING`,`bundletool not found in PATH. Install bundletool or set AGENT_DEVICE_BUNDLETOOL_JAR to a bundletool-all.jar path.`);let i={cmd:`java`,prefixArgs:[`-jar`,r]};return Y={key:e,invocation:i},i}async function X(e){let t=await Le();await s(t.cmd,[...t.prefixArgs,...e])}function Re(e){return h.extname(e).toLowerCase()===`.aab`}async function ze(e,t){let n=i(e),r=`universal`;if(n.installBundle){await n.installBundle(t,{mode:r});return}let a=await m.mkdtemp(h.join(te.tmpdir(),`agent-device-aab-`)),o=h.join(a,`bundle.apks`);try{await X([`build-apks`,`--bundle`,t,`--output`,o,`--mode`,r]),await X([`install-apks`,`--apks`,o,`--device-id`,e.id])}finally{await m.rm(a,{recursive:!0,force:!0})}}async function Be(e,t){if(Re(t)){await ze(e,t);return}await r(t,{device:e,replace:!0})}async function Z(e){let t=await u(e,[`shell`,`pm`,`list`,`packages`]);return new Set(t.stdout.split(`
7
+ `).map(e=>e.replace(`package:`,``).trim()).filter(Boolean))}async function Ve(e,t){let n=await Z(e),r=Array.from(n).filter(e=>!t.has(e));if(r.length===1)return r[0]}async function Q(e,t){await D.invalidateWhile(O(e),async()=>{e.booted||await p(e.id),await Be(e,t)})}async function $(e,t,n){let r=n?void 0:await Z(e);return await Q(e,t),n??(r?await Ve(e,r):void 0)}async function He(e,t){e.booted||await p(e.id);let n=await f({kind:`path`,path:t});try{let t=await $(e,n.installablePath,n.packageName),r=t?M(t):void 0;return{archivePath:n.archivePath,installablePath:n.installablePath,packageName:t,appName:r,launchTarget:t}}finally{await n.cleanup()}}async function Ue(e,t,n){return await D.invalidateWhile(O(e),async()=>{e.booted||await p(e.id);let{package:r}=await Fe(e,t),i=await f({kind:`path`,path:n},{resolveIdentity:!1});try{await Q(e,i.installablePath)}finally{await i.cleanup()}return{package:r}})}export{M as a,R as c,k as d,x as f,_ as g,g as h,P as i,G as l,v as m,K as n,U as o,fe as p,N as r,A as s,pe as t,W as u};
@@ -1 +1 @@
1
- import{pt as e}from"./internal/daemon.js";export{e as withAppLogProvider};
1
+ import{at as e}from"./internal/daemon.js";export{e as withAppLogProvider};
@@ -1 +1 @@
1
- import{t as e}from"./rolldown-runtime.js";import{_ as t}from"./sdk-contracts.js";import{c as n,s as r}from"./sdk-device.js";import{d as i,u as a}from"./logcat.js";import{O as o,w as s}from"./runner-disposal.js";import{i as c,r as l,s as u}from"./tool-provider.js";import{n as d}from"./helper.js";import{n as f}from"./setting-state.js";import p from"node:path";import{fileURLToPath as m}from"node:url";const h={settings:`com.apple.systempreferences`},g=/^[a-z0-9-]+(?:\.[a-z0-9-]+)+$/,_={platform:`macos`,deviceId:`host`,variant:`all`},v=a();function y(e){return g.test(e)}async function b(e){let n=e.trim(),r=h[n.toLowerCase()];if(r)return r;if(y(n))return n;let i=v.get(_,n);if(i)return i;let a=(await D(`all`)).filter(e=>e.name.toLowerCase()===n.toLowerCase()),o=a[0];if(o!==void 0&&a.length===1)return v.set(_,n,o.bundleId);throw a.length>1?new t(`INVALID_ARGS`,`Multiple apps matched "${e}"`,{matches:a}):new t(`APP_NOT_INSTALLED`,`No app found matching "${e}"`)}async function x(e,n,r){let a=r?.url?.trim();if(a){if(!i(a))throw new t(`INVALID_ARGS`,`open <app> <url> requires a valid URL target`);let e=r?.appBundleId??await b(n);await O().openBundle(e,a);return}let o=n.trim();if(i(o)){await O().openTarget(o);return}let s=r?.appBundleId??await b(o);await O().openBundle(s)}async function S(e,n){let r=await b(n),i=await d(r);if(!(!i.running||i.terminated||i.forceTerminated))throw new t(`COMMAND_FAILED`,`Failed to close macOS app ${n}`,{bundleId:r,running:i.running,terminated:i.terminated,forceTerminated:i.forceTerminated})}async function C(){return await O().readClipboard()}async function w(e){await O().writeClipboard(e)}async function T(){return await O().readDarkMode()}async function E(e){let t=f(e),n=t===`toggle`?!await T():t===`dark`;await O().setDarkMode(n)}async function D(e){return await O().listApps(e)}function O(){let e=l().macosHost;if(!e)throw new t(`UNSUPPORTED_OPERATION`,`macOS host provider is not available`);return e}var k=e({buildAppNotInstalledError:()=>F,findIosSimulatorInstalledApp:()=>I,invalidateIosAppResolutionCache:()=>N,listIosApps:()=>B,resolveIosApp:()=>P,resolveIosAppAlias:()=>L,resolveIosSimulatorDeepLinkBundleId:()=>R});const A={settings:`com.apple.Preferences`},j=a();function M(e){return{platform:`ios`,deviceId:e.id,variant:e.kind}}async function N(e,t){return await j.invalidateWhile(M(e),t)}async function P(e,r){if(n(e))return await b(r);let i=r.trim();if(i.includes(`.`))return i;let a=L(i);if(a!==i)return a;let o=M(e),c=j.get(o,i);if(c)return c;let l=(e.kind===`simulator`?await V(e):await s(e).listApps(e,`all`)).filter(e=>e.name.toLowerCase()===i.toLowerCase()),u=l[0];if(u!==void 0&&l.length===1)return j.set(o,i,u.bundleId);throw l.length>1?new t(`INVALID_ARGS`,`Multiple apps matched "${r}"`,{matches:l}):F(r)}function F(e){return new t(`APP_NOT_INSTALLED`,`No app found matching "${e}"`)}async function I(e,t){if(!r(e)||e.kind!==`simulator`||e.booted!==!0)return;let n=L(t.trim());if(!n)return;let i=await V(e);if(n.includes(`.`))return i.find(e=>e.bundleId===n)?.bundleId;let a=i.filter(e=>e.name.toLowerCase()===n.toLowerCase());return a.length===1?a[0]?.bundleId:void 0}function L(e){let t=e.trim();return A[t.toLowerCase()]??e}async function R(e,t){if(!r(e)||e.kind!==`simulator`)return;let n=z(t);if(!n)return;let i=await H(e),a=[];for(let e of i)e.bundleId.startsWith(`com.callstack.agentdevice.runner`)||e.path&&(await W(p.join(e.path,`Info.plist`))).has(n)&&a.push(e);let o=a.filter(e=>e.applicationType===`User`);if(o.length===1)return o[0]?.bundleId;if(!(o.length>1))return a.length===1?a[0]?.bundleId:void 0}function z(e){return/^([A-Za-z][A-Za-z0-9+.-]*):/.exec(e.trim())?.[1]?.toLowerCase()}async function B(e,t){return n(e)?await D(t):e.kind===`simulator`?u(await V(e),t):await s(e).listApps(e,t)}async function V(e){return(await H(e)).map(e=>({bundleId:e.bundleId,name:e.name}))}async function H(e){let t=(await o(e,[`listapps`,e.id],{allowFailure:!0})).stdout.trim();if(!t)return[];let n=null;if(t.startsWith(`{`))try{n=JSON.parse(t)}catch{n=null}if(!n&&t.startsWith(`{`))try{let e=await c(`plutil`,[`-convert`,`json`,`-o`,`-`,`-`],{allowFailure:!0,stdin:t});e.exitCode===0&&e.stdout.trim().startsWith(`{`)&&(n=JSON.parse(e.stdout))}catch{n=null}return n?Object.entries(n).map(([e,t])=>{let n=U(t);return{bundleId:e,name:t.CFBundleDisplayName??t.CFBundleName??e,...n?{path:n}:{},...t.ApplicationType?{applicationType:t.ApplicationType}:{}}}):[]}function U(e){if(e.Path)return e.Path;if(e.Bundle)try{return m(e.Bundle)}catch{return}}async function W(e){let t=await c(`plutil`,[`-convert`,`json`,`-o`,`-`,e],{allowFailure:!0});if(t.exitCode!==0)return new Set;try{let e=JSON.parse(t.stdout),n=new Set;for(let t of e.CFBundleURLTypes??[])if(Array.isArray(t.CFBundleURLSchemes))for(let e of t.CFBundleURLSchemes)typeof e==`string`&&e.trim()&&n.add(e.trim().toLowerCase());return n}catch{return new Set}}export{P as a,x as c,w as d,B as i,C as l,I as n,R as o,N as r,S as s,k as t,E as u};
1
+ import{t as e}from"./rolldown-runtime.js";import{_ as t}from"./sdk-contracts.js";import{c as n,s as r}from"./sdk-device.js";import{c as i,l as a}from"./install-artifact.js";import{n as o}from"./setting-state.js";import{i as s,r as c,s as l}from"./tool-provider.js";import{n as u}from"./helper.js";import{a as d,t as f}from"./physical-device-control.js";import p from"node:path";import{fileURLToPath as m}from"node:url";const h={settings:`com.apple.systempreferences`},g=/^[a-z0-9-]+(?:\.[a-z0-9-]+)+$/,_={platform:`macos`,deviceId:`host`,variant:`all`},v=i();function y(e){return g.test(e)}async function b(e){let n=e.trim(),r=h[n.toLowerCase()];if(r)return r;if(y(n))return n;let i=v.get(_,n);if(i)return i;let a=(await D(`all`)).filter(e=>e.name.toLowerCase()===n.toLowerCase()),o=a[0];if(o!==void 0&&a.length===1)return v.set(_,n,o.bundleId);throw a.length>1?new t(`INVALID_ARGS`,`Multiple apps matched "${e}"`,{matches:a}):new t(`APP_NOT_INSTALLED`,`No app found matching "${e}"`)}async function x(e,n,r){let i=r?.url?.trim();if(i){if(!a(i))throw new t(`INVALID_ARGS`,`open <app> <url> requires a valid URL target`);let e=r?.appBundleId??await b(n);await O().openBundle(e,i);return}let o=n.trim();if(a(o)){await O().openTarget(o);return}let s=r?.appBundleId??await b(o);await O().openBundle(s)}async function S(e,n){let r=await b(n),i=await u(r);if(!(!i.running||i.terminated||i.forceTerminated))throw new t(`COMMAND_FAILED`,`Failed to close macOS app ${n}`,{bundleId:r,running:i.running,terminated:i.terminated,forceTerminated:i.forceTerminated})}async function C(){return await O().readClipboard()}async function w(e){await O().writeClipboard(e)}async function T(){return await O().readDarkMode()}async function E(e){let t=o(e),n=t===`toggle`?!await T():t===`dark`;await O().setDarkMode(n)}async function D(e){return await O().listApps(e)}function O(){let e=c().macosHost;if(!e)throw new t(`UNSUPPORTED_OPERATION`,`macOS host provider is not available`);return e}var k=e({buildAppNotInstalledError:()=>F,findIosSimulatorInstalledApp:()=>I,invalidateIosAppResolutionCache:()=>N,listIosApps:()=>B,resolveIosApp:()=>P,resolveIosAppAlias:()=>L,resolveIosSimulatorDeepLinkBundleId:()=>R});const A={settings:`com.apple.Preferences`},j=i();function M(e){return{platform:`ios`,deviceId:e.id,variant:e.kind}}async function N(e,t){return await j.invalidateWhile(M(e),t)}async function P(e,r){if(n(e))return await b(r);let i=r.trim();if(i.includes(`.`))return i;let a=L(i);if(a!==i)return a;let o=M(e),s=j.get(o,i);if(s)return s;let c=(e.kind===`simulator`?await V(e):await f(e).listApps(e,`all`)).filter(e=>e.name.toLowerCase()===i.toLowerCase()),l=c[0];if(l!==void 0&&c.length===1)return j.set(o,i,l.bundleId);throw c.length>1?new t(`INVALID_ARGS`,`Multiple apps matched "${r}"`,{matches:c}):F(r)}function F(e){return new t(`APP_NOT_INSTALLED`,`No app found matching "${e}"`)}async function I(e,t){if(!r(e)||e.kind!==`simulator`||e.booted!==!0)return;let n=L(t.trim());if(!n)return;let i=await V(e);if(n.includes(`.`))return i.find(e=>e.bundleId===n)?.bundleId;let a=i.filter(e=>e.name.toLowerCase()===n.toLowerCase());return a.length===1?a[0]?.bundleId:void 0}function L(e){let t=e.trim();return A[t.toLowerCase()]??e}async function R(e,t){if(!r(e)||e.kind!==`simulator`)return;let n=z(t);if(!n)return;let i=await H(e),a=[];for(let e of i)e.bundleId.startsWith(`com.callstack.agentdevice.runner`)||e.path&&(await W(p.join(e.path,`Info.plist`))).has(n)&&a.push(e);let o=a.filter(e=>e.applicationType===`User`);if(o.length===1)return o[0]?.bundleId;if(!(o.length>1))return a.length===1?a[0]?.bundleId:void 0}function z(e){return/^([A-Za-z][A-Za-z0-9+.-]*):/.exec(e.trim())?.[1]?.toLowerCase()}async function B(e,t){return n(e)?await D(t):e.kind===`simulator`?l(await V(e),t):await f(e).listApps(e,t)}async function V(e){return(await H(e)).map(e=>({bundleId:e.bundleId,name:e.name}))}async function H(e){let t=(await d(e,[`listapps`,e.id],{allowFailure:!0})).stdout.trim();if(!t)return[];let n=null;if(t.startsWith(`{`))try{n=JSON.parse(t)}catch{n=null}if(!n&&t.startsWith(`{`))try{let e=await s(`plutil`,[`-convert`,`json`,`-o`,`-`,`-`],{allowFailure:!0,stdin:t});e.exitCode===0&&e.stdout.trim().startsWith(`{`)&&(n=JSON.parse(e.stdout))}catch{n=null}return n?Object.entries(n).map(([e,t])=>{let n=U(t);return{bundleId:e,name:t.CFBundleDisplayName??t.CFBundleName??e,...n?{path:n}:{},...t.ApplicationType?{applicationType:t.ApplicationType}:{}}}):[]}function U(e){if(e.Path)return e.Path;if(e.Bundle)try{return m(e.Bundle)}catch{return}}async function W(e){let t=await s(`plutil`,[`-convert`,`json`,`-o`,`-`,e],{allowFailure:!0});if(t.exitCode!==0)return new Set;try{let e=JSON.parse(t.stdout),n=new Set;for(let t of e.CFBundleURLTypes??[])if(Array.isArray(t.CFBundleURLSchemes))for(let e of t.CFBundleURLSchemes)typeof e==`string`&&e.trim()&&n.add(e.trim().toLowerCase());return n}catch{return new Set}}export{P as a,x as c,w as d,B as i,C as l,I as n,R as o,N as r,S as s,k as t,E as u};
package/dist/src/apps.js CHANGED
@@ -1,5 +1,5 @@
1
- import{t as e}from"./rolldown-runtime.js";import{_ as t}from"./sdk-contracts.js";import{h as n,j as r,p as i}from"./sdk-android-adb.js";import{Ct as a,Et as o}from"./recording-export-quality.js";import{c as s,s as c}from"./sdk-device.js";import{a as l}from"./runtime.js";import{d as u,f as ee,p as te}from"./logcat.js";import{l as d,o as ne,s as f}from"./boot-diagnostics.js";import{B as re,D as ie,E as p,H as ae,L as oe,M as m,O as h,P as se,R as ce,T as le,V as ue,k as g,w as _,z as de}from"./runner-disposal.js";import{n as fe,t as v}from"./launch-console.js";import{a as y,i as b}from"./tool-provider.js";import{a as pe}from"./helper.js";import{n as me,r as x}from"./simctl.js";import{a as S}from"./runner-client.js";import{At as he,kt as ge}from"./internal/daemon.js";import{a as _e,i as ve,n as ye,r as C,t as w}from"./setting-state.js";import{i as T,n as be,t as E}from"./simulator.js";import{a as D,c as xe,d as Se,i as Ce,l as we,n as Te,o as Ee,r as O,s as De,u as Oe}from"./app-resolution.js";import{n as ke}from"./install-artifact.js";import{promises as k}from"node:fs";import Ae from"node:os";import A from"node:path";const je=[`--time`,`9:41`,`--dataNetwork`,`wifi`,`--wifiMode`,`active`,`--wifiBars`,`3`,`--batteryState`,`charged`,`--batteryLevel`,`100`],Me={0:`hide`,1:`wifi`,6:`3g`,7:`4g`,8:`lte`,9:`lte-a`,10:`lte+`,11:`5g`,12:`5g+`,13:`5g-uwb`,14:`5g-uc`},Ne={1:`searching`,2:`failed`,3:`active`},Pe={0:`notSupported`,1:`searching`,2:`failed`,3:`active`};function j(e,t,n){return x(e,t,n)}const M=new Set;async function Fe(e){let t=null,n=!1;if(Le(e))n=!0;else try{t=await Re(e),n=!0}catch(t){R(e,`snapshot_failed`,t)}try{(!n||t)&&await I(e),await L(e,je)}catch(t){R(e,`prepare_failed`,t)}return async()=>{await Ie(e,n?t:null)}}async function Ie(e,t){if(await I(e),!t){P(e);return}await L(e,Be(t)),N(e)}function N(e){M.delete(F(e))}function P(e){M.add(F(e))}function Le(e){return M.has(F(e))}function F(e){return`${e.platform}:${e.kind}:${e.id}`}async function Re(e){return ze(n(await j(e,[`status_bar`,e.id,`list`],{allowFailure:!0}),`Failed to read simulator status bar overrides`).stdout)}async function I(e){await j(e,[`status_bar`,e.id,`clear`])}async function L(e,t){t.length!==0&&await j(e,[`status_bar`,e.id,`override`,...t])}function ze(e){let n={},r=e.split(`
2
- `).map(e=>e.trim()).filter(e=>e.length>0&&e!==`Current Status Bar Overrides:`&&!/^=+$/.test(e));for(let e of r){let r=/^DataNetworkType:\s+(\d+)$/.exec(e);if(r){let e=Number(r[1]),i=Me[e];if(!i)throw new t(`COMMAND_FAILED`,`Unsupported simulator data network type: ${e}`);n.dataNetwork=i;continue}let i=/^WiFi Mode:\s+(\d+),\s+WiFi Bars:\s+(\d+)$/.exec(e);if(i){let e=Ne[Number(i[1])];e&&(n.wifiMode=e),n.wifiBars=i[2];continue}let a=/^Cell Mode:\s+(\d+),\s+Cell Bars:\s+(\d+)$/.exec(e);if(a){let e=Number(a[1]),r=Pe[e];if(!r)throw new t(`COMMAND_FAILED`,`Unsupported simulator cellular mode: ${e}`);n.cellularMode=r,n.cellularBars=a[2];continue}let o=/^Operator Name:\s*(.*)$/.exec(e);if(o){n.operatorName=o[1]??``;continue}}return Object.keys(n).length===0?null:n}function Be(e){let t=[];return e.dataNetwork&&t.push(`--dataNetwork`,e.dataNetwork),e.wifiMode&&t.push(`--wifiMode`,e.wifiMode),e.wifiBars!==void 0&&(e.dataNetwork===`wifi`||e.wifiMode)&&t.push(`--wifiBars`,e.wifiBars),e.cellularMode&&t.push(`--cellularMode`,e.cellularMode),e.cellularBars!==void 0&&(e.cellularMode||Ve(e.dataNetwork)||e.operatorName!==void 0)&&t.push(`--cellularBars`,e.cellularBars),e.operatorName!==void 0&&t.push(`--operatorName`,e.operatorName),t}function Ve(e){return!!(e&&e!==`hide`&&e!==`wifi`)}function R(e,t,n){r({level:`warn`,phase:`ios_screenshot_status_bar_${t}`,data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,...p(n)}})}function z(e,t,n){return x(e,t,n)}const He={ensureBooted:E,prepareStatusBarForScreenshot:Fe,captureWithRetry:Ge,normalizeDensity:Ze,captureWithRunner:H,shouldFallbackToRunner:G},B=new Map,V=new Map;async function Ue(e,t,n={}){if(s(e)){await H(e,t,n.appBundleId,n.fullscreen,n.runnerOptions);return}if(e.kind===`simulator`){await We(e,t,n);return}await _(e).captureScreenshot(e,t,{appBundleId:n.appBundleId,fullscreen:n.fullscreen,runnerOptions:n.runnerOptions,runRunnerCommand:S})}async function We(e,n,r={}){if(e.kind!==`simulator`)throw new t(`UNSUPPORTED_OPERATION`,`Simulator screenshot fallback flow supports only iOS simulators`);let i={...He,...r.deps??{}};r.skipIosSimulatorBootCheck||await i.ensureBooted(e);let a=async()=>{};if(r.normalizeStatusBar===!0)try{a=await i.prepareStatusBarForScreenshot(e)}catch(t){W(e,`prepare_failed`,t)}try{try{await i.captureWithRetry(e,n),await i.normalizeDensity(e,n,r.pixelDensity);return}catch(t){let a=t;if(r.skipIosSimulatorBootCheck&&Xe(t)){await i.ensureBooted(e);try{await i.captureWithRetry(e,n),await i.normalizeDensity(e,n,r.pixelDensity);return}catch(e){a=e}}if(!i.shouldFallbackToRunner(a))throw a;Je(e,`simctl_screenshot`,a)}await i.captureWithRunner(e,n,r.appBundleId,r.fullscreen,r.runnerOptions),await i.normalizeDensity(e,n,r.pixelDensity)}finally{await a().catch(t=>W(e,`restore_failed`,t))}}async function Ge(e,t){let n=f.fromTimeoutMs(re);await d(async({deadline:n})=>{await z(e,[`io`,e.id,`screenshot`,t],{timeoutMs:Math.max(1e3,n?.remainingMs()??2e4)})},{maxAttempts:5,baseDelayMs:oe,maxDelayMs:ce,jitter:.2,shouldRetry:e=>G(e)},{deadline:n,phase:`ios_simulator_screenshot`})}async function H(e,n,r,i,a){if(e.kind===`device`&&!s(e)){await _(e).captureScreenshot(e,n,{appBundleId:r,fullscreen:i,runnerOptions:a,preferRunner:!0,runRunnerCommand:S});return}let o=(await S(e,{command:`screenshot`,appBundleId:r,fullscreen:i,inlineScreenshot:!1},a)).message;if(!o)throw new t(`COMMAND_FAILED`,`Failed to capture iOS screenshot: runner returned no file path`);if(s(e)){await k.copyFile(o,n);return}if(e.kind===`simulator`){await Ke(e,o,n);return}throw new t(`COMMAND_FAILED`,`Unsupported Apple screenshot target`)}async function Ke(e,n,r){let i=f.fromTimeoutMs(se),a=`Unable to locate runner container for simulator screenshot`,o=V.get(e.id);if(o){let t=await U(o,n,r);if(t.copied)return;a=t.error,V.delete(e.id)}for(let t of ae){let o=await z(e,[`get_app_container`,e.id,t,`data`],{allowFailure:!0,timeoutMs:qe(i,se,`runner screenshot container lookup`)});if(o.exitCode!==0){let e=o.stderr.trim();e&&(a=e);continue}let s=o.stdout.trim();if(!s){a=`simctl get_app_container returned empty output`;continue}let c=await U(s,n,r);if(c.copied){V.set(e.id,s);return}a=c.error}throw new t(`COMMAND_FAILED`,`Failed to capture iOS screenshot: ${a}`)}async function U(e,t,n){let r=`Runner screenshot was not found in the simulator container`;for(let i of Ye(e,t))try{return await k.copyFile(i,n),{copied:!0}}catch(e){r=e instanceof Error?e.message:String(e)}return{copied:!1,error:r}}function qe(e,n,r){let i=e.remainingMs();if(i>0)return i;throw new t(`COMMAND_FAILED`,`iOS ${r} timed out after ${n}ms`,{timeoutMs:n,step:r})}function Je(e,t,n){let i=p(n);r({level:`warn`,phase:`ios_screenshot_fallback`,data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,from:t,to:`runner`,...i}})}function W(e,t,n){r({level:`warn`,phase:`ios_screenshot_status_bar_${t}`,data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,...p(n)}})}function Ye(e,t){let n=A.resolve(e),r=t.trim();if(!r)return[];let i=[],a=new Set,o=e=>{let t=A.normalize(e);a.has(t)||(a.add(t),i.push(t))},s=r.replace(/^\/+/,``),c=s.replace(/\\/g,`/`);if(s&&o(A.join(n,s)),A.isAbsolute(r)&&o(A.normalize(r)),c.startsWith(`tmp/`))o(A.join(n,c));else{let e=c.lastIndexOf(`/tmp/`);if(e>=0){let t=c.slice(e+1);o(A.join(n,t))}}let l=A.basename(r);return l&&o(A.join(n,`tmp`,l)),i}function G(e){if(!(e instanceof t)||e.code!==`COMMAND_FAILED`)return!1;let n=le(e);return n.includes(`timeout waiting for screen surfaces`)||n.includes(`nsposixerrordomain`)&&n.includes(`code=60`)&&n.includes(`screenshot`)||n.includes(`timed out`)&&n.includes(`screenshot`)}function Xe(e){if(!(e instanceof t)||e.code!==`COMMAND_FAILED`)return!1;let n=le(e);return n.includes(`not booted`)||n.includes(`current state: shutdown`)||n.includes(`current state is shutdown`)||n.includes(`current state=shutdown`)||n.includes(`state: shutdown`)||n.includes(`state=shutdown`)}async function Ze(e,t,n){let r=await Qe(e),i=ge(await he(t),r,n);i&&await l(t,i.width,i.height)}async function Qe(e){let n=B.get(e.id);if(n!==void 0)return n;let r=await z(e,[`getenv`,e.id,`SIMULATOR_MAINSCREEN_SCALE`],{timeoutMs:de}),i=Number(r.stdout.trim());if(!Number.isFinite(i)||i<=0)throw new t(`COMMAND_FAILED`,`Failed to read iOS simulator screenshot scale from SIMULATOR_MAINSCREEN_SCALE`);return B.set(e.id,i),i}function K(e){if(!(e instanceof t)||e.code!==`COMMAND_FAILED`)return!1;let n=e.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 $e(e,t){let n=await y(me(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 b(`plutil`,[`-extract`,`CFBundleExecutable`,`raw`,`-o`,`-`,`${r}/Info.plist`],{allowFailure:!0});if(i.exitCode!==0||!i.stdout.trim())return{installed:!0};let a=await b(`otool`,[`-l`,`${r}/${i.stdout.trim()}`],{allowFailure:!0});if(a.exitCode!==0)return{installed:!0};let o=a.stdout.toLowerCase();return{installed:!0,simulatorCompatible:o.includes(`iossimulator`)||o.includes(`platform 7`)}}function et(e){return e.installed?e.simulatorCompatible===!1?`ARCH_MISMATCH`:`PERSISTENT_LAUNCH_FAIL`:`APP_NOT_INSTALLED`}function tt(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 q=25e3;async function nt(e,n,r){let i=r?.launchConsole?.trim(),a=r?.launchArgs;if(i&&(!c(e)||e.kind!==`simulator`))throw new t(`UNSUPPORTED_OPERATION`,fe);if(s(e)){if(a&&a.length>0)throw new t(`UNSUPPORTED_OPERATION`,`--launch-args is not supported on macOS; launch arguments are currently iOS-only.`);await xe(e,n,r);return}let o=r?.url?.trim();if(o){if(i)throw new t(`INVALID_ARGS`,v);if(!u(o))throw new t(`INVALID_ARGS`,`open <app> <url> requires a valid URL target`);if(e.kind===`simulator`){(a||ee(o))&&await X(e,r?.appBundleId??await D(e,n),{...a?{launchArgs:a}:{}}),await J(e,o,void 0);return}let s=te(r?.appBundleId??await D(e,n),o);if(!s)throw new t(`INVALID_ARGS`,`Deep link open on iOS devices requires an active app bundle ID. Open the app first, then open the URL.`);await Q(e,s,{payloadUrl:o,launchArgs:a,runnerOptions:r?.runnerOptions});return}let l=n.trim();if(u(l)){if(i)throw new t(`INVALID_ARGS`,v);if(e.kind===`simulator`){await J(e,l,a);return}let n=te(r?.appBundleId,l);if(!n)throw new t(`INVALID_ARGS`,`Deep link open on iOS devices requires an active app bundle ID. Open the app first, then open the URL.`);await Q(e,n,{payloadUrl:l,launchArgs:a,runnerOptions:r?.runnerOptions});return}let d=r?.appBundleId??await D(e,n);if(e.kind===`simulator`){await X(e,d,{...i?{launchConsole:i}:{},...a?{launchArgs:a}:{},...r?.terminateRunningApp?{terminateRunningApp:!0}:{}});return}await Q(e,d,{launchArgs:a,runnerOptions:r?.runnerOptions})}async function J(e,n,r){if(r&&r.length>0)throw new t(`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 E(e),await h(e,[`openurl`,e.id,n])}async function rt(e){s(e)||e.kind===`simulator`&&await be(e)!==`Booted`&&await E(e)}async function Y(e,n,r){if(s(e)){await De(e,n);return}let a=await D(e,n);if(e.kind===`simulator`){await E(e);let n=g(e,[`terminate`,e.id,a]),r=await y(n,{allowFailure:!0,timeoutMs:ue});if(r.exitCode!==0){if(r.stderr.toLowerCase().includes(`found nothing to terminate`))return;throw new t(`COMMAND_FAILED`,`xcrun exited with code ${r.exitCode}`,i(r,{cmd:`xcrun`,args:n}))}return}await _(e).terminateApp(e,a,{runnerOptions:r,runRunnerCommand:S})}async function X(e,n,r){await E(e);let a=0,o=f.fromTimeoutMs(m);try{await d(async({deadline:a})=>{if(a?.isExpired())throw new t(`COMMAND_FAILED`,`App launch deadline exceeded`,{timeoutMs:m});let o=g(e,it(e.id,n,r)),s=r?.launchConsole?await at(o,r.launchConsole):await y(o,{allowFailure:!0});if(s.exitCode!==0)throw new t(`COMMAND_FAILED`,`xcrun exited with code ${s.exitCode}`,i(s,{cmd:`xcrun`,args:o}))},{maxAttempts:10,baseDelayMs:1e3,maxDelayMs:5e3,jitter:.2,shouldRetry(e){return K(e)?(a+=1,a<3):!1}},{deadline:o})}catch(t){if(K(t)){let r=t,i=et(await $e(e,n));r.details={...r.details,hint:tt(i)}}throw t}}function it(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 at(e,n){await k.mkdir(A.dirname(n),{recursive:!0});try{let t=await y(e,{allowFailure:!0,timeoutMs:q});return await Z(n,t.stdout,t.stderr),t}catch(e){let i=(e instanceof t?e:void 0)?.details;if(i?.timeoutMs===q){let e=typeof i.stdout==`string`?i.stdout:``,t=typeof i.stderr==`string`?i.stderr:``;return await Z(n,e,t),r({level:`warn`,phase:`ios_simulator_launch_console_capture_timeout`,data:{timeoutMs:q,logPath:n,stdoutBytes:Buffer.byteLength(e),stderrBytes:Buffer.byteLength(t)}}),{stdout:e,stderr:t,exitCode:0}}throw e}}async function Z(e,t,n){await k.writeFile(e,ot(t,n),`utf8`)}function ot(e,t){return!e||!t||e.endsWith(`
3
- `)||e.endsWith(`\r`)?`${e}${t}`:`${e}\n${t}`}async function Q(e,t,n){await _(e).launchApp(e,t,{...n,runRunnerCommand:S})}async function st(e,n){return await O(e,async()=>{let r=await D(e,n);if(e.kind!==`simulator`)return await _(e).uninstallApp(e,r),{bundleId:r};await E(e);let a=await h(e,[`uninstall`,e.id,r],{allowFailure:!0});if(a.exitCode!==0&&!ie(`${a.stdout}\n${a.stderr}`.toLowerCase()))throw new t(`COMMAND_FAILED`,`simctl uninstall failed for ${r}`,i(a));return{bundleId:r}})}async function ct(e,t,n){e.kind!==`simulator`&&_(e).assertAppInstallationSupported(e);let r=await ke({kind:`path`,path:t},n);try{return await ut(e,r.installablePath),{archivePath:r.archivePath,installablePath:r.installablePath,bundleId:r.bundleId,appName:r.appName,launchTarget:r.bundleId}}finally{await r.cleanup()}}async function lt(e,t,n){return e.kind!==`simulator`&&_(e).assertAppInstallationSupported(e),await O(e,async()=>{let{bundleId:r}=await st(e,t);return await ct(e,n,{appIdentifierHint:t}),{bundleId:r}})}async function ut(e,t){await O(e,async()=>{if(e.kind!==`simulator`){await _(e).installApp(e,t);return}await E(e),await h(e,[`install`,e.id,t])})}async function dt(e){return s(e)?await we():(T(e,`clipboard`),await E(e),n(await h(e,[`pbpaste`,e.id],{allowFailure:!0}),`Failed to read iOS simulator clipboard`).stdout.replace(/\r\n/g,`
4
- `).replace(/\n$/,``))}async function ft(e,t){if(s(e)){await Se(t);return}T(e,`clipboard`),await E(e),n(await h(e,[`pbcopy`,e.id],{allowFailure:!0,stdin:t}),`Failed to write iOS simulator clipboard`)}async function pt(e,t,n){T(e,`push`),await E(e);let r=await k.mkdtemp(A.join(Ae.tmpdir(),`agent-device-ios-push-`)),i=A.join(r,`payload.apns`);try{await k.writeFile(i,`${JSON.stringify(n)}\n`,`utf8`),await h(e,[`push`,e.id,t,i])}finally{await k.rm(r,{recursive:!0,force:!0})}}let $=null,mt;async function ht(e,n,r,i,c){if(s(e)){let e=n.toLowerCase();if(e===`appearance`){await Oe(r);return}if(e===`permission`){let e=C(r);if(e===`deny`)throw new t(`INVALID_ARGS`,o(`permission`));return await pe(e,_t(c?.permissionTarget))}throw new t(`INVALID_ARGS`,o(n))}T(e,`settings`),await E(e);let l=n.toLowerCase();switch(l){case`clear-app-state`:{if(r.toLowerCase()!==`clear`)throw new t(`INVALID_ARGS`,`settings clear-app-state only supports clear.`);if(!i)throw new t(`INVALID_ARGS`,`settings clear-app-state requires an app id or an active app session.`);let n=await gt(e,i);return{bundleId:n.bundleId,containerPath:n.containerPath,cleared:!0}}case`wifi`:{let t=w(r)?`active`:`failed`;await h(e,[`status_bar`,e.id,`override`,`--wifiMode`,t]),N(e);return}case`airplane`:w(r)?(await h(e,[`status_bar`,e.id,`override`,`--dataNetwork`,`hide`,`--wifiMode`,`failed`,`--wifiBars`,`0`,`--cellularMode`,`failed`,`--cellularBars`,`0`,`--operatorName`,``]),N(e)):(await h(e,[`status_bar`,e.id,`clear`]),P(e));return;case`location`:{if(r.toLowerCase()===`set`){let{latitude:t,longitude:n}=a(c);return await h(e,[`location`,e.id,`set`,`${t},${n}`]),{latitude:t,longitude:n}}let n=w(r);if(!i)throw new t(`INVALID_ARGS`,`location setting requires an active app in session`);let o=n?`grant`:`revoke`;await h(e,[`privacy`,e.id,o,`location`,i]);return}case`faceid`:case`touchid`:{let t=l,n=bt[t];await Ot(e,Dt(r,t),{settingName:t,label:n.label,modalityAliases:n.modalityAliases});return}case`appearance`:{let t=await vt(e,r);await h(e,[`ui`,e.id,`appearance`,t]);return}case`permission`:if(!i)throw new t(`INVALID_ARGS`,`permission setting requires an active app in session`);await St(e,xt(C(r)),Et(c?.permissionTarget,c?.permissionMode),i);return;default:throw new t(`INVALID_ARGS`,`Unsupported setting: ${n}`)}}async function gt(e,r){if(!c(e)||e.kind!==`simulator`)throw new t(`UNSUPPORTED_OPERATION`,`Clearing app state is currently supported only on iOS simulators.`);let i=await D(e,r);await E(e),await Y(e,i);let a=n(await h(e,[`get_app_container`,e.id,i,`data`],{allowFailure:!0}),`simctl get_app_container failed for ${i}`).stdout.trim();if(!a)throw new t(`COMMAND_FAILED`,`simctl get_app_container returned an empty data container path for ${i}`);let o=await k.readdir(a);return await Promise.all(o.map(e=>k.rm(A.join(a,e),{recursive:!0,force:!0}))),{bundleId:i,containerPath:a}}function _t(e){let n=e?.trim().toLowerCase();if(n===`accessibility`||n===`screen-recording`||n===`input-monitoring`)return n;throw new t(`INVALID_ARGS`,`Unsupported macOS permission target. Use accessibility|screen-recording|input-monitoring.`)}async function vt(e,r){let i=ye(r);if(i!==`toggle`)return i;let a=n(await h(e,[`ui`,e.id,`appearance`],{allowFailure:!0}),`Failed to read current iOS appearance`),o=yt(a.stdout,a.stderr);if(!o)throw new t(`COMMAND_FAILED`,`Unable to determine current iOS appearance for toggle`,{stdout:a.stdout,stderr:a.stderr});return o===`dark`?`light`:`dark`}function yt(e,t){let n=/\b(light|dark|unsupported|unknown)\b/i.exec(`${e}\n${t}`);if(!n)return null;let r=n[1]?.toLowerCase();return r===`dark`?`dark`:r===`light`?`light`:null}const bt={faceid:{label:`Face ID`,modalityAliases:[`face`]},touchid:{label:`Touch ID`,modalityAliases:[`finger`,`touch`]}};function xt(e){return e===`deny`?`revoke`:e}async function St(e,n,r,i){let a=await wt(e);if(!a.has(r))throw new t(`UNSUPPORTED_OPERATION`,`iOS simctl privacy does not support service "${r}" on this runtime.`,{deviceId:e.id,appBundleId:i,hint:`Supported services: ${Array.from(a).sort().join(`, `)}`});let o=[`privacy`,e.id,n,r,i],s=r===`notifications`;if(!(n===`reset`&&s))try{await h(e,o);return}catch(n){throw s&&Ct(n)?new t(`UNSUPPORTED_OPERATION`,`iOS simulator does not support setting notifications permission via simctl privacy on this runtime.`,{deviceId:e.id,appBundleId:i,hint:`Use reset notifications for reprompt behavior, or toggle notifications manually in Settings.`}):n}try{await h(e,o);return}catch(e){if(!Ct(e))throw e}try{await h(e,[`privacy`,e.id,`reset`,`all`,i])}catch(n){throw new t(`COMMAND_FAILED`,`iOS simulator blocked direct notifications reset. Fallback reset-all also failed.`,{deviceId:e.id,appBundleId:i,hint:`Use reinstall to force a fresh notifications prompt, or reset simulator content and settings.`},n instanceof Error?n:void 0)}}function Ct(e){if(!(e instanceof t)||e.code!==`COMMAND_FAILED`)return!1;let n=String(e.details?.stderr??``).toLowerCase();return(n.includes(`failed to grant access`)||n.includes(`failed to revoke access`)||n.includes(`failed to reset access`))&&n.includes(`operation not permitted`)}async function wt(e){let n=ne(e.simulatorSetPath),r=`${process.env.PATH??``}::${n??``}`;if($&&mt===r)return $;let i=await h(e,[`privacy`,`help`],{allowFailure:!0}),a=Tt(`${i.stdout}\n${i.stderr}`);if(a.size===0)throw new t(`COMMAND_FAILED`,`Unable to determine supported simctl privacy services`,{stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode,hint:"Run `xcrun simctl privacy help` manually to verify available services for this runtime."});return $=a,mt=r,a}function Tt(e){let t=new Set,n=!1;for(let r of e.split(`
5
- `)){let e=r.trim();if(!e)continue;if(e===`service`){n=!0;continue}if(!n)continue;if(e.startsWith(`bundle identifier`))break;let i=/^([a-z-]+)\s+-\s+/.exec(e)?.[1];i!==void 0&&t.add(i)}return t}function Et(e,n){let r=ve(e);if(r!==`photos`&&n?.trim())throw new t(`INVALID_ARGS`,`Permission mode is only supported for photos. Received: ${n}.`);if(r===`camera`)return`camera`;if(r===`microphone`)return`microphone`;if(r===`contacts`)return`contacts`;if(r===`contacts-limited`)return`contacts-limited`;if(r===`notifications`)return`notifications`;if(r===`calendar`)return`calendar`;if(r===`location`)return`location`;if(r===`location-always`)return`location-always`;if(r===`media-library`)return`media-library`;if(r===`motion`)return`motion`;if(r===`reminders`)return`reminders`;if(r===`siri`)return`siri`;if(r===`photos`){let e=n?.trim().toLowerCase();if(!e||e===`full`)return`photos`;if(e===`limited`)return`photos-add`;throw new t(`INVALID_ARGS`,`Invalid photos mode: ${n}. Use full|limited.`)}throw new t(`INVALID_ARGS`,`Unsupported permission target: ${e}. Use camera|microphone|photos|contacts|contacts-limited|notifications|calendar|location|location-always|media-library|motion|reminders|siri.`)}function Dt(e,n){let r=e.trim().toLowerCase();if(r===`match`)return`match`;if(r===`nonmatch`)return`nonmatch`;if(r===`enroll`)return`enroll`;if(r===`unenroll`)return`unenroll`;throw new t(`INVALID_ARGS`,`Invalid ${n} state: ${e}. Use match|nonmatch|enroll|unenroll.`)}async function Ot(e,n,r){let i=kt(e.id,n,r.modalityAliases),a=[];for(let t of i){let n=g(e,t),r=await y(n,{allowFailure:!0});if(r.exitCode===0)return;a.push({args:n,stderr:r.stderr,stdout:r.stdout,exitCode:r.exitCode})}let o=_e(a);throw a.length>0&&a.every(e=>At(e.stdout,e.stderr))?new t(`UNSUPPORTED_OPERATION`,`${r.label} simulation is not supported on this simulator runtime.`,{deviceId:e.id,action:n,setting:r.settingName,attempts:o}):new t(`COMMAND_FAILED`,`Failed to simulate ${r.settingName}.`,{deviceId:e.id,action:n,setting:r.settingName,attempts:o})}function kt(e,t,n){let r=n.length>0?n:[`face`];switch(t){case`match`:return r.flatMap(t=>[[`biometric`,e,`match`,t],[`biometric`,`match`,e,t]]);case`nonmatch`:return r.flatMap(t=>[[`biometric`,e,`nonmatch`,t],[`biometric`,e,`nomatch`,t],[`biometric`,`nonmatch`,e,t],[`biometric`,`nomatch`,e,t]]);case`enroll`:return[[`biometric`,e,`enroll`,`yes`],[`biometric`,e,`enroll`,`1`],[`biometric`,`enroll`,e,`yes`],[`biometric`,`enroll`,e,`1`]];case`unenroll`:return[[`biometric`,e,`enroll`,`no`],[`biometric`,e,`enroll`,`0`],[`biometric`,`enroll`,e,`no`],[`biometric`,`enroll`,e,`0`]]}}function At(e,t){let n=`${e}\n${t}`.toLowerCase();return n.includes(`unrecognized subcommand`)||n.includes(`unknown subcommand`)||n.includes(`not supported`)||n.includes(`unavailable`)||n.includes(`biometric`)&&n.includes(`invalid`)}var jt=e({findIosSimulatorInstalledApp:()=>Te,installIosApp:()=>ct,installIosInstallablePath:()=>ut,listIosApps:()=>Ce,pushIosNotification:()=>pt,reinstallIosApp:()=>lt,resolveIosApp:()=>D,resolveIosSimulatorDeepLinkBundleId:()=>Ee});export{Y as a,H as c,ft as i,Ue as l,ht as n,nt as o,dt as r,rt as s,jt as t};
1
+ import{t as e}from"./rolldown-runtime.js";import{_ as t}from"./sdk-contracts.js";import{h as n,j as r,p as i}from"./sdk-android-adb.js";import{ft as a}from"./recording-export-quality.js";import{c as o,s}from"./sdk-device.js";import{S as c}from"./gesture-plan-types.js";import{a as l}from"./runtime.js";import{d as u,l as d,u as ee}from"./install-artifact.js";import{l as f,o as te,s as p}from"./boot-diagnostics.js";import{a as ne,i as re,n as ie,r as ae,t as m}from"./setting-state.js";import{n as oe,t as se}from"./launch-console.js";import{a as h,i as g}from"./tool-provider.js";import{a as ce}from"./helper.js";import{L as le,R as _,_ as ue,a as v,d as y,g as de,h as fe,i as pe,l as me,m as he,n as b,o as x,r as S,t as C,v as ge,y as _e}from"./physical-device-control.js";import{a as w}from"./runner-client.js";import{St as ve,xt as ye}from"./internal/daemon.js";import{i as T,n as be,t as E}from"./simulator.js";import{a as D,c as xe,d as Se,i as Ce,l as we,n as Te,o as Ee,r as O,s as De,u as Oe}from"./app-resolution.js";import{n as ke}from"./install-artifact2.js";import{promises as k}from"node:fs";import Ae from"node:os";import A from"node:path";const je=[`--time`,`9:41`,`--dataNetwork`,`wifi`,`--wifiMode`,`active`,`--wifiBars`,`3`,`--batteryState`,`charged`,`--batteryLevel`,`100`],Me={0:`hide`,1:`wifi`,6:`3g`,7:`4g`,8:`lte`,9:`lte-a`,10:`lte+`,11:`5g`,12:`5g+`,13:`5g-uwb`,14:`5g-uc`},Ne={1:`searching`,2:`failed`,3:`active`},Pe={0:`notSupported`,1:`searching`,2:`failed`,3:`active`};function j(e,t,n){return _(e,t,n)}const M=new Set;async function Fe(e){let t=null,n=!1;if(Re(e))n=!0;else try{t=await ze(e),n=!0}catch(t){L(e,`snapshot_failed`,t)}try{(!n||t)&&await F(e),await I(e,je)}catch(t){L(e,`prepare_failed`,t)}return async()=>{await Ie(e,n?t:null)}}async function Ie(e,t){if(await F(e),!t){Le(e);return}await I(e,Ve(t)),N(e)}function N(e){M.delete(P(e))}function Le(e){M.add(P(e))}function Re(e){return M.has(P(e))}function P(e){return`${e.platform}:${e.kind}:${e.id}`}async function ze(e){return Be(n(await j(e,[`status_bar`,e.id,`list`],{allowFailure:!0}),`Failed to read simulator status bar overrides`).stdout)}async function F(e){await j(e,[`status_bar`,e.id,`clear`])}async function I(e,t){t.length!==0&&await j(e,[`status_bar`,e.id,`override`,...t])}function Be(e){let n={},r=e.split(`
2
+ `).map(e=>e.trim()).filter(e=>e.length>0&&e!==`Current Status Bar Overrides:`&&!/^=+$/.test(e));for(let e of r){let r=/^DataNetworkType:\s+(\d+)$/.exec(e);if(r){let e=Number(r[1]),i=Me[e];if(!i)throw new t(`COMMAND_FAILED`,`Unsupported simulator data network type: ${e}`);n.dataNetwork=i;continue}let i=/^WiFi Mode:\s+(\d+),\s+WiFi Bars:\s+(\d+)$/.exec(e);if(i){let e=Ne[Number(i[1])];e&&(n.wifiMode=e),n.wifiBars=i[2];continue}let a=/^Cell Mode:\s+(\d+),\s+Cell Bars:\s+(\d+)$/.exec(e);if(a){let e=Number(a[1]),r=Pe[e];if(!r)throw new t(`COMMAND_FAILED`,`Unsupported simulator cellular mode: ${e}`);n.cellularMode=r,n.cellularBars=a[2];continue}let o=/^Operator Name:\s*(.*)$/.exec(e);if(o){n.operatorName=o[1]??``;continue}}return Object.keys(n).length===0?null:n}function Ve(e){let t=[];return e.dataNetwork&&t.push(`--dataNetwork`,e.dataNetwork),e.wifiMode&&t.push(`--wifiMode`,e.wifiMode),e.wifiBars!==void 0&&(e.dataNetwork===`wifi`||e.wifiMode)&&t.push(`--wifiBars`,e.wifiBars),e.cellularMode&&t.push(`--cellularMode`,e.cellularMode),e.cellularBars!==void 0&&(e.cellularMode||He(e.dataNetwork)||e.operatorName!==void 0)&&t.push(`--cellularBars`,e.cellularBars),e.operatorName!==void 0&&t.push(`--operatorName`,e.operatorName),t}function He(e){return!!(e&&e!==`hide`&&e!==`wifi`)}function L(e,t,n){r({level:`warn`,phase:`ios_screenshot_status_bar_${t}`,data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,...S(n)}})}function R(e,t,n){return _(e,t,n)}const Ue={ensureBooted:E,prepareStatusBarForScreenshot:Fe,captureWithRetry:Ke,normalizeDensity:Qe,captureWithRunner:V,shouldFallbackToRunner:W},z=new Map,B=new Map;async function We(e,t,n={}){if(o(e)){await V(e,t,n.appBundleId,n.fullscreen,n.runnerOptions);return}if(e.kind===`simulator`){await Ge(e,t,n);return}await C(e).captureScreenshot(e,t,{appBundleId:n.appBundleId,fullscreen:n.fullscreen,runnerOptions:n.runnerOptions,runRunnerCommand:w})}async function Ge(e,n,r={}){if(e.kind!==`simulator`)throw new t(`UNSUPPORTED_OPERATION`,`Simulator screenshot fallback flow supports only iOS simulators`);let i={...Ue,...r.deps??{}};r.skipIosSimulatorBootCheck||await i.ensureBooted(e);let a=async()=>{};if(r.normalizeStatusBar===!0)try{a=await i.prepareStatusBarForScreenshot(e)}catch(t){U(e,`prepare_failed`,t)}try{try{await i.captureWithRetry(e,n),await i.normalizeDensity(e,n,r.pixelDensity);return}catch(t){let a=t;if(r.skipIosSimulatorBootCheck&&Ze(t)){await i.ensureBooted(e);try{await i.captureWithRetry(e,n),await i.normalizeDensity(e,n,r.pixelDensity);return}catch(e){a=e}}if(!i.shouldFallbackToRunner(a))throw a;Ye(e,`simctl_screenshot`,a)}await i.captureWithRunner(e,n,r.appBundleId,r.fullscreen,r.runnerOptions),await i.normalizeDensity(e,n,r.pixelDensity)}finally{await a().catch(t=>U(e,`restore_failed`,t))}}async function Ke(e,t){let n=p.fromTimeoutMs(ue);await f(async({deadline:n})=>{await R(e,[`io`,e.id,`screenshot`,t],{timeoutMs:Math.max(1e3,n?.remainingMs()??2e4)})},{maxAttempts:5,baseDelayMs:he,maxDelayMs:fe,jitter:.2,shouldRetry:e=>W(e)},{deadline:n,phase:`ios_simulator_screenshot`})}async function V(e,n,r,i,a){if(e.kind===`device`&&!o(e)){await C(e).captureScreenshot(e,n,{appBundleId:r,fullscreen:i,runnerOptions:a,preferRunner:!0,runRunnerCommand:w});return}let s=(await w(e,{command:`screenshot`,appBundleId:r,fullscreen:i,inlineScreenshot:!1},a)).message;if(!s)throw new t(`COMMAND_FAILED`,`Failed to capture iOS screenshot: runner returned no file path`);if(o(e)){await k.copyFile(s,n);return}if(e.kind===`simulator`){await qe(e,s,n);return}throw new t(`COMMAND_FAILED`,`Unsupported Apple screenshot target`)}async function qe(e,n,r){let i=p.fromTimeoutMs(y),a=`Unable to locate runner container for simulator screenshot`,o=B.get(e.id);if(o){let t=await H(o,n,r);if(t.copied)return;a=t.error,B.delete(e.id)}for(let t of _e){let o=await R(e,[`get_app_container`,e.id,t,`data`],{allowFailure:!0,timeoutMs:Je(i,y,`runner screenshot container lookup`)});if(o.exitCode!==0){let e=o.stderr.trim();e&&(a=e);continue}let s=o.stdout.trim();if(!s){a=`simctl get_app_container returned empty output`;continue}let c=await H(s,n,r);if(c.copied){B.set(e.id,s);return}a=c.error}throw new t(`COMMAND_FAILED`,`Failed to capture iOS screenshot: ${a}`)}async function H(e,t,n){let r=`Runner screenshot was not found in the simulator container`;for(let i of Xe(e,t))try{return await k.copyFile(i,n),{copied:!0}}catch(e){r=e instanceof Error?e.message:String(e)}return{copied:!1,error:r}}function Je(e,n,r){let i=e.remainingMs();if(i>0)return i;throw new t(`COMMAND_FAILED`,`iOS ${r} timed out after ${n}ms`,{timeoutMs:n,step:r})}function Ye(e,t,n){let i=S(n);r({level:`warn`,phase:`ios_screenshot_fallback`,data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,from:t,to:`runner`,...i}})}function U(e,t,n){r({level:`warn`,phase:`ios_screenshot_status_bar_${t}`,data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,...S(n)}})}function Xe(e,t){let n=A.resolve(e),r=t.trim();if(!r)return[];let i=[],a=new Set,o=e=>{let t=A.normalize(e);a.has(t)||(a.add(t),i.push(t))},s=r.replace(/^\/+/,``),c=s.replace(/\\/g,`/`);if(s&&o(A.join(n,s)),A.isAbsolute(r)&&o(A.normalize(r)),c.startsWith(`tmp/`))o(A.join(n,c));else{let e=c.lastIndexOf(`/tmp/`);if(e>=0){let t=c.slice(e+1);o(A.join(n,t))}}let l=A.basename(r);return l&&o(A.join(n,`tmp`,l)),i}function W(e){if(!(e instanceof t)||e.code!==`COMMAND_FAILED`)return!1;let n=b(e);return n.includes(`timeout waiting for screen surfaces`)||n.includes(`nsposixerrordomain`)&&n.includes(`code=60`)&&n.includes(`screenshot`)||n.includes(`timed out`)&&n.includes(`screenshot`)}function Ze(e){if(!(e instanceof t)||e.code!==`COMMAND_FAILED`)return!1;let n=b(e);return n.includes(`not booted`)||n.includes(`current state: shutdown`)||n.includes(`current state is shutdown`)||n.includes(`current state=shutdown`)||n.includes(`state: shutdown`)||n.includes(`state=shutdown`)}async function Qe(e,t,n){let r=await $e(e),i=ye(await ve(t),r,n);i&&await l(t,i.width,i.height)}async function $e(e){let n=z.get(e.id);if(n!==void 0)return n;let r=await R(e,[`getenv`,e.id,`SIMULATOR_MAINSCREEN_SCALE`],{timeoutMs:de}),i=Number(r.stdout.trim());if(!Number.isFinite(i)||i<=0)throw new t(`COMMAND_FAILED`,`Failed to read iOS simulator screenshot scale from SIMULATOR_MAINSCREEN_SCALE`);return z.set(e.id,i),i}function G(e){if(!(e instanceof t)||e.code!==`COMMAND_FAILED`)return!1;let n=e.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 et(e,t){let n=await h(le(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=await g(`otool`,[`-l`,`${r}/${i.stdout.trim()}`],{allowFailure:!0});if(a.exitCode!==0)return{installed:!0};let o=a.stdout.toLowerCase();return{installed:!0,simulatorCompatible:o.includes(`iossimulator`)||o.includes(`platform 7`)}}function tt(e){return e.installed?e.simulatorCompatible===!1?`ARCH_MISMATCH`:`PERSISTENT_LAUNCH_FAIL`:`APP_NOT_INSTALLED`}function nt(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 K=25e3;async function rt(e,n,r){let i=r?.launchConsole?.trim(),a=r?.launchArgs;if(i&&(!s(e)||e.kind!==`simulator`))throw new t(`UNSUPPORTED_OPERATION`,oe);if(o(e)){if(a&&a.length>0)throw new t(`UNSUPPORTED_OPERATION`,`--launch-args is not supported on macOS; launch arguments are currently iOS-only.`);await xe(e,n,r);return}let c=r?.url?.trim();if(c){if(i)throw new t(`INVALID_ARGS`,se);if(!d(c))throw new t(`INVALID_ARGS`,`open <app> <url> requires a valid URL target`);if(e.kind===`simulator`){(a||ee(c))&&await Y(e,r?.appBundleId??await D(e,n),{...a?{launchArgs:a}:{}}),await q(e,c,void 0);return}let o=u(r?.appBundleId??await D(e,n),c);if(!o)throw new t(`INVALID_ARGS`,`Deep link open on iOS devices requires an active app bundle ID. Open the app first, then open the URL.`);await Z(e,o,{payloadUrl:c,launchArgs:a,runnerOptions:r?.runnerOptions});return}let l=n.trim();if(d(l)){if(i)throw new t(`INVALID_ARGS`,se);if(e.kind===`simulator`){await q(e,l,a);return}let n=u(r?.appBundleId,l);if(!n)throw new t(`INVALID_ARGS`,`Deep link open on iOS devices requires an active app bundle ID. Open the app first, then open the URL.`);await Z(e,n,{payloadUrl:l,launchArgs:a,runnerOptions:r?.runnerOptions});return}let f=r?.appBundleId??await D(e,n);if(e.kind===`simulator`){await Y(e,f,{...i?{launchConsole:i}:{},...a?{launchArgs:a}:{},...r?.terminateRunningApp?{terminateRunningApp:!0}:{}});return}await Z(e,f,{launchArgs:a,runnerOptions:r?.runnerOptions})}async function q(e,n,r){if(r&&r.length>0)throw new t(`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 E(e),await v(e,[`openurl`,e.id,n])}async function it(e){o(e)||e.kind===`simulator`&&await be(e)!==`Booted`&&await E(e)}async function J(e,n,r){if(o(e)){await De(e,n);return}let a=await D(e,n);if(e.kind===`simulator`){await E(e);let n=x(e,[`terminate`,e.id,a]),r=await h(n,{allowFailure:!0,timeoutMs:ge});if(r.exitCode!==0){if(r.stderr.toLowerCase().includes(`found nothing to terminate`))return;throw new t(`COMMAND_FAILED`,`xcrun exited with code ${r.exitCode}`,i(r,{cmd:`xcrun`,args:n}))}return}await C(e).terminateApp(e,a,{runnerOptions:r,runRunnerCommand:w})}async function Y(e,n,r){await E(e);let a=0,o=p.fromTimeoutMs(me);try{await f(async({deadline:a})=>{if(a?.isExpired())throw new t(`COMMAND_FAILED`,`App launch deadline exceeded`,{timeoutMs:me});let o=x(e,at(e.id,n,r)),s=r?.launchConsole?await ot(o,r.launchConsole):await h(o,{allowFailure:!0});if(s.exitCode!==0)throw new t(`COMMAND_FAILED`,`xcrun exited with code ${s.exitCode}`,i(s,{cmd:`xcrun`,args:o}))},{maxAttempts:10,baseDelayMs:1e3,maxDelayMs:5e3,jitter:.2,shouldRetry(e){return G(e)?(a+=1,a<3):!1}},{deadline:o})}catch(t){if(G(t)){let r=t,i=tt(await et(e,n));r.details={...r.details,hint:nt(i)}}throw t}}function at(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 ot(e,n){await k.mkdir(A.dirname(n),{recursive:!0});try{let t=await h(e,{allowFailure:!0,timeoutMs:K});return await X(n,t.stdout,t.stderr),t}catch(e){let i=(e instanceof t?e:void 0)?.details;if(i?.timeoutMs===K){let e=typeof i.stdout==`string`?i.stdout:``,t=typeof i.stderr==`string`?i.stderr:``;return await X(n,e,t),r({level:`warn`,phase:`ios_simulator_launch_console_capture_timeout`,data:{timeoutMs:K,logPath:n,stdoutBytes:Buffer.byteLength(e),stderrBytes:Buffer.byteLength(t)}}),{stdout:e,stderr:t,exitCode:0}}throw e}}async function X(e,t,n){await k.writeFile(e,st(t,n),`utf8`)}function st(e,t){return!e||!t||e.endsWith(`
3
+ `)||e.endsWith(`\r`)?`${e}${t}`:`${e}\n${t}`}async function Z(e,t,n){await C(e).launchApp(e,t,{...n,runRunnerCommand:w})}async function ct(e,n){return await O(e,async()=>{let r=await D(e,n);if(e.kind!==`simulator`)return await C(e).uninstallApp(e,r),{bundleId:r};await E(e);let a=await v(e,[`uninstall`,e.id,r],{allowFailure:!0});if(a.exitCode!==0&&!pe(`${a.stdout}\n${a.stderr}`.toLowerCase()))throw new t(`COMMAND_FAILED`,`simctl uninstall failed for ${r}`,i(a));return{bundleId:r}})}async function lt(e,t,n){e.kind!==`simulator`&&C(e).assertAppInstallationSupported(e);let r=await ke({kind:`path`,path:t},n);try{return await Q(e,r.installablePath),{archivePath:r.archivePath,installablePath:r.installablePath,bundleId:r.bundleId,appName:r.appName,launchTarget:r.bundleId}}finally{await r.cleanup()}}async function ut(e,t,n){return e.kind!==`simulator`&&C(e).assertAppInstallationSupported(e),await O(e,async()=>{let{bundleId:r}=await ct(e,t);return await lt(e,n,{appIdentifierHint:t}),{bundleId:r}})}async function Q(e,t){await O(e,async()=>{if(e.kind!==`simulator`){await C(e).installApp(e,t);return}await E(e),await v(e,[`install`,e.id,t])})}async function dt(e){return o(e)?await we():(T(e,`clipboard`),await E(e),n(await v(e,[`pbpaste`,e.id],{allowFailure:!0}),`Failed to read iOS simulator clipboard`).stdout.replace(/\r\n/g,`
4
+ `).replace(/\n$/,``))}async function ft(e,t){if(o(e)){await Se(t);return}T(e,`clipboard`),await E(e),n(await v(e,[`pbcopy`,e.id],{allowFailure:!0,stdin:t}),`Failed to write iOS simulator clipboard`)}async function pt(e,t,n){T(e,`push`),await E(e);let r=await k.mkdtemp(A.join(Ae.tmpdir(),`agent-device-ios-push-`)),i=A.join(r,`payload.apns`);try{await k.writeFile(i,`${JSON.stringify(n)}\n`,`utf8`),await v(e,[`push`,e.id,t,i])}finally{await k.rm(r,{recursive:!0,force:!0})}}let $=null,mt;async function ht(e,n,r,i,s){if(o(e)){let e=n.toLowerCase();if(e===`appearance`){await Oe(r);return}if(e===`permission`){let e=ae(r);if(e===`deny`)throw new t(`INVALID_ARGS`,a(`permission`));return await ce(e,_t(s?.permissionTarget))}throw new t(`INVALID_ARGS`,a(n))}T(e,`settings`),await E(e);let l=n.toLowerCase();switch(l){case`clear-app-state`:{if(r.toLowerCase()!==`clear`)throw new t(`INVALID_ARGS`,`settings clear-app-state only supports clear.`);if(!i)throw new t(`INVALID_ARGS`,`settings clear-app-state requires an app id or an active app session.`);let n=await gt(e,i);return{bundleId:n.bundleId,containerPath:n.containerPath,cleared:!0}}case`wifi`:{let t=m(r)?`active`:`failed`;await v(e,[`status_bar`,e.id,`override`,`--wifiMode`,t]),N(e);return}case`airplane`:m(r)?(await v(e,[`status_bar`,e.id,`override`,`--dataNetwork`,`hide`,`--wifiMode`,`failed`,`--wifiBars`,`0`,`--cellularMode`,`failed`,`--cellularBars`,`0`,`--operatorName`,``]),N(e)):(await v(e,[`status_bar`,e.id,`clear`]),Le(e));return;case`location`:{if(r.toLowerCase()===`set`){let{latitude:t,longitude:n}=c(s);return await v(e,[`location`,e.id,`set`,`${t},${n}`]),{latitude:t,longitude:n}}let n=m(r);if(!i)throw new t(`INVALID_ARGS`,`location setting requires an active app in session`);let a=n?`grant`:`revoke`;await v(e,[`privacy`,e.id,a,`location`,i]);return}case`faceid`:case`touchid`:{let t=l,n=bt[t];await Ot(e,Dt(r,t),{settingName:t,label:n.label,modalityAliases:n.modalityAliases});return}case`appearance`:{let t=await vt(e,r);await v(e,[`ui`,e.id,`appearance`,t]);return}case`permission`:if(!i)throw new t(`INVALID_ARGS`,`permission setting requires an active app in session`);await St(e,xt(ae(r)),Et(s?.permissionTarget,s?.permissionMode),i);return;default:throw new t(`INVALID_ARGS`,`Unsupported setting: ${n}`)}}async function gt(e,r){if(!s(e)||e.kind!==`simulator`)throw new t(`UNSUPPORTED_OPERATION`,`Clearing app state is currently supported only on iOS simulators.`);let i=await D(e,r);await E(e),await J(e,i);let a=n(await v(e,[`get_app_container`,e.id,i,`data`],{allowFailure:!0}),`simctl get_app_container failed for ${i}`).stdout.trim();if(!a)throw new t(`COMMAND_FAILED`,`simctl get_app_container returned an empty data container path for ${i}`);let o=await k.readdir(a);return await Promise.all(o.map(e=>k.rm(A.join(a,e),{recursive:!0,force:!0}))),{bundleId:i,containerPath:a}}function _t(e){let n=e?.trim().toLowerCase();if(n===`accessibility`||n===`screen-recording`||n===`input-monitoring`)return n;throw new t(`INVALID_ARGS`,`Unsupported macOS permission target. Use accessibility|screen-recording|input-monitoring.`)}async function vt(e,r){let i=ie(r);if(i!==`toggle`)return i;let a=n(await v(e,[`ui`,e.id,`appearance`],{allowFailure:!0}),`Failed to read current iOS appearance`),o=yt(a.stdout,a.stderr);if(!o)throw new t(`COMMAND_FAILED`,`Unable to determine current iOS appearance for toggle`,{stdout:a.stdout,stderr:a.stderr});return o===`dark`?`light`:`dark`}function yt(e,t){let n=/\b(light|dark|unsupported|unknown)\b/i.exec(`${e}\n${t}`);if(!n)return null;let r=n[1]?.toLowerCase();return r===`dark`?`dark`:r===`light`?`light`:null}const bt={faceid:{label:`Face ID`,modalityAliases:[`face`]},touchid:{label:`Touch ID`,modalityAliases:[`finger`,`touch`]}};function xt(e){return e===`deny`?`revoke`:e}async function St(e,n,r,i){let a=await wt(e);if(!a.has(r))throw new t(`UNSUPPORTED_OPERATION`,`iOS simctl privacy does not support service "${r}" on this runtime.`,{deviceId:e.id,appBundleId:i,hint:`Supported services: ${Array.from(a).sort().join(`, `)}`});let o=[`privacy`,e.id,n,r,i],s=r===`notifications`;if(!(n===`reset`&&s))try{await v(e,o);return}catch(n){throw s&&Ct(n)?new t(`UNSUPPORTED_OPERATION`,`iOS simulator does not support setting notifications permission via simctl privacy on this runtime.`,{deviceId:e.id,appBundleId:i,hint:`Use reset notifications for reprompt behavior, or toggle notifications manually in Settings.`}):n}try{await v(e,o);return}catch(e){if(!Ct(e))throw e}try{await v(e,[`privacy`,e.id,`reset`,`all`,i])}catch(n){throw new t(`COMMAND_FAILED`,`iOS simulator blocked direct notifications reset. Fallback reset-all also failed.`,{deviceId:e.id,appBundleId:i,hint:`Use reinstall to force a fresh notifications prompt, or reset simulator content and settings.`},n instanceof Error?n:void 0)}}function Ct(e){if(!(e instanceof t)||e.code!==`COMMAND_FAILED`)return!1;let n=String(e.details?.stderr??``).toLowerCase();return(n.includes(`failed to grant access`)||n.includes(`failed to revoke access`)||n.includes(`failed to reset access`))&&n.includes(`operation not permitted`)}async function wt(e){let n=te(e.simulatorSetPath),r=`${process.env.PATH??``}::${n??``}`;if($&&mt===r)return $;let i=await v(e,[`privacy`,`help`],{allowFailure:!0}),a=Tt(`${i.stdout}\n${i.stderr}`);if(a.size===0)throw new t(`COMMAND_FAILED`,`Unable to determine supported simctl privacy services`,{stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode,hint:"Run `xcrun simctl privacy help` manually to verify available services for this runtime."});return $=a,mt=r,a}function Tt(e){let t=new Set,n=!1;for(let r of e.split(`
5
+ `)){let e=r.trim();if(!e)continue;if(e===`service`){n=!0;continue}if(!n)continue;if(e.startsWith(`bundle identifier`))break;let i=/^([a-z-]+)\s+-\s+/.exec(e)?.[1];i!==void 0&&t.add(i)}return t}function Et(e,n){let r=re(e);if(r!==`photos`&&n?.trim())throw new t(`INVALID_ARGS`,`Permission mode is only supported for photos. Received: ${n}.`);if(r===`camera`)return`camera`;if(r===`microphone`)return`microphone`;if(r===`contacts`)return`contacts`;if(r===`contacts-limited`)return`contacts-limited`;if(r===`notifications`)return`notifications`;if(r===`calendar`)return`calendar`;if(r===`location`)return`location`;if(r===`location-always`)return`location-always`;if(r===`media-library`)return`media-library`;if(r===`motion`)return`motion`;if(r===`reminders`)return`reminders`;if(r===`siri`)return`siri`;if(r===`photos`){let e=n?.trim().toLowerCase();if(!e||e===`full`)return`photos`;if(e===`limited`)return`photos-add`;throw new t(`INVALID_ARGS`,`Invalid photos mode: ${n}. Use full|limited.`)}throw new t(`INVALID_ARGS`,`Unsupported permission target: ${e}. Use camera|microphone|photos|contacts|contacts-limited|notifications|calendar|location|location-always|media-library|motion|reminders|siri.`)}function Dt(e,n){let r=e.trim().toLowerCase();if(r===`match`)return`match`;if(r===`nonmatch`)return`nonmatch`;if(r===`enroll`)return`enroll`;if(r===`unenroll`)return`unenroll`;throw new t(`INVALID_ARGS`,`Invalid ${n} state: ${e}. Use match|nonmatch|enroll|unenroll.`)}async function Ot(e,n,r){let i=kt(e.id,n,r.modalityAliases),a=[];for(let t of i){let n=x(e,t),r=await h(n,{allowFailure:!0});if(r.exitCode===0)return;a.push({args:n,stderr:r.stderr,stdout:r.stdout,exitCode:r.exitCode})}let o=ne(a);throw a.length>0&&a.every(e=>At(e.stdout,e.stderr))?new t(`UNSUPPORTED_OPERATION`,`${r.label} simulation is not supported on this simulator runtime.`,{deviceId:e.id,action:n,setting:r.settingName,attempts:o}):new t(`COMMAND_FAILED`,`Failed to simulate ${r.settingName}.`,{deviceId:e.id,action:n,setting:r.settingName,attempts:o})}function kt(e,t,n){let r=n.length>0?n:[`face`];switch(t){case`match`:return r.flatMap(t=>[[`biometric`,e,`match`,t],[`biometric`,`match`,e,t]]);case`nonmatch`:return r.flatMap(t=>[[`biometric`,e,`nonmatch`,t],[`biometric`,e,`nomatch`,t],[`biometric`,`nonmatch`,e,t],[`biometric`,`nomatch`,e,t]]);case`enroll`:return[[`biometric`,e,`enroll`,`yes`],[`biometric`,e,`enroll`,`1`],[`biometric`,`enroll`,e,`yes`],[`biometric`,`enroll`,e,`1`]];case`unenroll`:return[[`biometric`,e,`enroll`,`no`],[`biometric`,e,`enroll`,`0`],[`biometric`,`enroll`,e,`no`],[`biometric`,`enroll`,e,`0`]]}}function At(e,t){let n=`${e}\n${t}`.toLowerCase();return n.includes(`unrecognized subcommand`)||n.includes(`unknown subcommand`)||n.includes(`not supported`)||n.includes(`unavailable`)||n.includes(`biometric`)&&n.includes(`invalid`)}var jt=e({findIosSimulatorInstalledApp:()=>Te,installIosApp:()=>lt,installIosInstallablePath:()=>Q,listIosApps:()=>Ce,pushIosNotification:()=>pt,reinstallIosApp:()=>ut,resolveIosApp:()=>D,resolveIosSimulatorDeepLinkBundleId:()=>Ee});export{J as a,V as c,ft as i,We as l,ht as n,rt as o,dt as r,it as s,jt as t};
@@ -1 +1 @@
1
- import{_ as e}from"./sdk-contracts.js";import{E as t,O as n}from"./sdk-android-adb.js";import{ur as r}from"./recording-export-quality.js";import{n as i,t as a}from"./path-resolution.js";import{f as o,t as s,u as c,v as l}from"./registry.js";import{n as u}from"./command-schema.js";import d from"node:fs";import f from"node:path";function p(e,t){for(let[n,r]of Object.entries(t))r!==void 0&&(e[n]=r);return e}const m=new Set([`config`,`remoteConfig`,`help`,`version`,`batchSteps`,`githubActionsArtifact`]),h=new Set([`appsFilter`,`iosSimulatorDeviceSet`]),g=S(),_=new Map(g.map(e=>[e.key,e]));function v(e){return _.get(e)}function y(e){return g.filter(t=>t.config.enabled&&t.supportsCommand(e))}function b(e,t){return v(e)?.supportsCommand(t)??!1}function x(e,t,r,i){return n(w(e),t,r,i)}function S(){let e=new Map;for(let t of l()){let n=e.get(t.key);n?n.push(t):e.set(t.key,[t])}let n=new Map;for(let e of o)n.set(e,new Set([`*`]));for(let e of r()){let t=u(e);for(let r of[...t.allowedFlags??[],...t.supportedFlags??[]]){let t=n.get(r);t&&t.has(`*`)||(t?t.add(e):n.set(r,new Set([e])))}}return[...e.entries()].map(([e,r])=>({key:e,flagDefinitions:r,config:{enabled:!m.has(e),key:e},env:{names:h.has(e)?[]:[t(e)]},supportsCommand(t){let r=n.get(e);return r?r.has(`*`)?!0:t?r.has(t):!1:!1}})).sort((e,t)=>e.key.localeCompare(t.key))}function C(e){let t=e.flagDefinitions[0];if(!t)throw Error(`Missing flag definition for option ${e.key}`);return t}function w(e){let t=e.flagDefinitions.find(e=>e.setValue===void 0);if(t)return t;let n=C(e);if(n.type===`enum`){let t=n.enumValues??e.flagDefinitions.map(e=>e.setValue).filter(e=>e!==void 0);return{...n,setValue:void 0,enumValues:t}}return n}const T=s();function E(e){return T[e.name]?.({input:e.input??{},result:e.result})}function D(e){let t=e.env??process.env;return p(p({},j(O(e.cwd,e.cliFlags.config,t))),P(t,e.command))}function O(e,t,n){let r=t??n.AGENT_DEVICE_CONFIG;return r?[{path:A(r,e,n),required:!0}]:[{path:k(n),required:!1},{path:f.resolve(e,`agent-device.json`),required:!1}]}function k(e){return f.join(a(`~`,{env:e}),`.agent-device`,`config.json`)}function A(e,t,n){return i(e,{cwd:t,env:n})}function j(e){let t={};for(let n of e)p(t,M(n.path,n.required));return t}function M(t,n){if(!d.existsSync(t)){if(n)throw new e(`INVALID_ARGS`,`Config file not found: ${t}`);return{}}let r;try{r=d.readFileSync(t,`utf8`)}catch(n){throw new e(`INVALID_ARGS`,`Failed to read config file: ${t}`,{cause:n instanceof Error?n.message:String(n)})}let i;try{i=JSON.parse(r)}catch(n){throw new e(`INVALID_ARGS`,`Invalid JSON in config file: ${t}`,{cause:n instanceof Error?n.message:String(n)})}if(!i||typeof i!=`object`||Array.isArray(i))throw new e(`INVALID_ARGS`,`Config file must contain a JSON object: ${t}`);return N(i,`config file ${t}`)}function N(t,n){let r={};for(let[i,a]of Object.entries(t)){if(i===`installSource`){r.installSource=c(a,n);continue}let t=i,o=v(t);if(!o)throw new e(`INVALID_ARGS`,`Unknown config key "${i}" in ${n}.`);if(!o.config.enabled)throw new e(`INVALID_ARGS`,`Unsupported config key "${i}" in ${n}.`);r[t]=x(o,a,n,i)}return r}function P(e,t){let n={};for(let r of y(t)){if(r.key===`installSource`)continue;let t=r.env.names.map(t=>({name:t,value:e[t]})).find(e=>typeof e.value==`string`&&e.value.trim().length>0);t&&(n[r.key]=x(r,t.value,`environment variable ${t.name}`,t.name))}return n}export{p as i,E as n,b as r,D as t};
1
+ import{_ as e}from"./sdk-contracts.js";import{E as t,O as n}from"./sdk-android-adb.js";import{An as r}from"./recording-export-quality.js";import{n as i,t as a}from"./path-resolution.js";import{f as o,t as s,u as c,v as l}from"./registry.js";import{r as u}from"./command-schema.js";import d from"node:fs";import f from"node:path";function p(e,t){for(let[n,r]of Object.entries(t))r!==void 0&&(e[n]=r);return e}const m=new Set([`config`,`remoteConfig`,`help`,`version`,`batchSteps`,`githubActionsArtifact`]),h=new Set([`appsFilter`,`iosSimulatorDeviceSet`]),g=S(),_=new Map(g.map(e=>[e.key,e]));function v(e){return _.get(e)}function y(e){return g.filter(t=>t.config.enabled&&t.supportsCommand(e))}function b(e,t){return v(e)?.supportsCommand(t)??!1}function x(e,t,r,i){return n(w(e),t,r,i)}function S(){let e=new Map;for(let t of l()){let n=e.get(t.key);n?n.push(t):e.set(t.key,[t])}let n=new Map;for(let e of o)n.set(e,new Set([`*`]));for(let e of r()){let t=u(e);for(let r of[...t.allowedFlags??[],...t.supportedFlags??[]]){let t=n.get(r);t&&t.has(`*`)||(t?t.add(e):n.set(r,new Set([e])))}}return[...e.entries()].map(([e,r])=>({key:e,flagDefinitions:r,config:{enabled:!m.has(e),key:e},env:{names:h.has(e)?[]:[t(e)]},supportsCommand(t){let r=n.get(e);return r?r.has(`*`)?!0:t?r.has(t):!1:!1}})).sort((e,t)=>e.key.localeCompare(t.key))}function C(e){let t=e.flagDefinitions[0];if(!t)throw Error(`Missing flag definition for option ${e.key}`);return t}function w(e){let t=e.flagDefinitions.find(e=>e.setValue===void 0);if(t)return t;let n=C(e);if(n.type===`enum`){let t=n.enumValues??e.flagDefinitions.map(e=>e.setValue).filter(e=>e!==void 0);return{...n,setValue:void 0,enumValues:t}}return n}const T=s();function E(e){return T[e.name]?.({input:e.input??{},result:e.result})}function D(e){let t=e.env??process.env;return p(p({},j(O(e.cwd,e.cliFlags.config,t))),P(t,e.command))}function O(e,t,n){let r=t??n.AGENT_DEVICE_CONFIG;return r?[{path:A(r,e,n),required:!0}]:[{path:k(n),required:!1},{path:f.resolve(e,`agent-device.json`),required:!1}]}function k(e){return f.join(a(`~`,{env:e}),`.agent-device`,`config.json`)}function A(e,t,n){return i(e,{cwd:t,env:n})}function j(e){let t={};for(let n of e)p(t,M(n.path,n.required));return t}function M(t,n){if(!d.existsSync(t)){if(n)throw new e(`INVALID_ARGS`,`Config file not found: ${t}`);return{}}let r;try{r=d.readFileSync(t,`utf8`)}catch(n){throw new e(`INVALID_ARGS`,`Failed to read config file: ${t}`,{cause:n instanceof Error?n.message:String(n)})}let i;try{i=JSON.parse(r)}catch(n){throw new e(`INVALID_ARGS`,`Invalid JSON in config file: ${t}`,{cause:n instanceof Error?n.message:String(n)})}if(!i||typeof i!=`object`||Array.isArray(i))throw new e(`INVALID_ARGS`,`Config file must contain a JSON object: ${t}`);return N(i,`config file ${t}`)}function N(t,n){let r={};for(let[i,a]of Object.entries(t)){if(i===`installSource`){r.installSource=c(a,n);continue}let t=i,o=v(t);if(!o)throw new e(`INVALID_ARGS`,`Unknown config key "${i}" in ${n}.`);if(!o.config.enabled)throw new e(`INVALID_ARGS`,`Unsupported config key "${i}" in ${n}.`);r[t]=x(o,a,n,i)}return r}function P(e,t){let n={};for(let r of y(t)){if(r.key===`installSource`)continue;let t=r.env.names.map(t=>({name:t,value:e[t]})).find(e=>typeof e.value==`string`&&e.value.trim().length>0);t&&(n[r.key]=x(r,t.value,`environment variable ${t.name}`,t.name))}return n}export{p as i,E as n,b as r,D as t};
@@ -1,4 +1,4 @@
1
- import{ur as e}from"./recording-export-quality.js";import{f as t,v as n}from"./registry.js";import{n as r,r as i}from"./command-schema.js";const a=[`Flows: launchApp; runFlow file/inline with platform, visibility, and limited boolean conditions; onFlowStart/onFlowComplete; repeat.times and retry.`,`Interactions: tapOn, doubleTapOn, longPressOn, inputText, eraseText, openLink, hideKeyboard, basic pressKey, and back; targets support index, childOf, label, points, and optional.`,`Assertions and navigation: assertVisible, assertNotVisible, extendedWaitUntil, scroll, scrollUntilVisible, absolute/percentage/target swipe, takeScreenshot, waitForAnimationToEnd, and stopApp.`,`Scripts: ordered runScript file/env scripts with http.post, json, and output variables.`],o=[`Runtime: iOS and Android only; launchApp.clearState supports Android and iOS simulators, launch arguments are Apple-only, and standalone device utility/state commands are unsupported.`,`Expressions: when.true supports boolean literals and maestro.platform comparisons; repeat.while, evalScript, and broader JavaScript expressions are unsupported.`,`Environment: flow env is the default, AD_VAR_* overrides it, and CLI -e KEY=VALUE wins over both.`,`Trust: runScript executes trusted scripts, may make http.post network requests, and is not a security sandbox; output keys cannot contain a dot.`,`Errors and tracking: unsupported commands and fields fail with source context when available; open a focused issue only when implementation work is planned.`];function s(){return[`Supported subset:`,...a.map(e=>` - ${e}`),``,`Boundaries:`,...o.map(e=>` - ${e}`)].join(`
1
+ import{An as e}from"./recording-export-quality.js";import{f as t,v as n}from"./registry.js";import{i as r,r as i}from"./command-schema.js";const a=[`Flows: launchApp; runFlow file/inline with platform, visibility, and limited boolean conditions; onFlowStart/onFlowComplete; repeat.times and retry.`,`Interactions: tapOn, doubleTapOn, longPressOn, inputText, eraseText, openLink, hideKeyboard, basic pressKey, and back; targets support index, childOf, label, points, and optional.`,`Assertions and navigation: assertVisible, assertNotVisible, extendedWaitUntil, scroll, scrollUntilVisible, absolute/percentage/target swipe, takeScreenshot, waitForAnimationToEnd, and stopApp.`,`Scripts: ordered runScript file/env scripts with http.post, json, and output variables.`],o=[`Runtime: iOS and Android only; launchApp.clearState supports Android and iOS simulators, launch arguments are Apple-only, and standalone device utility/state commands are unsupported.`,`Expressions: when.true supports boolean literals and maestro.platform comparisons; repeat.while, evalScript, and broader JavaScript expressions are unsupported.`,`Environment: flow env is the default, AD_VAR_* overrides it, and CLI -e KEY=VALUE wins over both.`,`Failure diagnostics: resolved targets and runFlow paths are rendered, while inputText payloads remain hidden; do not place secrets in diagnostic identifiers.`,`Trust: runScript executes trusted scripts, may make http.post network requests, and is not a security sandbox; output keys cannot contain a dot.`,`Errors and tracking: unsupported commands and fields fail with source context when available; open a focused issue only when implementation work is planned.`];function s(){return[`Supported subset:`,...a.map(e=>` - ${e}`),``,`Boundaries:`,...o.map(e=>` - ${e}`)].join(`
2
2
  `)}function c(e){let t=e.endsWith(`?`),n=t?e.slice(0,-1):e;return t?`[${n}]`:`<${n}>`}function l(e){return n().filter(t=>t.key===e)}function u(e,t){if(t.usageOverride)return t.usageOverride;let n=(t.positionalArgs??[]).map(c),r=(t.allowedFlags??[]).flatMap(e=>l(e).map(e=>e.usageLabel??e.names[0])).map(e=>`[${e}]`);return[e,...n,...r].join(` `)}const d=[{label:`agent-device help manual-qa`,description:`Follow a manual test script with exact interactions and verification`},{label:`agent-device help dogfood`,description:`Explore an app and report issues with evidence`},{label:`agent-device help validate`,description:`Validate code changes, perf, visuals, logs, and cleanup`},{label:`agent-device help workflow`,description:`Full app automation reference for commands, refs, selectors, and waits`},{label:`agent-device help debugging`,description:`Use when logs, network, audio, perf memory, traces, alerts, or diagnostics matter`},{label:`agent-device help tv`,description:`Use when navigating Android TV, tvOS, or Vega VVD focus-first surfaces`},{label:`agent-device help react-native`,description:`Use when the target app is React Native, Expo, or a dev client`},{label:`agent-device help react-devtools`,description:`Use when inspecting components, props/state/hooks, renders, or profiles`},{label:`agent-device help cdp`,description:`Use when investigating JS heap growth, heap snapshots, or retainers`},{label:`agent-device help physical-device`,description:`Use when using a connected phone/tablet or iOS signing setup`},{label:`agent-device help remote`,description:`Use when working through cloud config, tenants, leases, or local tunnels`},{label:`agent-device help web`,description:`Use when automating a browser through agent-device sessions`},{label:`agent-device help macos`,description:`Use when targeting desktop, frontmost app, or menu bar surfaces`}],f=[`Write full command lines starting with agent-device; do not output pseudo commands, helper prose, pipes, grep, jq, or hidden stderr.`,`Default app loop: agent-device open <app> -> agent-device snapshot -i -> mutate a current target with --settle -> continue from that settled diff -> agent-device close.`,`Use --settle only on planned press, click, fill, or longpress commands; never add it to open, snapshot, or close.`,`Follow structured command hints before choosing a recovery action.`,`Targets are concrete refs or selectors: @e12, label="Query", role=button label="Submit".`,`Selector keys are only: id, role, text, label, value, appname, windowtitle, visible, hidden, editable, selected, focused, enabled, hittable. placeholder, index, and key are not selector keys.`,`A literal @ handle is a label such as label="@account.example", never a bare @ref.`,`Boundary shapes: agent-device fill 'label="Query"' "text" --settle; agent-device press 'role=button label="Submit"' --settle.`,`fill takes a target then text. press targets an accessible element; key=Enter is not a supported target.`,`Pick the help mode below when the task is manual QA, dogfooding, engineering validation, or debugging.`],p=[`Planning output contract: when asked to plan commands, output command lines only: no prose, numbering, Markdown fences, pipes, or shell helpers.`,`If you did not use --settle, verify a mutation with diff snapshot (or diff snapshot -i), not a full snapshot: it prints only the added/removed/changed lines since the last snapshot in this session.`,`Network-backed or debounced results may arrive after the --settle quiet window; follow the settled action with wait text "Expected result" or wait <selector> instead of polling full snapshots.`,`Pin a raw CLI ref to the response that minted it with ~s<n> (n = refsGeneration): press @e12~s4. On iOS, stale refs are rejected for mutations; refresh refs or use a stable selector.`,`Plain snapshot reads state; snapshot -i refreshes current interactive refs only.`,`Default snapshot text is an agent-facing, token-efficient view for planning and targeting actions.`,`Read-only visible/state question: use snapshot/get/is/find; use snapshot -i only when refs are needed.`,`Truncated text/input preview: expand first with snapshot -s @e12, not get text.`,`React Native apps: read help react-native.`,`Text fields: use fill <target> <text> --settle to replace a field value. Use type <text> only to append after focusing a field with press.`,`Clearing text: do not use fill <target> ""; use a visible clear/reset control or report that clearing is unsupported.`,`Implicit default sessions are scoped to the current worktree; if a prompt names a Session, include --session <name> on every command in that flow.`,`Run mutating commands serially within one session; parallelize only read-only commands or separate sessions/devices.`,`After mutation: refs are stale. If the next target is known, use its selector directly; otherwise refresh with snapshot -i, scoped with -s when a stable container is known. Use press/click for taps.`,`macOS context menus use click <ref> --button secondary, then snapshot -i. Longpress is for mobile hold gestures, not macOS secondary-click menus.`,`Remote lifecycle: use connect, then open, commands, close, and disconnect. Read help remote for proxy, cloud, and device-cloud provider flows.`,`TV/D-pad targets: read help tv. Web browser sessions: read help web.`,`Debug evidence: Session state contains request diagnostics and runner.log; use logs clear --restart/mark/path, trace, and network dump --include headers for app evidence.`,`Routine QA loop with concrete command shapes: agent-device help manual-qa. Full operating guide: agent-device help workflow. Exploratory QA: agent-device help dogfood.`],m=[`Default config files: ~/.agent-device/config.json, ./agent-device.json`,`Use --config <path> or AGENT_DEVICE_CONFIG to load one explicit config file.`],h=[{label:`AGENT_DEVICE_SESSION`,description:`Explicit session name`},{label:`AGENT_DEVICE_PLATFORM`,description:`Default platform binding`},{label:`AGENT_DEVICE_SESSION_LOCK`,description:`Bound-session conflict mode`},{label:`AGENT_DEVICE_DAEMON_BASE_URL`,description:`Connect to remote daemon`},{label:`AGENT_DEVICE_DAEMON_AUTH_TOKEN`,description:`Remote daemon service/API token`},{label:`AGENT_DEVICE_CLOUD_BASE_URL`,description:`Bridge/control-plane API origin for cloud auth and /api-keys`}],g=[`agent-device open Settings --platform ios`,`agent-device open https://example.com --platform web`,`agent-device snapshot -i`,`agent-device fill @e3 "test@example.com"`,`agent-device replay ./session.ad`,`agent-device test ./suite --platform android`],_={"manual-qa":{summary:`Follow manual test scripts with exact interactions and verification`,body:`agent-device help manual-qa
3
3
 
4
4
  Use this when asked to follow a manual QA script, test case, checklist, acceptance flow, or user-provided instructions.
@@ -959,7 +959,7 @@ Evidence:
959
959
 
960
960
  Report:
961
961
  Summarize what changed, exact validation commands, pass/fail observations, artifact paths, and residual risk.
962
- If live validation is blocked, state the blocker, device/session, and exact next command needed.`}};function v(e,t,n){let r=n.endsWith(`?`),i=r?n.slice(0,-1):n,a=/^[a-z-]+(?:\|[a-z-]+)+$/i.test(i),o=a||t.usageOverride!==void 0&&t.usageOverride.startsWith(`${e} ${i}`);return r?a?`[${i}]`:o?i:`[${i}]`:o?i:`<${i}>`}function y(e,t){return t.listUsageOverride?t.listUsageOverride:[e,...(t.positionalArgs??[]).map(n=>v(e,t,n))].join(` `)}function b(){let n=E(e().map(e=>{let t=r(e);return{name:e,schema:t,usage:y(e,t)}})),i=C(`Global Flags:`,S(t)),a=T(`Agent Starting Point:`,f),o=T(`Agent Quickstart:`,p);return`agent-device <command> [args] [--json]
962
+ If live validation is blocked, state the blocker, device/session, and exact next command needed.`}};function v(e,t,n){let r=n.endsWith(`?`),i=r?n.slice(0,-1):n,a=/^[a-z-]+(?:\|[a-z-]+)+$/i.test(i),o=a||t.usageOverride!==void 0&&t.usageOverride.startsWith(`${e} ${i}`);return r?a?`[${i}]`:o?i:`[${i}]`:o?i:`<${i}>`}function y(e,t){return t.listUsageOverride?t.listUsageOverride:[e,...(t.positionalArgs??[]).map(n=>v(e,t,n))].join(` `)}function b(){let n=E(e().map(e=>{let t=i(e);return{name:e,schema:t,usage:y(e,t)}})),r=C(`Global Flags:`,S(t)),a=T(`Agent Starting Point:`,f),o=T(`Agent Quickstart:`,p);return`agent-device <command> [args] [--json]
963
963
 
964
964
  CLI to automate supported app, device, desktop, and web targets for AI agents.
965
965
 
@@ -969,7 +969,7 @@ ${w(`Agent Workflows:`,d)}
969
969
 
970
970
  ${n}
971
971
 
972
- ${i}
972
+ ${r}
973
973
 
974
974
  ${o}
975
975
 
@@ -980,14 +980,14 @@ ${w(`Environment:`,h)}
980
980
  ${T(`Examples:`,g)}
981
981
  `}function x(){return b()}function S(e){return n().filter(t=>e.has(t.key)&&t.usageLabel!==void 0&&t.usageDescription!==void 0)}function C(e,t){return w(e,t.map(e=>({label:e.usageLabel??``,description:e.usageDescription??``})))}function w(e,t){if(t.length===0)return`${e}\n (none)`;let n=Math.max(...t.map(e=>Math.min(e.label.length,26)))+2,r=[e];for(let e of t){let t=e.label.length<=26?e.label.padEnd(n):`${e.label} `;r.push(` ${t}${e.description}`)}return r.join(`
982
982
  `)}function T(e,t){return t.length===0?`${e}\n (none)`:[e,...t.map(e=>` ${e}`)].join(`
983
- `)}function E(e){return w(`Commands:`,e.map(e=>({label:e.usage,description:e.schema.summary??e.schema.helpDescription})))}function D(e){let t=O(e);if(t)return t;let n=i(e);if(!n)return null;let r=u(e,n),a=S(new Set(n.allowedFlags??[])),o=[];a.length>0&&o.push(C(`Command flags:`,a));let s=o.length>0?`\n\n${o.join(`
983
+ `)}function E(e){return w(`Commands:`,e.map(e=>({label:e.usage,description:e.schema.summary??e.schema.helpDescription})))}function D(e){let t=O(e);if(t)return t;let n=r(e);if(!n)return null;let i=u(e,n),a=S(new Set(n.allowedFlags??[])),o=[];a.length>0&&o.push(C(`Command flags:`,a));let s=o.length>0?`\n\n${o.join(`
984
984
 
985
- `)}`:``;return`agent-device ${r}
985
+ `)}`:``;return`agent-device ${i}
986
986
 
987
987
  ${n.helpDescription}
988
988
 
989
989
  Usage:
990
- agent-device ${r}${s}
990
+ agent-device ${i}${s}
991
991
  `}function O(e){let t=_[e];return t?`${t.body}
992
992
 
993
993
  Related:
@@ -1,2 +1,2 @@
1
- import{fn as e}from"./recording-export-quality.js";import{n as t}from"./registry.js";import{n}from"./cli-config.js";import{n as r}from"./command-surface.js";function i(t,n,r){if(t.json){e({success:!0,data:n});return}let i=r?.();i&&a(i)}function a(e){process.stdout.write(e.endsWith(`
1
+ import{Qt as e}from"./recording-export-quality.js";import{n as t}from"./registry.js";import{n}from"./cli-config.js";import{n as r}from"./command-surface.js";function i(t,n,r){if(t.json){e({success:!0,data:n});return}let i=r?.();i&&a(i)}function a(e){process.stdout.write(e.endsWith(`
2
2
  `)?e:`${e}\n`)}const o=t();function s(e,t,n){let r=o[e];if(!r)throw Error(`Missing CLI reader for command: ${e}`);return r(t,n)}async function c(e){return(await l(e)).result}async function l(e){let t=s(e.command,e.positionals,e.flags),i=await r(e.client,e.command,t);return{result:i,cliOutput:n({name:e.command,input:t,result:i})}}export{i,l as n,s as r,c as t};