agent-device 0.20.6 → 0.20.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.20.6.apk → agent-device-android-ime-helper-0.20.8.apk} +0 -0
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.8.apk.sha256 +1 -0
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.20.6.manifest.json → agent-device-android-ime-helper-0.20.8.manifest.json} +4 -4
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.20.6.apk → agent-device-android-snapshot-helper-0.20.8.apk} +0 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.8.apk.sha256 +1 -0
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.20.6.manifest.json → agent-device-android-snapshot-helper-0.20.8.manifest.json} +6 -6
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunner/AgentDeviceRunnerApp.m +20 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.h +67 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.m +339 -4
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSelectorMatchPolicy.swift +78 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+AXSnapshotFallback.swift +31 -2
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +34 -8
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CoordinateTextEntryTests.swift +4 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +36 -28
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +7 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+RecordingTests.swift +4 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SelectorMatchPolicyTests.swift +4 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +2 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCapturePlan.swift +100 -12
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedGesturePolicy.swift +4 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedTextEntry.swift +57 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntry.swift +1 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextTyping.swift +18 -3
- package/dist/src/agent-browser-tool.js +1 -1
- package/dist/src/agent-device-client.js +2 -2
- package/dist/src/android-adb.js +1 -1
- package/dist/src/android.js +1 -1
- package/dist/src/app-helpers.js +1 -1
- package/dist/src/app-lifecycle.js +7 -7
- package/dist/src/app-lifecycle2.js +2 -0
- package/dist/src/app-log-files.js +1 -0
- package/dist/src/app-log-reconnect.js +1 -0
- package/dist/src/app-log-runtime.js +4 -0
- package/dist/src/app-resolution.js +2 -1
- package/dist/src/apps.js +5 -5
- package/dist/src/audio-probe.js +1 -1
- package/dist/src/auth-session.js +1 -0
- package/dist/src/auth.js +2 -0
- package/dist/src/boot-diagnostics.js +2 -2
- package/dist/src/cli-config.js +1 -1
- package/dist/src/cli-grammar.js +1 -0
- package/dist/src/cli-help.js +199 -259
- package/dist/src/cli-output.js +1 -0
- package/dist/src/cli-runner.js +1 -2
- package/dist/src/cli.js +6 -16
- package/dist/src/client-metro.js +1 -1
- package/dist/src/cloud-artifacts.d.ts +2 -137
- package/dist/src/command-schema.js +3 -3
- package/dist/src/connection-runtime.js +1 -0
- package/dist/src/connection.js +5 -0
- package/dist/src/daemon-shutdown-report.js +1 -0
- package/dist/src/daemon.js +2 -0
- package/dist/src/debug-symbols.js +1 -1
- package/dist/src/device-claim-inspection.js +1 -0
- package/dist/src/device-input-state.js +2 -2
- package/dist/src/device-ready.js +1 -0
- package/dist/src/device.js +1 -1
- package/dist/src/device2.js +2 -0
- package/dist/src/dispatch.js +1 -0
- package/dist/src/find.js +1 -1
- package/dist/src/finders.js +1 -1
- package/dist/src/generic-settle.js +1 -1
- package/dist/src/generic.js +1 -1
- package/dist/src/handler-utils.js +1 -0
- package/dist/src/harmonyos.js +1 -0
- package/dist/src/hdc.js +1 -0
- package/dist/src/host-process.js +3 -2
- package/dist/src/ime-lifecycle.js +7 -7
- package/dist/src/index.d.ts +52 -21
- package/dist/src/input-actions.js +4 -4
- package/dist/src/input-actions2.js +1 -1
- package/dist/src/input-actions3.js +1 -0
- package/dist/src/install-artifact.js +1 -5
- package/dist/src/install-artifact2.js +1 -1
- package/dist/src/install-source2.js +1 -1
- package/dist/src/interaction-runtime.js +1 -1
- package/dist/src/interaction-snapshot.js +1 -1
- package/dist/src/interaction-touch-reference-frame.js +1 -1
- package/dist/src/interaction.js +1 -1
- package/dist/src/interactor.js +2 -2
- package/dist/src/interactor2.js +1 -1
- package/dist/src/internal/bin.js +2 -2
- package/dist/src/internal/daemon.js +7 -36
- package/dist/src/inventory.js +5 -0
- package/dist/src/inventory2.js +1 -0
- package/dist/src/inventory3.js +2 -0
- package/dist/src/inventory4.js +1 -0
- package/dist/src/inventory5.js +1 -0
- package/dist/src/inventory6.js +1 -0
- package/dist/src/lease-context.js +1 -1
- package/dist/src/lease.js +1 -1
- package/dist/src/limrun-runtime-dependencies.js +1 -0
- package/dist/src/limrun.d.ts +10 -125
- package/dist/src/limrun.js +1 -1
- package/dist/src/linux.js +1 -1
- package/dist/src/logcat.js +1 -1
- package/dist/src/manifest.js +1 -1
- package/dist/src/notifications.js +1 -1
- package/dist/src/output-path.js +1 -0
- package/dist/src/owner-identity.js +1 -0
- package/dist/src/physical-device-control.js +1 -1
- package/dist/src/platform-runtime-app-log-android-transport.js +1 -0
- package/dist/src/platform-runtime-app-log-process.js +1 -0
- package/dist/src/platform-runtime-host.js +1 -0
- package/dist/src/platform-runtime-network-web-transport.js +1 -0
- package/dist/src/platform-runtime-operation-host.js +5 -0
- package/dist/src/platform-runtime-screen-recording-android-host.js +1 -0
- package/dist/src/platform-runtime-screen-recording-apple-host.js +1 -0
- package/dist/src/platform-runtime-screen-recording-apple-runner-host.js +1 -0
- package/dist/src/platform-runtime-screen-recording-apple-runner-transport.js +1 -0
- package/dist/src/platform-runtime-screen-recording-apple-simulator-host.js +1 -0
- package/dist/src/platform-runtime-screen-recording-apple-transport.js +1 -0
- package/dist/src/platform-runtime-screen-recording-finalizer-host.js +1 -0
- package/dist/src/platform-runtime-screen-recording-harmony-host.js +1 -0
- package/dist/src/platform-runtime-screen-recording-output-host.js +1 -0
- package/dist/src/platform-runtime-screen-recording-web-host.js +1 -0
- package/dist/src/platform-runtime-toolchain-host.js +1 -0
- package/dist/src/platform-runtime.js +1 -0
- package/dist/src/prepare-kind.js +15 -0
- package/dist/src/process-entry.js +1 -0
- package/dist/src/process-lock.js +1 -1
- package/dist/src/provider-webdriver.js +1 -0
- package/dist/src/proxy.js +2 -0
- package/dist/src/react-native.js +1 -1
- package/dist/src/record-runtime.js +1 -0
- package/dist/src/record-trace.js +1 -1
- package/dist/src/recording-telemetry.js +1 -0
- package/dist/src/registry.js +24 -24
- package/dist/src/replay.js +3 -0
- package/dist/src/reporting.js +3 -3
- package/dist/src/runner-disposal.js +1 -1
- package/dist/src/runner-lease.js +1 -1
- package/dist/src/runtime.js +3 -3
- package/dist/src/runtime2.js +4 -0
- package/dist/src/runtime3.js +3 -0
- package/dist/src/runtime4.js +1 -0
- package/dist/src/runtime5.js +1 -0
- package/dist/src/runtime6.js +1 -0
- package/dist/src/runtime7.js +1 -0
- package/dist/src/screenshot-result.js +4 -4
- package/dist/src/screenshot.js +1 -0
- package/dist/src/sdk-android-adb.js +4 -4
- package/dist/src/sdk-batch-runner.js +3 -3
- package/dist/src/sdk-contracts.d.ts +31 -5
- package/dist/src/sdk-contracts.js +1 -1
- package/dist/src/sdk-device.js +1 -1
- package/dist/src/sdk-finders.js +1 -1
- package/dist/src/sdk-remote-config.js +1 -1
- package/dist/src/sdk-selectors.d.ts +285 -5
- package/dist/src/sdk-selectors.js +1 -1
- package/dist/src/selector-runtime.js +1 -1
- package/dist/src/selector-vocabulary.js +1 -1
- package/dist/src/selectors.js +1 -1
- package/dist/src/server.js +3 -3
- package/dist/src/session-target-evidence.js +1 -1
- package/dist/src/session.js +10 -9
- package/dist/src/shared.js +2 -0
- package/dist/src/shell-quote.js +1 -0
- package/dist/src/simulator.js +1 -1
- package/dist/src/snapshot-runtime.js +1 -0
- package/dist/src/snapshot-session.js +1 -0
- package/dist/src/snapshot2.js +1 -1
- package/dist/src/src.js +1 -1
- package/dist/src/src2.js +2 -0
- package/dist/src/src3.js +1 -0
- package/dist/src/text-surface.js +1 -1
- package/dist/src/timing-safe-equal.js +1 -0
- package/dist/src/tool-provider.js +2 -2
- package/dist/src/update-check.js +1 -1
- package/dist/src/version.js +1 -1
- package/dist/src/video.js +23 -0
- package/dist/src/web.js +1 -1
- package/package.json +34 -20
- package/server.json +2 -2
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.6.apk.sha256 +0 -1
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.6.apk.sha256 +0 -1
- package/dist/src/app-log-request-scope.js +0 -1
- package/dist/src/context.js +0 -1
- package/dist/src/devices.js +0 -1
- package/dist/src/devices2.js +0 -1
- package/dist/src/devices3.js +0 -1
- package/dist/src/devices4.js +0 -1
- package/dist/src/provider-limrun-runtime.js +0 -1
- package/dist/src/register-builtins.js +0 -1
- package/dist/src/runner-client.js +0 -1
- package/dist/src/runner-provider.js +0 -1
- package/dist/src/screenshot-geometry.js +0 -1
- package/dist/src/viewport-dimension.js +0 -15
- package/skills/agent-device/SKILL.md +0 -45
- package/skills/dogfood/SKILL.md +0 -27
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{t as e}from"./registry.js";const t=e();function n(e){return t[e.name]?.({input:e.input??{},result:e.result})}export{n as t};
|
package/dist/src/cli-runner.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
import{
|
|
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};
|
|
1
|
+
import{t as e}from"./cli-grammar.js";import{t}from"./cli-output.js";import{n}from"./command-surface.js";async function r(e){return(await i(e)).result}async function i(r){let i=e(r.command,r.positionals,r.flags),a=await n(r.client,r.command,i);return{result:a,cliOutput:t({name:r.command,input:i,result:a})}}export{i as n,r as t};
|
package/dist/src/cli.js
CHANGED
|
@@ -1,17 +1,7 @@
|
|
|
1
|
-
import{S as e,_ as t,
|
|
2
|
-
|
|
3
|
-
`)}\n`}function yt(e,n){let r={config:bt(n.metadata),warnings:[],unsupported:[]},i=[];for(let[t,a]of e.entries()){let e=n.actionLines?.[t]??t+1,o=St(a,n.resolveSelector);switch(o.kind){case`commands`:i.push(...o.commands),Yt(r,o.warnings,a,e);break;case`config`:qt(r,o.appId,a,e),i.push(...o.commands),Yt(r,o.warnings,a,e);break;case`unsupported`:r.unsupported.push({line:e,action:M(a),message:o.message});break}}if(r.unsupported.length>0)throw new t(`INVALID_ARGS`,`Cannot export replay to Maestro YAML: unsupported .ad action ${Qt(r.unsupported)}.`,{unsupported:r.unsupported});return{yaml:Zt(r.config,i),warnings:r.warnings}}function bt(e){return e?.env&&Object.keys(e.env).length>0?{env:e.env}:{}}const xt={open:Ct,click:Et,press:Et,longpress:Dt,fill:jt,type:Mt,keyboard:Nt,back:()=>({kind:`commands`,commands:[`back`]}),wait:Pt,find:Ft,screenshot:It,scroll:Lt,swipe:Rt};function St(e,t){return xt[e.command]?.(e,t)??{kind:`unsupported`,message:`${e.command} has no Maestro equivalent`}}function Ct(e){let[t,n]=e.positionals;if(!t)return{kind:`unsupported`,message:`open requires an app id or URL`};if($t(t))return{kind:`commands`,commands:[{openLink:t}]};let r=wt(e,t);return n&&$t(n)?{kind:`config`,appId:t,commands:[r,{openLink:n}]}:n?{kind:`unsupported`,message:`open with a non-URL second argument is unsupported`}:{kind:`config`,appId:t,commands:[r]}}function wt(e,t){let n=Tt(e);return n?{launchApp:{appId:t,...n}}:`launchApp`}function Tt(e){let t=e.flags?.launchArgs,n={};return e.flags?.relaunch===!0&&(n.stopApp=!0),e.flags?.clearAppState===!0&&(n.clearState=!0),Array.isArray(t)&&t.length>0&&(n.launchArguments=t),Object.keys(n).length>0?n:void 0}function Et(e,t){let[n,r]=e.positionals;if(!n)return{kind:`unsupported`,message:`${e.command} requires a target`};let i=Ht(n,r,t);if(!i)return{kind:`unsupported`,message:`tap target is not Maestro-compatible`};let a=Ut(e);return a.ok?e.flags?.doubleTap===!0?{kind:`commands`,commands:[{doubleTapOn:i}],warnings:At(e,`doubleTapOn`)}:typeof e.flags?.holdMs==`number`?{kind:`commands`,commands:[{longPressOn:i}],warnings:[kt(e.flags.holdMs),...At(e,`longPressOn`)]}:{kind:`commands`,commands:[Kt(i,a.options)]}:{kind:`unsupported`,message:a.message}}function Dt(e,t){let[n,r]=e.positionals;if(!n)return{kind:`unsupported`,message:`longpress requires a target`};let i=Ht(n,r,t);return i?{kind:`commands`,commands:[{longPressOn:i}],warnings:Ot(e).map(kt)}:{kind:`unsupported`,message:`longpress target is not Maestro-compatible`}}function Ot(e){let[t,n,r]=e.positionals,i=N(t)&&N(n)?r:n;return i&&N(i)?[Number(i)]:[]}function kt(e){return`long-press duration exports as Maestro longPressOn; Maestro uses its default long-press duration instead of ${e}ms`}function At(e,t){let n=[];return typeof e.flags?.count==`number`&&e.flags.count>1&&n.push(`tap --count ${e.flags.count} is not represented by Maestro ${t}`),typeof e.flags?.intervalMs==`number`&&e.flags.intervalMs>0&&n.push(`tap --interval-ms ${e.flags.intervalMs} is not represented by Maestro ${t}`),n}function jt(e,t){let[n,r]=e.positionals;if(!n||r===void 0)return{kind:`unsupported`,message:`fill requires a target and text`};let i=Ht(n,void 0,t);return i?{kind:`commands`,commands:[{tapOn:i},{inputText:r}],warnings:[`fill exports as tapOn + inputText; Maestro may append text instead of replacing existing field contents`]}:{kind:`unsupported`,message:`fill target is not Maestro-compatible`}}function Mt(e){let[t]=e.positionals;if(t===void 0)return{kind:`unsupported`,message:`type requires text`};let n=Jt(t);return n===null?{kind:`commands`,commands:[{inputText:t}]}:{kind:`commands`,commands:[{eraseText:n}]}}function Nt(e){let[t]=e.positionals;return t===`dismiss`?{kind:`commands`,commands:[`hideKeyboard`]}:t===`enter`||t===`return`?{kind:`commands`,commands:[{pressKey:`Enter`}]}:{kind:`unsupported`,message:`keyboard ${t??``}`.trim()}}function Pt(e,t){let[n,r]=e.positionals;if(!n)return{kind:`unsupported`,message:`wait requires a target or duration`};if(N(n))return{kind:`commands`,commands:[{waitForAnimationToEnd:{timeout:Number(n)}}],warnings:[`wait <ms> exports as waitForAnimationToEnd and may return before the full duration`]};if(n===`text`&&r)return{kind:`commands`,commands:[{extendedWaitUntil:{visible:r,timeout:Xt(e,Qe.extendedWaitUntilTimeoutMs)}}]};let i=t(n);return i?{kind:`commands`,commands:[{extendedWaitUntil:{visible:i,timeout:Xt(e,Qe.extendedWaitUntilTimeoutMs)}}]}:{kind:`unsupported`,message:`wait selector is not Maestro-compatible`}}function Ft(e){let[t,n,r]=e.positionals;return t!==`text`||!n||!r?{kind:`unsupported`,message:`only find text <query> exists|missing exports to Maestro`}:r===`exists`?{kind:`commands`,commands:[{assertVisible:n}]}:r===`missing`||r===`not-exists`?{kind:`commands`,commands:[{assertNotVisible:n}]}:{kind:`unsupported`,message:`find text assertion "${r}" is unsupported`}}function It(e){let[t]=e.positionals;return t?{kind:`commands`,commands:[{takeScreenshot:t}]}:{kind:`unsupported`,message:`screenshot requires an output path`}}function Lt(e){let[t]=e.positionals;return!t||t===`down`?{kind:`commands`,commands:[`scroll`]}:{kind:`unsupported`,message:`scroll ${t} is not exported yet`}}function Rt(e){let t=zt(e);if(!t)return{kind:`unsupported`,message:`only coordinate swipe exports to Maestro`};let n=Bt(e);if(n===null)return{kind:`unsupported`,message:`swipe count must be a positive integer`};let r=Vt(e);return r?{kind:`unsupported`,message:r}:{kind:`commands`,commands:Array.from({length:n},()=>({swipe:t}))}}function zt(e){let[t,n,r,i]=e.positionals;if(!(!N(t)||!N(n)||!N(r)||!N(i)))return{start:_t(t,n),end:_t(r,i),duration:100}}function Bt(e){let t=e.flags?.count??1;return Number.isInteger(t)&&t>=1?t:null}function Vt(e){if(e.flags?.pauseMs!==void 0)return`swipe --pause-ms has no Maestro equivalent`;if(e.flags?.pattern&&e.flags.pattern!==`one-way`)return`swipe ping-pong pattern has no Maestro equivalent`}function Ht(e,t,n){return N(e)&&N(t)?{point:_t(e,t)}:e.startsWith(`@`)?null:n(e)}function Ut(e){let t=Gt(e);return t?{ok:!1,message:t}:{ok:!0,options:Wt(e)}}function Wt(e){let t={};return typeof e.flags?.count==`number`&&e.flags.count>1&&(t.repeat=e.flags.count),typeof e.flags?.intervalMs==`number`&&e.flags.intervalMs>0&&(t.delay=e.flags.intervalMs),t}function Gt(e){if(e.flags?.jitterPx!==void 0)return`tap --jitter-px has no Maestro equivalent`;if(e.flags?.clickButton&&e.flags.clickButton!==`primary`)return`tap --button ${e.flags.clickButton} has no Maestro equivalent`}function Kt(e,t){return Object.keys(t).length===0?{tapOn:e}:typeof e==`string`?{tapOn:{text:e,...t}}:e&&typeof e==`object`&&!Array.isArray(e)?{tapOn:{...e,...t}}:{tapOn:e}}function qt(e,t,n,r){if(!e.config.appId){e.config.appId=t;return}e.config.appId!==t&&e.unsupported.push({line:r,action:M(n),message:`multiple app ids cannot be represented in one Maestro config (${e.config.appId} vs ${t})`})}function Jt(e){return e.length===0||![...e].every(e=>e===`\b`)?null:e.length}function Yt(e,t,n,r){for(let i of t??[])e.warnings.push({line:r,action:M(n),message:i})}function Xt(e,t){let n=e.positionals.at(-1);return n&&N(n)?Number(n):t}function Zt(e,t){return vt(Object.keys(e).length>0?[e,t]:[t])}function Qt(e){return e.map(e=>`line ${e.line} (${e.action}): ${e.message}`).join(`; `)}function M(e){return[e.command,...e.positionals??[]].join(` `).trim()}function $t(e){return/^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//.test(e)}function N(e){return e!==void 0&&Number.isFinite(Number(e))}const P=`open <app> --relaunch`,en={start:{command:`open`,example:P},restart:{command:`open`,example:P},touch:{command:`press`,example:`press`},input:{command:`fill`,example:`fill`},settext:{command:`fill`,example:`fill`},entertext:{command:`fill`,example:`fill`},screencap:{command:`screenshot`,example:`screenshot`},capture:{command:`screenshot`,example:`screenshot`},dismiss:{command:`keyboard`,example:`keyboard dismiss`},"get-text":{command:`get`,example:`get text`},gettext:{command:`get`,example:`get text`},get_text:{command:`get`,example:`get text`},"open-url":{command:`open`,example:`open <url>`},"close-session":{command:`close`,example:`close`}};function tn(e){if(e.length<=2)return[];let t=m(),n=t.filter(t=>t.startsWith(e));if(n.length>0)return n.sort((e,t)=>e.length-t.length||e.localeCompare(t)).slice(0,3);let r=nn(e),i=t.map(t=>({name:t,distance:rn(e,t)})).filter(e=>e.distance<=r);if(i.length===0)return[];let a=Math.min(...i.map(e=>e.distance));return i.filter(e=>e.distance===a).sort((e,t)=>e.name.localeCompare(t.name)).slice(0,3).map(e=>e.name)}function nn(e){return e.length<4?1:e.length<=6?2:3}function rn(e,t){return e===t?0:e.startsWith(t)||t.startsWith(e)?Math.abs(e.length-t.length):an(e,t)}function an(e,t){let n=e.length+1,r=t.length+1,i=Array.from({length:n},()=>Array(r).fill(0));for(let e=0;e<n;e+=1)i[e][0]=e;for(let e=0;e<r;e+=1)i[0][e]=e;for(let a=1;a<n;a+=1)for(let n=1;n<r;n+=1){let r=e[a-1]===t[n-1]?0:1;i[a][n]=Math.min(i[a-1][n]+1,i[a][n-1]+1,i[a-1][n-1]+r)}return i[n-1][r-1]}function on(e){let t=e.toLowerCase(),n=en[t]?.example;if(n)return n;let r=tn(t);if(r.length!==0)return r.length===1?r[0]:`one of: ${r.join(`, `)}`}const sn=new Set([`--bundle-id`,`--bundleid`,`--bundle`,`--package`,`--package-name`,`--packagename`,`--app-id`,`--appid`,`--pkg`]),cn=new Set([`--session-locked`,`--session-lock-conflicts`]);function ln(e){return sn.has(e.toLowerCase())?`Unknown flag: ${e}. The app or bundle id is a positional argument, e.g. ${P}.`:cn.has(e.toLowerCase())?`Unknown flag: ${e}. Use --session-lock reject|strip instead.`:e.toLowerCase()===a.cliToken?`Unknown flag: ${e}. ${a.migration.screenshot}. ${a.migration.record}.`:`Unknown flag: ${e}`}function un(e){let n={json:!1,help:!1,version:!1},r=null,i=null,a=[],o=[],s=[],c=!0;for(let o=0;o<e.length;o+=1){let l=e[o];if(c&&l===`--`){c=!1;continue}if(!c){r?a.push(l):(i=l,r=kn(l));continue}if(mn(r)){a.push(l);continue}let u=l.startsWith(`--`),d=l.startsWith(`-`)&&l.length>1;if(!u&&!d){r?a.push(l):(i=l,r=kn(l));continue}let[f,p]=u?vn(l):[l,void 0];if(fn(r,f))continue;let m=hn(f,r);if(pn(r,m)){a.push(l);continue}if(!m){if(Cn(r,a,l)){r?a.push(l):r=l;continue}throw new t(`INVALID_ARGS`,ln(f))}let h=yn(m,f,p,e[o+1]);h.consumeNext&&(o+=1);let g=n[m.key];if(m.multiple){let e=Array.isArray(g)?[...g,h.value]:g===void 0?[h.value]:[g,h.value];n[m.key]=e}else n[m.key]=h.value;s.push({key:m.key,token:f})}return dn(i,n),{command:r,positionals:a,flags:n,warnings:o,providedFlags:s}}function dn(e,t){if(e)for(let n of qe(e)?.impliedFlags??[])t[n]=!0}function fn(e,t){return t===`-c`&&(e===`snapshot`||e===`diff`)}function pn(e,t){return e===`react-devtools`?t?!E(t.key,e):!0:!1}function mn(e){return e===`cdp`}function hn(e,t){let n=we().filter(t=>t.names.includes(e));if(n.length<=1)return n[0]??x(e);if(t){let e=n.find(e=>E(e.key,t));if(e)return e}return x(e)}function gn(e,n){let r=n?.strictFlags??!0,i=[...e.warnings],a=T({json:!1,help:!1,version:!1},n?.defaultFlags??{});if(T(a,e.flags),e.command&&!ae(e.command)&&!a.help){let n=on(e.command);throw new t(`INVALID_ARGS`,n?`Unknown command: ${e.command}. Did you mean ${n}?`:`Unknown command: ${e.command}`)}let o=e.providedFlags.filter(t=>!E(t.key,e.command));if(o.length>0){let n=o.map(e=>e.token),s=En(e.command,n);if(r)throw new t(`INVALID_ARGS`,s);i.push(s);for(let e of o)delete a[e.key]}for(let t of Object.keys(a))a[t]!==void 0&&(E(t,e.command)||delete a[t]);_n(e),at(e.command,a);let s=Tn({command:e.command,positionals:e.positionals,flags:a,warnings:i});if(it(s.command,s.positionals),s.command===`batch`&&+!!a.steps+ +!!a.stepsFile!=1)throw new t(`INVALID_ARGS`,`batch requires exactly one step source: --steps or --steps-file.`);return s}function _n(e){if(e.command!==`back`)return;let n=e.providedFlags.filter(e=>e.key===`backMode`);if(!(new Set(n.map(e=>e.token)).size<=1))throw new t(`INVALID_ARGS`,`back accepts only one explicit mode flag: use either --in-app or --system.`)}function vn(e){let t=e.indexOf(`=`);return t===-1?[e,void 0]:[e.slice(0,t),e.slice(t+1)]}function yn(e,n,r,i){if(e.setValue!==void 0){if(r!==void 0)throw new t(`INVALID_ARGS`,`Flag ${n} does not take a value.`);return{value:e.setValue,consumeNext:!1}}if(e.type===`boolean`){if(r!==void 0)throw new t(`INVALID_ARGS`,`Flag ${n} does not take a value.`);return{value:!0,consumeNext:!1}}if(e.type===`booleanOrString`){if(r!==void 0){if(r.trim().length===0)throw new t(`INVALID_ARGS`,`Flag ${n} requires a non-empty value when provided.`);return{value:r,consumeNext:!1}}return i===void 0||xn(i)?{value:!0,consumeNext:!1}:Sn(i)?{value:i,consumeNext:!0}:{value:!0,consumeNext:!1}}let a=r??i;if(a===void 0||r===void 0&&xn(a))throw new t(`INVALID_ARGS`,`Flag ${n} requires a value.`);if(e.type===`string`)return{value:a,consumeNext:r===void 0};if(e.type===`enum`){if(!e.enumValues?.includes(a))throw new t(`INVALID_ARGS`,`Invalid ${bn(n)}: ${a}`);return{value:a,consumeNext:r===void 0}}let o=Number(a);if(!Number.isFinite(o)||typeof e.min==`number`&&o<e.min||typeof e.max==`number`&&o>e.max)throw new t(`INVALID_ARGS`,`Invalid ${bn(n)}: ${a}`);return{value:e.type===`int`?Math.floor(o):o,consumeNext:r===void 0}}function bn(e){return e.replace(/^-+/,``)}function xn(e){if(!e.startsWith(`-`)||e===`-`)return!1;let[t]=e.startsWith(`--`)?vn(e):[e,void 0];return x(t)!==void 0}function Sn(e){let t=e.trim();return!t||/^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//.test(t)?!1:!!(t.startsWith(`./`)||t.startsWith(`../`)||t.startsWith(`~/`)||t.startsWith(`/`)||t.includes(`/`)||t.includes(`\\`))}function Cn(e,t,n){if(!wn(n)||!e)return!1;let r=rt(e);if(!r||r.allowsExtraPositionals)return!0;let i=r.positionalArgs??[];return i.length===0?!1:t.length<i.length?!0:i.some(e=>e.includes(`?`))}function wn(e){return/^-\d+(\.\d+)?$/.test(e)}function Tn(e){if(e.flags.help)return e;if(e.command===`snapshot`&&e.flags.snapshotDiff){let{snapshotDiff:t,...n}=e.flags;return{command:`diff`,positionals:[`snapshot`,...e.positionals],flags:n,warnings:e.warnings}}return e}function En(e,t){return e?t.length===1?`Flag ${t[0]} is not supported for command ${e}.`:`Flags ${t.join(`, `)} are not supported for command ${e}.`:t.length===1?`Flag ${t[0]} requires a command that supports it.`:`Flags ${t.join(`, `)} require a command that supports them.`}async function Dn(){let{buildUsageText:e}=await import(`./cli-help.js`);return e()}async function On(e){let{buildCommandUsageText:t}=await import(`./cli-help.js`);return t(kn(e))}function kn(e){if(e.toLowerCase()===`rotate`)throw new t(`INVALID_ARGS`,`rotate was renamed to orientation; for the two-finger gesture use: gesture rotate`);return Ke(e)}const An={slug:`react-devtools-companion`,runArg:ze,displayName:`React DevTools companion`};async function jn(e){return await Ve({...e,definition:An,localBaseUrl:e.localBaseUrl??`http://127.0.0.1:8097`,registerPath:`/api/react-devtools/companion/register`,unregisterPath:`/api/react-devtools/companion/unregister`,devicePort:e.devicePort??8097})}async function Mn(e){return await Be({...e,definition:An})}function Nn(e){return e===`android-instance`||e===`ios-instance`}function Pn(e){return[`exec`,`--yes`,`--package`,`agent-cdp@1.6.1`,`--`,`agent-cdp`,...e]}function Fn(e){return e.some(e=>e===`--url`||e.startsWith(`--url=`))}function In(e){return e[0]===`target`&&(e[1]===`list`||e[1]===`select`)&&!Fn(e)}function Ln(e){let t=new URL(e);t.search=``,t.hash=``;let n=t.pathname.replace(/\/+$/,``);return t.pathname=n.endsWith(`/index.bundle`)?n.slice(0,-13)||`/`:n||`/`,t.toString().replace(/\/+$/,``)}function Rn(e){let t=e?.metroPublicBaseUrl?.trim();return t?Ln(t):null}function zn(e,n={}){if(!In(e)||!n.flags?.metroProxyBaseUrl||!Nn(n.flags.leaseBackend))return e;let r=Rn(n.flags);if(!r)throw new t(`INVALID_ARGS`,`cdp remote bridge target discovery requires a React Native dev-server public base URL.`,{hint:`Include metroPublicBaseUrl in the remote config so cdp can reach the local or tunneled Metro/Re.Pack CDP endpoint without bridge proxy authentication.`});return[...e,`--url`,r]}async function Bn(e,t={}){return(await Me(`npm`,Pn(zn(e,t)),{cwd:t.cwd??process.cwd(),env:t.env??process.env,allowFailure:!0,onStdoutChunk:e=>{process.stdout.write(e)},onStderrChunk:e=>{process.stderr.write(e)}})).exitCode}function F(e){let t=qn(e);if(!j.existsSync(t))return null;let n;try{n=JSON.parse(j.readFileSync(t,`utf8`))}catch(t){return $n(e,t),null}return tr(n)?n:($n(e),null)}function Vn(e){let t=qn({stateDir:e.stateDir,session:e.state.session});j.mkdirSync(k.dirname(t),{recursive:!0}),Zn(t,e.state),Zn(I(e.stateDir),{session:e.state.session})}function Hn(e){return{baseUrl:Qn(e.daemonBaseUrl),transport:e.daemonTransport,serverMode:e.daemonServerMode}}function Un(e){j.rmSync(qn(e),{force:!0});let t=I(e.stateDir);Jn(e.stateDir)===e.session&&j.rmSync(t,{force:!0})}function Wn(e){let n=e.validateRemoteConfigHash??!0,r=e.remoteConfig?Ue({configPath:e.remoteConfig,cwd:e.cwd,env:e.env}):void 0,i=F(e)??(e.allowActiveFallback?L({stateDir:e.stateDir}):null);if(!i||r&&i.remoteConfigPath!==r)return null;if(n&&Kn(i.remoteConfigPath)!==i.remoteConfigHash)throw new t(`INVALID_ARGS`,`Active remote connection config changed. Run agent-device connect --force to refresh it.`,{remoteConfig:i.remoteConfigPath});let a=Xn(i,e),o=g(i);return{runtime:i.runtime,connection:oe(o),flags:{...a,remoteConfig:i.remoteConfigPath,daemonBaseUrl:i.daemon?.baseUrl??a.daemonBaseUrl,daemonAuthToken:a.daemonAuthToken,daemonTransport:i.daemon?.transport??a.daemonTransport,daemonServerMode:i.daemon?.serverMode??a.daemonServerMode,...te(o),sessionIsolation:`tenant`,session:i.session,platform:i.platform??a.platform,target:i.target??a.target}}}function Gn(e){return oe(g(e))}function Kn(e){try{return A.createHash(`sha256`).update(j.readFileSync(e)).digest(`hex`)}catch(n){throw new t(`INVALID_ARGS`,`Remote config file not found: ${e}`,{cause:n instanceof Error?n.message:String(n)})}}function qn(e){return k.join(e.stateDir,`remote-connections`,`${er(e.session)}.json`)}function I(e){return k.join(e,`remote-connections`,`.active-session.json`)}function L(e){let t=Jn(e.stateDir);return t?F({stateDir:e.stateDir,session:t}):null}function Jn(e){let t=I(e);if(j.existsSync(t))try{let e=JSON.parse(j.readFileSync(t,`utf8`));return typeof e.session==`string`?e.session:void 0}catch{return}}function Yn(e){if(e)return A.createHash(`sha256`).update(e).digest(`hex`).slice(0,12)}function Xn(e,t){try{return C({configPath:e.remoteConfigPath,cwd:t.cwd,env:t.env}).profile}catch(e){if(t.validateRemoteConfigHash===!1)return{};throw e}}function Zn(e,t){j.writeFileSync(e,`${JSON.stringify(t,null,2)}\n`,{encoding:`utf8`,mode:384}),j.chmodSync(e,384)}function Qn(e){if(!e)return;let t=new URL(e);t.username=``,t.password=``;for(let e of[...t.searchParams.keys()])/(auth|key|password|secret|token)/i.test(e)&&t.searchParams.delete(e);return t.toString().replace(/\/+$/,``)}function $n(e,t){Ne({level:`warn`,phase:`remote_connection_state_invalid`,data:{session:e.session,cause:t instanceof Error?t.message:t?String(t):void 0}}),Un(e)}function er(e){let t=e.replaceAll(/[^a-zA-Z0-9._-]/g,`_`);return t?t===e?t:`${t}-${A.createHash(`sha256`).update(e).digest(`hex`).slice(0,8)}`:`default`}function tr(e){if(!e||typeof e!=`object`||Array.isArray(e))return!1;let t=e;return t.version===1&&nr(t,[`session`,`remoteConfigPath`,`remoteConfigHash`,`tenant`,`runId`,`connectedAt`,`updatedAt`])&&rr(t,[`leaseId`,`leaseBackend`,`leaseProvider`,`deviceKey`,`clientId`])&&ir(t.daemon)}function nr(e,t){return t.every(t=>typeof e[t]==`string`)}function rr(e,t){return t.every(t=>e[t]===void 0||typeof e[t]==`string`)}function ir(e){return e===void 0?!0:!e||typeof e!=`object`||Array.isArray(e)?!1:ar(e)}function ar(e){let t=e;return(t.baseUrl===void 0||typeof t.baseUrl==`string`)&&(t.authToken===void 0||typeof t.authToken==`string`)&&(t.transport===void 0||typeof t.transport==`string`)&&(t.serverMode===void 0||typeof t.serverMode==`string`)}const or=Te.map(e=>e.key);function R(e){let t={};for(let n of or){let r=e[n];r!==void 0&&(t[n]=r)}return t}function sr(e){return e.remoteConfig?{...R(C({configPath:e.remoteConfig,cwd:e.cwd,env:e.env}).profile),remoteConfig:e.remoteConfig}:{}}function cr(e){return e===`cloud`||e===`proxy`||z(e)}function z(e){return e===`limrun`||Ye(e)}function lr(){return[`cloud`,`proxy`,w.browserStack,w.awsDeviceFarm,`limrun`].join(`, `)}function ur(e){return!z(e)}function dr(e){return e===`proxy`?`proxy`:z(e)?`direct-device-provider`:`remote-provider`}function fr(e){return{providerDeviceOrientation:e.providerDeviceOrientation,providerGeoLocation:e.providerGeoLocation,providerTimezone:e.providerTimezone,providerLanguage:e.providerLanguage,providerLocale:e.providerLocale,providerNetworkProfile:e.providerNetworkProfile,providerCustomNetwork:e.providerCustomNetwork,providerNoResignApp:e.providerNoResignApp}}function B(e){return{metroProjectRoot:e.metroProjectRoot,metroKind:e.metroKind,metroPublicBaseUrl:e.metroPublicBaseUrl,metroProxyBaseUrl:e.metroProxyBaseUrl,metroPreparePort:e.metroPreparePort,metroListenHost:e.metroListenHost,metroStatusHost:e.metroStatusHost,metroStartupTimeoutMs:e.metroStartupTimeoutMs,metroProbeTimeoutMs:e.metroProbeTimeoutMs,metroRuntimeFile:e.metroRuntimeFile,metroNoReuseExisting:e.metroNoReuseExisting,metroNoInstallDeps:e.metroNoInstallDeps,launchUrl:e.launchUrl}}const V=new Set([`artifacts`,`connect`,`connection`,`close`,`disconnect`,`metro`,`session`]),pr=new Set([`open`]),mr=new Set([h.open,h.install,h.reinstall,p.installSource]);async function hr(e){let{command:n,flags:r,client:i}=e;if(!r.remoteConfig)return{flags:r,runtime:e.runtime};let a=b(r.stateDir).baseDir,o=C({configPath:r.remoteConfig,cwd:process.cwd(),env:process.env}),s={...R(o.profile),...r,remoteConfig:o.resolvedPath},c=F({stateDir:a,session:s.session??`default`});if(c&&c.remoteConfigPath!==o.resolvedPath)throw new t(`INVALID_ARGS`,`A different remote connection is already active for this session. Run connect --force or disconnect before using a different --remote-config.`,{session:c.session,activeRemoteConfig:c.remoteConfigPath,requestedRemoteConfig:o.resolvedPath});let l=c??Hr(s,o.resolvedPath,o.profile),u={...s,session:l.session},d=Vr(l.runtime,u.platform)??e.runtime,f=l,p=!c,m,h=Cr(f);if(h.shouldAllocate(n)){let e=await br({command:n,client:i,state:l,nextState:f,nextFlags:u,policy:h});f=e.state,p||=e.changed,m=e.acquiredLeaseForCleanup}let g=await gr({command:n,flags:u,client:i,state:l,nextState:f,runtime:d,positionals:e.positionals,batchSteps:e.batchSteps,forceRuntimePrepare:e.forceRuntimePrepare});return f=g.state,d=g.runtime,p||=g.changed,await yr({changed:p,stateDir:a,state:f,client:i,acquiredLeaseForCleanup:m,preparedMetroCleanupOnFailure:g.preparedMetroCleanupOnFailure,metroCleanupToStop:g.metroCleanupToStop}),{flags:{...u,session:f.session,leaseId:f.leaseId,leaseBackend:f.leaseBackend,platform:f.platform??u.platform,target:f.target??u.target},runtime:d,connection:Gn(f)}}async function gr(e){let{command:n,flags:r,state:i,client:a}=e,o=_r(e.nextState,r),s=e.runtime;if(!Lr(n,r,e.batchSteps,e.positionals)||!Rr(r)||!vr(e.forceRuntimePrepare,s,r.platform))return{state:o,runtime:s,changed:!1};if(!o.leaseId)throw new t(`INVALID_ARGS`,`${n} requires a resolved remote lease before Metro runtime can be prepared.`);let c=await Dr(r,a,i.remoteConfigPath,i.session,{tenantId:i.tenant,runId:i.runId,leaseId:o.leaseId}),l=!Br(o.metro,c.cleanup);return o={...o,runtime:c.runtime,metro:c.cleanup,updatedAt:new Date().toISOString()},{state:o,runtime:c.runtime,changed:!0,metroCleanupToStop:l?e.nextState.metro:void 0,preparedMetroCleanupOnFailure:l?c.cleanup:void 0}}function _r(e,t){return e.leaseId||!t.leaseId?e:{...e,leaseId:t.leaseId,leaseBackend:t.leaseBackend}}function vr(e,t,n){return e===!0||!t||!zr(t,n)}async function yr(e){if(e.changed)try{Vn({stateDir:e.stateDir,state:e.state})}catch(t){throw await H(e.preparedMetroCleanupOnFailure),await Fr(e.client,e.state,e.acquiredLeaseForCleanup),t}await H(e.metroCleanupToStop)}async function br(e){let{command:t,client:n,state:r,nextFlags:i,policy:a}=e,o=r.leaseBackend??U(i),s=e.nextState,c=await a.resolveLeaseState({command:t,client:n,state:s,flags:i,leaseBackend:o});s=c.state,c.device&&Gr(i,c.device);let l=s.leaseBackend??o??Ir(i,t);Yr(r,i,l);let u=await Ur(n,s,l,a,i),d=u.lease;return i.leaseId=d.leaseId,i.leaseBackend=l,i.platform=s.platform??i.platform,i.target=s.target??i.target,xr(s,d,l)?{state:s,changed:!1,acquiredLeaseForCleanup:u.acquired?d:void 0}:{state:Sr(s,d,l,i),changed:!0,acquiredLeaseForCleanup:u.acquired?d:void 0}}function xr(e,t,n){return e.leaseId===t.leaseId&&e.leaseBackend===n&&e.deviceKey===(t.deviceKey??e.deviceKey)}function Sr(e,t,n,r){return{...e,leaseId:t.leaseId,leaseBackend:n,leaseProvider:t.leaseProvider??e.leaseProvider,clientId:t.clientId??e.clientId,deviceKey:t.deviceKey??e.deviceKey,platform:e.platform??r.platform,target:e.target??r.target,updatedAt:new Date().toISOString()}}function Cr(e){return e.leaseProvider===`proxy`?Tr:Ye(e.leaseProvider)?Er:wr}const wr={shouldAllocate:e=>!V.has(e),ttlMs:()=>void 0,resolveLeaseState:async e=>({state:e.state})},Tr={shouldAllocate:e=>e!==`devices`&&!V.has(e),ttlMs:()=>3e5,resolveLeaseState:Wr},Er={shouldAllocate:e=>!V.has(e),ttlMs:()=>6e5,resolveLeaseState:async e=>({state:e.state})};async function Dr(e,n,r,i,a){if(!e.metroProjectRoot&&!e.metroPublicBaseUrl&&!e.metroProxyBaseUrl)return{};if(e.platform!==`ios`&&e.platform!==`android`)throw new t(`INVALID_ARGS`,`Deferred Metro preparation requires platform "ios" or "android".`);if(!e.metroPublicBaseUrl&&!e.metroProxyBaseUrl)throw new t(`INVALID_ARGS`,`Deferred Metro preparation requires metroPublicBaseUrl or metroProxyBaseUrl when Metro settings are provided.`);let o=await n.metro.prepare({projectRoot:e.metroProjectRoot,kind:Ce(e.metroKind),publicBaseUrl:e.metroPublicBaseUrl,proxyBaseUrl:e.metroProxyBaseUrl,bearerToken:e.metroBearerToken,bridgeScope:a,launchUrl:e.launchUrl,companionProfileKey:r,companionConsumerKey:i,port:e.metroPreparePort,listenHost:e.metroListenHost,statusHost:e.metroStatusHost,startupTimeoutMs:e.metroStartupTimeoutMs,probeTimeoutMs:e.metroProbeTimeoutMs,reuseExisting:e.metroNoReuseExisting?!1:void 0,installDependenciesIfNeeded:e.metroNoInstallDeps?!1:void 0,runtimeFilePath:e.metroRuntimeFile});return{runtime:e.platform===`ios`?o.iosRuntime:o.androidRuntime,cleanup:e.metroProxyBaseUrl?{projectRoot:o.projectRoot,profileKey:r,consumerKey:i}:void 0}}async function H(e){if(e)try{await He(e)}catch{}}async function Or(e){try{await Mn({projectRoot:process.cwd(),stateDir:e.stateDir,profileKey:e.state.remoteConfigPath,consumerKey:e.state.session})}catch{}}async function kr(e,t,n){return t.leaseId?await e.leases.release({tenant:t.tenant,runId:t.runId,leaseId:t.leaseId,leaseBackend:t.leaseBackend,daemonBaseUrl:t.daemon?.baseUrl,daemonAuthToken:n,daemonTransport:t.daemon?.transport,daemonServerMode:t.daemon?.serverMode,leaseProvider:t.leaseProvider,clientId:t.clientId,deviceKey:t.deviceKey}):{released:!1}}function Ar(e){let t=jr(e.previous,e.cwd,e.env);return t?{canAuthenticate:!0,daemonAuthToken:t}:e.previous.daemon?.baseUrl===e.nextDaemonBaseUrl?{canAuthenticate:!0,daemonAuthToken:e.ambientDaemonAuthToken}:{canAuthenticate:!1}}function jr(e,t,n){try{let{profile:r}=We({configPath:e.remoteConfigPath,cwd:t,env:n});return r.daemonAuthToken&&Mr(e,r.daemonBaseUrl)?r.daemonAuthToken:void 0}catch{return}}function Mr(e,t){let n=Hn({daemonBaseUrl:t})?.baseUrl;return n!==void 0&&n===e.daemon?.baseUrl}async function Nr(e,t,n){if(!t.leaseId)return;let r=Ar({previous:t,nextDaemonBaseUrl:n.nextDaemonBaseUrl,ambientDaemonAuthToken:n.ambientDaemonAuthToken,cwd:n.cwd,env:n.env});if(!r.canAuthenticate)return Pr(t,`no credential known to belong to that endpoint was available`);try{await kr(e,t,r.daemonAuthToken);return}catch{return Pr(t,`the release request failed`)}}function Pr(e,t){return{status:`unreleased`,message:`Could not release the previous lease ${e.leaseId} (tenant ${e.tenant}, run ${e.runId}) at ${e.daemon?.baseUrl??`its daemon`}: ${t}. It was left in place — release it manually if it is still active.`}}async function Fr(e,t,n){if(n)try{await e.leases.release({tenant:t.tenant,runId:t.runId,leaseId:n.leaseId,leaseBackend:t.leaseBackend??n.backend,leaseProvider:t.leaseProvider??n.leaseProvider,clientId:t.clientId??n.clientId,deviceKey:t.deviceKey??n.deviceKey})}catch{}}function U(e){if(e.leaseBackend)return e.leaseBackend;if(e.platform===`android`)return`android-instance`;if(e.platform===`ios`)return`ios-instance`}function Ir(e,n){let r=U(e);if(r)return r;throw new t(`INVALID_ARGS`,`${n} requires --platform ios|android or --lease-backend when the remote connection has not resolved a lease yet.`)}function Lr(e,t,n,r=[]){return e===`cdp`?In(r)&&!!t.metroPublicBaseUrl:pr.has(e)?!0:e!==`batch`||!n?!1:n.some(e=>{let t=e.command.trim().toLowerCase();return pr.has(t)&&e.runtime===void 0})}function Rr(e){let t=e.metroKind;return!!(e.metroPublicBaseUrl||e.metroProxyBaseUrl||e.metroProjectRoot||t)}function zr(e,t){return!e.platform||!t||t!==`ios`&&t!==`android`?!0:e.platform===t}function Br(e,t){return e?.projectRoot===t?.projectRoot&&e?.profileKey===t?.profileKey&&e?.consumerKey===t?.consumerKey}function Vr(e,t){if(e)return zr(e,t)?e:void 0}function Hr(e,n,r={}){if(!e.tenant)throw new t(`INVALID_ARGS`,`remote command requires tenant in remote config or via --tenant <id>.`);if(!e.runId)throw new t(`INVALID_ARGS`,`remote command requires runId in remote config or via --run-id <id>.`);if(!e.daemonBaseUrl&&ur(r.leaseProvider))throw new t(`INVALID_ARGS`,`remote command requires daemonBaseUrl in remote config, config, env, or --daemon-base-url.`);let i=new Date().toISOString();return{version:1,session:e.session??`default`,remoteConfigPath:n,remoteConfigHash:Kn(n),daemon:Hn(e),tenant:e.tenant,runId:e.runId,leaseId:e.leaseId,leaseBackend:e.leaseBackend??U(e),leaseProvider:r.leaseProvider,clientId:r.clientId,deviceKey:r.deviceKey,platform:e.platform,target:e.target,connectedAt:i,updatedAt:i}}async function Ur(e,t,n,r,i){if(t.leaseId&&t.leaseBackend===n){let i=await Xr(e,t.leaseId,{tenant:t.tenant,runId:t.runId,leaseBackend:n,leaseProvider:t.leaseProvider,clientId:t.clientId,deviceKey:t.deviceKey,ttlMs:r.ttlMs(t)});if(i)return{lease:i,acquired:!1}}return{lease:await e.leases.allocate({tenant:t.tenant,runId:t.runId,leaseBackend:n,leaseProvider:t.leaseProvider,clientId:t.clientId,deviceKey:t.deviceKey,ttlMs:r.ttlMs(t),platform:t.platform??i.platform,target:t.target??i.target,device:i.device,udid:i.udid,serial:i.serial,providerApp:i.providerApp,providerOsVersion:i.providerOsVersion,providerProject:i.providerProject,providerBuild:i.providerBuild,providerSessionName:i.providerSessionName,...fr(i),awsProjectArn:i.awsProjectArn,awsDeviceArn:i.awsDeviceArn,awsAppArn:i.awsAppArn,awsRegion:i.awsRegion,awsInteractionMode:i.awsInteractionMode}),acquired:!0}}async function Wr(e){if(!mr.has(e.command)){if(e.state.leaseId&&e.state.deviceKey)return{state:e.state};throw new t(`INVALID_ARGS`,`No active proxy device lease for this session; run open first.`)}let n=await Kr(e.client,e.flags),r=qr(n);return{state:{...e.state,deviceKey:r,leaseBackend:e.state.leaseBackend??e.leaseBackend??Jr(n),platform:e.state.platform??n.platform,target:e.state.target??n.target,updatedAt:new Date().toISOString()},device:n}}function Gr(e,t){if(e.platform=t.platform,e.target=t.target??e.target,d(t)){e.udid=t.id;return}t.platform===`android`&&(e.serial=t.id)}async function Kr(e,t){return await f((await e.devices.list({platform:t.platform,target:t.target,device:t.device,udid:t.udid,serial:t.serial,iosSimulatorDeviceSet:t.iosSimulatorDeviceSet,androidDeviceAllowlist:t.androidDeviceAllowlist})).map(e=>({...u(e.platform),id:e.id,name:e.name,kind:e.kind,target:e.target,booted:e.booted})),{platform:t.platform,target:t.target,deviceName:t.device,udid:t.udid,serial:t.serial})}function qr(e){return`${l(e)}:${e.target??`mobile`}:${e.id}`}function Jr(e){if(d(e))return`ios-instance`;if(e.platform===`android`)return`android-instance`}function Yr(e,n,r){if(e.leaseBackend&&e.leaseBackend!==r)throw new t(`INVALID_ARGS`,`Active remote connection is already bound to a different lease backend. Re-run connect --force to replace it.`,{session:e.session,leaseBackend:e.leaseBackend});if(e.platform&&n.platform&&e.platform!==n.platform)throw new t(`INVALID_ARGS`,`Active remote connection is already bound to a different platform. Re-run connect --force to replace it.`,{session:e.session,platform:e.platform});if(e.target&&n.target&&e.target!==n.target)throw new t(`INVALID_ARGS`,`Active remote connection is already bound to a different target. Re-run connect --force to replace it.`,{session:e.session,target:e.target})}async function Xr(e,t,n){try{return await e.leases.heartbeat({tenant:n.tenant,runId:n.runId,leaseId:t,leaseBackend:n.leaseBackend,leaseProvider:n.leaseProvider,clientId:n.clientId,deviceKey:n.deviceKey,ttlMs:n.ttlMs})}catch(e){if(Zr(e))return;throw e}}function Zr(e){return!(e instanceof t)||e.code!==`UNAUTHORIZED`?!1:e.details?.reason===`LEASE_NOT_FOUND`||e.details?.reason===`LEASE_EXPIRED`||e.details?.reason===`LEASE_REVOKED`}function Qr(e){return Ee(e)}async function $r(e,n){let r=await e.text(),i={};if(r.trim().length>0)try{i=JSON.parse(r)}catch(r){throw new t(`COMMAND_FAILED`,n.invalidJsonMessage,{status:e.status},r instanceof Error?r:void 0)}if(!e.ok)throw new t(`UNAUTHORIZED`,n.rejectedMessage,{status:e.status,response:i});return i}const ei=1e3;async function ti(e){return await ni({command:e.command,flags:e.flags,stateDir:e.stateDir,allowInteractiveLogin:e.command===`connect`&&!e.flags.noLogin,env:e.env})}async function ni(e){let n=e.env??e.io?.env??process.env;if(!e.flags.daemonBaseUrl)return{flags:e.flags,source:`none`};if(G(e.flags.daemonAuthToken))return{flags:e.flags,source:`flag`};if(G(n.AGENT_DEVICE_DAEMON_AUTH_TOKEN))return{flags:e.flags,source:`env`};if(!yi(e.flags.daemonBaseUrl,n))return{flags:e.flags,source:`none`};let r=await ui({stateDir:e.stateDir,flags:e.flags,env:n,io:e.io});if(r)return{flags:{...e.flags,daemonAuthToken:r.accessToken},source:`cli-session`};if(!e.allowInteractiveLogin)throw e.flags.noLogin?new t(`UNAUTHORIZED`,`Remote daemon authentication is required.`,{hint:`Run agent-device auth login, unset --no-login, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN.`}):vi(e.command,n);let i=await ii({stateDir:e.stateDir,flags:e.flags,env:n,io:e.io});return{flags:{...e.flags,daemonAuthToken:i.accessToken},source:`login`}}async function ri(e){let n=e.env??e.io?.env??process.env;if(G(e.flags.daemonAuthToken))return{accessToken:e.flags.daemonAuthToken,cloudBaseUrl:W(n)};if(G(n.AGENT_DEVICE_DAEMON_AUTH_TOKEN))return{accessToken:n.AGENT_DEVICE_DAEMON_AUTH_TOKEN,cloudBaseUrl:W(n)};let r=await ui({stateDir:e.stateDir,flags:e.flags,env:n,io:e.io});if(r)return{accessToken:r.accessToken,cloudBaseUrl:r.cloudBaseUrl};if(e.flags.noLogin)throw new t(`UNAUTHORIZED`,`Cloud connection profile authentication is required.`,{hint:`Run agent-device auth login, unset --no-login, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN.`});let i=await ii({stateDir:e.stateDir,flags:e.flags,env:n,io:e.io,commandLabel:`agent-device connect`});return{accessToken:i.accessToken,cloudBaseUrl:i.session.cloudBaseUrl}}async function ii(e){let n=e.env??e.io?.env??process.env,r=hi(n,e.io);if(r===`non-interactive`)throw vi(e.commandLabel??`agent-device connect`,n);let i=W(n),a=await pi({baseUrl:i,pathName:`/api/control-plane/device-auth/start`,body:{client:`agent-device`,tenant:e.flags.tenant,runId:e.flags.runId,daemonBaseUrl:e.flags.daemonBaseUrl,session:e.flags.session},fetchImpl:e.io?.fetch});mi(a);let o=a.verificationUriComplete??a.verificationUri,s=r===`local-browser`?a.verificationUri:bi(a.verificationUri,a.userCode);r===`local-browser`?(Si(e.io,`Opening ${a.verificationUri}...\n`),await xi(o,e.io)):Si(e.io,`Open this URL on your machine:\n${s}\n\nWaiting for approval for 10 minutes...\n`);let c=await fi({cloudBaseUrl:i,deviceCode:a.deviceCode,expiresIn:a.expiresIn,interval:a.interval,fetchImpl:e.io?.fetch,now:e.io?.now}),l=c.cliSession?.refreshCredential??c.cliSession?.refreshToken;if(!G(c.accessToken)||!G(l))throw new t(`UNAUTHORIZED`,`Device authorization did not return CLI credentials.`);let u=new Date(e.io?.now?.()??Date.now()).toISOString(),d={version:1,id:c.cliSession?.id??`cli-${Date.now().toString(36)}`,cloudBaseUrl:i,workspaceId:c.cliSession?.workspaceId,accountId:c.cliSession?.accountId,name:c.cliSession?.name,refreshCredential:l,createdAt:u,expiresAt:c.cliSession?.expiresAt};return oi({stateDir:e.stateDir,session:d}),{accessToken:c.accessToken,expiresAt:c.expiresAt,session:d}}function ai(e){let t=ci(e.stateDir);if(!j.existsSync(t))return null;try{let e=JSON.parse(j.readFileSync(t,`utf8`));return e.version!==1||!G(e.id)||!G(e.cloudBaseUrl)||!G(e.refreshCredential)||!G(e.createdAt)?null:e}catch{return null}}function oi(e){let t=ci(e.stateDir);j.mkdirSync(k.dirname(t),{recursive:!0,mode:448}),j.writeFileSync(t,`${JSON.stringify(e.session,null,2)}\n`,{mode:384});try{j.chmodSync(t,384)}catch{}}function si(e){let t=ci(e.stateDir);return j.existsSync(t)?(j.rmSync(t,{force:!0}),!0):!1}function ci(e){return k.join(e,`auth`,`cli-session.json`)}function li(e){let t=ai({stateDir:e.stateDir});return t?{authenticated:!0,source:`cli-session`,sessionId:t.id,cloudBaseUrl:t.cloudBaseUrl,workspaceId:t.workspaceId,accountId:t.accountId,name:t.name,createdAt:t.createdAt,expiresAt:t.expiresAt,expired:Ci(t.expiresAt,e.now)}:{authenticated:!1,source:`none`}}async function ui(e){let t=ai({stateDir:e.stateDir});return!t||Ci(t.expiresAt,e.io?.now)?null:{accessToken:(await di({session:t,flags:e.flags,env:e.env,io:e.io})).accessToken,cloudBaseUrl:W(e.env,t.cloudBaseUrl)}}async function di(e){let n=await pi({baseUrl:W(e.env,e.session.cloudBaseUrl),pathName:`/api/control-plane/cli-session/refresh`,body:{refreshCredential:e.session.refreshCredential,tenant:e.flags.tenant,runId:e.flags.runId,daemonBaseUrl:e.flags.daemonBaseUrl,session:e.flags.session},fetchImpl:e.io?.fetch});if(G(n.accessToken))return{accessToken:n.accessToken,expiresAt:n.expiresAt};throw n.status===`revoked`||n.error===`revoked`?new t(`UNAUTHORIZED`,`Stored cloud CLI session was revoked.`,{hint:`Run agent-device auth login again, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN.`,status:n.status,error:n.error}):new t(`UNAUTHORIZED`,`Failed to refresh CLI session.`,{hint:`Run agent-device auth login again, or set AGENT_DEVICE_DAEMON_AUTH_TOKEN.`,status:n.status,error:n.error})}async function fi(e){let n=e.now??Date.now,r=Math.min((e.expiresIn??600)*1e3,6e5),i=n()+r,a=Math.max(ei,(e.interval??5e3/1e3)*1e3);for(;n()<i;){let n=await pi({baseUrl:e.cloudBaseUrl,pathName:`/api/control-plane/device-auth/poll`,body:{deviceCode:e.deviceCode},fetchImpl:e.fetchImpl});if(n.status===`approved`||G(n.accessToken))return n;if(n.status===`slow_down`||n.error===`slow_down`)a+=ei;else if(n.status!==`authorization_pending`&&n.error!==`authorization_pending`)throw new t(`UNAUTHORIZED`,`Device authorization was not approved.`,{status:n.status,error:n.error});await wi(a)}throw new t(`TIMEOUT`,`Device authorization expired before approval.`)}async function pi(e){let t=await(e.fetchImpl??fetch)(new URL(e.pathName,e.baseUrl),{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify(e.body),signal:AbortSignal.timeout(15e3)});return await $r(t,{invalidJsonMessage:`Cloud auth endpoint returned invalid JSON (${t.status}).`,rejectedMessage:`Cloud auth endpoint rejected the request.`})}function mi(e){if(!G(e.deviceCode)||!G(e.userCode)||!G(e.verificationUri))throw new t(`COMMAND_FAILED`,`Cloud auth start returned an unusable response.`)}function hi(e,t){let n=t?.stdinIsTTY??process.stdin.isTTY,r=t?.stdoutIsTTY??process.stdout.isTTY;return gi(e)||!n||!r?`non-interactive`:_i(e)?`device-code`:`local-browser`}function gi(e){return e.CI===`true`||e.GITHUB_ACTIONS===`true`||e.BUILDKITE===`true`}function _i(e){return!!(e.SSH_TTY||e.SSH_CONNECTION||e.CODESPACES===`true`||e.GITPOD_WORKSPACE_ID||e.REMOTE_CONTAINERS===`true`)}function vi(e,n){let r=W(n);return new t(`UNAUTHORIZED`,`${e} cannot perform interactive login in CI or a non-interactive shell.`,{hint:`Create a service/API token: ${new URL(`/api-keys`,r).toString()} Then set AGENT_DEVICE_DAEMON_AUTH_TOKEN=adc_live_...`})}function W(e,n){let r=e.AGENT_DEVICE_CLOUD_BASE_URL??n??`https://cloud.agent-device.dev`;try{return new URL(r).toString().replace(/\/+$/,``)}catch(e){throw new t(`INVALID_ARGS`,`Invalid AGENT_DEVICE_CLOUD_BASE_URL.`,{cloudBaseUrl:r},e instanceof Error?e:void 0)}}function yi(e,t){if(t.AGENT_DEVICE_CLOUD_AUTH===`1`||t.AGENT_DEVICE_CLOUD_AUTH===`true`||G(t.AGENT_DEVICE_CLOUD_BASE_URL))return!0;try{let t=new URL(e).hostname.toLowerCase();return t===`agent-device.dev`||t.endsWith(`.agent-device.dev`)}catch{return!1}}function bi(e,t){let n=new URL(e);return n.searchParams.set(`user_code`,t),n.toString()}async function xi(e,t){if(t?.openBrowser){await t.openBrowser(e);return}let n=process.platform;try{n===`darwin`?await Pe(`open`,[e],{allowFailure:!0,timeoutMs:5e3}):n===`win32`?await Pe(`cmd`,[`/c`,`start`,``,e],{allowFailure:!0,timeoutMs:5e3}):await Pe(`xdg-open`,[e],{allowFailure:!0,timeoutMs:5e3})}catch{Si(t,`Open this URL on your machine:\n${e}\n`)}}function Si(e,t){(e?.stderr??process.stderr).write(t)}function Ci(e,t){if(!e)return!1;let n=Date.parse(e);return Number.isFinite(n)?n<=(t?.()??Date.now()):!0}function G(e){return typeof e==`string`&&e.trim().length>0}async function wi(e){await new Promise(t=>setTimeout(t,e))}const Ti=new Set([`daemonAuthToken`,`metroBearerToken`]);function Ei(e){let t=Ai(Oi(e.profile)),n=k.join(e.stateDir,`remote-connections`,`generated`);j.mkdirSync(n,{recursive:!0,mode:448});let r=k.join(n,`${ji(e.provider)}-${ki(t)}.json`);j.writeFileSync(r,`${JSON.stringify(t,null,2)}\n`,{mode:384});try{j.chmodSync(r,384)}catch{}return r}function Di(e){try{return C(e)}catch(n){let i=r(n);throw new t(`COMMAND_FAILED`,`${e.provider} connection profile returned invalid remote config.`,{generatedConfigPath:e.configPath,cause:i.message},i)}}function K(e){let t=Di({configPath:Ei({stateDir:e.stateDir,provider:e.provider,profile:e.profile}),cwd:e.cwd,env:e.env,provider:Mi(e.provider)});return{flags:{...R(t.profile),...e.flags,...e.extraFlags??{},remoteConfig:t.resolvedPath},remoteConfigPath:t.resolvedPath}}function Oi(e){return Object.fromEntries(Object.entries(e).filter(([e])=>!Ti.has(e)))}function ki(e){return A.createHash(`sha256`).update(JSON.stringify(e)).digest(`hex`).slice(0,16)}function Ai(e){return Array.isArray(e)?e.map(Ai):e&&typeof e==`object`?Object.fromEntries(Object.entries(e).filter(([,e])=>e!==void 0).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>[e,Ai(t)])):e}function ji(e){return e.replaceAll(/[^a-zA-Z0-9._-]/g,`_`)||`generated`}function Mi(e){let[t=``,...n]=e;return`${t.toUpperCase()}${n.join(``)}`}function Ni(...e){return A.createHash(`sha256`).update(e.map(e=>e??``).join(`\0`)).digest(`hex`).slice(0,16)}async function Pi(e){let t=await ri({stateDir:e.stateDir,flags:e.flags,env:e.env,io:{env:e.env,fetch:e.fetchImpl}}),n=await Fi({cloudBaseUrl:t.cloudBaseUrl,accessToken:t.accessToken,fetchImpl:e.fetchImpl}),r=Ni(e.stateDir,t.cloudBaseUrl,typeof n.daemonBaseUrl==`string`?n.daemonBaseUrl:``,e.flags.session);return K({stateDir:e.stateDir,provider:`cloud`,profile:{...n,leaseProvider:n.leaseProvider??`cloud`,clientId:n.clientId??r,runId:n.runId??`cloud-${r}`},cwd:e.cwd,env:e.env,flags:e.flags,extraFlags:{daemonAuthToken:t.accessToken}})}async function Fi(e){let t=await(e.fetchImpl??fetch)(new URL(`/api/control-plane/connection-profile`,e.cloudBaseUrl),{method:`GET`,headers:{authorization:`Bearer ${e.accessToken}`},signal:AbortSignal.timeout(15e3)});return Ii(await $r(t,{invalidJsonMessage:`Cloud connection profile endpoint returned invalid JSON (${t.status}).`,rejectedMessage:`Cloud connection profile endpoint rejected the request.`}))}function Ii(e){if(!e||typeof e!=`object`||Array.isArray(e))throw new t(`COMMAND_FAILED`,`Cloud connection profile response is invalid.`);let n=e.connection;if(!n||typeof n!=`object`)throw new t(`COMMAND_FAILED`,`Cloud connection profile response is missing profile.`);if(n.remoteConfigProfile!==void 0)return Li(n.remoteConfigProfile);throw new t(`COMMAND_FAILED`,`Cloud connection profile did not include remoteConfigProfile.`)}function Li(e){if(!e||typeof e!=`object`||Array.isArray(e))throw new t(`COMMAND_FAILED`,`Cloud connection profile remoteConfigProfile is invalid.`);if(Object.keys(e).length===0)throw new t(`COMMAND_FAILED`,`Cloud connection profile remoteConfigProfile is empty.`);return e}function Ri(e){let t=Bi(e.provider)(e),n=Ni(e.provider,e.stateDir,e.flags.session,t.device),r={tenant:e.flags.tenant??e.provider,sessionIsolation:e.flags.sessionIsolation??`tenant`,runId:e.flags.runId??`${e.provider}-${n}`,leaseProvider:e.provider,clientId:n,leaseBackend:e.flags.leaseBackend??U(e.flags),target:e.flags.target??`mobile`,session:e.flags.session,...t,...B(e.flags)};return K({stateDir:e.stateDir,provider:e.provider,profile:r,cwd:e.cwd,env:e.env,flags:e.flags})}const zi=[{provider:w.browserStack,buildProfileFields:Vi},{provider:w.awsDeviceFarm,buildProfileFields:Ui}];function Bi(e){let n=zi.find(t=>t.provider===e)?.buildProfileFields;if(n)return n;throw new t(`INVALID_ARGS`,`Unsupported cloud WebDriver provider "${e}".`)}function Vi(e){return Gi(e.env,`BROWSERSTACK_USERNAME`,`connect browserstack`),Gi(e.env,`BROWSERSTACK_ACCESS_KEY`,`connect browserstack`),{platform:Wi(e.flags.platform,`connect browserstack requires --platform ios|android.`),device:q(e.flags.device,`connect browserstack requires --device <name>.`),providerOsVersion:q(e.flags.providerOsVersion,`connect browserstack requires --provider-os-version <version>.`),providerApp:Hi(q(e.flags.providerApp,`connect browserstack requires --provider-app <bs://app-id-or-local-path>.`),e.cwd),providerProject:e.flags.providerProject,providerBuild:e.flags.providerBuild,providerSessionName:e.flags.providerSessionName,...fr(e.flags)}}function Hi(e,n){if(e.startsWith(`bs://`)||/^https?:\/\//i.test(e))return e;let r=k.resolve(n,e);try{if(j.statSync(r).isFile())return r}catch{}throw new t(`INVALID_ARGS`,`BrowserStack app file not found: ${r}`)}function Ui(e){let{env:t,flags:n}=e;Xe(n,w.awsDeviceFarm);let r=Wi(n.platform,`connect aws-device-farm requires --platform ios|android.`),i=Ki(n.awsProjectArn,t,[`AGENT_DEVICE_AWS_DEVICE_FARM_PROJECT_ARN`,`AWS_DEVICE_FARM_PROJECT_ARN`],`connect aws-device-farm requires --aws-project-arn <arn> or AWS_DEVICE_FARM_PROJECT_ARN.`);return{platform:r,device:n.device,awsProjectArn:i,awsDeviceArn:Ki(n.awsDeviceArn,t,[`AGENT_DEVICE_AWS_DEVICE_FARM_DEVICE_ARN`,`AWS_DEVICE_FARM_DEVICE_ARN`],`connect aws-device-farm requires --aws-device-arn <arn> or AWS_DEVICE_FARM_DEVICE_ARN.`),awsAppArn:J(n.awsAppArn,t,[`AGENT_DEVICE_AWS_DEVICE_FARM_APP_ARN`,`AWS_DEVICE_FARM_APP_ARN`]),awsRegion:J(n.awsRegion,t,[`AWS_REGION`,`AWS_DEFAULT_REGION`])??nt(i),awsInteractionMode:n.awsInteractionMode,providerSessionName:n.providerSessionName}}function Wi(e,n){if(e===`android`||e===`ios`)return e;throw new t(`INVALID_ARGS`,n)}function q(e,n){if(e)return e;throw new t(`INVALID_ARGS`,n)}function Gi(e,n,r){let i=e?.[n];if(i)return i;throw new t(`INVALID_ARGS`,`${r} requires ${n} in the environment.`)}function Ki(e,t,n,r){return q(J(e,t,n),r)}function J(e,t,n){return e||n.map(e=>t?.[e]).find(e=>!!e)}function qi(e){let n=e.env??process.env;if(!n.LIMRUN_API_KEY?.trim())throw new t(`INVALID_ARGS`,`connect limrun requires LIMRUN_API_KEY.`,{hint:`Set LIMRUN_API_KEY in the environment before running agent-device connect limrun.`});let r=Ji({flags:e.flags});return K({stateDir:e.stateDir,provider:`limrun`,profile:r,cwd:e.cwd,env:n,flags:e.flags})}function Ji(e){let t=e.flags,n=Yi(t);return{stateDir:b(t.stateDir).baseDir,daemonTransport:`auto`,tenant:t.tenant??`limrun`,runId:t.runId??`cli-${Date.now().toString(36)}`,sessionIsolation:`tenant`,leaseBackend:n,leaseProvider:`limrun`,platform:t.platform,target:`mobile`,session:t.session,...B(t)}}function Yi(e){if(e.platform!==`android`&&e.platform!==`ios`)throw new t(`INVALID_ARGS`,`connect limrun requires --platform ios or android.`);if(e.device!==void 0)throw new t(`INVALID_ARGS`,`connect limrun does not accept --device; Limrun selects a remote simulator or emulator.`);let n=U(e),r=e.platform===`ios`?`ios-instance`:`android-instance`;if(n!==r)throw new t(`INVALID_ARGS`,`connect limrun --platform ${e.platform} requires --lease-backend ${r}.`);return r}function Xi(e){let n=e.flags.daemonBaseUrl??e.env?.AGENT_DEVICE_DAEMON_BASE_URL;if(!n)throw new t(`INVALID_ARGS`,`connect proxy requires --daemon-base-url <url> or AGENT_DEVICE_DAEMON_BASE_URL.`);let r=Ni(e.stateDir,n,e.flags.session),i={daemonBaseUrl:n,daemonTransport:e.flags.daemonTransport??`http`,daemonServerMode:e.flags.daemonServerMode,tenant:e.flags.tenant??`proxy`,sessionIsolation:e.flags.sessionIsolation??`tenant`,runId:e.flags.runId??`proxy-${r}`,leaseProvider:`proxy`,clientId:r,leaseBackend:e.flags.leaseBackend??U(e.flags),platform:e.flags.platform,target:e.flags.target,device:e.flags.device,udid:e.flags.udid,serial:e.flags.serial,iosSimulatorDeviceSet:e.flags.iosSimulatorDeviceSet,androidDeviceAllowlist:e.flags.androidDeviceAllowlist,session:e.flags.session,...B(e.flags)};return K({stateDir:e.stateDir,provider:`proxy`,profile:i,cwd:e.cwd,env:e.env,flags:e.flags,extraFlags:{daemonBaseUrl:n,daemonTransport:e.flags.daemonTransport??`http`}})}const Zi={cloud:{resolve:Pi,verify:async()=>({service:`the configured cloud service`,status:`verified`,verificationMessage:`Credentials and connection profile verified.`})},proxy:{resolve:Xi,verify:async()=>({service:`Agent Device Proxy`,status:`configured`,verificationMessage:`Proxy configuration saved. Access is checked by the first remote command.`})},browserstack:{resolve:e=>Ri({provider:`browserstack`,...e}),verify:ea},"aws-device-farm":{resolve:e=>Ri({provider:`aws-device-farm`,...e}),verify:ta},limrun:{resolve:qi,verify:na}};async function Qi(e){let t=e.cwd??process.cwd(),n=e.env??process.env;if(e.flags.remoteConfig){let r=C({configPath:e.flags.remoteConfig,cwd:t,env:n}),i=r.profile.leaseProvider;return{flags:{...R(r.profile),...e.flags,remoteConfig:r.resolvedPath},remoteConfigPath:r.resolvedPath,...cr(i)?{provider:i}:{}}}let r=e.provider??(ra(e.flags)?`proxy`:`cloud`);return{...await Zi[r].resolve({flags:e.flags,stateDir:e.stateDir,cwd:t,env:n}),provider:r}}async function $i(e){let t=e.env??process.env;return e.provider?await Zi[e.provider].verify({flags:e.flags,env:t}):{service:`remote provider`,status:`configured`,verificationMessage:`Remote connection profile loaded. Access is checked by the first remote command.`}}async function ea(e){let{flags:t,env:n}=e;return await tt.verifyConnection({provider:`browserstack`,username:Y(n.BROWSERSTACK_USERNAME,`BrowserStack profile missed BROWSERSTACK_USERNAME.`),accessKey:Y(n.BROWSERSTACK_ACCESS_KEY,`BrowserStack profile missed BROWSERSTACK_ACCESS_KEY.`),platform:ia(t.platform,`BrowserStack`),deviceName:Y(t.device,`BrowserStack profile missed device.`),osVersion:Y(t.providerOsVersion,`BrowserStack profile missed OS version.`),app:Y(t.providerApp,`BrowserStack profile missed app.`)})}async function ta(e){let{flags:t}=e;return await tt.verifyConnection({provider:`aws-device-farm`,platform:ia(t.platform,`AWS Device Farm`),projectArn:Y(t.awsProjectArn,`AWS Device Farm profile missed project ARN.`),deviceArn:Y(t.awsDeviceArn,`AWS Device Farm profile missed device ARN.`),appArn:t.awsAppArn,region:t.awsRegion})}async function na(e){return await Ge({apiKey:Y(e.env.LIMRUN_API_KEY,`Limrun profile missed LIMRUN_API_KEY.`),clientVersion:Fe(),platform:ia(e.flags.platform,`Limrun`),region:e.env.LIMRUN_REGION?.trim()||void 0})}function ra(e){if(!e.daemonBaseUrl||e.tenant||e.runId||e.leaseId||e.leaseBackend)return!1;try{return new URL(e.daemonBaseUrl).pathname.replace(/\/+$/,``).endsWith(`/agent-device`)}catch{return!1}}function Y(e,n){if(e!==void 0)return e;throw new t(`COMMAND_FAILED`,n,{hint:`Reconnect to regenerate and validate the provider profile.`})}function ia(e,n){if(e===`android`||e===`ios`)return e;throw new t(`COMMAND_FAILED`,`${n} profile missed a mobile platform.`,{hint:`Reconnect with --platform ios|android.`})}function X(e,t){if(e.leaseId)return;let n=dr(e.leaseProvider);return n===`proxy`?{status:`deferred`,nextSteps:pa(e,t).nextSteps,message:`No live device session has been created. Run devices to inspect inventory without allocating, then open when ready.`}:n===`direct-device-provider`?{status:`deferred`,nextSteps:pa(e,t).nextSteps,message:`No live device session has been created. The first device command shown below will allocate one.`}:{status:`deferred`,nextSteps:[`agent-device install-from-source <artifact-url> --platform ios|android`,`agent-device open <app-id> --relaunch`,`agent-device snapshot -i`,`agent-device devices`],message:`No live device session has been created. Run a device command when ready to allocate or refresh the lease.`+(e.platform===void 0&&e.leaseBackend===void 0?` Add --platform ios|android if the profile does not set a platform.`:``)}}function aa(e,t){return{...t,preparationMessage:X(e,t)?.message??`No live device session has been created.`,...pa(e,t)}}function oa(e){let{state:t,readiness:n,runtimePreparation:r,previousLeaseNotice:i}=e;if(!n){let e=X(t);return[`Configured remote session "${t.session}" tenant "${t.tenant}" run "${t.runId}"${t.leaseId?` lease ${t.leaseId}`:``}.`,e?.message,r?.message,i?.message].filter(e=>!!e).join(`
|
|
4
|
-
`)}let
|
|
5
|
-
`)}function
|
|
6
|
-
`)),!0};function La(e){for(let t=0;t<8;t+=1){let t=`adc-${A.randomBytes(3).toString(`hex`)}`;if(!F({stateDir:e,session:t}))return t}return`adc-${Date.now().toString(36)}-${A.randomBytes(2).toString(`hex`)}`}function Ra(e,t){return[`Disconnected remote session "${e}".`,...za(t),...Va(t?.cloudArtifacts?.cloudArtifacts)].join(`
|
|
7
|
-
`)}function za(e){return(Array.isArray(e?.warnings)?e.warnings:[]).flatMap(e=>{let t=Ba(e);return t?[t]:[]})}function Ba(e){if(!e||typeof e!=`object`)return;let t=e;if(!(typeof t.message!=`string`||t.message.length===0))return`Provider release warning${typeof t.code==`string`&&t.code.length>0?` (${t.code})`:``}: ${t.message}`}function Va(e){return(e??[]).filter(e=>(e.availability??`ready`)===`ready`&&e.url).slice(0,3).map(e=>`${e.name}: ${e.url}`)}function Ha(e){let n=e[0];if(n!==void 0){if(e.length>1)throw new t(`INVALID_ARGS`,`connect accepts at most one provider positional.`);if(cr(n))return n;throw new t(`INVALID_ARGS`,`Unknown connect provider: ${n}. Supported providers: ${lr()}.`)}}function Ua(e){let t=e.session??`default`,n=b(e.stateDir).baseDir;return{session:t,stateDir:n,state:F({stateDir:n,session:t})??(e.session?null:L({stateDir:n}))}}function Wa(e,t){O(e,{connected:!1,session:t},()=>`No remote connection for "${t}".`)}function Ga(e,t){return Ka(e,t)&&qa(e,t)&&Ja(e.daemon,t.daemon)}function Ka(e,t){return[[e.remoteConfigPath,t.remoteConfigPath],[e.remoteConfigHash,t.remoteConfigHash],[e.session,t.session],[e.tenant,t.flags.tenant],[e.runId,t.flags.runId]].every(([e,t])=>e===t)}function qa(e,t){return[[e.leaseBackend,t.desiredLeaseBackend],[e.platform,t.flags.platform],[e.target,t.flags.target],[e.leaseProvider,t.connection?.leaseProvider],[e.clientId,t.connection?.clientId]].every(([e,t])=>t===void 0||e===t)}function Ja(e,t){return[`baseUrl`,`transport`,`serverMode`].every(n=>(e?.[n]??void 0)===(t?.[n]??void 0))}function Ya(e){return Hn(e)}function Xa(e,t){if(!t.runtime&&!(!Rr(e)&&!$a(t.remoteConfigPath)))return Qa(t.remoteConfigPath)}function Za(e){if(!(e.runtime||!$a(e.remoteConfigPath)))return Qa(e.remoteConfigPath)}function Qa(e){let t=`agent-device metro prepare --remote-config ${e}`;return{status:`deferred`,nextStep:t,message:`Metro runtime is not prepared yet; it will be prepared automatically on first open, or run "${t}" to inspect it before launch.`}}function $a(e){try{let t=C({configPath:e,cwd:process.cwd(),env:process.env}).profile;return!!(t.metroPublicBaseUrl||t.metroProxyBaseUrl||t.metroProjectRoot||t.metroKind)}catch{return!1}}const eo=async({positionals:e,flags:n})=>{let r=e[0]??`status`,i=b(n.stateDir).baseDir;if(r===`status`){let e=li({stateDir:i});return O(n,e,()=>to(e)),!0}if(r===`login`){let e=await ii({stateDir:i,flags:n,commandLabel:`agent-device auth login`});return O(n,{authenticated:!0,source:`cli-session`,sessionId:e.session.id,cloudBaseUrl:e.session.cloudBaseUrl,workspaceId:e.session.workspaceId,accountId:e.session.accountId,expiresAt:e.session.expiresAt,agentTokenExpiresAt:e.expiresAt},()=>`Authenticated with cloud CLI session.`),!0}if(r===`logout`){let e=si({stateDir:i});return O(n,{authenticated:!1,removed:e},()=>e?`Removed stored cloud CLI session.`:`No stored cloud CLI session.`),!0}throw new t(`INVALID_ARGS`,`auth accepts only: status, login, logout`)};function to(e){return e.authenticated?[`Authenticated with cloud CLI session.`,`cloud=${e.cloudBaseUrl}`,`session=${e.sessionId}`,e.workspaceId?`workspace=${e.workspaceId}`:null,e.accountId?`account=${e.accountId}`:null,e.expiresAt?`expiresAt=${e.expiresAt}`:null,e.expired?`status=expired`:null].filter(e=>!!e).join(`
|
|
8
|
-
`):`Not authenticated.`}async function no(e){let n=ao(e.paths.infoPath);if(!n)return Z();if(!n.processStartTime){if(!Le(n.pid))return Z();throw new t(`COMMAND_FAILED`,`Refusing to stop a daemon without a verified process start-time identity.`,{pid:n.pid})}if(!fe(n.pid,n.processStartTime)){if(!Le(n.pid))return Z();throw new t(`COMMAND_FAILED`,`Refusing to stop a daemon whose PID or start-time identity could not be verified.`,{pid:n.pid,processStartTime:n.processStartTime})}if(!ro(n.pid,`SIGTERM`))return Z();if(await Re(n.pid,e.graceTimeoutMs??1e4))return await so(e.paths,1e3),{stopped:!0,mode:`graceful`,cleanupConfidence:`known`,claimsReleased:[],claimsOrphaned:[],providerReleases:{status:`completed`,released:[],pending:[]},warnings:[]};if(fe(n.pid,n.processStartTime)&&ro(n.pid,`SIGKILL`),!await Re(n.pid,e.killTimeoutMs??2e3))throw new t(`COMMAND_FAILED`,`Daemon did not exit after SIGKILL.`,{pid:n.pid});return{stopped:!0,mode:`forced`,cleanupConfidence:`unknown`,claimsReleased:[],claimsOrphaned:[],providerReleases:{status:`unknown`,released:[],pending:null},warnings:[`The daemon was force-killed before provider lease state could be finalized. Provider allocations may remain active.`]}}function ro(e,n){if(ge(e,n))return!0;if(!Le(e))return!1;throw new t(`COMMAND_FAILED`,`Daemon could not be signaled with ${n}.`,{pid:e,signal:n})}function io(e){let t=ao(e);return t?.processStartTime?{pid:t.pid,processStartTime:t.processStartTime}:null}function ao(e){try{let t=JSON.parse(j.readFileSync(e,`utf8`)),n=t.pid;return typeof n!=`number`||!Number.isInteger(n)||n<=0?null:{pid:n,...oo(t.processStartTime)?{processStartTime:t.processStartTime}:{}}}catch{return null}}function oo(e){return typeof e==`string`&&e.trim().length>0}async function so(e,t){let n=Date.now();for(;Date.now()-n<t;){if(!j.existsSync(e.infoPath)&&!j.existsSync(e.lockPath))return;await Ie(25)}}function Z(){return{stopped:!1,mode:`not-running`,cleanupConfidence:`known`,claimsReleased:[],claimsOrphaned:[],providerReleases:{status:`completed`,released:[],pending:[]},warnings:[]}}const co=async({positionals:e,flags:n})=>{if(e[0]!==`stop`||e.length!==1)throw new t(`INVALID_ARGS`,`daemon accepts only: stop`);let r=b(n.stateDir),i=io(r.infoPath),a=await no({paths:r}),o=lo(a,a.mode===`graceful`?$e(r.baseDir):null),s=n.clean===!0&&i!==null&&o.stopped;if(s){let[{cleanupRunnerLeasesForOwner:e},{runnerLeaseCleanupAdapter:t}]=await Promise.all([import(`./runner-lease.js`).then(e=>e.c),import(`./runner-disposal.js`).then(e=>e.s)]);await e({pid:i.pid,startTime:i.processStartTime},t)}let c={...o,clean:s};return O(n,c,()=>uo(c)),!0};function lo(e,t){return e.mode!==`graceful`||t?t?{...e,providerReleases:{status:`completed`,...t.providerReleases}}:e:{...e,cleanupConfidence:`unknown`,providerReleases:{status:`unknown`,released:[],pending:null},warnings:[...e.warnings,`The graceful shutdown report is unavailable, so provider cleanup state is unknown. Provider allocations may remain active.`]}}function uo(e){return[e.stopped?`Daemon stopped (${e.mode}).`:`No running daemon found.`,e.clean?`Retained runner cleanup completed.`:null,...e.warnings].filter(e=>!!e).join(`
|
|
9
|
-
`)}const fo=async({positionals:e,flags:n})=>{if(e[0]!==`status`||e.length!==1)throw new t(`INVALID_ARGS`,`device accepts only: status`);let r=Ze({platform:n.platform,device:n.device,udid:n.udid,serial:n.serial}),i=r.filter(po),a=(n.stale?i:r.filter(e=>!po(e))).map(mo);return O(n,{claims:a,...n.stale?{}:{hiddenStaleClaims:i.length}},()=>ho(a,{staleOnly:n.stale===!0,hiddenStaleClaims:i.length,staleCommand:yo(n)})),!0};function po(e){return e.classification===`owner-process-dead`||e.classification===`owner-state-dir-gone`}function mo(e){let t=e.claim;return{...e.deviceKey?{deviceKey:e.deviceKey}:{},...t?{}:{fileName:e.fileName},classification:e.classification,...t?{device:t.device,owner:{session:t.session,workspace:t.workspace,stateDir:t.stateDir,pid:t.ownerPid,startTime:t.ownerStartTime}}:{},...e.error?{error:e.error}:{}}}function ho(e,t){let n=e.map(go);if(n.length===0){if(t.staleOnly)return`No stale local advisory device claims found.`;if(t.hiddenStaleClaims===0)return`No local advisory device claims found.`}return[...n.length===0?[`No live local advisory device claims found.`]:n,!t.staleOnly&&t.hiddenStaleClaims>0?`${t.hiddenStaleClaims} stale ${t.hiddenStaleClaims===1?`claim`:`claims`} hidden; inspect with: ${t.staleCommand}`:null].filter(e=>!!e).join(`
|
|
10
|
-
`)}function go(e){return`${_o(e)}: ${e.classification}${vo(e.owner)}`}function _o(e){let t=e.device;return t?`${t.platform??`unknown`} ${t.name??t.id??`claim`}`:String(e.deviceKey??e.fileName??`claim`)}function vo(e){if(!e||typeof e!=`object`)return``;let t=e;return` session=${t.session} workspace=${t.workspace}`}function yo(e){return[`agent-device device status`,...[e.platform?`--platform ${y(e.platform)}`:null,e.device?`--device ${y(e.device)}`:null,e.udid?`--udid ${y(e.udid)}`:null,e.serial?`--serial ${y(e.serial)}`:null].filter(e=>!!e),`--stale`].join(` `)}const bo=`${_e}/`,xo=[`content-type`,`content-range`,`x-artifact-type`,`x-artifact-filename`,`x-artifact-hash`,`x-artifact-hash-algorithm`,he],So=[`content-type`,`content-disposition`,`x-request-id`];function Co(e){let t=Fo(e);return ft.createServer((e,n)=>{wo(e,n,t).catch(e=>{Qo(n,e)})})}async function wo(e,t,n){let r=Ro(e.url??`/`);if(e.method===`GET`&&r===`/health`){await To(t,n);return}if(!zo(r,e.method)){t.statusCode=404,t.end(`Not found`);return}let i;if(r===`/rpc`&&(i=(await ye(e,n.maxRpcBodyBytes,`Proxy request body is too large.`)).toString(`utf8`)),!Go(e,n.clientToken,i)){Zo(t,r,Yo(i));return}await Do({req:e,res:t,route:r,options:n,rpcBody:i})}async function To(e,t){let n=await Eo(t);e.statusCode=200,e.setHeader(`content-type`,`application/json`),e.end(JSON.stringify(ve(`agent-device-proxy`,{upstream:n})))}async function Eo(e){let t=new URL(xe(e.upstreamBaseUrl,`health`)),n=await e.fetchImpl(t,{method:`GET`,headers:Uo({headers:{}},e.upstreamToken,`/health`),signal:AbortSignal.timeout(e.upstreamTimeoutMs)}),r=await n.text();try{return r?JSON.parse(r):{ok:n.ok,status:n.status}}catch{return{ok:n.ok,status:n.status}}}async function Do(e){let{req:t,res:n,route:r,options:i,rpcBody:a}=e,o=Ho(i.upstreamBaseUrl,r,t.url??`/`),s=t.method??`GET`,c=Uo(t,i.upstreamToken,r),l=Wo(t,r,a,i.upstreamToken);await Oo({req:t,res:n,route:r,response:await i.fetchImpl(o,{method:s,headers:c,signal:AbortSignal.timeout(i.upstreamTimeoutMs),...l?{body:l,duplex:`half`}:{}}),clientToken:i.clientToken})}async function Oo(e){let{req:t,res:n,route:r,response:i,clientToken:a}=e;if(n.statusCode=i.status,ko(i,n),Ao(t,n),Vo(r)){await jo({req:t,res:n,response:i,clientToken:a});return}await Po(i,n)}function ko(e,t){for(let n of So){let r=e.headers.get(n);r&&t.setHeader(n,r)}}function Ao(e,t){t.hasHeader(`x-request-id`)||t.setHeader(`x-request-id`,Xo(e))}async function jo(e){let{req:t,res:n,response:r,clientToken:i}=e,a=await r.text();n.setHeader(`content-type`,r.headers.get(`content-type`)??`application/json`),n.end(Mo(a,t,i))}function Mo(e,t,n){let r;try{r=JSON.parse(e)}catch{return e}if(!r||typeof r!=`object`)return e;let i=r;if(!i.upload||typeof i.upload.url!=`string`)return e;let a=No(i.upload.url,t);if(!a)return e;let o=i.upload.headers&&typeof i.upload.headers==`object`?{...i.upload.headers}:{};return Object.assign(o,me(n)),JSON.stringify({...r,upload:{...i.upload,url:a,headers:o}})}function No(e,t){let n;try{n=new URL(e)}catch{return null}if(!n.pathname.startsWith(`/upload/`))return null;let r=typeof t.headers.host==`string`?t.headers.host:``;if(!r)return null;let i=new URL(t.url??`/`,`http://127.0.0.1`).pathname,a=i.lastIndexOf(`/upload/preflight`),o=a>=0?i.slice(0,a):``,s=t.headers[`x-forwarded-proto`],c=Array.isArray(s)?s[0]:s,l=new URL(`${c||`http`}://${r}`);return l.pathname=`${o}${n.pathname}`,l.search=n.search,l.toString()}async function Po(e,t){if(!e.body){t.end();return}await pt(mt.fromWeb(e.body),t)}function Fo(e){return{upstreamBaseUrl:Io(e.upstreamBaseUrl,`upstreamBaseUrl`),upstreamToken:Lo(e.upstreamToken,`upstreamToken`),clientToken:Lo(e.clientToken,`clientToken`),maxRpcBodyBytes:e.maxRpcBodyBytes??1048576,upstreamTimeoutMs:e.upstreamTimeoutMs??3e5,fetchImpl:e.fetchImpl??fetch}}function Io(e,n){try{let t=new URL(e);if(t.protocol!==`http:`&&t.protocol!==`https:`)throw Error(`unsupported protocol`);return t.toString().replace(/\/+$/,``)}catch(r){throw new t(`INVALID_ARGS`,`Invalid ${n}`,{[n]:e},r)}}function Lo(e,n){let r=e.trim();if(!r)throw new t(`INVALID_ARGS`,`Proxy ${n} is required.`);return r}function Ro(e){let t=new URL(e,`http://127.0.0.1`).pathname;return t===`/agent-device`?`/`:t.startsWith(bo)?`/${t.slice(bo.length)}`:t}function zo(e,t){return e===`/rpc`?t===`POST`:Bo(e,t)?!0:e===`/artifacts`||e===`/artifacts/`||e.startsWith(`/artifacts/`)?t===`GET`:!1}function Bo(e,t){return e===`/upload`||Vo(e)||e===`/upload/finalize`?t===`POST`:e.startsWith(`/upload/direct/`)?t===`PUT`:!1}function Vo(e){return e===`/upload/preflight`}function Ho(e,t,n){let r=new URL(xe(e,t)),i=n.indexOf(`?`);return i>=0&&(r.search=n.slice(i)),r}function Uo(e,t,n){let r=new Headers;for(let t of xo){let n=e.headers[t];typeof n==`string`&&n.trim()&&r.set(t,n)}n===`/rpc`&&!r.has(`content-type`)&&r.set(`content-type`,`application/json`);for(let[e,n]of Object.entries(me(t)))r.set(e,n);return r}function Wo(e,t,n,r){if(!(e.method===`GET`||e.method===`HEAD`))return t===`/rpc`?qo(n??``,r):e}function Go(e,t,n){let r=Ko(e,n);return r.length>0&&Je(r,t)}function Ko(e,t){let n=typeof e.headers.authorization==`string`?e.headers.authorization:``;if(n.toLowerCase().startsWith(`bearer `))return n.slice(7);let r=e.headers[`x-agent-device-token`];if(typeof r==`string`)return r;if(t){let e=Jo(t);if(e)return e}return``}function qo(e,t){let n=JSON.parse(e);return n.params={...n.params??{},token:t},JSON.stringify(n)}function Jo(e){try{let t=JSON.parse(e);return typeof t.params?.token==`string`?t.params.token:``}catch{return``}}function Yo(e){if(!e)return null;try{return JSON.parse(e).id??null}catch{return null}}function Xo(e){let t=e.headers[`x-request-id`];return typeof t==`string`&&t.trim()?t.trim().slice(0,128):dt()}function Zo(n,r,i){if(n.statusCode=401,n.setHeader(`content-type`,`application/json`),r===`/rpc`){n.end(JSON.stringify({jsonrpc:`2.0`,id:i,error:{code:-32001,message:`Invalid proxy token`,data:e(new t(`UNAUTHORIZED`,`Invalid proxy token`))}}));return}n.end(JSON.stringify({ok:!1,error:`Invalid proxy token`,code:`UNAUTHORIZED`}))}function Qo(t,n){if(t.headersSent){t.destroy(n instanceof Error?n:void 0);return}let r=e(n);t.statusCode=r.code===`INVALID_ARGS`?400:500,t.setHeader(`content-type`,`application/json`),t.end(JSON.stringify({ok:!1,error:r.message,code:r.code}))}const $o=async({positionals:e,flags:n})=>{if(e.length>0)throw new t(`INVALID_ARGS`,`proxy does not accept positional arguments.`);let r=await es(n);return O(n,r,()=>as(r)),await os(),!0};async function es(e){let n=se({session:`default`,command:`proxy`,positionals:[],flags:{stateDir:e.stateDir,daemonBaseUrl:``,daemonTransport:`http`,daemonServerMode:`http`}}),r=await ce(n),i=ts(r.info.httpPort),a=ns(e),o=Co({upstreamBaseUrl:i,upstreamToken:r.info.token,clientToken:a});await rs(o,e.proxyHost?.trim()||`127.0.0.1`,e.proxyPort??0);let s=o.address();if(!s||typeof s==`string`)throw new t(`COMMAND_FAILED`,`Proxy did not bind to a TCP address.`);let c=`http://${is(s.address)}:${s.port}`;return{proxyBaseUrl:c,agentDeviceBaseUrl:pe(c),token:a,upstreamBaseUrl:i,stateDir:n.paths.baseDir}}function ts(e){if(!e)throw new t(`COMMAND_FAILED`,`Local daemon HTTP endpoint is unavailable.`,{hint:`Retry after cleaning daemon state, or run proxy with a fresh --state-dir.`});return`http://127.0.0.1:${e}`}function ns(e){return e.daemonAuthToken?.trim()||ut(32).toString(`hex`)}function rs(e,t,n){return new Promise((r,i)=>{e.once(`error`,i),e.listen(n,t,()=>{e.off(`error`,i),r()})})}function is(e){return e.includes(`:`)&&!e.startsWith(`[`)?`[${e}]`:e}function as(e,t={}){let n=t.useColor??ee(),r=Q(`✓`,`green`,n),i=Q(e.proxyBaseUrl,`cyan`,n),a=Q(`<tunnel URL>`,`cyan`,n),o=Q(e.token,`yellow`,n);return[`${r} Proxy listening at ${i}`,``,`Provide this to the agent-device instance connecting:`,``,`Daemon base URL: ${a}`,`Daemon auth token: ${o}`].join(`
|
|
11
|
-
`)}function Q(e,t,n){return n?ne(e,t,{validateStream:!1}):e}function os(){return new Promise(()=>{})}const ss=async e=>{let{positionals:t}=e;return t[0]===`export`?await ls(e):cs(e)};function cs({positionals:e,flags:n}){if(e.length>1)throw new t(`INVALID_ARGS`,`replay accepts exactly one input path: replay <path>`);if(n.out!==void 0)throw new t(`INVALID_ARGS`,`replay --out is only supported with replay export.`);return!1}async function ls({positionals:e,flags:n}){us(e,n);let r=e[1];if(!r)throw new t(`INVALID_ARGS`,`replay export requires an input path.`);let i=S(r),a=j.readFileSync(i,`utf8`),s=de(a),c=yt(s.actions,{actionLines:s.actionLines,metadata:Se(a),resolveSelector:e=>o(e,et)}),l=typeof n.out==`string`?S(n.out):void 0;l&&(j.mkdirSync(k.dirname(l),{recursive:!0}),j.writeFileSync(l,c.yaml));for(let e of c.warnings)process.stderr.write(`Warning: line ${e.line}: ${e.message}\n`);return O(n,{format:`maestro`,sourcePath:i,...l?{path:l}:{yaml:c.yaml},warnings:c.warnings},()=>l??c.yaml),!0}function us(e,n){if(e.length>2)throw new t(`INVALID_ARGS`,`replay export accepts exactly one input path: replay export <file.ad>`);if(n.replayUpdate)throw new t(`INVALID_ARGS`,`replay export does not support --update.`);if(n.replayMaestro)throw new t(`INVALID_ARGS`,`replay export reads .ad files; omit --maestro.`);if(n.replayEnv?.length)throw new t(`INVALID_ARGS`,`replay export does not evaluate --env substitutions.`)}const ds=async({positionals:e,flags:t,client:r})=>{let i=await lt({client:r,command:`screenshot`,positionals:e,flags:t});return n(t.responseLevel)?(O(t,i,()=>JSON.stringify(i,null,2)),!0):(O(t,be(i),()=>i.overlayRefs?`Annotated ${i.overlayRefs.length} refs onto ${i.path}`:ms(i)),!0)},fs=async({positionals:e,flags:n,client:r})=>{if(e[0]===`snapshot`){let t=await lt({client:r,command:`diff`,positionals:e,flags:n});return O(n,t,()=>ie(t)),!0}if(e[0]!==`screenshot`)return!1;let i=n.baseline;if(!i||typeof i!=`string`)throw new t(`INVALID_ARGS`,`diff screenshot requires --baseline <path>`);let a=S(i),o=typeof n.out==`string`?S(n.out):void 0,s=e[1];if(e.length>2)throw new t(`INVALID_ARGS`,`diff screenshot accepts at most one current screenshot path`);let[{createAgentDevice:c,localCommandPolicy:l},{createLocalArtifactAdapter:u}]=await Promise.all([import(`./runtime.js`).then(e=>e.r),import(`./sdk-io.js`).then(e=>e.n)]),d=await c({backend:ps(r,n),artifacts:u(),sessions:{get:e=>({name:e}),set:()=>{}},policy:l()}).capture.diffScreenshot({session:n.session,baseline:{kind:`path`,path:a},current:s?{kind:`path`,path:S(s)}:{kind:`live`},...o?{out:{kind:`path`,path:o}}:{},threshold:gs(n.threshold),overlayRefs:n.overlayRefs,normalizeStatusBar:n.screenshotNormalizeStatusBar,surface:n.surface});return O(n,d,()=>re(d)),!0};function ps(e,t){return{platform:hs(t),captureScreenshot:async(t,n,r)=>be(await e.capture.screenshot({path:n,session:t.session,overlayRefs:r?.overlayRefs,pixelDensity:r?.pixelDensity,fullscreen:r?.fullscreen,normalizeStatusBar:r?.normalizeStatusBar,stabilize:r?.stabilize,surface:r?.surface}))}}function ms(e){if(typeof e.width!=`number`||typeof e.height!=`number`)return e.path;let t=typeof e.pixelDensity==`number`?` @${e.pixelDensity}x`:``;return`${e.path} (${e.width}x${e.height}${t})`}function hs(e){switch(e.platform){case`android`:case`linux`:case`macos`:return e.platform;default:return`ios`}}function gs(e){if(!(e==null||e===``))return Number(e)}const _s={connect:wa,disconnect:Fa,connection:Ia,auth:eo,daemon:co,device:fo,proxy:$o,replay:ss,screenshot:ds,diff:fs};async function vs(e){let t={...e.flags},n=_s[e.command];return n&&await n({...e,flags:t})?!0:Qr(e.command)?await ys({...e,command:e.command,flags:t}):!1}async function ys(e){let{runGenericClientBackedCommand:t}=await import(`./generic.js`);return await t(e)}function bs(e){return[`exec`,`--yes`,`--package`,`agent-react-devtools@0.4.0`,`--`,`agent-react-devtools`,...e]}function xs(e){return e===`ios-instance`}function Ss(e){return e[0]===`wait`&&e.includes(`--connected`)}function Cs(e,t,n){n===0||!Ss(e)||!xs(t?.leaseBackend)||process.stderr.write([`Hint: Remote iOS React DevTools connects during JavaScript startup.`,"If the app was already open before `agent-device react-devtools start`, relaunch it with `agent-device open <bundle-id> --platform ios --relaunch`, then retry `agent-device react-devtools wait --connected`.",``].join(`
|
|
12
|
-
`))}function $(e,t,n){return n||(e.push(t),``)}function ws(e){if(!e?.metroProxyBaseUrl||!Nn(e.leaseBackend))return null;let n=[],r={serverBaseUrl:$(n,`metroProxyBaseUrl`,e.metroProxyBaseUrl),bearerToken:$(n,`metroBearerToken`,e.metroBearerToken),tenantId:$(n,`tenant`,e.tenant),runId:$(n,`runId`,e.runId),leaseId:$(n,`leaseId`,e.leaseId)};if(n.length>0)throw new t(`INVALID_ARGS`,`react-devtools remote bridge requires ${n.join(`, `)}.`,{missing:n});return r}async function Ts(e,t,n){let{flags:r}=t,i=ws(r);if(!i)return n();let a=t.stateDir??process.cwd(),o=t.session??r?.session??`default`,s=r?.remoteConfig??`${i.tenantId}:${i.runId}:${i.leaseId}`;if(e[0]===`stop`)try{return await n()}finally{await Mn({projectRoot:t.cwd??process.cwd(),stateDir:a,profileKey:s,consumerKey:o})}return await jn({projectRoot:t.cwd??process.cwd(),stateDir:a,serverBaseUrl:i.serverBaseUrl,bearerToken:i.bearerToken,bridgeScope:{tenantId:i.tenantId,runId:i.runId,leaseId:i.leaseId},session:o,profileKey:s,consumerKey:o,env:t.env??process.env}),await n()}function Es(e,t){if(e[0]!==`start`)return!1;let{flags:n}=t;return n?n.leaseProvider===`limrun`&&n.leaseBackend===`android-instance`&&n.metroProxyBaseUrl===void 0&&t.configureDirectPortReverse!==void 0:!1}async function Ds(e,t={}){let n=t.cwd??process.cwd(),r=t.env??process.env,i=await Ts(e,t,async()=>(Es(e,t)&&await t.configureDirectPortReverse?.(),(await Me(`npm`,bs(e),{cwd:n,env:r,allowFailure:!0,onStdoutChunk:e=>{process.stdout.write(e)},onStderrChunk:e=>{process.stderr.write(e)}})).exitCode));return Cs(e,t.flags,i),i}async function Os(e,n){switch(e[0]){case`setup`:{ks(n.flags.json);let{setupManagedAgentBrowser:e}=await import(`./agent-browser-tool.js`).then(e=>e.t),t=await e({stateDir:n.stateDir});return As(n.flags.json,t),0}case`doctor`:{let{doctorManagedAgentBrowser:e}=await import(`./agent-browser-tool.js`).then(e=>e.t),t=await e({stateDir:n.stateDir});return js(n.flags.json,t.exitCode===0?`Web backend is healthy.`:`Web backend doctor reported issues.`,t),t.exitCode}default:throw new t(`INVALID_ARGS`,`web requires setup or doctor`)}}function ks(e){e||process.stdout.write(`Setting up managed agent-browser backend (downloads if needed)...
|
|
13
|
-
`)}function As(e,t){if(e){_({success:!0,data:{status:Ms(t)}});return}process.stdout.write(`Managed web backend installed.\nagent-browser available at: ${t.binaryPath}\n`)}function js(e,t,n){if(e){_({success:!0,data:Ns(n)});return}process.stdout.write(`${t}\n`)}function Ms(e){let{socketDir:t,...n}=e;return n}function Ns(e){let t=e.status;return Ps(t)?{...e,status:Ms(t)}:e}function Ps(e){return typeof e==`object`&&!!e&&`socketDir`in e&&`installDir`in e&&`binaryPath`in e}function Fs(e){let n;try{n=JSON.parse(e)}catch{throw new t(`INVALID_ARGS`,`Batch steps must be valid JSON.`)}if(!Array.isArray(n)||n.length===0)throw new t(`INVALID_ARGS`,`Batch steps must be a non-empty JSON array.`);return Is(n)}function Is(e){let t=!1,n=e.map((e,n)=>{if(Rs(e))return zs(e,n+1);let r=Bs(e,n+1);return t=!0,Ls(r)});return t&&process.stderr.write(`Warning: batch steps using positionals/flags are deprecated and will be removed in the next major version. Use {"command":"...","input":{...}} steps instead.
|
|
14
|
-
`),n}function Ls(e){let t=ct(e.command,e.positionals??[],Gs(e.flags));return{command:e.command,input:t,...e.runtime===void 0?{}:{runtime:e.runtime}}}function Rs(e){return c(e)&&`input`in e&&!(`positionals`in e)&&!(`flags`in e)}function zs(e,t){let n=s(e.runtime,t),{runtime:r,...i}=e;return{...i,...n===void 0?{}:{runtime:n}}}function Bs(e,n){if(!c(e))throw new t(`INVALID_ARGS`,`Invalid batch step ${n}.`);Hs(e,n);let r=Vs(e.command,n),i=Us(e.positionals,n);it(r,i??[],`Batch step ${n}`);let a=Ws(e.flags,n),o=s(e.runtime,n);return{command:r,...i===void 0?{}:{positionals:i},...a===void 0?{}:{flags:a},...o===void 0?{}:{runtime:o}}}function Vs(e,n){let r=typeof e==`string`?e.trim().toLowerCase():``;if(!r)throw new t(`INVALID_ARGS`,`Batch step ${n} requires command.`);if(Ee(r))return r;throw new t(`INVALID_ARGS`,`Batch step ${n} command is not available through command batch: ${String(e)}`)}function Hs(e,n){let r=Object.keys(e).filter(e=>![`command`,`positionals`,`flags`,`runtime`].includes(e));if(r.length>0)throw new t(`INVALID_ARGS`,`Batch step ${n} has unknown legacy field(s): ${r.join(`, `)}.`)}function Us(e,n){if(e!==void 0){if(!Array.isArray(e)||e.some(e=>typeof e!=`string`))throw new t(`INVALID_ARGS`,`Batch step ${n} positionals must contain only strings.`);return e}}function Ws(e,n){if(e!==void 0){if(!c(e))throw new t(`INVALID_ARGS`,`Batch step ${n} flags must be an object.`);return e}}function Gs(e){return{json:!1,help:!1,version:!1,...e}}function Ks(e,t={}){let n=qs(t),r={...e};return n.defaultPlatform&&r.platform===void 0&&(r.platform=n.defaultPlatform),r}function qs(e){let t=e.env??process.env,n=e.inheritedPlatform??e.configuredPlatform??Ys(t.AGENT_DEVICE_PLATFORM),r=Zs(e.configuredSession??t.AGENT_DEVICE_SESSION);return{defaultPlatform:n,lockPolicy:Js(e.policyOverrides,t,r)}}function Js(e,t,n){let r=e?.sessionLock??Xs(t.AGENT_DEVICE_SESSION_LOCK);if(r)return r;if(n)return`reject`}function Ys(e){if(e===void 0)return;let n=e.trim().toLowerCase();if(n){if(n===`ios`||n===`android`||n===`apple`)return n;throw new t(`INVALID_ARGS`,`Invalid AGENT_DEVICE_PLATFORM: ${e}. Use ios, android, or apple.`)}}function Xs(e){if(e===void 0)return;let n=e.trim().toLowerCase();if(n){if(n===`reject`||n===`strip`)return n;throw new t(`INVALID_ARGS`,`Invalid session lock mode: ${e}. Use reject or strip.`)}}function Zs(e){return typeof e==`string`&&e.trim().length>0}function Qs(e,t){let n=un(e),r=t?.env??process.env,i=t?.cwd??process.cwd(),a=$s(n.command)?sr({remoteConfig:n.flags.remoteConfig,cwd:i,env:r}):{},o=T(st({command:n.command,cwd:i,cliFlags:n.flags,env:r}),a);return{...gn(n,{strictFlags:t?.strictFlags,defaultFlags:o}),providedFlags:n.providedFlags}}function $s(e){return e!==null}const ec={sendToDaemon:ue},tc=new Set([`launchUrl`,`kind`,`metroBearerToken`,`metroKind`,`metroListenHost`,`metroNoInstallDeps`,`metroNoReuseExisting`,`metroPreparePort`,`metroProbeTimeoutMs`,`metroProjectRoot`,`metroProxyBaseUrl`,`metroPublicBaseUrl`,`metroRuntimeFile`,`metroStartupTimeoutMs`,`metroStatusHost`]),nc=new Set([`connect`,`connection`,`close`,`daemon`,`device`,`disconnect`,`metro`,`proxy`,`session`]);async function rc(e,t=ec){let n=De(),r=Fe(),i=gc(e),a=e.includes(`--json`);await Oe({session:Mc(e)??process.env.AGENT_DEVICE_SESSION??`default`,requestId:n,command:e[0],debug:i},async()=>{let{parsed:o,command:s,positionals:c}=await ac(e,{version:r,jsonRequested:a,debugEnabled:i}),l=yc(s,o.providedFlags),u=await oc(o,{command:s,positionals:c,requestId:n,debugOutputEnabled:l});ic(u.effectiveFlags);let d=null;try{if(s===`react-devtools`){await D(await sc(u,t));return}if(s===`web`){await D(await Os(c,{flags:u.effectiveFlags,stateDir:u.daemonPaths.baseDir}));return}if(ot({command:s,currentVersion:r,stateDir:u.daemonPaths.baseDir,flags:u.effectiveFlags}),await cc(u,t),ic(u.effectiveFlags),s===`cdp`){await D(await Bn(c,{flags:u.effectiveFlags,runtime:u.resolvedRuntime,cwd:process.cwd(),env:process.env}));return}d=uc(u);let e=await dc(u);await fc(u,le(lc(u),{transport:kc({command:s,flags:u.effectiveFlags,replayTestReporterRuntime:e,transport:t.sendToDaemon})}),e)}catch(e){await pc(e,u,d)}finally{d&&d()}})}function ic(e){e.daemonAuthToken&&je(e.daemonAuthToken)}async function ac(n,r){let i;try{i=Qs(n,{cwd:process.cwd(),env:process.env})}catch(t){Ne({level:`error`,phase:`cli_parse_failed`,data:{error:t instanceof Error?t.message:String(t)}});let n=e(t,{diagnosticId:Ae().diagnosticId,logPath:ke({force:!0})??void 0});return r.jsonRequested?_({success:!1,error:n}):v(n,{showDetails:r.debugEnabled}),D(1)}for(let e of i.warnings)process.stderr.write(`Warning: ${e}\n`);if(i.flags.version)return process.stdout.write(`${r.version}\n`),D(0);let a=i.command===`help`,o=i.flags.help;if(a||o){if(a&&i.positionals.length>1)return v(new t(`INVALID_ARGS`,`help accepts at most one command.`)),D(1);let e=a?i.positionals[0]:i.command;if(!e)return process.stdout.write(`${await Dn()}\n`),D(0);let n=await On(e);return n?(process.stdout.write(n),D(0)):(v(new t(`INVALID_ARGS`,_c(e))),process.stdout.write(`${await Dn()}\n`),D(1))}return i.command?{parsed:i,command:i.command,positionals:i.positionals}:(process.stdout.write(`${await Dn()}\n`),D(1))}async function oc(t,n){let i=new Set(t.providedFlags.map(e=>e.key));try{let e=qs({policyOverrides:t.flags,configuredPlatform:t.flags.platform,configuredSession:t.flags.session}),r=e.lockPolicy?{...t.flags}:Ks(t.flags,{policyOverrides:t.flags,configuredPlatform:t.flags.platform,configuredSession:t.flags.session}),a=b(r.stateDir),o=r.session??`default`,s=Sc({command:n.command,explicitFlagKeys:i,stateDir:a.baseDir,session:o,remoteConfig:r.remoteConfig,hasResolvedSession:r.session!==void 0}),c=s?Dc(r,s.flags,i):r;return{...n,binding:e,flags:r,daemonPaths:a,sessionName:o,connectionDefaults:s,explicitFlagKeys:i,effectiveFlags:c,resolvedRuntime:s?.runtime,connectionMetadata:s?.connection,parsedBatchSteps:void 0}}catch(i){let a=e(r(i),{diagnosticId:Ae().diagnosticId,logPath:ke({force:!0})??void 0});return t.flags.json?_({success:!1,error:a}):v(a,{showDetails:n.debugOutputEnabled}),D(1)}}async function sc(e,t){let{daemonAuthToken:n,...r}=e.effectiveFlags;return await Ds(e.positionals,{flags:{...r,leaseProvider:e.connectionDefaults?.connection?.leaseProvider},stateDir:e.daemonPaths.baseDir,session:e.effectiveFlags.session??e.sessionName,cwd:process.cwd(),env:process.env,configureDirectPortReverse:async()=>{let a=await t.sendToDaemon({command:p.runtime,positionals:[`port-reverse`],flags:{...r,leaseProvider:e.connectionDefaults?.connection?.leaseProvider,devicePort:8097,hostPort:8097,portReverseName:`react-devtools`},session:e.effectiveFlags.session??e.sessionName},{authToken:n});a.ok||i(a.error)}})}async function cc(e,n){if(e.command===`batch`){if(e.positionals.length>0)throw new t(`INVALID_ARGS`,`batch does not accept positional arguments.`);e.parsedBatchSteps=bc(e.flags)}if(wc(e.command)&&(e.effectiveFlags=(await ti({command:e.command,flags:e.effectiveFlags,stateDir:e.daemonPaths.baseDir,env:process.env})).flags),e.effectiveFlags.remoteConfig&&Cc(e.command)){let t=le(lc(e),{transport:Ac(n.sendToDaemon)}),r=await hr({command:e.command,flags:e.effectiveFlags,client:t,runtime:e.resolvedRuntime,positionals:e.positionals,batchSteps:e.parsedBatchSteps,forceRuntimePrepare:Oc(e.explicitFlagKeys)});e.effectiveFlags=r.flags,e.resolvedRuntime=r.runtime,e.connectionMetadata=r.connection}Tc({command:e.command,flags:e.effectiveFlags,runtime:e.resolvedRuntime,explicitFlagKeys:e.explicitFlagKeys,hadConnectionDefaults:!!e.connectionDefaults})&&process.stderr.write(`Warning: open is using explicit remote daemon or tenant flags without saved Metro runtime hints. React Native apps may launch without bundle/runtime hints; prefer connect --remote-config <path> first or pass --remote-config <path> on this command.
|
|
15
|
-
`)}function lc(e){let t=e.effectiveFlags,n=e.connectionMetadata;return{session:t.session,requestId:e.requestId,stateDir:t.stateDir,daemonBaseUrl:t.daemonBaseUrl,daemonAuthToken:t.daemonAuthToken,daemonTransport:t.daemonTransport,daemonServerMode:t.daemonServerMode,tenant:t.tenant,sessionIsolation:t.sessionIsolation,runId:t.runId,leaseId:t.leaseId,leaseBackend:t.leaseBackend,leaseProvider:n?.leaseProvider,clientId:n?.clientId,deviceKey:n?.deviceKey,providerApp:t.providerApp,providerOsVersion:t.providerOsVersion,providerProject:t.providerProject,providerBuild:t.providerBuild,providerSessionName:t.providerSessionName,providerDeviceOrientation:t.providerDeviceOrientation,providerGeoLocation:t.providerGeoLocation,providerTimezone:t.providerTimezone,providerLanguage:t.providerLanguage,providerLocale:t.providerLocale,providerNetworkProfile:t.providerNetworkProfile,providerCustomNetwork:t.providerCustomNetwork,providerNoResignApp:t.providerNoResignApp,awsProjectArn:t.awsProjectArn,awsDeviceArn:t.awsDeviceArn,awsAppArn:t.awsAppArn,awsRegion:t.awsRegion,awsInteractionMode:t.awsInteractionMode,runtime:e.resolvedRuntime,lockPolicy:e.binding.lockPolicy,lockPlatform:e.binding.defaultPlatform,cwd:process.cwd(),debug:e.debugOutputEnabled,cost:t.cost,responseLevel:t.responseLevel}}function uc(e){let t=e.effectiveFlags.daemonBaseUrl;return e.debugOutputEnabled&&!e.effectiveFlags.json&&!t?Nc(e.daemonPaths.logPath):null}async function dc(e){if(e.command!==`test`)return;let{createReplayTestReporterRuntime:t}=await import(`./reporting.js`);return t({debug:e.debugOutputEnabled,verbose:e.effectiveFlags.verbose,json:e.effectiveFlags.json,reporter:e.effectiveFlags.reporter,reportJunit:e.effectiveFlags.reportJunit})}async function fc(e,n,r){let{command:i,positionals:a,effectiveFlags:o}=e;if(i===`batch`){if(!e.parsedBatchSteps)throw new t(`INVALID_ARGS`,`batch requires --steps or --steps-file.`);let s=e.parsedBatchSteps.map((t,n)=>({...t,input:e.binding.lockPolicy&&e.flags.platform===void 0?{...t.input}:Ks(t.input,{policyOverrides:o,configuredPlatform:o.platform,configuredSession:o.session,inheritedPlatform:o.platform})}));if(await vs({command:i,positionals:a,flags:{...o,batchSteps:s},client:n,debug:e.debugOutputEnabled,replayTestReporterRuntime:r}))return}else if(i===`runtime`)throw new t(`INVALID_ARGS`,`runtime command was removed. Use connect --remote-config <path> for remote runs, or metro prepare --remote-config <path> for inspection.`);else if(await vs({command:i,positionals:a,flags:o,client:n,debug:e.debugOutputEnabled,replayTestReporterRuntime:r}))return;throw new t(`INVALID_ARGS`,vc(i))}async function pc(t,n,i){let a=r(t),o=e(a,{diagnosticId:Ae().diagnosticId,logPath:ke({force:!0})??void 0});if(n.command===`close`&&xc(a)){n.effectiveFlags.json&&_({success:!0,data:{closed:`session`,source:`no-daemon`}});return}n.effectiveFlags.json?_({success:!1,error:o}):(v(o,{showDetails:n.debugOutputEnabled}),n.debugOutputEnabled&&hc(n.daemonPaths.logPath)),i&&i(),await D(1)}const mc=64e3;function hc(e){try{if(j.existsSync(e)){let t=j.readFileSync(e,`utf8`).split(`
|
|
1
|
+
import{S as e,_ as t,v as n,w as r}from"./sdk-contracts.js";import{Tt as i,n as a}from"./version.js";import{Gn as o,f as s}from"./sdk-batch-runner.js";import{Qt as c,Yt as l,Zt as u,vt as d,yt as f}from"./prepare-kind.js";import{n as p,r as m}from"./agent-device-client.js";import{_ as h}from"./screenshot-result.js";import{S as g,x as _}from"./registry.js";import{n as v}from"./command-metadata.js";import{A as ee,L as te,M as y,N as b,P as ne,S as re,j as x}from"./sdk-android-adb.js";import{n as ie,t as ae}from"./internal/bin.js";import{i as S,n as C,t as oe}from"./command-schema.js";import{t as se}from"./update-check.js";import{n as w,r as T,t as ce}from"./cli-config.js";import{exitAfterFlush as E}from"./process-exit.js";import{D as le,E as ue,S as de,T as fe,h as pe,n as me,w as he}from"./connection-runtime.js";import{t as ge}from"./cli-grammar.js";import{i as _e}from"./auth-session.js";import D from"node:fs";import{pathToFileURL as ve}from"node:url";const O=`open <app> --relaunch`,ye={start:{command:`open`,example:O},restart:{command:`open`,example:O},touch:{command:`press`,example:`press`},input:{command:`fill`,example:`fill`},settext:{command:`fill`,example:`fill`},entertext:{command:`fill`,example:`fill`},screencap:{command:`screenshot`,example:`screenshot`},capture:{command:`screenshot`,example:`screenshot`},dismiss:{command:`keyboard`,example:`keyboard dismiss`},"get-text":{command:`get`,example:`get text`},gettext:{command:`get`,example:`get text`},get_text:{command:`get`,example:`get text`},"open-url":{command:`open`,example:`open <url>`},"close-session":{command:`close`,example:`close`}};function k(e){if(e.length<=2)return[];let t=c(),n=t.filter(t=>t.startsWith(e));if(n.length>0)return n.sort((e,t)=>e.length-t.length||e.localeCompare(t)).slice(0,3);let r=A(e),i=t.map(t=>({name:t,distance:j(e,t)})).filter(e=>e.distance<=r);if(i.length===0)return[];let a=Math.min(...i.map(e=>e.distance));return i.filter(e=>e.distance===a).sort((e,t)=>e.name.localeCompare(t.name)).slice(0,3).map(e=>e.name)}function A(e){return e.length<4?1:e.length<=6?2:3}function j(e,t){return e===t?0:e.startsWith(t)||t.startsWith(e)?Math.abs(e.length-t.length):M(e,t)}function M(e,t){let n=e.length+1,r=t.length+1,i=Array.from({length:n},()=>Array(r).fill(0));for(let e=0;e<n;e+=1)i[e][0]=e;for(let e=0;e<r;e+=1)i[0][e]=e;for(let a=1;a<n;a+=1)for(let n=1;n<r;n+=1){let r=e[a-1]===t[n-1]?0:1;i[a][n]=Math.min(i[a-1][n]+1,i[a][n-1]+1,i[a-1][n-1]+r)}return i[n-1][r-1]}function N(e){let t=e.toLowerCase(),n=ye[t]?.example;if(n)return n;let r=k(t);if(r.length!==0)return r.length===1?r[0]:`one of: ${r.join(`, `)}`}const P=new Set([`--bundle-id`,`--bundleid`,`--bundle`,`--package`,`--package-name`,`--packagename`,`--app-id`,`--appid`,`--pkg`]),be=new Set([`--session-locked`,`--session-lock-conflicts`]);function xe(e){return P.has(e.toLowerCase())?`Unknown flag: ${e}. The app or bundle id is a positional argument, e.g. ${O}.`:be.has(e.toLowerCase())?`Unknown flag: ${e}. Use --session-lock reject|strip instead.`:e.toLowerCase()===i.cliToken?`Unknown flag: ${e}. ${i.migration.screenshot}. ${i.migration.record}.`:`Unknown flag: ${e}`}function F(e){let n={json:!1,help:!1,version:!1},r=null,i=null,a=[],o=[],s=[],c=!0;for(let o=0;o<e.length;o+=1){let l=e[o];if(c&&l===`--`){c=!1;continue}if(!c){r?a.push(l):(i=l,r=B(l));continue}if(Te(r)){a.push(l);continue}let u=l.startsWith(`--`),d=l.startsWith(`-`)&&l.length>1;if(!u&&!d){r?a.push(l):(i=l,r=B(l));continue}let[f,p]=u?I(l):[l,void 0];if(Ce(r,f))continue;let m=Ee(f,r);if(we(r,m)){a.push(l);continue}if(!m){if(je(r,a,l)){r?a.push(l):r=l;continue}throw new t(`INVALID_ARGS`,xe(f))}let h=ke(m,f,p,e[o+1]);h.consumeNext&&(o+=1);let g=n[m.key];if(m.multiple){let e=Array.isArray(g)?[...g,h.value]:g===void 0?[h.value]:[g,h.value];n[m.key]=e}else n[m.key]=h.value;s.push({key:m.key,token:f})}return Se(i,n),{command:r,positionals:a,flags:n,warnings:o,providedFlags:s}}function Se(e,t){if(e)for(let n of ae(e)?.impliedFlags??[])t[n]=!0}function Ce(e,t){return t===`-c`&&(e===`snapshot`||e===`diff`)}function we(e,t){return e===`react-devtools`?t?!w(t.key,e):!0:!1}function Te(e){return e===`cdp`}function Ee(e,t){let n=g().filter(t=>t.names.includes(e));if(n.length<=1)return n[0]??_(e);if(t){let e=n.find(e=>w(e.key,t));if(e)return e}return _(e)}function De(e,n){let r=n?.strictFlags??!0,i=[...e.warnings],a=T({json:!1,help:!1,version:!1},n?.defaultFlags??{});if(T(a,e.flags),e.command&&!u(e.command)&&!a.help){let n=N(e.command);throw new t(`INVALID_ARGS`,n?`Unknown command: ${e.command}. Did you mean ${n}?`:`Unknown command: ${e.command}`)}let o=e.providedFlags.filter(t=>!w(t.key,e.command));if(o.length>0){let n=o.map(e=>e.token),s=Pe(e.command,n);if(r)throw new t(`INVALID_ARGS`,s);i.push(s);for(let e of o)delete a[e.key]}for(let t of Object.keys(a))a[t]!==void 0&&(w(t,e.command)||delete a[t]);Oe(e),oe(e.command,a);let s=Ne({command:e.command,positionals:e.positionals,flags:a,warnings:i});if(C(s.command,s.positionals),s.command===`batch`&&+!!a.steps+ +!!a.stepsFile!=1)throw new t(`INVALID_ARGS`,`batch requires exactly one step source: --steps or --steps-file.`);return s}function Oe(e){if(e.command!==`back`)return;let n=e.providedFlags.filter(e=>e.key===`backMode`);if(!(new Set(n.map(e=>e.token)).size<=1))throw new t(`INVALID_ARGS`,`back accepts only one explicit mode flag: use either --in-app or --system.`)}function I(e){let t=e.indexOf(`=`);return t===-1?[e,void 0]:[e.slice(0,t),e.slice(t+1)]}function ke(e,n,r,i){if(e.setValue!==void 0){if(r!==void 0)throw new t(`INVALID_ARGS`,`Flag ${n} does not take a value.`);return{value:e.setValue,consumeNext:!1}}if(e.type===`boolean`){if(r!==void 0)throw new t(`INVALID_ARGS`,`Flag ${n} does not take a value.`);return{value:!0,consumeNext:!1}}if(e.type===`booleanOrString`){if(r!==void 0){if(r.trim().length===0)throw new t(`INVALID_ARGS`,`Flag ${n} requires a non-empty value when provided.`);return{value:r,consumeNext:!1}}return i===void 0||R(i)?{value:!0,consumeNext:!1}:Ae(i)?{value:i,consumeNext:!0}:{value:!0,consumeNext:!1}}let a=r??i;if(a===void 0||r===void 0&&R(a))throw new t(`INVALID_ARGS`,`Flag ${n} requires a value.`);if(e.type===`string`)return{value:a,consumeNext:r===void 0};if(e.type===`enum`){if(!e.enumValues?.includes(a))throw new t(`INVALID_ARGS`,`Invalid ${L(n)}: ${a}`);return{value:a,consumeNext:r===void 0}}let o=Number(a);if(!Number.isFinite(o)||typeof e.min==`number`&&o<e.min||typeof e.max==`number`&&o>e.max)throw new t(`INVALID_ARGS`,`Invalid ${L(n)}: ${a}`);return{value:e.type===`int`?Math.floor(o):o,consumeNext:r===void 0}}function L(e){return e.replace(/^-+/,``)}function R(e){if(!e.startsWith(`-`)||e===`-`)return!1;let[t]=e.startsWith(`--`)?I(e):[e,void 0];return _(t)!==void 0}function Ae(e){let t=e.trim();return!t||/^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//.test(t)?!1:!!(t.startsWith(`./`)||t.startsWith(`../`)||t.startsWith(`~/`)||t.startsWith(`/`)||t.includes(`/`)||t.includes(`\\`))}function je(e,t,n){if(!Me(n)||!e)return!1;let r=S(e);if(!r||r.allowsExtraPositionals)return!0;let i=r.positionalArgs??[];return i.length===0?!1:t.length<i.length?!0:i.some(e=>e.includes(`?`))}function Me(e){return/^-\d+(\.\d+)?$/.test(e)}function Ne(e){if(e.flags.help)return e;if(e.command===`snapshot`&&e.flags.snapshotDiff){let{snapshotDiff:t,...n}=e.flags;return{command:`diff`,positionals:[`snapshot`,...e.positionals],flags:n,warnings:e.warnings}}return e}function Pe(e,t){return e?t.length===1?`Flag ${t[0]} is not supported for command ${e}.`:`Flags ${t.join(`, `)} are not supported for command ${e}.`:t.length===1?`Flag ${t[0]} requires a command that supports it.`:`Flags ${t.join(`, `)} require a command that supports them.`}async function z(){let{buildUsageText:e}=await import(`./cli-help.js`);return e()}async function Fe(e){let{buildCommandUsageText:t}=await import(`./cli-help.js`);return t(B(e))}function B(e){if(e.toLowerCase()===`rotate`)throw new t(`INVALID_ARGS`,`rotate was renamed to orientation; for the two-finger gesture use: gesture rotate`);return ie(e)}function Ie(e){return v(e)}const Le={connect:async()=>(await import(`./connection.js`)).connectCommand,disconnect:async()=>(await import(`./connection.js`)).disconnectCommand,connection:async()=>(await import(`./connection.js`)).connectionCommand,auth:async()=>(await import(`./auth.js`)).authCommand,daemon:async()=>(await import(`./daemon.js`)).daemonCommand,device:async()=>(await import(`./device2.js`)).deviceCommand,proxy:async()=>(await import(`./proxy.js`)).proxyCommand,replay:async()=>(await import(`./replay.js`)).replayCommand,screenshot:async()=>(await import(`./screenshot.js`)).screenshotCommand,diff:async()=>(await import(`./screenshot.js`)).diffCommand};async function V(e){let t={...e.flags},n=Le[e.command];return n&&await(await n())({...e,flags:t})?!0:Ie(e.command)?await Re({...e,command:e.command,flags:t}):!1}async function Re(e){let{runGenericClientBackedCommand:t}=await import(`./generic.js`);return await t(e)}function ze(e){return[`exec`,`--yes`,`--package`,`agent-react-devtools@0.4.0`,`--`,`agent-react-devtools`,...e]}function Be(e){return e===`ios-instance`}function Ve(e){return e[0]===`wait`&&e.includes(`--connected`)}function He(e,t,n){n===0||!Ve(e)||!Be(t?.leaseBackend)||process.stderr.write([`Hint: Remote iOS React DevTools connects during JavaScript startup.`,"If the app was already open before `agent-device react-devtools start`, relaunch it with `agent-device open <bundle-id> --platform ios --relaunch`, then retry `agent-device react-devtools wait --connected`.",``].join(`
|
|
2
|
+
`))}function H(e,t,n){return n||(e.push(t),``)}function Ue(e){if(!e?.metroProxyBaseUrl||!fe(e.leaseBackend))return null;let n=[],r={serverBaseUrl:H(n,`metroProxyBaseUrl`,e.metroProxyBaseUrl),bearerToken:H(n,`metroBearerToken`,e.metroBearerToken),tenantId:H(n,`tenant`,e.tenant),runId:H(n,`runId`,e.runId),leaseId:H(n,`leaseId`,e.leaseId)};if(n.length>0)throw new t(`INVALID_ARGS`,`react-devtools remote bridge requires ${n.join(`, `)}.`,{missing:n});return r}async function We(e,t,n){let{flags:r}=t,i=Ue(r);if(!i)return n();let a=t.stateDir??process.cwd(),o=t.session??r?.session??`default`,s=r?.remoteConfig??`${i.tenantId}:${i.runId}:${i.leaseId}`;if(e[0]===`stop`)try{return await n()}finally{await le({projectRoot:t.cwd??process.cwd(),stateDir:a,profileKey:s,consumerKey:o})}return await ue({projectRoot:t.cwd??process.cwd(),stateDir:a,serverBaseUrl:i.serverBaseUrl,bearerToken:i.bearerToken,bridgeScope:{tenantId:i.tenantId,runId:i.runId,leaseId:i.leaseId},session:o,profileKey:s,consumerKey:o,env:t.env??process.env}),await n()}function Ge(e,t){if(e[0]!==`start`)return!1;let{flags:n}=t;return n?n.leaseProvider===`limrun`&&n.leaseBackend===`android-instance`&&n.metroProxyBaseUrl===void 0&&t.configureDirectPortReverse!==void 0:!1}async function Ke(e,t={}){let n=t.cwd??process.cwd(),r=t.env??process.env,i=await We(e,t,async()=>(Ge(e,t)&&await t.configureDirectPortReverse?.(),(await re(`npm`,ze(e),{cwd:n,env:r,allowFailure:!0,onStdoutChunk:e=>{process.stdout.write(e)},onStderrChunk:e=>{process.stderr.write(e)}})).exitCode));return He(e,t.flags,i),i}async function qe(e,n){switch(e[0]){case`setup`:{Je(n.flags.json);let{setupManagedAgentBrowser:e}=await import(`./agent-browser-tool.js`).then(e=>e.t),t=await e({stateDir:n.stateDir});return Ye(n.flags.json,t),0}case`doctor`:{let{doctorManagedAgentBrowser:e}=await import(`./agent-browser-tool.js`).then(e=>e.t),t=await e({stateDir:n.stateDir});return Xe(n.flags.json,t.exitCode===0?`Web backend is healthy.`:`Web backend doctor reported issues.`,t),t.exitCode}default:throw new t(`INVALID_ARGS`,`web requires setup or doctor`)}}function Je(e){e||process.stdout.write(`Setting up managed agent-browser backend (downloads if needed)...
|
|
3
|
+
`)}function Ye(e,t){if(e){f({success:!0,data:{status:U(t)}});return}process.stdout.write(`Managed web backend installed.\nagent-browser available at: ${t.binaryPath}\n`)}function Xe(e,t,n){if(e){f({success:!0,data:Ze(n)});return}process.stdout.write(`${t}\n`)}function U(e){let{socketDir:t,...n}=e;return n}function Ze(e){let t=e.status;return Qe(t)?{...e,status:U(t)}:e}function Qe(e){return typeof e==`object`&&!!e&&`socketDir`in e&&`installDir`in e&&`binaryPath`in e}function $e(e){let n;try{n=JSON.parse(e)}catch{throw new t(`INVALID_ARGS`,`Batch steps must be valid JSON.`)}if(!Array.isArray(n)||n.length===0)throw new t(`INVALID_ARGS`,`Batch steps must be a non-empty JSON array.`);return et(n)}function et(e){let t=!1,n=e.map((e,n)=>{if(nt(e))return rt(e,n+1);let r=it(e,n+1);return t=!0,tt(r)});return t&&process.stderr.write(`Warning: batch steps using positionals/flags are deprecated and will be removed in the next major version. Use {"command":"...","input":{...}} steps instead.
|
|
4
|
+
`),n}function tt(e){let t=ge(e.command,e.positionals??[],lt(e.flags));return{command:e.command,input:t,...e.runtime===void 0?{}:{runtime:e.runtime}}}function nt(e){return o(e)&&`input`in e&&!(`positionals`in e)&&!(`flags`in e)}function rt(e,t){let n=s(e.runtime,t),{runtime:r,...i}=e;return{...i,...n===void 0?{}:{runtime:n}}}function it(e,n){if(!o(e))throw new t(`INVALID_ARGS`,`Invalid batch step ${n}.`);ot(e,n);let r=at(e.command,n),i=st(e.positionals,n);C(r,i??[],`Batch step ${n}`);let a=ct(e.flags,n),c=s(e.runtime,n);return{command:r,...i===void 0?{}:{positionals:i},...a===void 0?{}:{flags:a},...c===void 0?{}:{runtime:c}}}function at(e,n){let r=typeof e==`string`?e.trim().toLowerCase():``;if(!r)throw new t(`INVALID_ARGS`,`Batch step ${n} requires command.`);if(v(r))return r;throw new t(`INVALID_ARGS`,`Batch step ${n} command is not available through command batch: ${String(e)}`)}function ot(e,n){let r=Object.keys(e).filter(e=>![`command`,`positionals`,`flags`,`runtime`].includes(e));if(r.length>0)throw new t(`INVALID_ARGS`,`Batch step ${n} has unknown legacy field(s): ${r.join(`, `)}.`)}function st(e,n){if(e!==void 0){if(!Array.isArray(e)||e.some(e=>typeof e!=`string`))throw new t(`INVALID_ARGS`,`Batch step ${n} positionals must contain only strings.`);return e}}function ct(e,n){if(e!==void 0){if(!o(e))throw new t(`INVALID_ARGS`,`Batch step ${n} flags must be an object.`);return e}}function lt(e){return{json:!1,help:!1,version:!1,...e}}function W(e,t={}){let n=G(t),r={...e};return n.defaultPlatform&&r.platform===void 0&&(r.platform=n.defaultPlatform),r}function G(e){let t=e.env??process.env,n=e.inheritedPlatform??e.configuredPlatform??dt(t.AGENT_DEVICE_PLATFORM),r=pt(e.configuredSession??t.AGENT_DEVICE_SESSION);return{defaultPlatform:n,lockPolicy:ut(e.policyOverrides,t,r)}}function ut(e,t,n){let r=e?.sessionLock??ft(t.AGENT_DEVICE_SESSION_LOCK);if(r)return r;if(n)return`reject`}function dt(e){if(e===void 0)return;let n=e.trim().toLowerCase();if(n){if(n===`ios`||n===`android`||n===`apple`)return n;throw new t(`INVALID_ARGS`,`Invalid AGENT_DEVICE_PLATFORM: ${e}. Use ios, android, or apple.`)}}function ft(e){if(e===void 0)return;let n=e.trim().toLowerCase();if(n){if(n===`reject`||n===`strip`)return n;throw new t(`INVALID_ARGS`,`Invalid session lock mode: ${e}. Use reject or strip.`)}}function pt(e){return typeof e==`string`&&e.trim().length>0}function mt(e,t){let n=F(e),r=t?.env??process.env,i=t?.cwd??process.cwd(),a=ht(n.command)?pe({remoteConfig:n.flags.remoteConfig,cwd:i,env:r}):{},o=T(ce({command:n.command,cwd:i,cliFlags:n.flags,env:r}),a);return{...De(n,{strictFlags:t?.strictFlags,defaultFlags:o}),providedFlags:n.providedFlags}}function ht(e){return e!==null}const gt={sendToDaemon:m},_t=new Set([`launchUrl`,`kind`,`metroBearerToken`,`metroKind`,`metroListenHost`,`metroNoInstallDeps`,`metroNoReuseExisting`,`metroPreparePort`,`metroProbeTimeoutMs`,`metroProjectRoot`,`metroProxyBaseUrl`,`metroPublicBaseUrl`,`metroRuntimeFile`,`metroStartupTimeoutMs`,`metroStatusHost`]),vt=new Set([`connect`,`connection`,`close`,`daemon`,`device`,`disconnect`,`metro`,`proxy`,`session`]);async function K(e,t=gt){let n=ee(),r=a(),i=Ot(e),o=e.includes(`--json`);await te({session:Bt(e)??process.env.AGENT_DEVICE_SESSION??`default`,requestId:n,command:e[0],debug:i},async()=>{let{parsed:a,command:s,positionals:c}=await yt(e,{version:r,jsonRequested:o,debugEnabled:i}),l=Z(s,a.providedFlags),u=await bt(a,{command:s,positionals:c,requestId:n,debugOutputEnabled:l});q(u.effectiveFlags);let d=null;try{if(s===`react-devtools`){await E(await xt(u,t));return}if(s===`web`){await E(await qe(c,{flags:u.effectiveFlags,stateDir:u.daemonPaths.baseDir}));return}if(se({command:s,currentVersion:r,stateDir:u.daemonPaths.baseDir,flags:u.effectiveFlags}),await St(u,t),q(u.effectiveFlags),s===`cdp`){await E(await he(c,{flags:u.effectiveFlags,runtime:u.resolvedRuntime,cwd:process.cwd(),env:process.env}));return}d=Ct(u);let e=await wt(u);await Tt(u,p(J(u),{transport:zt({command:s,flags:u.effectiveFlags,replayTestReporterRuntime:e,transport:t.sendToDaemon})}),e)}catch(e){await Et(e,u,d)}finally{d&&d()}})}function q(e){e.daemonAuthToken&&ne(e.daemonAuthToken)}async function yt(n,r){let i;try{i=mt(n,{cwd:process.cwd(),env:process.env})}catch(t){x({level:`error`,phase:`cli_parse_failed`,data:{error:t instanceof Error?t.message:String(t)}});let n=e(t,{diagnosticId:b().diagnosticId,logPath:y({force:!0})??void 0});return r.jsonRequested?f({success:!1,error:n}):d(n,{showDetails:r.debugEnabled}),E(1)}for(let e of i.warnings)process.stderr.write(`Warning: ${e}\n`);if(i.flags.version)return process.stdout.write(`${r.version}\n`),E(0);let a=i.command===`help`,o=i.flags.help;if(a||o){if(a&&i.positionals.length>1)return d(new t(`INVALID_ARGS`,`help accepts at most one command.`)),E(1);let e=a?i.positionals[0]:i.command;if(!e)return process.stdout.write(`${await z()}\n`),E(0);let n=await Fe(e);return n?(process.stdout.write(n),E(0)):(d(new t(`INVALID_ARGS`,kt(e))),process.stdout.write(`${await z()}\n`),E(1))}return i.command?{parsed:i,command:i.command,positionals:i.positionals}:(process.stdout.write(`${await z()}\n`),E(1))}async function bt(t,r){let i=new Set(t.providedFlags.map(e=>e.key));try{let e=G({policyOverrides:t.flags,configuredPlatform:t.flags.platform,configuredSession:t.flags.session}),n=e.lockPolicy?{...t.flags}:W(t.flags,{policyOverrides:t.flags,configuredPlatform:t.flags.platform,configuredSession:t.flags.session}),a=h(n.stateDir),o=n.session??`default`,s=Mt({command:r.command,explicitFlagKeys:i,stateDir:a.baseDir,session:o,remoteConfig:n.remoteConfig,hasResolvedSession:n.session!==void 0}),c=s?Lt(n,s.flags,i):n;return{...r,binding:e,flags:n,daemonPaths:a,sessionName:o,connectionDefaults:s,explicitFlagKeys:i,effectiveFlags:c,resolvedRuntime:s?.runtime,connectionMetadata:s?.connection,parsedBatchSteps:void 0}}catch(i){let a=e(n(i),{diagnosticId:b().diagnosticId,logPath:y({force:!0})??void 0});return t.flags.json?f({success:!1,error:a}):d(a,{showDetails:r.debugOutputEnabled}),E(1)}}async function xt(e,t){let{daemonAuthToken:n,...i}=e.effectiveFlags;return await Ke(e.positionals,{flags:{...i,leaseProvider:e.connectionDefaults?.connection?.leaseProvider},stateDir:e.daemonPaths.baseDir,session:e.effectiveFlags.session??e.sessionName,cwd:process.cwd(),env:process.env,configureDirectPortReverse:async()=>{let a=await t.sendToDaemon({command:l.runtime,positionals:[`port-reverse`],flags:{...i,leaseProvider:e.connectionDefaults?.connection?.leaseProvider,devicePort:8097,hostPort:8097,portReverseName:`react-devtools`},session:e.effectiveFlags.session??e.sessionName},{authToken:n});a.ok||r(a.error)}})}async function St(e,n){if(e.command===`batch`){if(e.positionals.length>0)throw new t(`INVALID_ARGS`,`batch does not accept positional arguments.`);e.parsedBatchSteps=At(e.flags)}if(Pt(e.command)&&(e.effectiveFlags=(await _e({command:e.command,flags:e.effectiveFlags,stateDir:e.daemonPaths.baseDir,env:process.env})).flags),e.effectiveFlags.remoteConfig&&Nt(e.command)){let t=p(J(e),{transport:Q(n.sendToDaemon)}),r=await me({command:e.command,flags:e.effectiveFlags,client:t,runtime:e.resolvedRuntime,positionals:e.positionals,batchSteps:e.parsedBatchSteps,forceRuntimePrepare:Rt(e.explicitFlagKeys)});e.effectiveFlags=r.flags,e.resolvedRuntime=r.runtime,e.connectionMetadata=r.connection}Ft({command:e.command,flags:e.effectiveFlags,runtime:e.resolvedRuntime,explicitFlagKeys:e.explicitFlagKeys,hadConnectionDefaults:!!e.connectionDefaults})&&process.stderr.write(`Warning: open is using explicit remote daemon or tenant flags without saved Metro runtime hints. React Native apps may launch without bundle/runtime hints; prefer connect --remote-config <path> first or pass --remote-config <path> on this command.
|
|
5
|
+
`)}function J(e){let t=e.effectiveFlags,n=e.connectionMetadata;return{session:t.session,requestId:e.requestId,stateDir:t.stateDir,daemonBaseUrl:t.daemonBaseUrl,daemonAuthToken:t.daemonAuthToken,daemonTransport:t.daemonTransport,daemonServerMode:t.daemonServerMode,tenant:t.tenant,sessionIsolation:t.sessionIsolation,runId:t.runId,leaseId:t.leaseId,leaseBackend:t.leaseBackend,leaseProvider:n?.leaseProvider,clientId:n?.clientId,deviceKey:n?.deviceKey,providerApp:t.providerApp,providerOsVersion:t.providerOsVersion,providerProject:t.providerProject,providerBuild:t.providerBuild,providerSessionName:t.providerSessionName,providerDeviceOrientation:t.providerDeviceOrientation,providerGeoLocation:t.providerGeoLocation,providerTimezone:t.providerTimezone,providerLanguage:t.providerLanguage,providerLocale:t.providerLocale,providerNetworkProfile:t.providerNetworkProfile,providerCustomNetwork:t.providerCustomNetwork,providerNoResignApp:t.providerNoResignApp,awsProjectArn:t.awsProjectArn,awsDeviceArn:t.awsDeviceArn,awsAppArn:t.awsAppArn,awsRegion:t.awsRegion,awsInteractionMode:t.awsInteractionMode,runtime:e.resolvedRuntime,lockPolicy:e.binding.lockPolicy,lockPlatform:e.binding.defaultPlatform,cwd:process.cwd(),debug:e.debugOutputEnabled,cost:t.cost,responseLevel:t.responseLevel}}function Ct(e){let t=e.effectiveFlags.daemonBaseUrl;return e.debugOutputEnabled&&!e.effectiveFlags.json&&!t?Vt(e.daemonPaths.logPath):null}async function wt(e){if(e.command!==`test`)return;let{createReplayTestReporterRuntime:t}=await import(`./reporting.js`);return t({debug:e.debugOutputEnabled,verbose:e.effectiveFlags.verbose,json:e.effectiveFlags.json,reporter:e.effectiveFlags.reporter,reportJunit:e.effectiveFlags.reportJunit})}async function Tt(e,n,r){let{command:i,positionals:a,effectiveFlags:o}=e;if(i===`batch`){if(!e.parsedBatchSteps)throw new t(`INVALID_ARGS`,`batch requires --steps or --steps-file.`);let s=e.parsedBatchSteps.map((t,n)=>({...t,input:e.binding.lockPolicy&&e.flags.platform===void 0?{...t.input}:W(t.input,{policyOverrides:o,configuredPlatform:o.platform,configuredSession:o.session,inheritedPlatform:o.platform})}));if(await V({command:i,positionals:a,flags:{...o,batchSteps:s},client:n,debug:e.debugOutputEnabled,replayTestReporterRuntime:r}))return}else if(i===`runtime`)throw new t(`INVALID_ARGS`,`runtime command was removed. Use connect --remote-config <path> for remote runs, or metro prepare --remote-config <path> for inspection.`);else if(await V({command:i,positionals:a,flags:o,client:n,debug:e.debugOutputEnabled,replayTestReporterRuntime:r}))return;throw new t(`INVALID_ARGS`,X(i))}async function Et(t,r,i){let a=n(t),o=e(a,{diagnosticId:b().diagnosticId,logPath:y({force:!0})??void 0});if(r.command===`close`&&jt(a)){r.effectiveFlags.json&&f({success:!0,data:{closed:`session`,source:`no-daemon`}});return}r.effectiveFlags.json?f({success:!1,error:o}):(d(o,{showDetails:r.debugOutputEnabled}),r.debugOutputEnabled&&Dt(r.daemonPaths.logPath)),i&&i(),await E(1)}const Y=64e3;function Dt(e){try{if(D.existsSync(e)){let t=D.readFileSync(e,`utf8`).split(`
|
|
16
6
|
`),n=t.slice(Math.max(0,t.length-200)).join(`
|
|
17
|
-
`);n.length>
|
|
7
|
+
`);n.length>Y&&(n=n.slice(n.length-Y)),n.trim().length>0&&process.stderr.write(`\n[daemon log]\n${n}\n`)}}catch{}}function Ot(e){try{let t=F(e);return Z(t.command??``,t.providedFlags)}catch{return e.includes(`--debug`)||e.includes(`-v`)||e.includes(`--verbose`)}}function kt(e){let t=N(e);return t?`Unknown command: ${e}. Did you mean ${t}?`:`Unknown command: ${e}`}function X(e){return u(e)?(x({level:`error`,phase:`cli_known_command_unhandled`,data:{command:e}}),`Command is registered but no CLI handler accepted it: ${e}`):`Unknown command: ${e}`}function Z(e,t){return t.some(t=>t.key===`verbose`&&(t.token===`--debug`||t.token===`-v`||e!==`test`))}function At(e){let n=``;if(e.steps)n=e.steps;else if(e.stepsFile)try{n=D.readFileSync(e.stepsFile,`utf8`)}catch(n){let r=n instanceof Error?n.message:String(n);throw new t(`INVALID_ARGS`,`Failed to read --steps-file ${e.stepsFile}: ${r}`)}return $e(n)}function jt(e){return e.code===`COMMAND_FAILED`?e.details?.kind===`daemon_startup_failed`?!0:e.message.toLowerCase().includes(`failed to start daemon`)?typeof e.details?.infoPath==`string`||typeof e.details?.lockPath==`string`:!1:!1}function Mt(e){return e.command===`connect`||e.command===`connection`||e.command===`daemon`||e.command===`proxy`?null:de({stateDir:e.stateDir,session:e.session,remoteConfig:e.remoteConfig,cwd:process.cwd(),env:process.env,allowActiveFallback:!e.explicitFlagKeys.has(`session`)&&(!e.remoteConfig||e.command===`disconnect`||!e.hasResolvedSession),validateRemoteConfigHash:e.command!==`disconnect`})}function Nt(e){return!vt.has(e)}function Pt(e){return e!==`auth`&&e!==`connection`&&e!==`daemon`&&e!==`device`&&e!==`proxy`}function Ft(e){return e.command!==`open`||e.runtime||e.flags.bundleUrl||e.flags.metroHost||e.flags.metroPort||e.flags.remoteConfig||e.hadConnectionDefaults?!1:It(e.explicitFlagKeys)}function It(e){return e.has(`daemonBaseUrl`)||e.has(`daemonTransport`)||e.has(`tenant`)||e.has(`sessionIsolation`)||e.has(`runId`)||e.has(`leaseId`)||e.has(`leaseBackend`)}function Lt(e,t,n){let r={...e};for(let[e,i]of Object.entries(t))i!==void 0&&(n.has(e)||(r[e]=i));return r}function Rt(e){for(let t of _t)if(e.has(t))return!0;return!1}function zt(e){let{command:t,flags:n,replayTestReporterRuntime:r,transport:i}=e;return n.json?Q(i):async(e,n)=>{let a=t===`test`&&r?{...n,onProgress:r.onProgress}:n;return await $(i,{...e,meta:{...e.meta,requestProgress:t===`test`?`replay-test`:`command`}},a)}}function Q(e){return async(t,n)=>await $(e,t,n)}async function $(e,t,n){return await e(t,n)}function Bt(e){for(let t=0;t<e.length;t+=1){let n=e[t];if(n.startsWith(`--session=`)){let e=n.slice(10).trim();return e.length>0?e:null}if(n===`--session`){let n=e[t+1]?.trim();return n&&!n.startsWith(`-`)?n:null}}return null}ve(process.argv[1]??``).href===import.meta.url&&K(process.argv.slice(2)).catch(async t=>{d(e(n(t)),{showDetails:!0}),await E(1)});function Vt(e){try{let t=D.existsSync(e)?D.statSync(e).size:0,n=!1,r=setInterval(()=>{if(!n&&D.existsSync(e))try{let n=D.statSync(e);if(n.size<t&&(t=0),n.size<=t)return;let r=D.openSync(e,`r`);try{let e=Buffer.alloc(n.size-t);D.readSync(r,e,0,e.length,t),t=n.size,e.length>0&&process.stdout.write(e.toString(`utf8`))}finally{D.closeSync(r)}}catch{}},200);return()=>{n=!0,clearInterval(r)}}catch{return null}}export{K as runCli};
|
package/dist/src/client-metro.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{_ as e,v as t}from"./sdk-contracts.js";import{C as n,b as r}from"./sdk-android-adb.js";import{n as i}from"./path-resolution.js";import{t as a}from"./timeouts.js";import{a as o,n as s,o as c,u as l}from"./host-process.js";import{a as u,c as d,d as f,f as ee,g as te,h as p,i as ne,l as re,m as ie,n as m,o as h,p as g,s as ae,t as oe,u as se}from"./url.js";import{a as ce,i as le,t as ue}from"./runtime-transport.js";import _ from"node:path";import{createHash as de}from"node:crypto";import v from"node:fs";import{fileURLToPath as fe}from"node:url";const y=`companion-tunnel`;function b(e){return de(`sha256`).update(e).digest(`hex`)}function x(e){return e?.trim()?e.trim():void 0}function pe(e){if(!e||typeof e!=`object`||Array.isArray(e))return;let t=e;if(!(typeof t.tenantId!=`string`||typeof t.runId!=`string`||typeof t.leaseId!=`string`))return{tenantId:t.tenantId,runId:t.runId,leaseId:t.leaseId}}function me(e,t){return e.tenantId===t.tenantId&&e.runId===t.runId&&e.leaseId===t.leaseId}function S(e,t,n,r){let i=r??_.join(e,`.agent-device`);if(!n)return{statePath:_.join(i,`${t.slug}.json`),logPath:_.join(i,`${t.slug}.log`)};let a=b(n).slice(0,12),o=_.join(i,t.slug);return{statePath:_.join(o,`${t.slug}-${a}.json`),logPath:_.join(o,`${t.slug}-${a}.log`)}}function C(e){try{let t=JSON.parse(v.readFileSync(e,`utf8`));if(!Number.isInteger(t.pid)||Number(t.pid)<=0||typeof t.serverBaseUrl!=`string`||typeof t.localBaseUrl!=`string`||typeof t.tokenHash!=`string`||t.tokenHash.length===0)return null;let n=Array.isArray(t.consumers)?t.consumers.filter(e=>typeof e==`string`&&e.length>0):[];return{pid:Number(t.pid),startTime:typeof t.startTime==`string`?t.startTime:void 0,command:typeof t.command==`string`?t.command:void 0,serverBaseUrl:t.serverBaseUrl,localBaseUrl:t.localBaseUrl,launchUrl:x(typeof t.launchUrl==`string`?t.launchUrl:void 0),registerPath:x(typeof t.registerPath==`string`?t.registerPath:void 0),unregisterPath:x(typeof t.unregisterPath==`string`?t.unregisterPath:void 0),devicePort:Number.isInteger(t.devicePort)?Number(t.devicePort):void 0,session:x(typeof t.session==`string`?t.session:void 0),bridgeScope:pe(t.bridgeScope),tokenHash:t.tokenHash,consumers:n}}catch{return null}}function w(e,t){v.mkdirSync(_.dirname(e),{recursive:!0}),v.writeFileSync(e,`${JSON.stringify(t,null,2)}\n`,`utf8`)}function he(e){v.mkdirSync(_.dirname(e),{recursive:!0}),v.closeSync(v.openSync(e,`a`))}function ge(e){try{v.unlinkSync(e)}catch{}}function _e(e){try{v.unlinkSync(e)}catch{}}function T(e){try{v.readdirSync(e).length===0&&v.rmdirSync(e)}catch{}}function E(e,t){let n=_.dirname(e.statePath),r=_.dirname(e.logPath);ge(e.statePath),_e(e.logPath),T(n),r!==n&&T(r),_.basename(n)===t.slug&&T(_.dirname(n))}function D(e,t){return e.includes(t.runArg)}function ve(e,t){if(!s(e.pid))return!1;if(e.startTime){let t=c(e.pid);if(!t||t!==e.startTime)return!1}let n=o(e.pid);return!n||!D(n,t.definition)||!e.bridgeScope?!1:e.serverBaseUrl===m(t.serverBaseUrl)&&e.localBaseUrl===m(t.localBaseUrl)&&e.launchUrl===x(t.launchUrl)&&e.registerPath===x(t.registerPath)&&e.unregisterPath===x(t.unregisterPath)&&e.devicePort===t.devicePort&&e.session===x(t.session)&&me(e.bridgeScope,t.bridgeScope)&&e.tokenHash===b(t.bearerToken)}function O(e){return x(e.consumerKey)??x(e.profileKey)??null}function k(e,t){return!t||e.consumers.includes(t)?e:{...e,consumers:[...e.consumers,t]}}function ye(e,t){return t?{...e,consumers:e.consumers.filter(e=>e!==t)}:{...e,consumers:[]}}async function A(e,t){if(!s(e.pid))return;let n=o(e.pid);if(!(!n||!D(n,t))){try{process.kill(e.pid,`SIGTERM`)}catch(e){let t=e.code;if(t===`ESRCH`||t===`EPERM`)return;throw e}if(!await l(e.pid,1e3)){try{process.kill(e.pid,`SIGKILL`)}catch(e){let t=e.code;if(t===`ESRCH`||t===`EPERM`)return;throw e}await l(e.pid,1e3)}}}function be(e,t){let n={...t};return n[ee]=m(e.serverBaseUrl),n[ne]=e.bearerToken,n[ae]=m(e.localBaseUrl),n[ie]=S(e.projectRoot,e.definition,e.profileKey,e.stateDir).statePath,n[f]=e.bridgeScope.tenantId,n[se]=e.bridgeScope.runId,n[re]=e.bridgeScope.leaseId,e.launchUrl?.trim()?n[h]=e.launchUrl.trim():delete n[h],e.registerPath?.trim()?n[d]=e.registerPath.trim():delete n[d],e.unregisterPath?.trim()?n[p]=e.unregisterPath.trim():delete n[p],e.devicePort===void 0?delete n[u]:n[u]=String(e.devicePort),e.session?.trim()?n[g]=e.session.trim():delete n[g],n}function xe(e){let t=fe(import.meta.url),n=_.extname(t)||`.js`,r=[_.join(_.dirname(t),`${y}${n}`),_.join(_.dirname(t),`internal`,`${y}${n}`)].find(e=>v.existsSync(e));if(!r)throw Error(`${e.displayName} entrypoint not found. Rebuild the package to include the companion worker entry.`);return r}function Se(e,t){let n=xe(e.definition),i=n.endsWith(`.ts`)?[`--experimental-strip-types`]:[];v.mkdirSync(_.dirname(t),{recursive:!0});let a=v.openSync(t,`a`),s=0;try{s=r(process.execPath,[...i,n,e.definition.runArg],{env:be(e,e.env??process.env),stdio:[`ignore`,a,a]})}finally{v.closeSync(a)}if(!Number.isInteger(s)||s<=0)throw Error(`Failed to start ${e.definition.displayName} process.`);return{pid:s,startTime:c(s)??void 0,command:o(s)??void 0,serverBaseUrl:m(e.serverBaseUrl),localBaseUrl:m(e.localBaseUrl),launchUrl:x(e.launchUrl),registerPath:x(e.registerPath),unregisterPath:x(e.unregisterPath),devicePort:e.devicePort,session:x(e.session),bridgeScope:e.bridgeScope,tokenHash:b(e.bearerToken),consumers:[]}}async function j(e){let t=O(e),n=S(e.projectRoot,e.definition,e.profileKey,e.stateDir),r=C(n.statePath);if(r&&ve(r,e)){let e=k(r,t);return e!==r&&w(n.statePath,e),{pid:r.pid,spawned:!1,statePath:n.statePath,logPath:n.logPath}}r&&(await A(r,e.definition),E(n,e.definition)),he(n.statePath);let i;try{i=Se(e,n.logPath),w(n.statePath,k(i,t))}catch(t){throw i&&await A(i,e.definition).catch(()=>{}),E(n,e.definition),t}return{pid:i.pid,spawned:!0,statePath:n.statePath,logPath:n.logPath}}async function M(e){let t=O(e),n=S(e.projectRoot,e.definition,e.profileKey,e.stateDir),r=C(n.statePath);if(!r)return E(n,e.definition),{stopped:!1,statePath:n.statePath};let i=ye(r,t);return i.consumers.length>0?(w(n.statePath,i),{stopped:!1,statePath:n.statePath}):(await A(r,e.definition),E(n,e.definition),{stopped:!0,statePath:n.statePath})}const N={slug:`metro-companion`,runArg:te,displayName:`Metro companion`};async function Ce(e){return await j({...e,definition:N,registerPath:e.registerPath??`/api/metro/companion/register`})}async function we(e){return await M({...e,definition:N})}const P=8081,F=`.expo/.virtual-metro-entry.bundle`;function I(t,n){if(t==null||t===``)return n;let r=Number.parseInt(String(t),10);if(!Number.isInteger(r)||r<1||r>65535)throw new e(`INVALID_ARGS`,`Invalid Metro port: ${String(t)}. Use 1-65535.`);return r}function Te(t){let n=R(t.bundleUrl),r=n??t.runtime?.bundleUrl,i=!!n,a=!!R(r),o=ue({metroHost:Ee(t,i,a),metroPort:De(t,i,a),bundleUrl:r});if(!o)throw new e(`INVALID_ARGS`,`Unable to resolve Metro host and port for reload.`);let s=Oe(r);return{reloadUrl:L(o,o.scheme,`${s}/reload`),messageSocketUrl:L(o,o.scheme===`https`?`wss`:`ws`,`${s}/message`)}}function Ee(e,t,n){return R(e.metroHost)??(t?void 0:R(e.runtime?.metroHost))??(n?void 0:`localhost`)}function De(e,t,n){if(e.metroPort!==void 0)return I(e.metroPort,P);if(!t)return e.runtime?.metroPort??(n?void 0:P)}function Oe(e){let t=R(e);if(!t)return``;let n;try{n=new URL(t)}catch{return``}let r=n.pathname.replace(/\/+$/,``),i=`/${F}`;if(r.endsWith(i))return r.slice(0,-i.length);let a=r.lastIndexOf(`/`);return(a>=0?r.slice(a+1):r).endsWith(`.bundle`)&&a>0?r.slice(0,a):``}function L(e,t,n){let r=new URL(`${t}://localhost`);return r.hostname=e.host,r.port=String(e.port),r.pathname=n,r.toString()}function R(e){return typeof e==`string`&&e.trim()?e.trim():void 0}function z(e){return typeof e==`string`&&e.trim()?m(e.trim()):``}function B(e){return typeof e==`string`&&e.trim()?e.trim():void 0}function V(e,t,n){return i(e,{env:t,cwd:n})}function H(e){try{return v.accessSync(e,v.constants.F_OK),!0}catch{return!1}}function ke(e){try{return v.statSync(e).isDirectory()}catch{return!1}}function U(t){let n=_.join(t,`package.json`),r=ce(t);if(!r)throw new e(`INVALID_ARGS`,`package.json not found at ${n}`);return r}const Ae=[{file:`pnpm-lock.yaml`,command:`pnpm`},{file:`yarn.lock`,command:`yarn`},{file:`bun.lock`,command:`bun`},{file:`bun.lockb`,command:`bun`},{file:`package-lock.json`,command:`npm`}];function je(e){let t=e;for(;;){for(let{file:e,command:n}of Ae)if(H(_.join(t,e)))return{command:n,installArgs:[`install`]};if(H(_.join(t,`.git`)))return null;let e=_.dirname(t);if(e===t)return null;t=e}}function Me(e){return je(e)??{command:`npm`,installArgs:[`install`]}}function Ne(e,t){if(t!==`auto`)return t;let n=le(e);return n===`expo`||n===`repack`?n:`react-native`}function W(e,t){return typeof{...e.dependencies??{},...e.devDependencies??{}}[t]==`string`}function G(e,t){return[`js`,`mjs`,`cjs`,`ts`,`mts`,`cts`].some(n=>H(_.join(e,`${t}.config.${n}`)))}function Pe(e,t){return G(e,`rspack`)?`rspack`:G(e,`webpack`)?`webpack`:W(t,`@rspack/core`)?`rspack`:W(t,`webpack`)?`webpack`:`rspack`}function K(e,t,n){if(e==null||e===``)return t;let r=Number.parseInt(String(e),10);return Number.isInteger(r)?Math.max(r,n):t}function Fe(e){return e===`expo`?F:`index.bundle`}function q(e,t,n){return{platform:t,bundleUrl:oe(e,t,Fe(n))}}function J(e,t){return{platform:t,metroHost:B(e?.metro_host),metroPort:e?.metro_port,bundleUrl:B(e?.metro_bundle_url),launchUrl:B(e?.launch_url)}}function Ie(e,t){if(ke(_.join(e,`node_modules`)))return{installed:!1};let r=Me(e);try{n(r.command,r.installArgs,{cwd:e,env:t})}catch(e){throw Le(e,r)}return{installed:!0,packageManager:r.command}}function Le(n,r){let i=t(n),a=`Dependency install failed using detected package manager "${r.command}". If dependencies are already installed (for example via a monorepo root install), pass --no-install-deps to skip this step, or install manually with "${r.command} ${r.installArgs.join(` `)}" from the project root.`;return new e(i.code,i.message,{...i.details??{},hint:a,packageManager:r.command},i)}async function Y(e){await a(e)}async function X(t,n,r={}){try{let e=await fetch(t,{headers:r,signal:AbortSignal.timeout(n)});return{ok:e.ok,status:e.status,body:await e.text()}}catch(r){throw r instanceof Error&&r.name===`TimeoutError`?new e(`COMMAND_FAILED`,`Timed out fetching ${t} after ${n}ms`):r}}async function Re(e,t){try{let n=await X(e,t);return n.ok&&n.body.includes(`packager-status:running`)}catch{return!1}}function ze(e,t,n,r){return e===`expo`?{command:`npx`,installArgs:[`expo`,`start`,`--host`,`lan`,`--port`,String(n)]}:e===`repack`?{command:`npx`,installArgs:[`react-native`,t===`webpack`?`webpack-start`:`rspack-start`,`--host`,r,`--port`,String(n)]}:{command:`npx`,installArgs:[`react-native`,`start`,`--host`,r,`--port`,String(n)]}}function Be(t,n,i,a,o,s,c){let l=ze(n,i,a,o);v.mkdirSync(_.dirname(s),{recursive:!0});let u=v.openSync(s,`a`),d=0;try{d=r(l.command,l.installArgs,{cwd:t,env:c,stdio:[`ignore`,u,u]})}finally{v.closeSync(u)}if(!Number.isInteger(d)||d<=0)throw new e(`COMMAND_FAILED`,`Failed to start React Native dev server. Expected a detached child PID.`);return{pid:d}}async function Ve(e){if(!(!Number.isInteger(e)||e<=0)){try{process.kill(e,`SIGTERM`)}catch(e){let t=e.code;if(t===`ESRCH`||t===`EPERM`)return;throw e}if(!await l(e,1e3)){try{process.kill(e,`SIGKILL`)}catch(e){let t=e.code;if(t===`ESRCH`||t===`EPERM`)return;throw e}await l(e,1e3)}}}function He(e,t){return{Authorization:`Bearer ${t}`,"Content-Type":`application/json`,...e.includes(`ngrok`)?{"ngrok-skip-browser-warning":`1`}:{}}}function Z(t,n){let r=new e(`COMMAND_FAILED`,t);return r.retryable=n,r}function Ue(e,t){return!!(e>=500||e===408||e===425||e===429||JSON.stringify(t).includes(`Metro companion is not connected`))}function We(e){return!!(e&&typeof e==`object`&&`retryable`in e&&e.retryable===!0)}async function Q(e){let t;try{t=await fetch(`${e.baseUrl}/api/metro/bridge`,{method:`POST`,headers:He(e.baseUrl,e.bearerToken),body:JSON.stringify({...e.scope,...e.runtime?{ios_runtime:e.runtime}:{},timeout_ms:e.timeoutMs}),signal:AbortSignal.timeout(e.timeoutMs)})}catch(t){throw t instanceof Error&&t.name===`TimeoutError`?Z(`/api/metro/bridge timed out after ${e.timeoutMs}ms calling ${e.baseUrl}/api/metro/bridge`,!0):Z(t instanceof Error?t.message:String(t),!0)}let n=Ge(await t.text(),t.status,e.baseUrl);if(!t.ok)throw Z(`/api/metro/bridge failed (${t.status}): ${JSON.stringify(n)}`,Ue(t.status,n));return qe(n)}function Ge(e,t,n){if(!e)return{};try{let t=JSON.parse(e);if(!t||typeof t!=`object`||Array.isArray(t))throw Error(`Expected a JSON object`);return t}catch(r){let i=e.slice(0,200);throw Z(`/api/metro/bridge returned invalid JSON (${t}) from ${n}: ${r instanceof Error?r.message:String(r)}. body=${JSON.stringify(i)}`,Ue(t,e))}}function Ke(e){return{enabled:e.enabled,baseUrl:e.base_url,statusUrl:e.status_url??``,bundleUrl:e.bundle_url??``,iosRuntime:J(e.ios_runtime,`ios`),androidRuntime:J(e.android_runtime,`android`),upstream:{bundleUrl:e.upstream.bundle_url??``,host:e.upstream.host??``,port:e.upstream.port??0,statusUrl:e.upstream.status_url??``},probe:{reachable:e.probe.reachable,statusCode:e.probe.status_code,latencyMs:e.probe.latency_ms,detail:e.probe.detail}}}function qe(e){let t=e.data??e;if(!t||typeof t!=`object`||Array.isArray(t))throw Z(`/api/metro/bridge returned malformed descriptor: Expected a JSON object.`,!1);try{return Ke(t)}catch(e){throw Z(`/api/metro/bridge returned malformed descriptor: ${e instanceof Error?e.message:String(e)}`,!1)}}function $(e,t,n,r,i){let a=[`Metro bridge is required for this run but could not be configured via ${e}/api/metro/bridge.`];return t&&a.push(`bridgeError=${t}`),n?.probe.reachable===!1&&a.push(`bridgeProbe=${n.probe.detail||`unreachable (status ${n.probe.statusCode||0})`}`),r&&r!==t&&a.push(`initialBridgeError=${r}`),i&&a.push(`metroCompanionLog=${i}`),a.join(` `)}function Je(t,n){if(!n?.iosRuntime.bundleUrl)throw new e(`COMMAND_FAILED`,$(t,`bridge descriptor is missing ios_runtime.metro_bundle_url`,n))}function Ye(t,n,r){let i=n||B(r.AGENT_DEVICE_METRO_BEARER_TOKEN)||``,a=i||t&&B(r.AGENT_DEVICE_DAEMON_AUTH_TOKEN)||``;if(t&&!a)throw new e(`INVALID_ARGS`,`metro prepare requires proxy auth when --proxy-base-url is provided. Pass --bearer-token or set AGENT_DEVICE_METRO_BEARER_TOKEN or AGENT_DEVICE_DAEMON_AUTH_TOKEN.`);if(!t&&i)throw new e(`INVALID_ARGS`,`metro prepare requires --proxy-base-url when proxy auth is provided.`);return{proxyEnabled:!!(t&&a),proxyBaseUrl:t,proxyBearerToken:a}}function Xe(t){if(!t?.tenantId||!t.runId||!t.leaseId)throw new e(`INVALID_ARGS`,`metro prepare with proxy requires tenantId, runId, and leaseId bridge scope.`);return t}function Ze(t,n){if(!(t||n))throw new e(`INVALID_ARGS`,`metro prepare requires --public-base-url <url> or --proxy-base-url <url>.`)}function Qe(e,t,n){return e.runtimeFilePath?V(e.runtimeFilePath,t,n):null}function $e(e,t,n,r){return V(e.logPath??_.join(r,`.agent-device`,`metro.log`),t,n)}function et(e){let t=e.env??process.env,n=process.cwd(),r=V(e.projectRoot??n,t,n),i=e.kind??`auto`,a=null,o;i===`auto`?(a=U(r),o=Ne(a,i)):o=i;let s=null;o===`repack`&&(a??=U(r),s=Pe(r,a));let c=z(e.publicBaseUrl),l=z(e.proxyBaseUrl);Ze(c,l);let{proxyEnabled:u,proxyBaseUrl:d,proxyBearerToken:f}=Ye(l,B(e.proxyBearerToken)??``,t);return{env:t,projectRoot:r,kind:o,repackBundler:s,metroPort:I(e.metroPort??8081,8081),listenHost:B(e.listenHost)??`0.0.0.0`,statusHost:B(e.statusHost)??`127.0.0.1`,publicBaseUrl:c,proxyBaseUrl:d,proxyBearerToken:f,bridgeScope:u?Xe(e.bridgeScope):null,startupTimeoutMs:K(e.startupTimeoutMs,18e4,3e4),probeTimeoutMs:K(e.probeTimeoutMs,1e4,1e3),reuseExisting:e.reuseExisting??!0,installProjectDeps:e.installDependenciesIfNeeded??!0,runtimeFilePath:Qe(e,t,n),logPath:$e(e,t,n,r)}}async function tt(e,t,n){let r=Date.now()+t;for(;Date.now()<r;){let t=r-Date.now();if(await Re(e,Math.min(n,Math.max(t,1))))return!0;let i=Math.min(500,Math.max(r-Date.now(),0));i>0&&await Y(i)}return!1}async function nt(t){let n=Date.now()+t.startupTimeoutMs,r=null,i=null;for(;Date.now()<n;){try{let e=await Q({baseUrl:t.baseUrl,bearerToken:t.bearerToken,scope:t.scope,runtime:t.runtime,timeoutMs:t.probeTimeoutMs});if(e.probe.reachable!==!1)return e;r=e,i=null}catch(n){if(i=n instanceof Error?n.message:String(n),!We(n))throw new e(`COMMAND_FAILED`,$(t.baseUrl,i,r,t.initialBridgeError,t.companionLogPath),void 0,n)}let a=Math.min(1e3,Math.max(n-Date.now(),0));a>0&&await Y(a)}throw new e(`COMMAND_FAILED`,$(t.baseUrl,i,r,t.initialBridgeError,t.companionLogPath))}async function rt(t){let n=`http://${t.statusHost}:${t.metroPort}/status`;if(t.reuseExisting&&await Re(n,t.probeTimeoutMs))return{started:!1,reused:!0,pid:0,statusUrl:n};let r=Be(t.projectRoot,t.kind,t.repackBundler,t.metroPort,t.listenHost,t.logPath,t.env);if(await tt(n,t.startupTimeoutMs,t.probeTimeoutMs))return{started:!0,reused:!1,pid:r.pid,statusUrl:n};throw await Ve(r.pid).catch(()=>{}),new e(`COMMAND_FAILED`,`React Native dev server did not become ready at ${n} within ${t.startupTimeoutMs}ms. Check ${t.logPath}.`,{logPath:t.logPath})}async function it(e,t){let n=t.bridgeScope;if(!n)return null;let r=null,i=null;try{r=await Q({baseUrl:t.proxyBaseUrl,bearerToken:t.proxyBearerToken,scope:n,timeoutMs:t.probeTimeoutMs})}catch(e){if(!We(e))throw e;i=e instanceof Error?e.message:String(e)}return(!r||r.probe.reachable===!1)&&(r=await at(e,t,n,r,i)),Je(t.proxyBaseUrl,r),r}async function at(t,n,r,i,a){let o;try{o=(await Ce({projectRoot:n.projectRoot,serverBaseUrl:n.proxyBaseUrl,bearerToken:n.proxyBearerToken,bridgeScope:r,localBaseUrl:`http://${n.statusHost}:${n.metroPort}`,launchUrl:B(t.launchUrl),profileKey:B(t.companionProfileKey),consumerKey:B(t.companionConsumerKey),env:n.env})).logPath}catch(t){throw new e(`COMMAND_FAILED`,$(n.proxyBaseUrl,t instanceof Error?t.message:String(t),i,a),void 0,t)}try{return await nt({baseUrl:n.proxyBaseUrl,bearerToken:n.proxyBearerToken,scope:r,probeTimeoutMs:n.probeTimeoutMs,startupTimeoutMs:n.startupTimeoutMs,initialBridgeError:a,companionLogPath:o})}catch(e){throw e instanceof Error?e:Error(String(e))}}function ot(e,t){return{baseIosRuntime:e?q(e,`ios`,t):{platform:`ios`},baseAndroidRuntime:e?q(e,`android`,t):{platform:`android`}}}function st(e,t){e&&(v.mkdirSync(_.dirname(e),{recursive:!0}),v.writeFileSync(e,JSON.stringify(t,null,2)))}async function ct(e={}){let t=et(e),n=t.installProjectDeps?Ie(t.projectRoot,t.env):{installed:!1},r=await rt(t),{baseIosRuntime:i,baseAndroidRuntime:a}=ot(t.publicBaseUrl,t.kind),o=await it(e,t),s=o?.iosRuntime??i,c=o?.androidRuntime??a,l={projectRoot:t.projectRoot,kind:t.kind,dependenciesInstalled:n.installed,packageManager:n.packageManager??null,started:r.started,reused:r.reused,pid:r.pid,logPath:t.logPath,statusUrl:r.statusUrl,runtimeFilePath:t.runtimeFilePath,iosRuntime:s,androidRuntime:c,bridge:o};return st(t.runtimeFilePath,l),l}function lt(e){let t=e.trimStart().slice(0,15).toLowerCase();return t.startsWith(`<!doctype`)||t.startsWith(`<html`)}async function ut(t,n){await new Promise((r,i)=>{let a=new WebSocket(t),o=t=>{clearTimeout(s);try{a.close()}catch{}i(new e(`COMMAND_FAILED`,t))},s=setTimeout(()=>{o(`Timed out broadcasting reload to ${t} after ${n}ms`)},n);a.addEventListener(`open`,()=>{a.send(JSON.stringify({version:2,method:`reload`}));let e=()=>{if(a.bufferedAmount===0){clearTimeout(s),a.close(),r();return}setTimeout(e,20)};e()}),a.addEventListener(`error`,()=>{o(`Failed to reach the dev server message socket at ${t}`)})})}async function dt(t={}){let n=K(t.timeoutMs,1e4,1e3),{reloadUrl:r,messageSocketUrl:i}=Te(t),a=await X(r,n);if(a.ok&&!lt(a.body))return{reloaded:!0,reloadUrl:r,status:a.status,body:a.body,transport:`http`};try{await ut(i,n)}catch(t){throw new e(`COMMAND_FAILED`,`React Native dev server reload failed (${a.status}).`,{reloadUrl:r,status:a.status,body:a.body.slice(0,500),messageSocketUrl:i,hint:`Verify Metro or Re.Pack is running and the target React Native app is connected to this dev server instance.`},t instanceof Error?t:void 0)}return{reloaded:!0,reloadUrl:i,status:a.status,body:``,transport:`message-socket`}}export{M as a,j as i,dt as n,we as r,ct as t};
|
|
1
|
+
import{_ as e,v as t}from"./sdk-contracts.js";import{C as n,b as r}from"./sdk-android-adb.js";import{n as i}from"./path-resolution.js";import{t as a}from"./timeouts.js";import{c as o,d as s,n as c,s as l}from"./host-process.js";import{a as u,c as d,d as f,f as ee,g as te,h as p,i as ne,l as re,m as ie,n as m,o as h,p as g,s as ae,t as oe,u as se}from"./url.js";import{a as ce,i as le,t as ue}from"./runtime-transport.js";import _ from"node:path";import{createHash as de}from"node:crypto";import v from"node:fs";import{fileURLToPath as fe}from"node:url";const y=`companion-tunnel`;function b(e){return de(`sha256`).update(e).digest(`hex`)}function x(e){return e?.trim()?e.trim():void 0}function pe(e){if(!e||typeof e!=`object`||Array.isArray(e))return;let t=e;if(!(typeof t.tenantId!=`string`||typeof t.runId!=`string`||typeof t.leaseId!=`string`))return{tenantId:t.tenantId,runId:t.runId,leaseId:t.leaseId}}function me(e,t){return e.tenantId===t.tenantId&&e.runId===t.runId&&e.leaseId===t.leaseId}function S(e,t,n,r){let i=r??_.join(e,`.agent-device`);if(!n)return{statePath:_.join(i,`${t.slug}.json`),logPath:_.join(i,`${t.slug}.log`)};let a=b(n).slice(0,12),o=_.join(i,t.slug);return{statePath:_.join(o,`${t.slug}-${a}.json`),logPath:_.join(o,`${t.slug}-${a}.log`)}}function C(e){try{let t=JSON.parse(v.readFileSync(e,`utf8`));if(!Number.isInteger(t.pid)||Number(t.pid)<=0||typeof t.serverBaseUrl!=`string`||typeof t.localBaseUrl!=`string`||typeof t.tokenHash!=`string`||t.tokenHash.length===0)return null;let n=Array.isArray(t.consumers)?t.consumers.filter(e=>typeof e==`string`&&e.length>0):[];return{pid:Number(t.pid),startTime:typeof t.startTime==`string`?t.startTime:void 0,command:typeof t.command==`string`?t.command:void 0,serverBaseUrl:t.serverBaseUrl,localBaseUrl:t.localBaseUrl,launchUrl:x(typeof t.launchUrl==`string`?t.launchUrl:void 0),registerPath:x(typeof t.registerPath==`string`?t.registerPath:void 0),unregisterPath:x(typeof t.unregisterPath==`string`?t.unregisterPath:void 0),devicePort:Number.isInteger(t.devicePort)?Number(t.devicePort):void 0,session:x(typeof t.session==`string`?t.session:void 0),bridgeScope:pe(t.bridgeScope),tokenHash:t.tokenHash,consumers:n}}catch{return null}}function w(e,t){v.mkdirSync(_.dirname(e),{recursive:!0}),v.writeFileSync(e,`${JSON.stringify(t,null,2)}\n`,`utf8`)}function he(e){v.mkdirSync(_.dirname(e),{recursive:!0}),v.closeSync(v.openSync(e,`a`))}function ge(e){try{v.unlinkSync(e)}catch{}}function _e(e){try{v.unlinkSync(e)}catch{}}function T(e){try{v.readdirSync(e).length===0&&v.rmdirSync(e)}catch{}}function E(e,t){let n=_.dirname(e.statePath),r=_.dirname(e.logPath);ge(e.statePath),_e(e.logPath),T(n),r!==n&&T(r),_.basename(n)===t.slug&&T(_.dirname(n))}function D(e,t){return e.includes(t.runArg)}function ve(e,t){if(!c(e.pid))return!1;if(e.startTime){let t=o(e.pid);if(!t||t!==e.startTime)return!1}let n=l(e.pid);return!n||!D(n,t.definition)||!e.bridgeScope?!1:e.serverBaseUrl===m(t.serverBaseUrl)&&e.localBaseUrl===m(t.localBaseUrl)&&e.launchUrl===x(t.launchUrl)&&e.registerPath===x(t.registerPath)&&e.unregisterPath===x(t.unregisterPath)&&e.devicePort===t.devicePort&&e.session===x(t.session)&&me(e.bridgeScope,t.bridgeScope)&&e.tokenHash===b(t.bearerToken)}function O(e){return x(e.consumerKey)??x(e.profileKey)??null}function k(e,t){return!t||e.consumers.includes(t)?e:{...e,consumers:[...e.consumers,t]}}function ye(e,t){return t?{...e,consumers:e.consumers.filter(e=>e!==t)}:{...e,consumers:[]}}async function A(e,t){if(!c(e.pid))return;let n=l(e.pid);if(!(!n||!D(n,t))){try{process.kill(e.pid,`SIGTERM`)}catch(e){let t=e.code;if(t===`ESRCH`||t===`EPERM`)return;throw e}if(!await s(e.pid,1e3)){try{process.kill(e.pid,`SIGKILL`)}catch(e){let t=e.code;if(t===`ESRCH`||t===`EPERM`)return;throw e}await s(e.pid,1e3)}}}function be(e,t){let n={...t};return n[ee]=m(e.serverBaseUrl),n[ne]=e.bearerToken,n[ae]=m(e.localBaseUrl),n[ie]=S(e.projectRoot,e.definition,e.profileKey,e.stateDir).statePath,n[f]=e.bridgeScope.tenantId,n[se]=e.bridgeScope.runId,n[re]=e.bridgeScope.leaseId,e.launchUrl?.trim()?n[h]=e.launchUrl.trim():delete n[h],e.registerPath?.trim()?n[d]=e.registerPath.trim():delete n[d],e.unregisterPath?.trim()?n[p]=e.unregisterPath.trim():delete n[p],e.devicePort===void 0?delete n[u]:n[u]=String(e.devicePort),e.session?.trim()?n[g]=e.session.trim():delete n[g],n}function xe(e){let t=fe(import.meta.url),n=_.extname(t)||`.js`,r=[_.join(_.dirname(t),`${y}${n}`),_.join(_.dirname(t),`internal`,`${y}${n}`)].find(e=>v.existsSync(e));if(!r)throw Error(`${e.displayName} entrypoint not found. Rebuild the package to include the companion worker entry.`);return r}function Se(e,t){let n=xe(e.definition),i=n.endsWith(`.ts`)?[`--experimental-strip-types`]:[];v.mkdirSync(_.dirname(t),{recursive:!0});let a=v.openSync(t,`a`),s=0;try{s=r(process.execPath,[...i,n,e.definition.runArg],{env:be(e,e.env??process.env),stdio:[`ignore`,a,a]})}finally{v.closeSync(a)}if(!Number.isInteger(s)||s<=0)throw Error(`Failed to start ${e.definition.displayName} process.`);return{pid:s,startTime:o(s)??void 0,command:l(s)??void 0,serverBaseUrl:m(e.serverBaseUrl),localBaseUrl:m(e.localBaseUrl),launchUrl:x(e.launchUrl),registerPath:x(e.registerPath),unregisterPath:x(e.unregisterPath),devicePort:e.devicePort,session:x(e.session),bridgeScope:e.bridgeScope,tokenHash:b(e.bearerToken),consumers:[]}}async function j(e){let t=O(e),n=S(e.projectRoot,e.definition,e.profileKey,e.stateDir),r=C(n.statePath);if(r&&ve(r,e)){let e=k(r,t);return e!==r&&w(n.statePath,e),{pid:r.pid,spawned:!1,statePath:n.statePath,logPath:n.logPath}}r&&(await A(r,e.definition),E(n,e.definition)),he(n.statePath);let i;try{i=Se(e,n.logPath),w(n.statePath,k(i,t))}catch(t){throw i&&await A(i,e.definition).catch(()=>{}),E(n,e.definition),t}return{pid:i.pid,spawned:!0,statePath:n.statePath,logPath:n.logPath}}async function M(e){let t=O(e),n=S(e.projectRoot,e.definition,e.profileKey,e.stateDir),r=C(n.statePath);if(!r)return E(n,e.definition),{stopped:!1,statePath:n.statePath};let i=ye(r,t);return i.consumers.length>0?(w(n.statePath,i),{stopped:!1,statePath:n.statePath}):(await A(r,e.definition),E(n,e.definition),{stopped:!0,statePath:n.statePath})}const N={slug:`metro-companion`,runArg:te,displayName:`Metro companion`};async function Ce(e){return await j({...e,definition:N,registerPath:e.registerPath??`/api/metro/companion/register`})}async function we(e){return await M({...e,definition:N})}const P=8081,F=`.expo/.virtual-metro-entry.bundle`;function I(t,n){if(t==null||t===``)return n;let r=Number.parseInt(String(t),10);if(!Number.isInteger(r)||r<1||r>65535)throw new e(`INVALID_ARGS`,`Invalid Metro port: ${String(t)}. Use 1-65535.`);return r}function Te(t){let n=R(t.bundleUrl),r=n??t.runtime?.bundleUrl,i=!!n,a=!!R(r),o=ue({metroHost:Ee(t,i,a),metroPort:De(t,i,a),bundleUrl:r});if(!o)throw new e(`INVALID_ARGS`,`Unable to resolve Metro host and port for reload.`);let s=Oe(r);return{reloadUrl:L(o,o.scheme,`${s}/reload`),messageSocketUrl:L(o,o.scheme===`https`?`wss`:`ws`,`${s}/message`)}}function Ee(e,t,n){return R(e.metroHost)??(t?void 0:R(e.runtime?.metroHost))??(n?void 0:`localhost`)}function De(e,t,n){if(e.metroPort!==void 0)return I(e.metroPort,P);if(!t)return e.runtime?.metroPort??(n?void 0:P)}function Oe(e){let t=R(e);if(!t)return``;let n;try{n=new URL(t)}catch{return``}let r=n.pathname.replace(/\/+$/,``),i=`/${F}`;if(r.endsWith(i))return r.slice(0,-i.length);let a=r.lastIndexOf(`/`);return(a>=0?r.slice(a+1):r).endsWith(`.bundle`)&&a>0?r.slice(0,a):``}function L(e,t,n){let r=new URL(`${t}://localhost`);return r.hostname=e.host,r.port=String(e.port),r.pathname=n,r.toString()}function R(e){return typeof e==`string`&&e.trim()?e.trim():void 0}function z(e){return typeof e==`string`&&e.trim()?m(e.trim()):``}function B(e){return typeof e==`string`&&e.trim()?e.trim():void 0}function V(e,t,n){return i(e,{env:t,cwd:n})}function H(e){try{return v.accessSync(e,v.constants.F_OK),!0}catch{return!1}}function ke(e){try{return v.statSync(e).isDirectory()}catch{return!1}}function U(t){let n=_.join(t,`package.json`),r=ce(t);if(!r)throw new e(`INVALID_ARGS`,`package.json not found at ${n}`);return r}const Ae=[{file:`pnpm-lock.yaml`,command:`pnpm`},{file:`yarn.lock`,command:`yarn`},{file:`bun.lock`,command:`bun`},{file:`bun.lockb`,command:`bun`},{file:`package-lock.json`,command:`npm`}];function je(e){let t=e;for(;;){for(let{file:e,command:n}of Ae)if(H(_.join(t,e)))return{command:n,installArgs:[`install`]};if(H(_.join(t,`.git`)))return null;let e=_.dirname(t);if(e===t)return null;t=e}}function Me(e){return je(e)??{command:`npm`,installArgs:[`install`]}}function Ne(e,t){if(t!==`auto`)return t;let n=le(e);return n===`expo`||n===`repack`?n:`react-native`}function W(e,t){return typeof{...e.dependencies??{},...e.devDependencies??{}}[t]==`string`}function G(e,t){return[`js`,`mjs`,`cjs`,`ts`,`mts`,`cts`].some(n=>H(_.join(e,`${t}.config.${n}`)))}function Pe(e,t){return G(e,`rspack`)?`rspack`:G(e,`webpack`)?`webpack`:W(t,`@rspack/core`)?`rspack`:W(t,`webpack`)?`webpack`:`rspack`}function K(e,t,n){if(e==null||e===``)return t;let r=Number.parseInt(String(e),10);return Number.isInteger(r)?Math.max(r,n):t}function Fe(e){return e===`expo`?F:`index.bundle`}function q(e,t,n){return{platform:t,bundleUrl:oe(e,t,Fe(n))}}function J(e,t){return{platform:t,metroHost:B(e?.metro_host),metroPort:e?.metro_port,bundleUrl:B(e?.metro_bundle_url),launchUrl:B(e?.launch_url)}}function Ie(e,t){if(ke(_.join(e,`node_modules`)))return{installed:!1};let r=Me(e);try{n(r.command,r.installArgs,{cwd:e,env:t})}catch(e){throw Le(e,r)}return{installed:!0,packageManager:r.command}}function Le(n,r){let i=t(n),a=`Dependency install failed using detected package manager "${r.command}". If dependencies are already installed (for example via a monorepo root install), pass --no-install-deps to skip this step, or install manually with "${r.command} ${r.installArgs.join(` `)}" from the project root.`;return new e(i.code,i.message,{...i.details??{},hint:a,packageManager:r.command},i)}async function Y(e){await a(e)}async function X(t,n,r={}){try{let e=await fetch(t,{headers:r,signal:AbortSignal.timeout(n)});return{ok:e.ok,status:e.status,body:await e.text()}}catch(r){throw r instanceof Error&&r.name===`TimeoutError`?new e(`COMMAND_FAILED`,`Timed out fetching ${t} after ${n}ms`):r}}async function Re(e,t){try{let n=await X(e,t);return n.ok&&n.body.includes(`packager-status:running`)}catch{return!1}}function ze(e,t,n,r){return e===`expo`?{command:`npx`,installArgs:[`expo`,`start`,`--host`,`lan`,`--port`,String(n)]}:e===`repack`?{command:`npx`,installArgs:[`react-native`,t===`webpack`?`webpack-start`:`rspack-start`,`--host`,r,`--port`,String(n)]}:{command:`npx`,installArgs:[`react-native`,`start`,`--host`,r,`--port`,String(n)]}}function Be(t,n,i,a,o,s,c){let l=ze(n,i,a,o);v.mkdirSync(_.dirname(s),{recursive:!0});let u=v.openSync(s,`a`),d=0;try{d=r(l.command,l.installArgs,{cwd:t,env:c,stdio:[`ignore`,u,u]})}finally{v.closeSync(u)}if(!Number.isInteger(d)||d<=0)throw new e(`COMMAND_FAILED`,`Failed to start React Native dev server. Expected a detached child PID.`);return{pid:d}}async function Ve(e){if(!(!Number.isInteger(e)||e<=0)){try{process.kill(e,`SIGTERM`)}catch(e){let t=e.code;if(t===`ESRCH`||t===`EPERM`)return;throw e}if(!await s(e,1e3)){try{process.kill(e,`SIGKILL`)}catch(e){let t=e.code;if(t===`ESRCH`||t===`EPERM`)return;throw e}await s(e,1e3)}}}function He(e,t){return{Authorization:`Bearer ${t}`,"Content-Type":`application/json`,...e.includes(`ngrok`)?{"ngrok-skip-browser-warning":`1`}:{}}}function Z(t,n){let r=new e(`COMMAND_FAILED`,t);return r.retryable=n,r}function Ue(e,t){return!!(e>=500||e===408||e===425||e===429||JSON.stringify(t).includes(`Metro companion is not connected`))}function We(e){return!!(e&&typeof e==`object`&&`retryable`in e&&e.retryable===!0)}async function Q(e){let t;try{t=await fetch(`${e.baseUrl}/api/metro/bridge`,{method:`POST`,headers:He(e.baseUrl,e.bearerToken),body:JSON.stringify({...e.scope,...e.runtime?{ios_runtime:e.runtime}:{},timeout_ms:e.timeoutMs}),signal:AbortSignal.timeout(e.timeoutMs)})}catch(t){throw t instanceof Error&&t.name===`TimeoutError`?Z(`/api/metro/bridge timed out after ${e.timeoutMs}ms calling ${e.baseUrl}/api/metro/bridge`,!0):Z(t instanceof Error?t.message:String(t),!0)}let n=Ge(await t.text(),t.status,e.baseUrl);if(!t.ok)throw Z(`/api/metro/bridge failed (${t.status}): ${JSON.stringify(n)}`,Ue(t.status,n));return qe(n)}function Ge(e,t,n){if(!e)return{};try{let t=JSON.parse(e);if(!t||typeof t!=`object`||Array.isArray(t))throw Error(`Expected a JSON object`);return t}catch(r){let i=e.slice(0,200);throw Z(`/api/metro/bridge returned invalid JSON (${t}) from ${n}: ${r instanceof Error?r.message:String(r)}. body=${JSON.stringify(i)}`,Ue(t,e))}}function Ke(e){return{enabled:e.enabled,baseUrl:e.base_url,statusUrl:e.status_url??``,bundleUrl:e.bundle_url??``,iosRuntime:J(e.ios_runtime,`ios`),androidRuntime:J(e.android_runtime,`android`),upstream:{bundleUrl:e.upstream.bundle_url??``,host:e.upstream.host??``,port:e.upstream.port??0,statusUrl:e.upstream.status_url??``},probe:{reachable:e.probe.reachable,statusCode:e.probe.status_code,latencyMs:e.probe.latency_ms,detail:e.probe.detail}}}function qe(e){let t=e.data??e;if(!t||typeof t!=`object`||Array.isArray(t))throw Z(`/api/metro/bridge returned malformed descriptor: Expected a JSON object.`,!1);try{return Ke(t)}catch(e){throw Z(`/api/metro/bridge returned malformed descriptor: ${e instanceof Error?e.message:String(e)}`,!1)}}function $(e,t,n,r,i){let a=[`Metro bridge is required for this run but could not be configured via ${e}/api/metro/bridge.`];return t&&a.push(`bridgeError=${t}`),n?.probe.reachable===!1&&a.push(`bridgeProbe=${n.probe.detail||`unreachable (status ${n.probe.statusCode||0})`}`),r&&r!==t&&a.push(`initialBridgeError=${r}`),i&&a.push(`metroCompanionLog=${i}`),a.join(` `)}function Je(t,n){if(!n?.iosRuntime.bundleUrl)throw new e(`COMMAND_FAILED`,$(t,`bridge descriptor is missing ios_runtime.metro_bundle_url`,n))}function Ye(t,n,r){let i=n||B(r.AGENT_DEVICE_METRO_BEARER_TOKEN)||``,a=i||t&&B(r.AGENT_DEVICE_DAEMON_AUTH_TOKEN)||``;if(t&&!a)throw new e(`INVALID_ARGS`,`metro prepare requires proxy auth when --proxy-base-url is provided. Pass --bearer-token or set AGENT_DEVICE_METRO_BEARER_TOKEN or AGENT_DEVICE_DAEMON_AUTH_TOKEN.`);if(!t&&i)throw new e(`INVALID_ARGS`,`metro prepare requires --proxy-base-url when proxy auth is provided.`);return{proxyEnabled:!!(t&&a),proxyBaseUrl:t,proxyBearerToken:a}}function Xe(t){if(!t?.tenantId||!t.runId||!t.leaseId)throw new e(`INVALID_ARGS`,`metro prepare with proxy requires tenantId, runId, and leaseId bridge scope.`);return t}function Ze(t,n){if(!(t||n))throw new e(`INVALID_ARGS`,`metro prepare requires --public-base-url <url> or --proxy-base-url <url>.`)}function Qe(e,t,n){return e.runtimeFilePath?V(e.runtimeFilePath,t,n):null}function $e(e,t,n,r){return V(e.logPath??_.join(r,`.agent-device`,`metro.log`),t,n)}function et(e){let t=e.env??process.env,n=process.cwd(),r=V(e.projectRoot??n,t,n),i=e.kind??`auto`,a=null,o;i===`auto`?(a=U(r),o=Ne(a,i)):o=i;let s=null;o===`repack`&&(a??=U(r),s=Pe(r,a));let c=z(e.publicBaseUrl),l=z(e.proxyBaseUrl);Ze(c,l);let{proxyEnabled:u,proxyBaseUrl:d,proxyBearerToken:f}=Ye(l,B(e.proxyBearerToken)??``,t);return{env:t,projectRoot:r,kind:o,repackBundler:s,metroPort:I(e.metroPort??8081,8081),listenHost:B(e.listenHost)??`0.0.0.0`,statusHost:B(e.statusHost)??`127.0.0.1`,publicBaseUrl:c,proxyBaseUrl:d,proxyBearerToken:f,bridgeScope:u?Xe(e.bridgeScope):null,startupTimeoutMs:K(e.startupTimeoutMs,18e4,3e4),probeTimeoutMs:K(e.probeTimeoutMs,1e4,1e3),reuseExisting:e.reuseExisting??!0,installProjectDeps:e.installDependenciesIfNeeded??!0,runtimeFilePath:Qe(e,t,n),logPath:$e(e,t,n,r)}}async function tt(e,t,n){let r=Date.now()+t;for(;Date.now()<r;){let t=r-Date.now();if(await Re(e,Math.min(n,Math.max(t,1))))return!0;let i=Math.min(500,Math.max(r-Date.now(),0));i>0&&await Y(i)}return!1}async function nt(t){let n=Date.now()+t.startupTimeoutMs,r=null,i=null;for(;Date.now()<n;){try{let e=await Q({baseUrl:t.baseUrl,bearerToken:t.bearerToken,scope:t.scope,runtime:t.runtime,timeoutMs:t.probeTimeoutMs});if(e.probe.reachable!==!1)return e;r=e,i=null}catch(n){if(i=n instanceof Error?n.message:String(n),!We(n))throw new e(`COMMAND_FAILED`,$(t.baseUrl,i,r,t.initialBridgeError,t.companionLogPath),void 0,n)}let a=Math.min(1e3,Math.max(n-Date.now(),0));a>0&&await Y(a)}throw new e(`COMMAND_FAILED`,$(t.baseUrl,i,r,t.initialBridgeError,t.companionLogPath))}async function rt(t){let n=`http://${t.statusHost}:${t.metroPort}/status`;if(t.reuseExisting&&await Re(n,t.probeTimeoutMs))return{started:!1,reused:!0,pid:0,statusUrl:n};let r=Be(t.projectRoot,t.kind,t.repackBundler,t.metroPort,t.listenHost,t.logPath,t.env);if(await tt(n,t.startupTimeoutMs,t.probeTimeoutMs))return{started:!0,reused:!1,pid:r.pid,statusUrl:n};throw await Ve(r.pid).catch(()=>{}),new e(`COMMAND_FAILED`,`React Native dev server did not become ready at ${n} within ${t.startupTimeoutMs}ms. Check ${t.logPath}.`,{logPath:t.logPath})}async function it(e,t){let n=t.bridgeScope;if(!n)return null;let r=null,i=null;try{r=await Q({baseUrl:t.proxyBaseUrl,bearerToken:t.proxyBearerToken,scope:n,timeoutMs:t.probeTimeoutMs})}catch(e){if(!We(e))throw e;i=e instanceof Error?e.message:String(e)}return(!r||r.probe.reachable===!1)&&(r=await at(e,t,n,r,i)),Je(t.proxyBaseUrl,r),r}async function at(t,n,r,i,a){let o;try{o=(await Ce({projectRoot:n.projectRoot,serverBaseUrl:n.proxyBaseUrl,bearerToken:n.proxyBearerToken,bridgeScope:r,localBaseUrl:`http://${n.statusHost}:${n.metroPort}`,launchUrl:B(t.launchUrl),profileKey:B(t.companionProfileKey),consumerKey:B(t.companionConsumerKey),env:n.env})).logPath}catch(t){throw new e(`COMMAND_FAILED`,$(n.proxyBaseUrl,t instanceof Error?t.message:String(t),i,a),void 0,t)}try{return await nt({baseUrl:n.proxyBaseUrl,bearerToken:n.proxyBearerToken,scope:r,probeTimeoutMs:n.probeTimeoutMs,startupTimeoutMs:n.startupTimeoutMs,initialBridgeError:a,companionLogPath:o})}catch(e){throw e instanceof Error?e:Error(String(e))}}function ot(e,t){return{baseIosRuntime:e?q(e,`ios`,t):{platform:`ios`},baseAndroidRuntime:e?q(e,`android`,t):{platform:`android`}}}function st(e,t){e&&(v.mkdirSync(_.dirname(e),{recursive:!0}),v.writeFileSync(e,JSON.stringify(t,null,2)))}async function ct(e={}){let t=et(e),n=t.installProjectDeps?Ie(t.projectRoot,t.env):{installed:!1},r=await rt(t),{baseIosRuntime:i,baseAndroidRuntime:a}=ot(t.publicBaseUrl,t.kind),o=await it(e,t),s=o?.iosRuntime??i,c=o?.androidRuntime??a,l={projectRoot:t.projectRoot,kind:t.kind,dependenciesInstalled:n.installed,packageManager:n.packageManager??null,started:r.started,reused:r.reused,pid:r.pid,logPath:t.logPath,statusUrl:r.statusUrl,runtimeFilePath:t.runtimeFilePath,iosRuntime:s,androidRuntime:c,bridge:o};return st(t.runtimeFilePath,l),l}function lt(e){let t=e.trimStart().slice(0,15).toLowerCase();return t.startsWith(`<!doctype`)||t.startsWith(`<html`)}async function ut(t,n){await new Promise((r,i)=>{let a=new WebSocket(t),o=t=>{clearTimeout(s);try{a.close()}catch{}i(new e(`COMMAND_FAILED`,t))},s=setTimeout(()=>{o(`Timed out broadcasting reload to ${t} after ${n}ms`)},n);a.addEventListener(`open`,()=>{a.send(JSON.stringify({version:2,method:`reload`}));let e=()=>{if(a.bufferedAmount===0){clearTimeout(s),a.close(),r();return}setTimeout(e,20)};e()}),a.addEventListener(`error`,()=>{o(`Failed to reach the dev server message socket at ${t}`)})})}async function dt(t={}){let n=K(t.timeoutMs,1e4,1e3),{reloadUrl:r,messageSocketUrl:i}=Te(t),a=await X(r,n);if(a.ok&&!lt(a.body))return{reloaded:!0,reloadUrl:r,status:a.status,body:a.body,transport:`http`};try{await ut(i,n)}catch(t){throw new e(`COMMAND_FAILED`,`React Native dev server reload failed (${a.status}).`,{reloadUrl:r,status:a.status,body:a.body.slice(0,500),messageSocketUrl:i,hint:`Verify Metro or Re.Pack is running and the target React Native app is connected to this dev server instance.`},t instanceof Error?t:void 0)}return{reloaded:!0,reloadUrl:i,status:a.status,body:``,transport:`message-socket`}}export{M as a,j as i,dt as n,we as r,ct as t};
|
|
@@ -1,139 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
//#region packages/contracts/src/back-mode.d.ts
|
|
3
|
-
declare const BACK_MODES: readonly ['in-app', 'system'];
|
|
4
|
-
type BackMode = (typeof BACK_MODES)[number];
|
|
5
|
-
//#endregion
|
|
6
|
-
//#region packages/contracts/src/device-rotation.d.ts
|
|
7
|
-
declare const DEVICE_ROTATIONS: readonly ['portrait', 'portrait-upside-down', 'landscape-left', 'landscape-right'];
|
|
8
|
-
type DeviceRotation = (typeof DEVICE_ROTATIONS)[number];
|
|
9
|
-
//#endregion
|
|
10
|
-
//#region packages/contracts/src/tv-remote.d.ts
|
|
11
|
-
declare const TV_REMOTE_BUTTON_DEFINITIONS: {
|
|
12
|
-
readonly up: {
|
|
13
|
-
readonly aliases: readonly [];
|
|
14
|
-
readonly androidKeyevent: 'KEYCODE_DPAD_UP';
|
|
15
|
-
readonly appleRemoteButton: 'up';
|
|
16
|
-
readonly vegaKey: 'KEY_UP';
|
|
17
|
-
};
|
|
18
|
-
readonly down: {
|
|
19
|
-
readonly aliases: readonly [];
|
|
20
|
-
readonly androidKeyevent: 'KEYCODE_DPAD_DOWN';
|
|
21
|
-
readonly appleRemoteButton: 'down';
|
|
22
|
-
readonly vegaKey: 'KEY_DOWN';
|
|
23
|
-
};
|
|
24
|
-
readonly left: {
|
|
25
|
-
readonly aliases: readonly [];
|
|
26
|
-
readonly androidKeyevent: 'KEYCODE_DPAD_LEFT';
|
|
27
|
-
readonly appleRemoteButton: 'left';
|
|
28
|
-
readonly vegaKey: 'KEY_LEFT';
|
|
29
|
-
};
|
|
30
|
-
readonly right: {
|
|
31
|
-
readonly aliases: readonly [];
|
|
32
|
-
readonly androidKeyevent: 'KEYCODE_DPAD_RIGHT';
|
|
33
|
-
readonly appleRemoteButton: 'right';
|
|
34
|
-
readonly vegaKey: 'KEY_RIGHT';
|
|
35
|
-
};
|
|
36
|
-
readonly select: {
|
|
37
|
-
readonly aliases: readonly ["ok", "center", "enter"];
|
|
38
|
-
readonly androidKeyevent: 'KEYCODE_DPAD_CENTER';
|
|
39
|
-
readonly appleRemoteButton: 'select';
|
|
40
|
-
readonly vegaKey: 'KEY_ENTER';
|
|
41
|
-
};
|
|
42
|
-
readonly menu: {
|
|
43
|
-
readonly aliases: readonly [];
|
|
44
|
-
readonly androidKeyevent: 'KEYCODE_MENU';
|
|
45
|
-
readonly appleRemoteButton: 'menu';
|
|
46
|
-
readonly vegaKey: 'KEY_MENU';
|
|
47
|
-
};
|
|
48
|
-
readonly home: {
|
|
49
|
-
readonly aliases: readonly [];
|
|
50
|
-
readonly androidKeyevent: 'KEYCODE_HOME';
|
|
51
|
-
readonly appleRemoteButton: 'home';
|
|
52
|
-
readonly vegaKey: 'KEY_HOMEPAGE';
|
|
53
|
-
};
|
|
54
|
-
readonly back: {
|
|
55
|
-
readonly aliases: readonly [];
|
|
56
|
-
readonly androidKeyevent: 'KEYCODE_BACK';
|
|
57
|
-
readonly appleRemoteButton: 'menu';
|
|
58
|
-
readonly vegaKey: 'KEY_BACK';
|
|
59
|
-
};
|
|
60
|
-
};
|
|
61
|
-
declare const TV_REMOTE_BUTTONS: (keyof typeof TV_REMOTE_BUTTON_DEFINITIONS)[];
|
|
62
|
-
type TvRemoteButton = (typeof TV_REMOTE_BUTTONS)[number];
|
|
63
|
-
//#endregion
|
|
64
|
-
//#region packages/contracts/src/session-surface.d.ts
|
|
65
|
-
declare const SESSION_SURFACES: readonly ['app', 'frontmost-app', 'desktop', 'menubar'];
|
|
66
|
-
type SessionSurface = (typeof SESSION_SURFACES)[number];
|
|
67
|
-
//#endregion
|
|
68
|
-
//#region packages/contracts/src/snapshot-diagnostics.d.ts
|
|
69
|
-
type SnapshotTimingStats = {
|
|
70
|
-
count: number;
|
|
71
|
-
p50Ms: number;
|
|
72
|
-
p95Ms: number;
|
|
73
|
-
maxMs: number;
|
|
74
|
-
slowThresholdMs: number;
|
|
75
|
-
platform?: PublicPlatform;
|
|
76
|
-
backends?: Record<string, number>;
|
|
77
|
-
};
|
|
78
|
-
type SnapshotDiagnosticsSummary = {
|
|
79
|
-
stats: SnapshotTimingStats;
|
|
80
|
-
warning?: string;
|
|
81
|
-
};
|
|
82
|
-
//#endregion
|
|
83
|
-
//#region packages/contracts/src/snapshot-types.d.ts
|
|
84
|
-
type ScreenshotResultData = {
|
|
85
|
-
path?: string;
|
|
86
|
-
width?: number;
|
|
87
|
-
height?: number;
|
|
88
|
-
logicalWidth?: number;
|
|
89
|
-
logicalHeight?: number;
|
|
90
|
-
pixelDensity?: number;
|
|
91
|
-
overlayRefs?: ScreenshotOverlayRef[];
|
|
92
|
-
};
|
|
93
|
-
type BackendSnapshotResult = {
|
|
94
|
-
nodes?: SnapshotNode[];
|
|
95
|
-
truncated?: boolean;
|
|
96
|
-
backend?: string;
|
|
97
|
-
snapshot?: SnapshotState;
|
|
98
|
-
appName?: string;
|
|
99
|
-
appBundleId?: string;
|
|
100
|
-
snapshotDiagnostics?: SnapshotDiagnosticsSummary;
|
|
101
|
-
analysis?: {
|
|
102
|
-
rawNodeCount: number;
|
|
103
|
-
maxDepth: number;
|
|
104
|
-
};
|
|
105
|
-
androidSnapshot?: AndroidSnapshotBackendMetadata;
|
|
106
|
-
freshness?: {
|
|
107
|
-
action: string;
|
|
108
|
-
retryCount: number;
|
|
109
|
-
staleAfterRetries: boolean;
|
|
110
|
-
reason?: 'empty-interactive' | 'sharp-drop' | 'stuck-route';
|
|
111
|
-
};
|
|
112
|
-
quality?: SnapshotQualityVerdict;
|
|
113
|
-
warnings?: string[];
|
|
114
|
-
};
|
|
115
|
-
type AndroidSnapshotBackendMetadata = {
|
|
116
|
-
backend: 'android-helper';
|
|
117
|
-
helperVersion?: string;
|
|
118
|
-
helperApiVersion?: string;
|
|
119
|
-
helperTransport?: string;
|
|
120
|
-
helperSessionReused?: boolean;
|
|
121
|
-
installReason?: string;
|
|
122
|
-
waitForIdleTimeoutMs?: number;
|
|
123
|
-
waitForIdleQuietMs?: number;
|
|
124
|
-
timeoutMs?: number;
|
|
125
|
-
maxDepth?: number;
|
|
126
|
-
maxNodes?: number;
|
|
127
|
-
rootPresent?: boolean;
|
|
128
|
-
captureMode?: string;
|
|
129
|
-
systemSurfaceOnly?: boolean;
|
|
130
|
-
windowCount?: number;
|
|
131
|
-
nodeCount?: number;
|
|
132
|
-
helperTruncated?: boolean;
|
|
133
|
-
elapsedMs?: number;
|
|
134
|
-
};
|
|
135
|
-
type FindLocator = 'any' | 'text' | 'label' | 'value' | 'role' | 'id';
|
|
136
|
-
//#endregion
|
|
1
|
+
import { n as DaemonArtifactType } from "./sdk-contracts.js";
|
|
137
2
|
//#region packages/contracts/src/cloud-artifacts.d.ts
|
|
138
3
|
declare const CLOUD_ARTIFACT_KINDS: readonly ['video', 'appium-log', 'device-log', 'automation-log', 'provider-session', 'raw'];
|
|
139
4
|
type CloudArtifactKind = (typeof CLOUD_ARTIFACT_KINDS)[number];
|
|
@@ -193,4 +58,4 @@ type CloudArtifactProvider = {
|
|
|
193
58
|
listCloudArtifacts?: (query: CloudArtifactsQuery) => Promise<CloudArtifactsResult | undefined>;
|
|
194
59
|
};
|
|
195
60
|
//#endregion
|
|
196
|
-
export {
|
|
61
|
+
export { CloudArtifactProvider as n, CloudProviderSessionResult as r, AgentArtifactsResult as t };
|