agent-device 0.21.3 → 0.21.4
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/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.3.apk → agent-device-android-ime-helper-0.21.4.apk} +0 -0
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.4.apk.sha256 +1 -0
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.3.manifest.json → agent-device-android-ime-helper-0.21.4.manifest.json} +4 -4
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.21.3.apk → agent-device-android-snapshot-helper-0.21.4.apk} +0 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.4.apk.sha256 +1 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.4.manifest.json +16 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunner/AgentDeviceRunnerApp.m +39 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSystemSurfaceHostPolicy.swift +9 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+AXSnapshotFallback.swift +2 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Alert.swift +10 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +26 -124
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandJournal.swift +46 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Lifecycle.swift +36 -4
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+MainThreadWork.swift +229 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +15 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +4 -40
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCapturePlan.swift +6 -40
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Transport.swift +30 -9
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests.swift +22 -6
- package/dist/src/adapter.js +1 -1
- package/dist/src/adb-executor.js +2 -2
- package/dist/src/adb-failure.js +1 -1
- package/dist/src/agent-browser-process-record.js +1 -1
- package/dist/src/agent-device-client.js +2 -2
- package/dist/src/api.js +3 -11
- package/dist/src/app-launch.js +1 -1
- package/dist/src/app-lifecycle.js +1 -1
- package/dist/src/app-log-reconnect.js +1 -1
- package/dist/src/archive.js +2 -2
- package/dist/src/cli-help.js +2 -2
- package/dist/src/cli.js +4 -4
- package/dist/src/client-metro-companion.js +1 -1
- package/dist/src/client-metro.js +1 -1
- package/dist/src/client-types.d.ts +69 -4
- package/dist/src/code-signature-cache.js +1 -1
- package/dist/src/command-tools.js +2 -2
- package/dist/src/command.js +1 -1
- package/dist/src/connection-runtime.js +1 -1
- package/dist/src/contracts.js +1 -1
- package/dist/src/daemon-client-lifecycle.js +1 -1
- package/dist/src/daemon-shutdown-report.js +1 -1
- package/dist/src/device-claim-rule.js +1 -1
- package/dist/src/device-input-state.d.ts +10 -8
- package/dist/src/device-inventory-context.js +1 -1
- package/dist/src/device-session.js +1 -1
- package/dist/src/diagnostics.js +1 -1
- package/dist/src/error.js +2 -2
- package/dist/src/exec.js +1 -1
- package/dist/src/file.js +1 -1
- package/dist/src/find.js +1 -1
- package/dist/src/gesture-runtime.js +1 -1
- package/dist/src/helper.js +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/install-source-network-transport.js +1 -1
- package/dist/src/interaction2.js +1 -1
- package/dist/src/interactor.js +4 -4
- package/dist/src/internal/bin.js +1 -1
- package/dist/src/internal/daemon.js +2 -2
- package/dist/src/internal/png-worker.js +1 -1
- package/dist/src/ios-client.js +121 -7
- package/dist/src/ios-snapshot-adapter.js +1 -1
- package/dist/src/ios-system-surface.js +1 -1
- package/dist/src/limrun-delta-sync-omitted.js +1 -0
- package/dist/src/limrun.d.ts +0 -1598
- package/dist/src/location-coordinates.js +1 -1
- package/dist/src/mechanics.js +16 -16
- package/dist/src/output-common.js +2 -0
- package/dist/src/owner-identity.js +1 -1
- package/dist/src/perf-runtime-operation-builder.js +1 -1
- package/dist/src/perf-runtime-plan.js +1 -1
- package/dist/src/platform-runtime-android-adb-host.js +1 -1
- package/dist/src/platform-runtime-app-log-android-transport.js +1 -1
- package/dist/src/platform-runtime-app-log-process.js +1 -1
- package/dist/src/platform-runtime-host.js +1 -1
- package/dist/src/platform-runtime-operation-host.js +2 -2
- package/dist/src/platform-runtime-screen-recording-android-host.js +1 -1
- package/dist/src/platform-runtime-screen-recording-finalizer-host.js +1 -1
- package/dist/src/platform-runtime-screen-recording-output-host.js +1 -1
- package/dist/src/platform-runtime-screen-recording-process-host.js +1 -1
- package/dist/src/process.js +1 -1
- package/dist/src/proxy.js +1 -1
- package/dist/src/quality-warnings.js +1 -1
- package/dist/src/react-native.js +1 -1
- package/dist/src/record-runtime.js +1 -1
- package/dist/src/recording-stop-observation.js +1 -0
- package/dist/src/registry.js +35 -36
- package/dist/src/replay-divergence.js +1 -1
- package/dist/src/reporting.js +11 -9
- package/dist/src/result-serialization.js +1 -1
- package/dist/src/runner-cache-metadata.js +1 -1
- package/dist/src/runner-client.js +1 -1
- package/dist/src/runner-disposal.js +1 -1
- package/dist/src/runner-operations-facade.js +1 -1
- package/dist/src/runner.js +1 -1
- package/dist/src/runtime.js +3 -3
- package/dist/src/runtime10.js +1 -1
- package/dist/src/runtime2.js +4 -4
- package/dist/src/runtime3.js +1 -1
- package/dist/src/runtime4.js +4 -4
- package/dist/src/runtime5.js +1 -1
- package/dist/src/runtime6.js +1 -1
- package/dist/src/runtime9.js +1 -1
- package/dist/src/screen-recording-completion.js +1 -1
- package/dist/src/screen-recording-resource-recovery.js +1 -1
- package/dist/src/screenshot-result.js +1 -1
- package/dist/src/sdk-contracts.js +2 -2
- package/dist/src/sdk-selectors.d.ts +36 -24
- package/dist/src/selector-runtime.js +1 -1
- package/dist/src/session-observation.js +1 -1
- package/dist/src/session-snapshot.js +1 -1
- package/dist/src/session-store.js +2 -2
- package/dist/src/session2.js +5 -5
- package/dist/src/snapshot-runtime.js +1 -1
- package/dist/src/snapshot.js +1 -1
- package/dist/src/snapshot4.js +1 -1
- package/dist/src/stop-sequence.js +1 -0
- package/dist/src/success-text.js +1 -1
- package/dist/src/text-entry-focus.js +1 -0
- package/dist/src/tool-provider.js +1 -1
- package/dist/src/tool-provider2.js +1 -1
- package/dist/src/tool-provider3.js +1 -1
- package/dist/src/type-text-runtime.js +1 -1
- package/dist/src/video.js +2 -2
- package/dist/src/yauzl.js +1 -0
- package/package.json +2 -2
- package/server.json +2 -2
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.3.apk.sha256 +0 -1
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.3.apk.sha256 +0 -1
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.3.manifest.json +0 -17
- package/dist/src/audio-probe-support.js +0 -1
- package/dist/src/screen-recording-live-handle.js +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import{B as e,C as t,M as n,N as r,R as i}from"./sdk-contracts.js";import{a,p as o,u as s}from"./lease-scope.js";import{w as c}from"./sdk-batch.js";import{n as l}from"./catalog.js";import{n as u,r as d}from"./diagnostics.js";import{c as f,d as p,p as m}from"./exec.js";import{t as h}from"./timeouts.js";import"./diagnostics2.js";import{r as ee,t as te}from"./output-path.js";import{d as g,i as ne,m as _,n as v,p as re,t as y}from"./transport.js";import{n as b,r as x}from"./command.js";import{i as ie}from"./replay-divergence.js";import"./retry.js";import{t as ae}from"./session-repair-tombstone.js";import{i as oe,n as se,r as S}from"./version.js";import{t as ce}from"./ttl-memo.js";import{n as le,r as ue,t as de}from"./daemon-resolution.js";import{i as fe,n as pe}from"./code-signature.js";import{n as me,t as C}from"./daemon-process.js";import{n as he,o as ge,t as _e}from"./request-progress-protocol.js";import{t as ve}from"./session-artifact-paths.js";import w from"node:path";import T from"node:fs";import{createHash as ye,randomUUID as E}from"node:crypto";import D from"node:os";import{Transform as be,Writable as xe}from"node:stream";import{pipeline as O}from"node:stream/promises";import k from"node:net";async function Se(e,t){let n=T.statSync(e),r=w.basename(e),i=n.isDirectory(),a=Te(t)??we(e,n),o=[];try{let t=i?await Ce(e,o):e,n=T.statSync(t);return{payloadPath:t,fileName:r,artifactType:i?`app-bundle`:`file`,platform:a,contentType:i?`application/gzip`:`application/octet-stream`,sha256:await Ee(t),sizeBytes:n.size,cleanup:()=>A(o)}}catch(e){throw A(o),e}}async function Ce(e,t){let n=T.mkdtempSync(w.join(D.tmpdir(),`agent-device-upload-${E()}-`));t.push(n);let r=w.join(n,`${w.basename(e)}.tar.gz`);return await f(`tar`,[`czf`,r,`-C`,w.dirname(e),w.basename(e)],{env:{...process.env,COPYFILE_DISABLE:`1`}}),r}function we(e,t){let n=e.toLowerCase();if(t.isDirectory()&&n.endsWith(`.app`)||n.endsWith(`.ipa`))return`ios`;if(n.endsWith(`.apk`)||n.endsWith(`.aab`))return`android`}function Te(e){return e===`ios`||e===`android`?e:void 0}function A(e){for(let t of e)T.rmSync(t,{recursive:!0,force:!0})}async function Ee(e){let n=ye(`sha256`),r=new xe({write(e,t,r){n.update(e),r()}});return await O(T.createReadStream(e),r).catch(e=>{throw new t(`COMMAND_FAILED`,`Failed to read local artifact`,{},e instanceof Error?e:void 0)}),n.digest(`hex`)}function De(e){let{stage:t,fileName:n,startOffset:r,totalBytes:i,onProgress:a}=e,o=r,s=Ae(i),c=Math.min(i,r+s);return new be({transform(e,r,l){o=Math.min(i,o+e.byteLength),o>=c&&(a?.({type:`progress`,stage:t,fileName:n,transferredBytes:o,totalBytes:i}),c=Math.min(i,o+s)),l(null,e)}})}function Oe(){if(!(process.stderr.isTTY!==!0||process.env.CI))return e=>{process.stderr.write(`${ke(e)}\n`)}}function ke(e){switch(e.type){case`start`:return`Uploading ${e.fileName} (${M(e.totalBytes)}) via ${j(e.stage)} upload`;case`resume`:return`Resuming ${e.fileName} at ${M(e.transferredBytes)} of ${M(e.totalBytes)}`;case`progress`:return`Uploaded ${M(e.transferredBytes)} of ${M(e.totalBytes)} (${je(e.transferredBytes,e.totalBytes)})`;case`fallback`:return`Direct upload did not complete; retrying ${e.fileName} with ${j(e.to)} upload`}}function Ae(e){return Math.max(8388608,Math.ceil(e*.05))}function j(e){return e===`direct`?`direct`:`legacy`}function je(e,t){return t<=0?`100%`:`${Math.min(100,Math.floor(e/t*100))}%`}function M(e){if(e<1024)return`${e} B`;let t=e/1024;if(t<1024)return`${t.toFixed(1)} KiB`;let n=t/1024;return n<1024?`${n.toFixed(1)} MiB`:`${(n/1024).toFixed(1)} GiB`}const N=3e5,P=`uploadStreamRetryable`;async function F(e){return await I({...e,url:e.url,redirectCount:0,startOffset:0})}function Me(e){return e instanceof t&&e.details?.[P]===!0}async function I(e){let n=await v(e.url.protocol),r=T.statSync(e.payloadPath).size,i=Fe(e.headers,e.startOffset,r);return Pe(e.progress,e.startOffset,r),await new Promise((a,o)=>{let s=!1,c=n.request({protocol:e.url.protocol,host:e.url.hostname,port:e.url.port,method:e.method,path:e.url.pathname+e.url.search,headers:i},n=>{s=!0,ne(n).then(i=>{clearTimeout(l);let s=n.statusCode??500,c=n.headers.location;if(c&&Ie(s)){if(e.redirectCount>=5){o(new t(`COMMAND_FAILED`,`Artifact upload exceeded redirect limit`,{maxRedirects:5,url:e.url.toString()}));return}let n=new URL(c,e.url);I({...e,url:n,redirectCount:e.redirectCount+1}).then(a,o);return}let u=Le(s)?Re(n.headers,r):void 0;if(u!==void 0){if(u>=r){a({statusCode:200,statusMessage:`Upload already complete`,body:``});return}if(u<=e.startOffset){o(new t(`COMMAND_FAILED`,`Artifact upload resume did not advance`,{offset:u,previousOffset:e.startOffset,url:e.url.toString()}));return}I({...e,startOffset:u}).then(a,o);return}a({statusCode:s,statusMessage:n.statusMessage,body:i})}).catch(o)}),l=setTimeout(()=>{c.destroy(),o(new t(`COMMAND_FAILED`,e.timeoutMessage,{timeoutMs:N,...e.timeoutHint?{hint:e.timeoutHint}:{},...Ne(e)}))},N);c.on(`error`,n=>{s||(clearTimeout(l),o(new t(`COMMAND_FAILED`,e.errorMessage,{...e.errorHint?{hint:e.errorHint}:{},...Ne(e)},n)))}),c.on(`close`,()=>clearTimeout(l)),O(T.createReadStream(e.payloadPath,{start:e.startOffset}),De({stage:e.progress?.stage??`legacy`,fileName:e.progress?.fileName??w.basename(e.payloadPath),startOffset:e.startOffset,totalBytes:r,onProgress:e.progress?.onProgress}),c).catch(e=>{if(s)return;c.destroy();let n=e instanceof Error?e:Error(String(e));o(new t(`COMMAND_FAILED`,`Failed to read local artifact`,{},n))})})}function Ne(e){return e.retryable===!0?{[P]:!0}:{}}function Pe(e,t,n){e?.onProgress?.({type:t>0?`resume`:`start`,stage:e.stage,fileName:e.fileName,transferredBytes:t,totalBytes:n})}function Fe(e,t,n){return t<=0?e:{...e,"content-length":Math.max(n-t,0),"content-range":`bytes ${t}-${n-1}/${n}`}}function Ie(e){return[301,302,303,307,308].includes(e)}function Le(e){return e===308}function Re(e,t){let n=ze(e[`x-upload-offset`]??e[`upload-offset`]);if(n!==void 0)return Math.min(n,t);let r=Be(e.range)?.match(/^bytes=0-(\d+)$/);if(!r)return;let i=Number(r[1]);if(!(!Number.isSafeInteger(i)||i<0))return Math.min(i+1,t)}function ze(e){let t=Be(e);if(t===void 0)return;let n=Number(t);return Number.isSafeInteger(n)&&n>=0?n:void 0}function Be(e){return Array.isArray(e)?e[0]:e}const Ve=3e4;async function He(e){let t=await Se(e.localPath,e.platform),n=e.baseUrl.endsWith(`/`)?e.baseUrl:`${e.baseUrl}/`,r=E();try{let i=await Ke({normalizedBase:n,token:e.token,artifact:t,uploadAttemptId:r});return i?.kind===`cache-hit`?i.uploadId:i?.kind===`direct-upload`?await Ue({normalizedBase:n,token:e.token,artifact:t,preflight:i,uploadAttemptId:r,onProgress:e.onProgress})||(e.onProgress?.({type:`fallback`,from:`direct`,to:`legacy`,fileName:t.fileName}),await Ge({normalizedBase:n,token:e.token,artifact:t,onProgress:e.onProgress})):await Ge({normalizedBase:n,token:e.token,artifact:t,onProgress:e.onProgress})}finally{t.cleanup()}}async function Ue(e){let t=async t=>(await Ye(e.artifact,t,e.onProgress),await Xe({normalizedBase:e.normalizedBase,token:e.token,uploadId:t.uploadId}));try{return await t(e.preflight)}catch(n){if(!We(n))return;let r=await Ke({normalizedBase:e.normalizedBase,token:e.token,artifact:e.artifact,uploadAttemptId:e.uploadAttemptId});if(r?.kind===`cache-hit`)return r.uploadId;if(r?.kind===`direct-upload`)try{return await t(r)}catch{return}return}}function We(e){return e instanceof t?Me(e):!0}async function Ge(e){let{normalizedBase:n,token:r,artifact:i}=e,a=new URL(`upload`,n),o={"content-type":i.contentType,"x-artifact-type":i.artifactType,"x-artifact-filename":i.fileName,"x-artifact-hash":i.sha256,"x-artifact-hash-algorithm":`sha256`,"transfer-encoding":`chunked`};Object.assign(o,g(r));let s=await F({url:a,method:`POST`,headers:o,payloadPath:i.payloadPath,timeoutMessage:`Artifact upload timed out`,timeoutHint:`The upload to the remote daemon exceeded the 5-minute timeout.`,errorMessage:`Failed to upload artifact to remote daemon`,errorHint:`Verify the remote daemon is reachable and supports artifact uploads.`,progress:{stage:`legacy`,fileName:i.fileName,onProgress:e.onProgress}});try{let e=JSON.parse(s.body);if(!e.ok||!e.uploadId)throw new t(`COMMAND_FAILED`,`Upload failed: ${s.body}`);return e.uploadId}catch(e){throw e instanceof t?e:new t(`COMMAND_FAILED`,`Invalid upload response: ${s.body}`)}}async function Ke(e){let t=new URL(`upload/preflight`,e.normalizedBase),n={"content-type":`application/json`};Object.assign(n,g(e.token));let r=await fetch(t,{method:`POST`,headers:n,signal:AbortSignal.timeout(Ve),body:JSON.stringify({uploadAttemptId:e.uploadAttemptId,sha256:e.artifact.sha256,fileName:e.artifact.fileName,sizeBytes:e.artifact.sizeBytes,artifactType:e.artifact.artifactType,...e.artifact.platform?{platform:e.artifact.platform}:{},contentType:e.artifact.contentType})}).catch(()=>void 0);if(r?.ok)return qe(await r.json().catch(()=>void 0))}function qe(e){if(!e||typeof e!=`object`)return;let t=e;if(t.ok!==!0||typeof t.uploadId!=`string`)return;if(t.cacheHit===!0)return{kind:`cache-hit`,uploadId:t.uploadId};let n=t.upload;if(!n||typeof n.url!=`string`)return;let r=n.headers??{};if(Je(r))return{kind:`direct-upload`,uploadId:t.uploadId,url:n.url,headers:r}}function Je(e){return!e||typeof e!=`object`||Array.isArray(e)?!1:Object.values(e).every(e=>typeof e==`string`)}async function Ye(e,n,r){let i=await F({url:new URL(n.url),method:`PUT`,headers:n.headers,payloadPath:e.payloadPath,timeoutMessage:`Direct artifact upload timed out`,timeoutHint:`The direct upload ticket did not accept the artifact within the timeout.`,errorMessage:`Failed to upload artifact with direct upload ticket`,retryable:!0,progress:{stage:`direct`,fileName:e.fileName,onProgress:r}});if(i.statusCode<200||i.statusCode>=300)throw new t(`COMMAND_FAILED`,`Direct artifact upload failed`,{statusCode:i.statusCode,statusMessage:i.statusMessage})}async function Xe(e){let n=new URL(`upload/finalize`,e.normalizedBase),r={"content-type":`application/json`};Object.assign(r,g(e.token));let i=await fetch(n,{method:`POST`,headers:r,signal:AbortSignal.timeout(Ve),body:JSON.stringify({uploadId:e.uploadId})}).catch(e=>{throw new t(`COMMAND_FAILED`,`Failed to finalize direct artifact upload`,{},e)});if(!i.ok)throw new t(`COMMAND_FAILED`,`Direct artifact upload finalize failed`,{status:i.status,statusText:i.statusText});let a=await i.json().catch(()=>void 0);if(!a?.ok||!a.uploadId)throw new t(`COMMAND_FAILED`,`Invalid upload finalize response`);return a.uploadId}async function Ze(e,t){let n=[...e.positionals??[]],r=e.flags?{...e.flags}:void 0,i=e.meta?.installSource,a={},o,s=Oe();if(!_t(t))return rt({positionals:n,flags:r,installSource:i,uploadedArtifactId:o,clientArtifactPaths:a});Qe(e),r=et(e,n,r,a);let c=await it(e,t,s);return c&&(i=c.installSource,o=c.uploadedArtifactId??o),e.command!==`install`&&e.command!==`reinstall`||(o=await $e(e,t,n,s)??o),rt({positionals:n,flags:r,installSource:i,uploadedArtifactId:o,clientArtifactPaths:a})}function Qe(e){if(e.flags?.saveScript!==void 0)throw new t(`INVALID_ARGS`,`--save-script is not supported against a remote daemon: the healed script would be written on the daemon host, not on this machine.`,{hint:`Run the script against a local daemon to capture a healed .ad, or re-run without --save-script.`,command:e.command})}async function $e(e,t,n,r){let i=n.length===1?0:1,a=n[i];if(a===void 0)return;if(a.startsWith(`remote:`)){n[i]=a.slice(7);return}let o=nt(a,e.meta?.cwd);if(o)return await He({localPath:o,baseUrl:t.baseUrl,token:t.token,platform:e.flags?.platform,onProgress:r})}function et(e,t,n,r){let i=at(e,t);if(!i)return n;i.positionalIndex!==void 0&&i.positionalPath!==void 0&&(t[i.positionalIndex]=i.positionalPath);let a=tt(n,i.flagKey??`out`,i.flagPath);return r[i.field]=i.localPath,a}function tt(e,t,n){return n===void 0?e:{...e??{},[t]:n}}function nt(e,t){let n=w.isAbsolute(e)?e:w.resolve(t??process.cwd(),e);return T.existsSync(n)?n:void 0}function rt(e){return{positionals:e.positionals,flags:e.flags,installSource:e.installSource,uploadedArtifactId:e.uploadedArtifactId,...Object.keys(e.clientArtifactPaths).length>0?{clientArtifactPaths:e.clientArtifactPaths}:{}}}async function it(e,t,n){let r=e.meta?.installSource;if(e.command!==`install_source`||!r||r.kind!==`path`)return null;let i=r.path.trim();if(!i)return{installSource:r};if(i.startsWith(`remote:`))return{installSource:{...r,path:i.slice(7)}};let a=w.isAbsolute(i)?i:w.resolve(e.meta?.cwd??process.cwd(),i);if(!T.existsSync(a))return{installSource:{...r,path:a}};let o=await He({localPath:a,baseUrl:t.baseUrl,token:t.token,platform:e.flags?.platform,onProgress:n});return{installSource:{...r,path:a},uploadedArtifactId:o}}function at(e,t){if(e.command===`screenshot`){let n=ut(e,`path`,`.png`);return t[0]?{field:`path`,localPath:n,positionalIndex:0,positionalPath:R(`screenshot`,`.png`)}:{field:`path`,localPath:n,positionalIndex:0,flagPath:R(`screenshot`,`.png`)}}if(e.command===`record`&&(t[0]??``).toLowerCase()===`start`){if(!ct(e)&&e.flags?.platform===void 0)return null;let t=st(e),n=lt(ut(e,`outPath`,t,1),e);return{field:`outPath`,localPath:n,positionalIndex:1,positionalPath:R(`recording`,w.extname(n)||t)}}return e.command===`test`?{field:`artifactsDir`,localPath:ot(e),flagKey:`artifactsDir`,flagPath:ft(`test-artifacts`)}:null}function ot(e){let t=e.flags?.artifactsDir;return dt(L(t)?t:`.agent-device/test-artifacts`,e.meta?.cwd)}function st(e){return ee(e.flags?.platform)}function ct(e){return L(e.positionals?.[1])||L(e.flags?.out)}function lt(e,t){return t.flags?.platform===`web`?te(e,st(t)):e}function ut(e,t,n,r=0){let i=e.positionals?.[r]??e.flags?.out,a=`${t===`path`?`screenshot`:`recording`}-${Date.now()}${n}`;return dt(L(i)?i:a,e.meta?.cwd)}function dt(e,t){return w.isAbsolute(e)?e:w.resolve(t??process.cwd(),e)}function L(e){return typeof e==`string`&&e.trim().length>0}function R(e,t){let n=t.startsWith(`.`)?t:`.${t}`;return w.posix.join(`/tmp`,`agent-device-${e}-${Date.now()}-${Math.random().toString(36).slice(2,8)}${n}`)}function ft(e){return w.posix.join(`/tmp`,`agent-device-${e}-${Date.now()}-${Math.random().toString(36).slice(2,8)}`)}async function pt(e,t,n){let r=Array.isArray(n.data?.artifacts)?n.data.artifacts:[];if(r.length===0||!e.baseUrl)return n;let i=n.data?{...n.data}:{},a=[];for(let n of r){if(!n||typeof n!=`object`||typeof n.artifactId!=`string`){a.push(n);continue}let r=mt(n,t),o=await ht({baseUrl:e.baseUrl,token:e.token,artifactId:n.artifactId,destinationPath:r,requestScope:t.meta,isDirectory:n.artifactType===`test-artifacts`});i[n.field]=o,a.push({...n,localPath:o})}return i.artifacts=a,{ok:!0,data:i}}function mt(e,t){if(e.localPath&&e.localPath.trim().length>0)return e.localPath;let n=t.meta?.clientArtifactPaths?.[e.field];if(n&&n.trim().length>0)return n;let r=e.fileName?.trim()||`${e.field}-${Date.now()}`;return w.resolve(t.meta?.cwd??process.cwd(),r)}async function ht(e){let{downloadRemoteArtifactFromUrl:t}=await import(`./artifact-download.js`);return await t({artifactUrl:new URL(gt(e.baseUrl,e.artifactId)),token:e.token,artifactId:e.artifactId,destinationPath:e.destinationPath,requestScope:e.requestScope,...e.timeoutMs===void 0?{}:{timeoutMs:e.timeoutMs},...e.isDirectory===void 0?{}:{isDirectory:e.isDirectory}})}function gt(e,t){let n=e.endsWith(`/`)?e:`${e}/`;return new URL(`artifacts/${encodeURIComponent(t)}`,n).toString()}function _t(e){return typeof e.baseUrl==`string`&&e.baseUrl.length>0}const vt=ce();function yt(){let e=vt.get(`local`);if(e)return e;let n=se(),r=[w.join(n,`dist`,`src`,`internal`,`daemon.js`),w.join(n,`dist`,`src`,`daemon.js`)],i=r[0];if(i===void 0)throw new t(`COMMAND_FAILED`,`Daemon dist path list is empty`);let a=r.find(e=>T.existsSync(e))??i,o=w.join(n,oe),s=r.some(e=>T.existsSync(e)),c=T.existsSync(o);if(!s&&!c)throw new t(`COMMAND_FAILED`,`Daemon entry not found`,{distPaths:r,srcPath:o});let l={root:n,distPath:a,distPaths:r,srcPath:o,useSrc:(process.execArgv.includes(`--experimental-strip-types`)||!s)&&c};return vt.set(`local`,l),l}async function bt(){let e=yt(),t=fe(e.root);if(t===`installed`)return{origin:t};if(!e.useSrc)return{origin:t,codeSignature:pe(e.distPath,e.root)};let{resolveCachedDaemonCodeSignature:n}=await import(`./code-signature-cache.js`);return{origin:t,codeSignature:await n(e.srcPath,e.root)}}async function xt(e,t){if(e.version!==S())return`version mismatch (client v${S()})`;let n=St(await bt(),e);if(n)return n;if(!t)return`unreachable`}function St(e,t){return e.origin===`installed`?t.codeOrigin===`installed`?void 0:Ct(e,t):t.codeOrigin===`installed`?Ct(e,t):t.codeSignature===e.codeSignature?void 0:`code-signature mismatch`}function Ct(e,t){return`code origin mismatch (daemon ${t.codeOrigin??`unreported`}, client ${e.origin})`}const wt=3e3,Tt=1e3;function z(e){let t=Ft(e);if(!t||typeof t!=`object`)return null;let n=t,r=Et(n);if(!r)return null;let i=Dt(n);return i?{token:r,...i,transport:kt(n.transport),pid:V(n.pid)??0,version:B(n.version),codeOrigin:Ot(n.codeOrigin),codeSignature:B(n.codeSignature),processStartTime:B(n.processStartTime)}:null}function Et(e){return typeof e.token==`string`&&e.token.length>0?e.token:null}function Dt(e){let t=V(e.port),n=V(e.httpPort);return t===void 0&&n===void 0?null:{port:t,httpPort:n}}function Ot(e){return e===`installed`||e===`checkout`?e:void 0}function kt(e){return e===`socket`||e===`http`||e===`dual`?e:void 0}function B(e){return typeof e==`string`?e:void 0}function V(e){return Number.isInteger(e)&&Number(e)>0?Number(e):void 0}function H(e){let t=Ft(e);if(!t||typeof t!=`object`)return null;let n=t;return Number.isInteger(n.pid)&&Number(n.pid)>0?{pid:Number(n.pid),processStartTime:typeof n.processStartTime==`string`?n.processStartTime:void 0,startedAt:typeof n.startedAt==`number`?n.startedAt:void 0}:null}function U(e){It(e)}function W(e){It(e)}function At(e){let t=K(e);if(!t.hasLock||t.hasInfo)return;let n=H(e.lockPath);if(!n){W(e.lockPath);return}C(n.pid,n.processStartTime)||W(e.lockPath)}async function G(e,t,n={}){let r=n.stopLiveProcesses??!0,i={reason:t,removedInfo:!1,removedLock:!1,stoppedInfoProcess:!1,stoppedLockProcess:!1};try{let t=T.existsSync(e.infoPath),n=z(e.infoPath);if(n){let t=C(n.pid,n.processStartTime);t&&!r?i.retainedInfoProcess=!0:(t&&(await q(n),i.stoppedInfoProcess=!0),U(e.infoPath),i.removedInfo=!0)}else t&&(U(e.infoPath),i.removedInfo=!0);let a=T.existsSync(e.lockPath),o=H(e.lockPath);if(o){let t=C(o.pid,o.processStartTime);t&&!r?i.retainedLockProcess=!0:(t&&(await me(o.pid,{termTimeoutMs:wt,killTimeoutMs:Tt,expectedStartTime:o.processStartTime}),i.stoppedLockProcess=!0),W(e.lockPath),i.removedLock=!0)}else a&&(W(e.lockPath),i.removedLock=!0)}catch(e){i.error=e instanceof Error?e.message:String(e)}return d({level:i.error?`warn`:`info`,phase:`daemon_startup_metadata_cleanup`,data:i}),i}function K(e){return{hasInfo:T.existsSync(e.infoPath),hasLock:T.existsSync(e.lockPath)}}async function jt(e){let t=K(e);if(!t.hasLock||t.hasInfo)return!1;let n=H(e.lockPath);return!n||!C(n.pid,n.processStartTime)?(W(e.lockPath),!0):!1}async function q(e){await me(e.pid,{termTimeoutMs:wt,killTimeoutMs:Tt,expectedStartTime:e.processStartTime})}function Mt(e){return typeof e.baseUrl==`string`&&e.baseUrl.length>0}function Nt(e,t=de(process.env.AGENT_DEVICE_STATE_DIR)){let n=Pt(t);return e.hasLock&&!e.hasInfo?`agent-device attempted to clean stale daemon metadata automatically, but ${t.lockPath} still exists without ${t.infoPath}. Retry with --debug; if this persists after confirming no agent-device daemon process is running, run: ${n}`:e.hasLock&&e.hasInfo?`agent-device attempted to clean stale daemon metadata automatically, but ${t.infoPath} and ${t.lockPath} still remain. Retry with --debug; if this persists after confirming no agent-device daemon process is running, run: ${n}`:e.hasInfo?`agent-device did not observe reachable daemon metadata after retrying, and ${t.infoPath} still remains. Stale metadata was cleaned automatically when safe; retry with --debug. If this persists after confirming no agent-device daemon process is running, run: ${n}`:`agent-device did not observe reachable daemon metadata after retrying. Stale metadata was cleaned automatically when safe; retry with --debug and check daemon diagnostics logs. If stale metadata returns after confirming no agent-device daemon process is running, run: ${n}`}function Pt(e){return`rm -f ${b(e.infoPath)} ${b(e.lockPath)}`}function Ft(e){if(!T.existsSync(e))return null;try{return JSON.parse(T.readFileSync(e,`utf8`))}catch{return null}}function It(e){try{T.existsSync(e)&&T.unlinkSync(e)}catch{}}function J(e,n,r){return new t(`COMMAND_FAILED`,`Invalid daemon response`,{requestId:e.meta?.requestId,line:n},r instanceof Error?r:void 0)}function Lt(e){let t=t=>(e.onError(t),!0);return{handleLine(n){let r;try{r=JSON.parse(n)}catch(r){return t(J(e.req,n,r))}if(_e(r))try{return e.onProgress?.(r.event),!1}catch(e){return t(e)}return he(r)?(e.onResponse(r.response),!0):e.responseFormat===`socket-legacy`?(e.onResponse(r),!0):t(J(e.req,n,Error(`Missing daemon progress response envelope`)))}}}function Rt(e,t){return ge(e)&&String(Array.isArray(t)?t.join(`,`):t??``).includes(`application/x-ndjson`)}function zt(e,t){let{req:n,isSettled:r,resolve:i,reject:a,clearTimeout:o}=t,s=``,c=Lt({req:n,onProgress:t.onProgress,responseFormat:`socket-legacy`,onResponse(t){o(),i(t),e.end()},onError(e){o(),a(e)}});e.setEncoding(`utf8`),e.on(`data`,e=>{if(r())return;let t=y(s,e);s=t.buffer;for(let e of t.lines)if(c.handleLine(e))return}),e.on(`end`,()=>{if(r())return;let e=s.trim();e&&c.handleLine(e)||(o(),a(J(n,e)))})}function Bt(e,n){let{req:r,handleResponseBody:i,reject:a,clearTimeout:o}=n,s=``,c=!1,l=Lt({req:r,onProgress:n.onProgress,responseFormat:`ndjson-envelope`,onResponse(e){c=!0,o(),i(JSON.stringify(e))},onError(e){c=!0,o(),a(e)}});e.setEncoding(`utf8`),e.on(`data`,e=>{if(c)return;let t=y(s,e);s=t.buffer;for(let e of t.lines)if(e&&l.handleLine(e))return}),e.on(`end`,()=>{if(c)return;let e=s.trim();e&&l.handleLine(e)||(c=!0,o(),a(J(r,e)))}),e.on(`error`,e=>{c||(c=!0,o(),a(new t(`COMMAND_FAILED`,`Failed to read daemon response`,{requestId:r.meta?.requestId},e instanceof Error?e:void 0)))})}const Vt=1e4,Ht=8388608;function Ut(e,t){return _(e,`sessions/${encodeURIComponent(t.session)}/requests/${encodeURIComponent(t.requestId)}/diagnostics`)}function Wt(e){let{logPath:t,...n}=e;return n}async function Gt(e,t){let n=Wt(e),r=e.diagnosticsRecord,i=r?.requestId??t.requestId;if(!r)return Y(n,t.endpoint,i,`the daemon named no diagnostics record`);try{let e=ve(t.stateDir,r),a=await Kt({endpoint:t.endpoint,ref:r,destinationPath:e});return a?Y(n,t.endpoint,i,a):{...n,logPath:e}}catch(e){return Y(n,t.endpoint,i,e instanceof Error?e.message:String(e))}}function Y(e,t,n,r){return{...e,logPathUnavailable:`remote daemon ${t.baseUrl}, request ${n??`unknown`}: ${r}`}}async function Kt(e){let{endpoint:t,ref:n,destinationPath:r}=e,i;try{i=new URL(Ut(t.baseUrl,n))}catch{return`daemon base URL is not a valid URL`}try{let e=await v(i.protocol);return await T.promises.mkdir(w.dirname(r),{recursive:!0}),await new Promise(n=>{let a=!1,o=e=>{if(!a){if(a=!0,clearTimeout(c),e===void 0){n(void 0);return}T.promises.rm(r,{force:!0}).finally(()=>{n(e)})}},s=e.request({protocol:i.protocol,host:i.hostname,port:i.port,method:`GET`,path:i.pathname+i.search,headers:{...g(t.token),...re(t.tenantId)}},e=>{let t=e.statusCode??500;if(t!==200){e.resume(),o(`HTTP ${t}`);return}let n=T.createWriteStream(r),i=0;e.on(`data`,e=>{i+=e.length,i>Ht&&(s.destroy(),n.destroy(),o(`record exceeds ${Ht} bytes`))}),e.on(`error`,e=>{n.destroy(),o(e.message)}),n.on(`error`,e=>{o(e.message)}),n.on(`finish`,()=>{o(void 0)}),e.pipe(n)}),c=setTimeout(()=>{o(`fetch timed out after ${Vt}ms`),s.destroy()},Vt);s.on(`error`,e=>{o(e.message)}),s.end()})}catch(e){return e instanceof Error?e.message:String(e)}}function qt(e,n){let{info:r,req:i,stateDir:a,resolve:o,reject:s}=n;try{let n=Jt(e);if(n.error){Yt(n.error,{info:r,req:i,stateDir:a,reject:s});return}if(!n.result||typeof n.result!=`object`){s(new t(`COMMAND_FAILED`,`Invalid daemon RPC response`,{requestId:i.meta?.requestId}));return}$t(r,i,n.result,o,s)}catch(n){s(new t(`COMMAND_FAILED`,`Invalid daemon response`,{requestId:i.meta?.requestId,line:e},n instanceof Error?n:void 0))}}function Jt(e){return JSON.parse(e)}async function Yt(e,t){let{info:n,req:r,stateDir:i,reject:a}=t,o=r.meta?.requestId,s=Xt(e);if(!n.baseUrl){a(Qt(s,o));return}a(Qt(await Gt(s,{endpoint:{baseUrl:n.baseUrl,token:n.token,tenantId:r.meta?.tenantId},stateDir:i,requestId:o}),o))}function Xt(e){let t=e.data??{},n=Zt(t.cause);return{code:i(t.code==null?void 0:String(t.code),`COMMAND_FAILED`),message:String(t.message??e.message??`Daemon RPC request failed`),cause:n,details:typeof t.details==`object`&&t.details?t.details:void 0,hint:typeof t.hint==`string`?t.hint:void 0,diagnosticId:typeof t.diagnosticId==`string`?t.diagnosticId:void 0,logPath:typeof t.logPath==`string`?t.logPath:void 0,diagnosticsRecord:r(t.diagnosticsRecord),retriable:typeof t.retriable==`boolean`?t.retriable:void 0,supportedOn:typeof t.supportedOn==`string`?t.supportedOn:void 0}}function Zt(t){return e(t)}function Qt(e,n){return new t(i(e.code,`COMMAND_FAILED`),e.message,{...e.details??{},hint:e.hint,diagnosticId:e.diagnosticId,logPath:e.logPath,logPathUnavailable:e.logPathUnavailable,diagnosticsRecord:e.diagnosticsRecord,retriable:e.retriable,supportedOn:e.supportedOn,requestId:n},e.cause)}async function $t(e,t,n,r,i){try{r(e.baseUrl&&n.ok?await pt(e,t,n):n)}catch(e){i(e)}}function en(e,t){let n=e.meta?.requestId??u();return tn(e.command)?{jsonrpc:`2.0`,id:n,method:nn(e.command),params:{...rn(e,e.command,t),...e.command===`lease_allocate`?o(e.flags):{}}}:{jsonrpc:`2.0`,id:n,method:`agent_device.command`,params:e}}function tn(e){return e===`lease_allocate`||e===`lease_heartbeat`||e===`lease_release`}function nn(e){switch(e){case`lease_allocate`:return`agent_device.lease.allocate`;case`lease_heartbeat`:return`agent_device.lease.heartbeat`;case`lease_release`:return`agent_device.lease.release`}}function rn(e,t,n){return s(a(e),t,{includeTokenParam:n.includeTokenParam,token:e.token,session:e.session})}const an=[`xcodebuild .*AgentDeviceRunnerUITests/RunnerTests/testCommand`,String.raw`xcodebuild .*AgentDeviceRunner\.env\.session-`,String.raw`xcodebuild build-for-testing .*apple/runner/AgentDeviceRunner/AgentDeviceRunner\.xcodeproj`],on=new Set([`apple`,`ios`,`macos`]);function sn(e){return e!==void 0&&on.has(e)}function cn(e){let{info:n,statePaths:r,remote:i,timeoutMs:a,requestId:o,command:s,platform:c,session:l,action:u}=e,f=i?{terminated:0}:dn(),p=!i&&ln(s),m=p?fn(n,r):{forcedKill:!1},h=sn(c)||f.terminated>0;return d({level:`error`,phase:`daemon_request_timeout`,data:{timeoutMs:a,requestId:o,command:s,timedOutRunnerPidsTerminated:f.terminated,timedOutRunnerCleanupError:f.error,daemonPidReset:p?n.pid:void 0,daemonPidForceKilled:p?m.forcedKill:void 0,daemonPreservedAfterTimeout:!i&&!p,daemonBaseUrl:n.baseUrl}}),new t(`COMMAND_FAILED`,`Daemon request timed out`,{timeoutMs:a,requestId:o,hint:un({remote:i,resetDaemon:p,command:s,appleCleanupEvidence:h,session:l,action:u})})}function ln(e){return c(e).onTimeout===`reset-daemon`}function un(e){let{remote:t,resetDaemon:n,command:r,appleCleanupEvidence:i,session:a,action:o}=e;if(t)return r===l.record&&o===`stop`?`The remote daemon is still exporting the recording. Run agent-device record stop${a?` --session ${a}`:``} again to wait for that export and receive the completed recording.`:`Retry with --debug and verify the remote daemon URL, auth token, and remote host logs.`;if(!n){let e=i&&r===l.snapshot?` If this was the first Apple-platform snapshot on the device, run agent-device prepare ios-runner with the same --platform before snapshot/test so runner startup is handled explicitly.`:``;return`Retry with --debug and check daemon diagnostics logs. The timed-out ${r??`request`} request was canceled${i?` and Apple runner work was aborted when detected`:``}; the daemon was kept alive so the session can still be closed or inspected.${e}`}return i?`Retry with --debug and check daemon diagnostics logs. Timed-out Apple runner xcodebuild processes were terminated when detected.`:`Retry with --debug and check daemon diagnostics logs. The daemon was reset after the timeout.`}function dn(){let e=0;try{for(let t of an)m(`pkill`,[`-f`,t],{allowFailure:!0}).exitCode===0&&(e+=1);return{terminated:e}}catch(t){return{terminated:e,error:t instanceof Error?t.message:String(t)}}}function fn(e,t){let n=!1;try{C(e.pid,e.processStartTime)&&(process.kill(e.pid,`SIGKILL`),n=!0)}catch{q(e)}finally{U(t.infoPath),W(t.lockPath)}return{forcedKill:n}}const pn=`Daemon HTTP endpoint is unavailable`,mn=`Daemon socket endpoint is unavailable`;async function hn(e,t){let n=Tn(e,t);if(await gn(e,n))return!0;let r=En(e,t,n);return r?await gn(e,r):!1}async function gn(e,t){return t===`http`?await vn(e):await _n(e.port)}function _n(e){return e?new Promise(t=>{let n=!1,r=k.createConnection({host:`127.0.0.1`,port:e},()=>{i(!0)}),i=e=>{n||(n=!0,r.destroy(),t(e))};r.setTimeout(500),r.on(`timeout`,()=>{i(!1)}),r.on(`error`,()=>{i(!1)})}):Promise.resolve(!1)}function vn(e){return bn(e).then(e=>e.reachable)}async function yn(e){let n=await bn(e);if(!e.baseUrl||!n.reachable)return n;let r=[n,n.upstream].find(e=>typeof e?.rpcProtocolVersion==`number`&&e.rpcProtocolVersion!==2);if(r)throw new t(`COMMAND_FAILED`,`Remote daemon RPC protocol is incompatible`,{daemonBaseUrl:e.baseUrl,clientVersion:S(),remoteVersion:r.version,remoteService:r.service,supportedRpcProtocolVersion:2,remoteRpcProtocolVersion:r.rpcProtocolVersion,hint:`Upgrade agent-device on the client or remote host so both support the same daemon RPC protocol.`});return n}async function bn(e){let t=e.baseUrl?_(e.baseUrl,`health`):e.httpPort?`http://127.0.0.1:${e.httpPort}/health`:null;if(!t)return{reachable:!1};let n=new URL(t),r=await v(n.protocol),i=e.baseUrl?3e3:500;return await new Promise(t=>{let a=e.baseUrl?g(e.token):{},o=r.request({protocol:n.protocol,host:n.hostname,port:n.port,path:n.pathname+n.search,method:`GET`,timeout:i,headers:a},e=>{let n=``;e.setEncoding(`utf8`),e.on(`data`,e=>{n+=e}),e.on(`end`,()=>{let r=e.statusCode??500;t({reachable:r<500,statusCode:r,...xn(n)})})});o.on(`timeout`,()=>{o.destroy(),t({reachable:!1})}),o.on(`error`,()=>{t({reachable:!1})}),o.end()})}function xn(e){try{let t=JSON.parse(e),n=t.upstream&&typeof t.upstream==`object`?Sn(t.upstream):void 0;return{...Sn(t),...n?{upstream:n}:{}}}catch{return{}}}function Sn(e){return{service:typeof e.service==`string`?e.service:void 0,version:typeof e.version==`string`?e.version:void 0,rpcProtocolVersion:typeof e.rpcProtocolVersion==`number`?e.rpcProtocolVersion:void 0}}async function Cn(e,t,n,r,i,a={}){let o=Tn(e,n);try{return await wn(e,t,r,i,o,a)}catch(s){let c=En(e,n,o);if(!c||!Dn(s,o))throw s;return await wn(e,t,r,i,c,a)}}async function wn(e,t,n,r,i,a){return i===`http`?await jn(e,t,n,r,a):await An(e,t,n,r,a)}function Tn(e,n){if(e.baseUrl){if(n===`socket`)throw new t(`COMMAND_FAILED`,`Remote daemon endpoint only supports HTTP transport`,{daemonBaseUrl:e.baseUrl});return`http`}if(n===`http`||n===`socket`)return On(e,n);let r=(e.transport===`socket`||e.transport===`dual`?[`socket`,`http`]:[`http`,`socket`]).find(t=>X(e,t));if(r)return r;throw new t(`COMMAND_FAILED`,`Daemon metadata has no reachable transport`)}function X(e,t){return t===`http`?!!e.httpPort:!!e.port}function En(e,t,n){if(t!==`auto`||e.baseUrl)return null;let r=n===`socket`?`http`:`socket`;return X(e,r)?r:null}function Dn(e,n){return n===`socket`&&e instanceof t&&e.code===`COMMAND_FAILED`&&e.message===`Failed to communicate with daemon`&&e.details?.daemonSocketRequestWritten===!1}function On(e,n){if(X(e,n))return n;throw new t(`COMMAND_FAILED`,n===`http`?pn:mn)}function kn(e,n,r,i={}){return d({level:`error`,phase:`daemon_request_socket_error`,data:{requestId:n,message:e instanceof Error?e.message:String(e)}}),new t(`COMMAND_FAILED`,`Failed to communicate with daemon`,{...i,requestId:n,hint:r?`Retry command. If this persists, verify the remote daemon URL, auth token, and remote host reachability.`:`Retry command. If this persists, clean stale daemon metadata and start a fresh session.`},e instanceof Error?e:void 0)}async function An(e,n,r,i,a){let o=e.port;if(!o)throw new t(`COMMAND_FAILED`,mn);return new Promise((t,s)=>{let c=!1,l=k.createConnection({host:`127.0.0.1`,port:o},()=>{c=!0,l.write(`${JSON.stringify(n)}\n`)}),u=!1,d=typeof i==`number`?setTimeout(()=>{u=!0,l.destroy(),s(cn({info:e,statePaths:r,...Z(n,!1,i)}))},i):void 0;zt(l,{req:n,onProgress:a.onProgress,isSettled:()=>u,clearTimeout:()=>{d&&clearTimeout(d)},resolve:e=>{u=!0,t(e)},reject:e=>{u=!0,s(e)}}),l.on(`error`,e=>{u||(u=!0,d&&clearTimeout(d),s(kn(e,n.meta?.requestId,!1,{daemonSocketRequestWritten:c})))})})}function Z(e,t,n){return{remote:t,timeoutMs:n,requestId:e.meta?.requestId,command:e.command,platform:e.flags?.platform,session:e.session,action:e.positionals?.[0]}}async function jn(e,n,r,i,a){let o=e.baseUrl?new URL(_(e.baseUrl,`rpc`)):e.httpPort?new URL(`http://127.0.0.1:${e.httpPort}/rpc`):null;if(!o)throw new t(`COMMAND_FAILED`,pn);let s=JSON.stringify(en(n,{includeTokenParam:!e.baseUrl})),c={"content-type":`application/json`,"content-length":Buffer.byteLength(s)};e.baseUrl&&Object.assign(c,g(e.token));let l=await v(o.protocol);return await new Promise((u,d)=>{let f=l.request({protocol:o.protocol,host:o.hostname,port:o.port,method:`POST`,path:o.pathname+o.search,headers:c},i=>{if(Rt(n,i.headers?.[`content-type`])){Bt(i,{req:n,onProgress:a.onProgress,reject:d,clearTimeout:()=>{m&&clearTimeout(m)},handleResponseBody:t=>qt(t,{info:e,req:n,stateDir:r.baseDir,resolve:u,reject:d})});return}ne(i).then(t=>{m&&clearTimeout(m),qt(t,{info:e,req:n,stateDir:r.baseDir,resolve:u,reject:d})}).catch(e=>{m&&clearTimeout(m),d(new t(`COMMAND_FAILED`,`Failed to read daemon response`,{requestId:n.meta?.requestId},e instanceof Error?e:void 0))})}),p=Mt(e),m=typeof i==`number`?setTimeout(()=>{f.destroy(),d(cn({info:e,statePaths:r,...Z(n,p,i)}))},i):void 0;f.on(`error`,e=>{m&&clearTimeout(m),d(kn(e,n.meta?.requestId,p))}),f.write(s),f.end()})}const Q=15e3,$=new k.BlockList;$.addSubnet(`127.0.0.0`,8,`ipv4`),$.addAddress(`::1`,`ipv6`),$.addSubnet(`::ffff:127.0.0.0`,104,`ipv6`);function Mn(e,t){let n=Nn(e),r=Pn(e,t),i=Fn(e,r.remoteBaseUrl),a=In(e,n,r.rawBaseUrl),o=a?Ln():n;return{paths:de(o),transportPreference:i.preference,serverMode:i.serverMode,ownedStateDir:a,remoteBaseUrl:r.remoteBaseUrl,remoteAuthToken:r.authToken}}function Nn(e){return e.flags?.stateDir??process.env.AGENT_DEVICE_STATE_DIR}function Pn(e,t){let n=e.flags?.daemonBaseUrl??process.env.AGENT_DEVICE_DAEMON_BASE_URL,r=nr(n),i=t??process.env.AGENT_DEVICE_DAEMON_AUTH_TOKEN;return rr(r,i),{rawBaseUrl:n,remoteBaseUrl:r,authToken:i}}function Fn(e,n){let r=e.flags?.daemonTransport??process.env.AGENT_DEVICE_DAEMON_TRANSPORT,i=ue(r);if(n&&i===`socket`)throw new t(`INVALID_ARGS`,`Remote daemon base URL only supports HTTP transport. Remove --daemon-transport socket.`,{daemonBaseUrl:n});let a=e.flags?.daemonServerMode??process.env.AGENT_DEVICE_DAEMON_SERVER_MODE??(r===`dual`?`dual`:void 0);return{preference:i,serverMode:le(a)}}function In(e,t,n){return Yn(e.command)&&!t&&!n}function Ln(){return T.mkdtempSync(w.join(D.tmpdir(),`agent-device-replay-daemon-`))}async function Rn(e){if(e.remoteBaseUrl)return await zn(e);let t=await Bn(e);return t?{info:t,startedByClient:!1}:(At(e.paths),await Wn(e))}async function zn(e){let n={transport:`http`,token:e.remoteAuthToken??``,pid:0,baseUrl:e.remoteBaseUrl};if((await yn(n)).reachable)return{info:n,startedByClient:!1};throw new t(`COMMAND_FAILED`,`Remote daemon is unavailable`,{daemonBaseUrl:e.remoteBaseUrl,hint:`Verify AGENT_DEVICE_DAEMON_BASE_URL points to a reachable daemon with GET /health and POST /rpc. If this CLI was connected with connect proxy, run agent-device disconnect to return to the local daemon.`})}async function Bn(e){let t=z(e.paths.infoPath);if(!t)return null;let n=await xt(t,await Vn(t,e.transportPreference));return n?(Un(t,n,e.paths.baseDir),await q(t),U(e.paths.infoPath),null):t}async function Vn(e,t){try{return await hn(e,t)}catch(e){if(Hn(e))return!1;throw e}}function Hn(e){return e instanceof t&&e.code===`COMMAND_FAILED`&&(e.message===`Daemon HTTP endpoint is unavailable`||e.message===`Daemon socket endpoint is unavailable`)}function Un(e,t,n){try{let r=e.version?`pid ${e.pid}, v${e.version}`:`pid ${e.pid}`;process.stderr.write(`Replacing daemon (${r}) in ${n}: ${t}\n`)}catch{}}async function Wn(e){let n=0,r=[],i,a;for(let t=1;t<=2;t+=1){let o;try{o=$n(e),a={pid:o.pid}}catch(n){if(i=n instanceof Error?n.message:String(n),r.push(await G(e.paths,`start_error`)),t<2){await h(150);continue}break}let s=await Qn(Q,e,o);if(s.kind===`ready`)return{info:s.info,startedByClient:!0};if(s.kind===`early_exit`){if(a=s.exit,i=er(s.exit),r.push(await G(e.paths,`start_error`)),t<2){await h(150);continue}break}if(await jt(e.paths)){n+=1;continue}let c=K(e.paths),l=t<2,u=await G(e.paths,`startup_timeout`,{stopLiveProcesses:!1});if(r.push(u),u.retainedInfoProcess||u.retainedLockProcess){let t=await Qn(Q,e,o);if(t.kind===`ready`)return{info:t.info,startedByClient:!0};t.kind===`early_exit`&&(a=t.exit,i=er(t.exit));break}if(!l)break;!c.hasInfo&&!c.hasLock&&await h(150)}let o=K(e.paths),s=tr(e.paths.logPath);throw new t(`COMMAND_FAILED`,`Failed to start daemon`,{kind:`daemon_startup_failed`,stateDir:e.paths.baseDir,infoPath:e.paths.infoPath,lockPath:e.paths.lockPath,logPath:e.paths.logPath,startupTimeoutMs:Q,startupAttempts:2,lockRecoveryCount:n,cleanupResults:r,startError:i,daemonProcess:a,...s?{daemonLogTail:s}:{},metadataState:o,hint:Nt(o,e.paths)})}async function Gn(e,t,n,r){if(!Yn(e.command)||!t.startedByClient&&!n.ownedStateDir||Mt(t.info)||qn(r)||Xn(e,r))return r;let i={pid:t.info.pid,removedInfo:!1,removedLock:!1,removedStateDir:!1,error:void 0},a=r;try{await q(t.info)}catch(e){i.error=e instanceof Error?e.message:String(e)}finally{let e=T.existsSync(n.paths.infoPath);U(n.paths.infoPath),i.removedInfo=e&&!T.existsSync(n.paths.infoPath);let t=T.existsSync(n.paths.lockPath);if(W(n.paths.lockPath),i.removedLock=t&&!T.existsSync(n.paths.lockPath),n.ownedStateDir){let e=ae(n.paths.sessionsDir);e?a=Kn(r,e):(T.rmSync(n.paths.baseDir,{recursive:!0,force:!0}),i.removedStateDir=!T.existsSync(n.paths.baseDir))}}return d({level:i.error?`warn`:`info`,phase:`daemon_replay_cleanup`,data:i}),a}function Kn(e,r){if(e&&!e.ok)return e;let{sessionName:i,tombstone:a}=r,o=a.sourcePath?`re-run: replay ${a.sourcePath} --save-script`:`re-run your replay <script> --save-script from the start`,s=`The repair transaction for session "${i}" completed, but committing its healed script failed at teardown: ${a.commitFailure.message}. ${o}.`;return{ok:!1,error:n(new t(`REPAIR_COMMIT_FAILED`,s))}}function qn(e){return!e||e.ok||e.error.code!==`REPLAY_DIVERGENCE`?!1:ie(e.error.details?.divergence)?.repairSessionHeld===!0}function Jn(e,t){let n=`This repair session's daemon was kept alive to continue the repair; pass --state-dir ${t} on your next command (press, replay --from, or close --save-script) to reach it.`,r=e.error.hint;return{...e,error:{...e.error,hint:r?`${r} ${n}`:n}}}function Yn(e){return e===l.replay||e===l.test}function Xn(e,t){return e.command!==l.replay||!t||!t.ok?!1:t.data?.sessionActive===!0}function Zn(e,t){let n=e.data??{},r=typeof n.session==`string`?n.session:void 0,i=[...t?[`--state-dir ${x(t)}`]:[],...r?[`--session ${x(r)}`]:[]];if(i.length===0)return e;let a=`This session's daemon was kept alive because its script left the session active; pass ${i.join(` `)} on your next command to reach it.`,o=typeof n.message==`string`?n.message:void 0;return{...e,data:{...n,hint:a,message:o?`${o} ${a}`:a}}}async function Qn(e,t,n){let r=Date.now(),i;for(n.exited.then(e=>{i=e});Date.now()-r<e;){if(i)return{kind:`early_exit`,exit:i};let e=z(t.paths.infoPath);if(e&&await hn(e,t.transportPreference))return{kind:`ready`,info:e};if(i)return{kind:`early_exit`,exit:i};await h(100)}return{kind:`timeout`}}function $n(e){let t=yt(),n=t.useSrc?[`--experimental-strip-types`,t.srcPath]:[t.distPath],r={...process.env,AGENT_DEVICE_STATE_DIR:e.paths.baseDir,AGENT_DEVICE_DAEMON_SERVER_MODE:e.serverMode};T.mkdirSync(e.paths.baseDir,{recursive:!0});let i=T.openSync(e.paths.logPath,`a`),a=T.openSync(e.paths.logPath,`a`);try{return p(process.execPath,n,{env:r,stdio:[`ignore`,i,a]})}finally{T.closeSync(i),T.closeSync(a)}}function er(e){return e.error?`daemon process ${e.pid} failed to start: ${e.error}`:e.signal?`daemon process ${e.pid} exited before readiness with signal ${e.signal}`:`daemon process ${e.pid} exited before readiness with code ${e.exitCode??0}`}function tr(e){try{if(!T.existsSync(e))return;let t=T.statSync(e);if(t.size<=0)return;let n=Math.min(t.size,64e3),r=T.openSync(e,`r`);try{let e=Buffer.alloc(n);T.readSync(r,e,0,n,t.size-n);let i=e.toString(`utf8`).trim();return i.length>0?i:void 0}finally{T.closeSync(r)}}catch{return}}function nr(e){if(!e)return;let n;try{n=new URL(e)}catch(n){throw new t(`INVALID_ARGS`,`Invalid daemon base URL`,{daemonBaseUrl:e},n instanceof Error?n:void 0)}if(n.protocol!==`http:`&&n.protocol!==`https:`)throw new t(`INVALID_ARGS`,`Daemon base URL must use http or https`,{daemonBaseUrl:e});return n.toString().replace(/\/+$/,``)}function rr(e,n){if(!e)return;let r=new URL(e).hostname;if(!ir(r)&&!(typeof n==`string`&&n.trim().length>0))throw new t(`INVALID_ARGS`,`Remote daemon base URL for non-loopback hosts requires daemon authentication`,{daemonBaseUrl:e,hint:`Provide --daemon-auth-token or AGENT_DEVICE_DAEMON_AUTH_TOKEN when using a non-loopback remote daemon URL.`})}function ir(e){let t=e.trim().toLowerCase().replace(/^\[(.*)\]$/,`$1`);return t===`localhost`?!0:k.isIPv4(t)?$.check(t,`ipv4`):k.isIPv6(t)?$.check(t,`ipv6`):!1}export{Xn as a,Cn as c,Rn as i,Ze as l,Jn as n,qn as o,Gn as r,Mn as s,Zn as t};
|
|
1
|
+
import{C as e,N as t,P as n,V as r,z as i}from"./sdk-contracts.js";import{a,p as o,u as s}from"./lease-scope.js";import{w as c}from"./sdk-batch.js";import{n as l}from"./catalog.js";import{n as u,r as d}from"./diagnostics.js";import{c as f,d as p,p as m}from"./exec.js";import{t as h}from"./timeouts.js";import"./diagnostics2.js";import{r as ee,t as te}from"./output-path.js";import{d as g,i as ne,m as _,n as v,p as re,t as y}from"./transport.js";import{n as b,r as x}from"./command.js";import{i as ie}from"./replay-divergence.js";import"./retry.js";import{t as ae}from"./session-repair-tombstone.js";import{i as oe,n as se,r as S}from"./version.js";import{t as ce}from"./ttl-memo.js";import{n as le,r as ue,t as de}from"./daemon-resolution.js";import{i as fe,n as pe}from"./code-signature.js";import{n as me,t as C}from"./daemon-process.js";import{n as he,o as ge,t as _e}from"./request-progress-protocol.js";import{t as ve}from"./session-artifact-paths.js";import w from"node:path";import T from"node:fs";import{createHash as ye,randomUUID as E}from"node:crypto";import D from"node:os";import{Transform as be,Writable as xe}from"node:stream";import{pipeline as O}from"node:stream/promises";import k from"node:net";async function Se(e,t){let n=T.statSync(e),r=w.basename(e),i=n.isDirectory(),a=Te(t)??we(e,n),o=[];try{let t=i?await Ce(e,o):e,n=T.statSync(t);return{payloadPath:t,fileName:r,artifactType:i?`app-bundle`:`file`,platform:a,contentType:i?`application/gzip`:`application/octet-stream`,sha256:await Ee(t),sizeBytes:n.size,cleanup:()=>A(o)}}catch(e){throw A(o),e}}async function Ce(e,t){let n=T.mkdtempSync(w.join(D.tmpdir(),`agent-device-upload-${E()}-`));t.push(n);let r=w.join(n,`${w.basename(e)}.tar.gz`);return await f(`tar`,[`czf`,r,`-C`,w.dirname(e),w.basename(e)],{env:{...process.env,COPYFILE_DISABLE:`1`}}),r}function we(e,t){let n=e.toLowerCase();if(t.isDirectory()&&n.endsWith(`.app`)||n.endsWith(`.ipa`))return`ios`;if(n.endsWith(`.apk`)||n.endsWith(`.aab`))return`android`}function Te(e){return e===`ios`||e===`android`?e:void 0}function A(e){for(let t of e)T.rmSync(t,{recursive:!0,force:!0})}async function Ee(t){let n=ye(`sha256`),r=new xe({write(e,t,r){n.update(e),r()}});return await O(T.createReadStream(t),r).catch(t=>{throw new e(`COMMAND_FAILED`,`Failed to read local artifact`,{},t instanceof Error?t:void 0)}),n.digest(`hex`)}function De(e){let{stage:t,fileName:n,startOffset:r,totalBytes:i,onProgress:a}=e,o=r,s=Ae(i),c=Math.min(i,r+s);return new be({transform(e,r,l){o=Math.min(i,o+e.byteLength),o>=c&&(a?.({type:`progress`,stage:t,fileName:n,transferredBytes:o,totalBytes:i}),c=Math.min(i,o+s)),l(null,e)}})}function Oe(){if(!(process.stderr.isTTY!==!0||process.env.CI))return e=>{process.stderr.write(`${ke(e)}\n`)}}function ke(e){switch(e.type){case`start`:return`Uploading ${e.fileName} (${M(e.totalBytes)}) via ${j(e.stage)} upload`;case`resume`:return`Resuming ${e.fileName} at ${M(e.transferredBytes)} of ${M(e.totalBytes)}`;case`progress`:return`Uploaded ${M(e.transferredBytes)} of ${M(e.totalBytes)} (${je(e.transferredBytes,e.totalBytes)})`;case`fallback`:return`Direct upload did not complete; retrying ${e.fileName} with ${j(e.to)} upload`}}function Ae(e){return Math.max(8388608,Math.ceil(e*.05))}function j(e){return e===`direct`?`direct`:`legacy`}function je(e,t){return t<=0?`100%`:`${Math.min(100,Math.floor(e/t*100))}%`}function M(e){if(e<1024)return`${e} B`;let t=e/1024;if(t<1024)return`${t.toFixed(1)} KiB`;let n=t/1024;return n<1024?`${n.toFixed(1)} MiB`:`${(n/1024).toFixed(1)} GiB`}const N=3e5,P=`uploadStreamRetryable`;async function F(e){return await I({...e,url:e.url,redirectCount:0,startOffset:0})}function Me(t){return t instanceof e&&t.details?.[P]===!0}async function I(t){let n=await v(t.url.protocol),r=T.statSync(t.payloadPath).size,i=Fe(t.headers,t.startOffset,r);return Pe(t.progress,t.startOffset,r),await new Promise((a,o)=>{let s=!1,c=n.request({protocol:t.url.protocol,host:t.url.hostname,port:t.url.port,method:t.method,path:t.url.pathname+t.url.search,headers:i},n=>{s=!0,ne(n).then(i=>{clearTimeout(l);let s=n.statusCode??500,c=n.headers.location;if(c&&Ie(s)){if(t.redirectCount>=5){o(new e(`COMMAND_FAILED`,`Artifact upload exceeded redirect limit`,{maxRedirects:5,url:t.url.toString()}));return}let n=new URL(c,t.url);I({...t,url:n,redirectCount:t.redirectCount+1}).then(a,o);return}let u=Le(s)?Re(n.headers,r):void 0;if(u!==void 0){if(u>=r){a({statusCode:200,statusMessage:`Upload already complete`,body:``});return}if(u<=t.startOffset){o(new e(`COMMAND_FAILED`,`Artifact upload resume did not advance`,{offset:u,previousOffset:t.startOffset,url:t.url.toString()}));return}I({...t,startOffset:u}).then(a,o);return}a({statusCode:s,statusMessage:n.statusMessage,body:i})}).catch(o)}),l=setTimeout(()=>{c.destroy(),o(new e(`COMMAND_FAILED`,t.timeoutMessage,{timeoutMs:N,...t.timeoutHint?{hint:t.timeoutHint}:{},...Ne(t)}))},N);c.on(`error`,n=>{s||(clearTimeout(l),o(new e(`COMMAND_FAILED`,t.errorMessage,{...t.errorHint?{hint:t.errorHint}:{},...Ne(t)},n)))}),c.on(`close`,()=>clearTimeout(l)),O(T.createReadStream(t.payloadPath,{start:t.startOffset}),De({stage:t.progress?.stage??`legacy`,fileName:t.progress?.fileName??w.basename(t.payloadPath),startOffset:t.startOffset,totalBytes:r,onProgress:t.progress?.onProgress}),c).catch(t=>{if(s)return;c.destroy();let n=t instanceof Error?t:Error(String(t));o(new e(`COMMAND_FAILED`,`Failed to read local artifact`,{},n))})})}function Ne(e){return e.retryable===!0?{[P]:!0}:{}}function Pe(e,t,n){e?.onProgress?.({type:t>0?`resume`:`start`,stage:e.stage,fileName:e.fileName,transferredBytes:t,totalBytes:n})}function Fe(e,t,n){return t<=0?e:{...e,"content-length":Math.max(n-t,0),"content-range":`bytes ${t}-${n-1}/${n}`}}function Ie(e){return[301,302,303,307,308].includes(e)}function Le(e){return e===308}function Re(e,t){let n=ze(e[`x-upload-offset`]??e[`upload-offset`]);if(n!==void 0)return Math.min(n,t);let r=Be(e.range)?.match(/^bytes=0-(\d+)$/);if(!r)return;let i=Number(r[1]);if(!(!Number.isSafeInteger(i)||i<0))return Math.min(i+1,t)}function ze(e){let t=Be(e);if(t===void 0)return;let n=Number(t);return Number.isSafeInteger(n)&&n>=0?n:void 0}function Be(e){return Array.isArray(e)?e[0]:e}const Ve=3e4;async function He(e){let t=await Se(e.localPath,e.platform),n=e.baseUrl.endsWith(`/`)?e.baseUrl:`${e.baseUrl}/`,r=E();try{let i=await Ke({normalizedBase:n,token:e.token,artifact:t,uploadAttemptId:r});return i?.kind===`cache-hit`?i.uploadId:i?.kind===`direct-upload`?await Ue({normalizedBase:n,token:e.token,artifact:t,preflight:i,uploadAttemptId:r,onProgress:e.onProgress})||(e.onProgress?.({type:`fallback`,from:`direct`,to:`legacy`,fileName:t.fileName}),await Ge({normalizedBase:n,token:e.token,artifact:t,onProgress:e.onProgress})):await Ge({normalizedBase:n,token:e.token,artifact:t,onProgress:e.onProgress})}finally{t.cleanup()}}async function Ue(e){let t=async t=>(await Ye(e.artifact,t,e.onProgress),await Xe({normalizedBase:e.normalizedBase,token:e.token,uploadId:t.uploadId}));try{return await t(e.preflight)}catch(n){if(!We(n))return;let r=await Ke({normalizedBase:e.normalizedBase,token:e.token,artifact:e.artifact,uploadAttemptId:e.uploadAttemptId});if(r?.kind===`cache-hit`)return r.uploadId;if(r?.kind===`direct-upload`)try{return await t(r)}catch{return}return}}function We(t){return t instanceof e?Me(t):!0}async function Ge(t){let{normalizedBase:n,token:r,artifact:i}=t,a=new URL(`upload`,n),o={"content-type":i.contentType,"x-artifact-type":i.artifactType,"x-artifact-filename":i.fileName,"x-artifact-hash":i.sha256,"x-artifact-hash-algorithm":`sha256`,"transfer-encoding":`chunked`};Object.assign(o,g(r));let s=await F({url:a,method:`POST`,headers:o,payloadPath:i.payloadPath,timeoutMessage:`Artifact upload timed out`,timeoutHint:`The upload to the remote daemon exceeded the 5-minute timeout.`,errorMessage:`Failed to upload artifact to remote daemon`,errorHint:`Verify the remote daemon is reachable and supports artifact uploads.`,progress:{stage:`legacy`,fileName:i.fileName,onProgress:t.onProgress}});try{let t=JSON.parse(s.body);if(!t.ok||!t.uploadId)throw new e(`COMMAND_FAILED`,`Upload failed: ${s.body}`);return t.uploadId}catch(t){throw t instanceof e?t:new e(`COMMAND_FAILED`,`Invalid upload response: ${s.body}`)}}async function Ke(e){let t=new URL(`upload/preflight`,e.normalizedBase),n={"content-type":`application/json`};Object.assign(n,g(e.token));let r=await fetch(t,{method:`POST`,headers:n,signal:AbortSignal.timeout(Ve),body:JSON.stringify({uploadAttemptId:e.uploadAttemptId,sha256:e.artifact.sha256,fileName:e.artifact.fileName,sizeBytes:e.artifact.sizeBytes,artifactType:e.artifact.artifactType,...e.artifact.platform?{platform:e.artifact.platform}:{},contentType:e.artifact.contentType})}).catch(()=>void 0);if(r?.ok)return qe(await r.json().catch(()=>void 0))}function qe(e){if(!e||typeof e!=`object`)return;let t=e;if(t.ok!==!0||typeof t.uploadId!=`string`)return;if(t.cacheHit===!0)return{kind:`cache-hit`,uploadId:t.uploadId};let n=t.upload;if(!n||typeof n.url!=`string`)return;let r=n.headers??{};if(Je(r))return{kind:`direct-upload`,uploadId:t.uploadId,url:n.url,headers:r}}function Je(e){return!e||typeof e!=`object`||Array.isArray(e)?!1:Object.values(e).every(e=>typeof e==`string`)}async function Ye(t,n,r){let i=await F({url:new URL(n.url),method:`PUT`,headers:n.headers,payloadPath:t.payloadPath,timeoutMessage:`Direct artifact upload timed out`,timeoutHint:`The direct upload ticket did not accept the artifact within the timeout.`,errorMessage:`Failed to upload artifact with direct upload ticket`,retryable:!0,progress:{stage:`direct`,fileName:t.fileName,onProgress:r}});if(i.statusCode<200||i.statusCode>=300)throw new e(`COMMAND_FAILED`,`Direct artifact upload failed`,{statusCode:i.statusCode,statusMessage:i.statusMessage})}async function Xe(t){let n=new URL(`upload/finalize`,t.normalizedBase),r={"content-type":`application/json`};Object.assign(r,g(t.token));let i=await fetch(n,{method:`POST`,headers:r,signal:AbortSignal.timeout(Ve),body:JSON.stringify({uploadId:t.uploadId})}).catch(t=>{throw new e(`COMMAND_FAILED`,`Failed to finalize direct artifact upload`,{},t)});if(!i.ok)throw new e(`COMMAND_FAILED`,`Direct artifact upload finalize failed`,{status:i.status,statusText:i.statusText});let a=await i.json().catch(()=>void 0);if(!a?.ok||!a.uploadId)throw new e(`COMMAND_FAILED`,`Invalid upload finalize response`);return a.uploadId}async function Ze(e,t){let n=[...e.positionals??[]],r=e.flags?{...e.flags}:void 0,i=e.meta?.installSource,a={},o,s=Oe();if(!_t(t))return rt({positionals:n,flags:r,installSource:i,uploadedArtifactId:o,clientArtifactPaths:a});Qe(e),r=et(e,n,r,a);let c=await it(e,t,s);return c&&(i=c.installSource,o=c.uploadedArtifactId??o),e.command!==`install`&&e.command!==`reinstall`||(o=await $e(e,t,n,s)??o),rt({positionals:n,flags:r,installSource:i,uploadedArtifactId:o,clientArtifactPaths:a})}function Qe(t){if(t.flags?.saveScript!==void 0)throw new e(`INVALID_ARGS`,`--save-script is not supported against a remote daemon: the healed script would be written on the daemon host, not on this machine.`,{hint:`Run the script against a local daemon to capture a healed .ad, or re-run without --save-script.`,command:t.command})}async function $e(e,t,n,r){let i=n.length===1?0:1,a=n[i];if(a===void 0)return;if(a.startsWith(`remote:`)){n[i]=a.slice(7);return}let o=nt(a,e.meta?.cwd);if(o)return await He({localPath:o,baseUrl:t.baseUrl,token:t.token,platform:e.flags?.platform,onProgress:r})}function et(e,t,n,r){let i=at(e,t);if(!i)return n;i.positionalIndex!==void 0&&i.positionalPath!==void 0&&(t[i.positionalIndex]=i.positionalPath);let a=tt(n,i.flagKey??`out`,i.flagPath);return r[i.field]=i.localPath,a}function tt(e,t,n){return n===void 0?e:{...e??{},[t]:n}}function nt(e,t){let n=w.isAbsolute(e)?e:w.resolve(t??process.cwd(),e);return T.existsSync(n)?n:void 0}function rt(e){return{positionals:e.positionals,flags:e.flags,installSource:e.installSource,uploadedArtifactId:e.uploadedArtifactId,...Object.keys(e.clientArtifactPaths).length>0?{clientArtifactPaths:e.clientArtifactPaths}:{}}}async function it(e,t,n){let r=e.meta?.installSource;if(e.command!==`install_source`||!r||r.kind!==`path`)return null;let i=r.path.trim();if(!i)return{installSource:r};if(i.startsWith(`remote:`))return{installSource:{...r,path:i.slice(7)}};let a=w.isAbsolute(i)?i:w.resolve(e.meta?.cwd??process.cwd(),i);if(!T.existsSync(a))return{installSource:{...r,path:a}};let o=await He({localPath:a,baseUrl:t.baseUrl,token:t.token,platform:e.flags?.platform,onProgress:n});return{installSource:{...r,path:a},uploadedArtifactId:o}}function at(e,t){if(e.command===`screenshot`){let n=ut(e,`path`,`.png`);return t[0]?{field:`path`,localPath:n,positionalIndex:0,positionalPath:R(`screenshot`,`.png`)}:{field:`path`,localPath:n,positionalIndex:0,flagPath:R(`screenshot`,`.png`)}}if(e.command===`record`&&(t[0]??``).toLowerCase()===`start`){if(!ct(e)&&e.flags?.platform===void 0)return null;let t=st(e),n=lt(ut(e,`outPath`,t,1),e);return{field:`outPath`,localPath:n,positionalIndex:1,positionalPath:R(`recording`,w.extname(n)||t)}}return e.command===`test`?{field:`artifactsDir`,localPath:ot(e),flagKey:`artifactsDir`,flagPath:ft(`test-artifacts`)}:null}function ot(e){let t=e.flags?.artifactsDir;return dt(L(t)?t:`.agent-device/test-artifacts`,e.meta?.cwd)}function st(e){return ee(e.flags?.platform)}function ct(e){return L(e.positionals?.[1])||L(e.flags?.out)}function lt(e,t){return t.flags?.platform===`web`?te(e,st(t)):e}function ut(e,t,n,r=0){let i=e.positionals?.[r]??e.flags?.out,a=`${t===`path`?`screenshot`:`recording`}-${Date.now()}${n}`;return dt(L(i)?i:a,e.meta?.cwd)}function dt(e,t){return w.isAbsolute(e)?e:w.resolve(t??process.cwd(),e)}function L(e){return typeof e==`string`&&e.trim().length>0}function R(e,t){let n=t.startsWith(`.`)?t:`.${t}`;return w.posix.join(`/tmp`,`agent-device-${e}-${Date.now()}-${Math.random().toString(36).slice(2,8)}${n}`)}function ft(e){return w.posix.join(`/tmp`,`agent-device-${e}-${Date.now()}-${Math.random().toString(36).slice(2,8)}`)}async function pt(e,t,n){let r=Array.isArray(n.data?.artifacts)?n.data.artifacts:[];if(r.length===0||!e.baseUrl)return n;let i=n.data?{...n.data}:{},a=[];for(let n of r){if(!n||typeof n!=`object`||typeof n.artifactId!=`string`){a.push(n);continue}let r=mt(n,t),o=await ht({baseUrl:e.baseUrl,token:e.token,artifactId:n.artifactId,destinationPath:r,requestScope:t.meta,isDirectory:n.artifactType===`test-artifacts`});i[n.field]=o,a.push({...n,localPath:o})}return i.artifacts=a,{ok:!0,data:i}}function mt(e,t){if(e.localPath&&e.localPath.trim().length>0)return e.localPath;let n=t.meta?.clientArtifactPaths?.[e.field];if(n&&n.trim().length>0)return n;let r=e.fileName?.trim()||`${e.field}-${Date.now()}`;return w.resolve(t.meta?.cwd??process.cwd(),r)}async function ht(e){let{downloadRemoteArtifactFromUrl:t}=await import(`./artifact-download.js`);return await t({artifactUrl:new URL(gt(e.baseUrl,e.artifactId)),token:e.token,artifactId:e.artifactId,destinationPath:e.destinationPath,requestScope:e.requestScope,...e.timeoutMs===void 0?{}:{timeoutMs:e.timeoutMs},...e.isDirectory===void 0?{}:{isDirectory:e.isDirectory}})}function gt(e,t){let n=e.endsWith(`/`)?e:`${e}/`;return new URL(`artifacts/${encodeURIComponent(t)}`,n).toString()}function _t(e){return typeof e.baseUrl==`string`&&e.baseUrl.length>0}const vt=ce();function yt(){let t=vt.get(`local`);if(t)return t;let n=se(),r=[w.join(n,`dist`,`src`,`internal`,`daemon.js`),w.join(n,`dist`,`src`,`daemon.js`)],i=r[0];if(i===void 0)throw new e(`COMMAND_FAILED`,`Daemon dist path list is empty`);let a=r.find(e=>T.existsSync(e))??i,o=w.join(n,oe),s=r.some(e=>T.existsSync(e)),c=T.existsSync(o);if(!s&&!c)throw new e(`COMMAND_FAILED`,`Daemon entry not found`,{distPaths:r,srcPath:o});let l={root:n,distPath:a,distPaths:r,srcPath:o,useSrc:(process.execArgv.includes(`--experimental-strip-types`)||!s)&&c};return vt.set(`local`,l),l}async function bt(){let e=yt(),t=fe(e.root);if(t===`installed`)return{origin:t};if(!e.useSrc)return{origin:t,codeSignature:pe(e.distPath,e.root)};let{resolveCachedDaemonCodeSignature:n}=await import(`./code-signature-cache.js`);return{origin:t,codeSignature:await n(e.srcPath,e.root)}}async function xt(e,t){if(e.version!==S())return`version mismatch (client v${S()})`;let n=St(await bt(),e);if(n)return n;if(!t)return`unreachable`}function St(e,t){return e.origin===`installed`?t.codeOrigin===`installed`?void 0:Ct(e,t):t.codeOrigin===`installed`?Ct(e,t):t.codeSignature===e.codeSignature?void 0:`code-signature mismatch`}function Ct(e,t){return`code origin mismatch (daemon ${t.codeOrigin??`unreported`}, client ${e.origin})`}const wt=3e3,Tt=1e3;function z(e){let t=Ft(e);if(!t||typeof t!=`object`)return null;let n=t,r=Et(n);if(!r)return null;let i=Dt(n);return i?{token:r,...i,transport:kt(n.transport),pid:V(n.pid)??0,version:B(n.version),codeOrigin:Ot(n.codeOrigin),codeSignature:B(n.codeSignature),processStartTime:B(n.processStartTime)}:null}function Et(e){return typeof e.token==`string`&&e.token.length>0?e.token:null}function Dt(e){let t=V(e.port),n=V(e.httpPort);return t===void 0&&n===void 0?null:{port:t,httpPort:n}}function Ot(e){return e===`installed`||e===`checkout`?e:void 0}function kt(e){return e===`socket`||e===`http`||e===`dual`?e:void 0}function B(e){return typeof e==`string`?e:void 0}function V(e){return Number.isInteger(e)&&Number(e)>0?Number(e):void 0}function H(e){let t=Ft(e);if(!t||typeof t!=`object`)return null;let n=t;return Number.isInteger(n.pid)&&Number(n.pid)>0?{pid:Number(n.pid),processStartTime:typeof n.processStartTime==`string`?n.processStartTime:void 0,startedAt:typeof n.startedAt==`number`?n.startedAt:void 0}:null}function U(e){It(e)}function W(e){It(e)}function At(e){let t=K(e);if(!t.hasLock||t.hasInfo)return;let n=H(e.lockPath);if(!n){W(e.lockPath);return}C(n.pid,n.processStartTime)||W(e.lockPath)}async function G(e,t,n={}){let r=n.stopLiveProcesses??!0,i={reason:t,removedInfo:!1,removedLock:!1,stoppedInfoProcess:!1,stoppedLockProcess:!1};try{let t=T.existsSync(e.infoPath),n=z(e.infoPath);if(n){let t=C(n.pid,n.processStartTime);t&&!r?i.retainedInfoProcess=!0:(t&&(await q(n),i.stoppedInfoProcess=!0),U(e.infoPath),i.removedInfo=!0)}else t&&(U(e.infoPath),i.removedInfo=!0);let a=T.existsSync(e.lockPath),o=H(e.lockPath);if(o){let t=C(o.pid,o.processStartTime);t&&!r?i.retainedLockProcess=!0:(t&&(await me(o.pid,{termTimeoutMs:wt,killTimeoutMs:Tt,expectedStartTime:o.processStartTime}),i.stoppedLockProcess=!0),W(e.lockPath),i.removedLock=!0)}else a&&(W(e.lockPath),i.removedLock=!0)}catch(e){i.error=e instanceof Error?e.message:String(e)}return d({level:i.error?`warn`:`info`,phase:`daemon_startup_metadata_cleanup`,data:i}),i}function K(e){return{hasInfo:T.existsSync(e.infoPath),hasLock:T.existsSync(e.lockPath)}}async function jt(e){let t=K(e);if(!t.hasLock||t.hasInfo)return!1;let n=H(e.lockPath);return!n||!C(n.pid,n.processStartTime)?(W(e.lockPath),!0):!1}async function q(e){await me(e.pid,{termTimeoutMs:wt,killTimeoutMs:Tt,expectedStartTime:e.processStartTime})}function Mt(e){return typeof e.baseUrl==`string`&&e.baseUrl.length>0}function Nt(e,t=de(process.env.AGENT_DEVICE_STATE_DIR)){let n=Pt(t);return e.hasLock&&!e.hasInfo?`agent-device attempted to clean stale daemon metadata automatically, but ${t.lockPath} still exists without ${t.infoPath}. Retry with --debug; if this persists after confirming no agent-device daemon process is running, run: ${n}`:e.hasLock&&e.hasInfo?`agent-device attempted to clean stale daemon metadata automatically, but ${t.infoPath} and ${t.lockPath} still remain. Retry with --debug; if this persists after confirming no agent-device daemon process is running, run: ${n}`:e.hasInfo?`agent-device did not observe reachable daemon metadata after retrying, and ${t.infoPath} still remains. Stale metadata was cleaned automatically when safe; retry with --debug. If this persists after confirming no agent-device daemon process is running, run: ${n}`:`agent-device did not observe reachable daemon metadata after retrying. Stale metadata was cleaned automatically when safe; retry with --debug and check daemon diagnostics logs. If stale metadata returns after confirming no agent-device daemon process is running, run: ${n}`}function Pt(e){return`rm -f ${b(e.infoPath)} ${b(e.lockPath)}`}function Ft(e){if(!T.existsSync(e))return null;try{return JSON.parse(T.readFileSync(e,`utf8`))}catch{return null}}function It(e){try{T.existsSync(e)&&T.unlinkSync(e)}catch{}}function J(t,n,r){return new e(`COMMAND_FAILED`,`Invalid daemon response`,{requestId:t.meta?.requestId,line:n},r instanceof Error?r:void 0)}function Lt(e){let t=t=>(e.onError(t),!0);return{handleLine(n){let r;try{r=JSON.parse(n)}catch(r){return t(J(e.req,n,r))}if(_e(r))try{return e.onProgress?.(r.event),!1}catch(e){return t(e)}return he(r)?(e.onResponse(r.response),!0):e.responseFormat===`socket-legacy`?(e.onResponse(r),!0):t(J(e.req,n,Error(`Missing daemon progress response envelope`)))}}}function Rt(e,t){return ge(e)&&String(Array.isArray(t)?t.join(`,`):t??``).includes(`application/x-ndjson`)}function zt(e,t){let{req:n,isSettled:r,resolve:i,reject:a,clearTimeout:o}=t,s=``,c=Lt({req:n,onProgress:t.onProgress,responseFormat:`socket-legacy`,onResponse(t){o(),i(t),e.end()},onError(e){o(),a(e)}});e.setEncoding(`utf8`),e.on(`data`,e=>{if(r())return;let t=y(s,e);s=t.buffer;for(let e of t.lines)if(c.handleLine(e))return}),e.on(`end`,()=>{if(r())return;let e=s.trim();e&&c.handleLine(e)||(o(),a(J(n,e)))})}function Bt(t,n){let{req:r,handleResponseBody:i,reject:a,clearTimeout:o}=n,s=``,c=!1,l=Lt({req:r,onProgress:n.onProgress,responseFormat:`ndjson-envelope`,onResponse(e){c=!0,o(),i(JSON.stringify(e))},onError(e){c=!0,o(),a(e)}});t.setEncoding(`utf8`),t.on(`data`,e=>{if(c)return;let t=y(s,e);s=t.buffer;for(let e of t.lines)if(e&&l.handleLine(e))return}),t.on(`end`,()=>{if(c)return;let e=s.trim();e&&l.handleLine(e)||(c=!0,o(),a(J(r,e)))}),t.on(`error`,t=>{c||(c=!0,o(),a(new e(`COMMAND_FAILED`,`Failed to read daemon response`,{requestId:r.meta?.requestId},t instanceof Error?t:void 0)))})}const Vt=1e4,Ht=8388608;function Ut(e,t){return _(e,`sessions/${encodeURIComponent(t.session)}/requests/${encodeURIComponent(t.requestId)}/diagnostics`)}function Wt(e){let{logPath:t,...n}=e;return n}async function Gt(e,t){let n=Wt(e),r=e.diagnosticsRecord,i=r?.requestId??t.requestId;if(!r)return Y(n,t.endpoint,i,`the daemon named no diagnostics record`);try{let e=ve(t.stateDir,r),a=await Kt({endpoint:t.endpoint,ref:r,destinationPath:e});return a?Y(n,t.endpoint,i,a):{...n,logPath:e}}catch(e){return Y(n,t.endpoint,i,e instanceof Error?e.message:String(e))}}function Y(e,t,n,r){return{...e,logPathUnavailable:`remote daemon ${t.baseUrl}, request ${n??`unknown`}: ${r}`}}async function Kt(e){let{endpoint:t,ref:n,destinationPath:r}=e,i;try{i=new URL(Ut(t.baseUrl,n))}catch{return`daemon base URL is not a valid URL`}try{let e=await v(i.protocol);return await T.promises.mkdir(w.dirname(r),{recursive:!0}),await new Promise(n=>{let a=!1,o=e=>{if(!a){if(a=!0,clearTimeout(c),e===void 0){n(void 0);return}T.promises.rm(r,{force:!0}).finally(()=>{n(e)})}},s=e.request({protocol:i.protocol,host:i.hostname,port:i.port,method:`GET`,path:i.pathname+i.search,headers:{...g(t.token),...re(t.tenantId)}},e=>{let t=e.statusCode??500;if(t!==200){e.resume(),o(`HTTP ${t}`);return}let n=T.createWriteStream(r),i=0;e.on(`data`,e=>{i+=e.length,i>Ht&&(s.destroy(),n.destroy(),o(`record exceeds ${Ht} bytes`))}),e.on(`error`,e=>{n.destroy(),o(e.message)}),n.on(`error`,e=>{o(e.message)}),n.on(`finish`,()=>{o(void 0)}),e.pipe(n)}),c=setTimeout(()=>{o(`fetch timed out after ${Vt}ms`),s.destroy()},Vt);s.on(`error`,e=>{o(e.message)}),s.end()})}catch(e){return e instanceof Error?e.message:String(e)}}function qt(t,n){let{info:r,req:i,stateDir:a,resolve:o,reject:s}=n;try{let n=Jt(t);if(n.error){Yt(n.error,{info:r,req:i,stateDir:a,reject:s});return}if(!n.result||typeof n.result!=`object`){s(new e(`COMMAND_FAILED`,`Invalid daemon RPC response`,{requestId:i.meta?.requestId}));return}$t(r,i,n.result,o,s)}catch(n){s(new e(`COMMAND_FAILED`,`Invalid daemon response`,{requestId:i.meta?.requestId,line:t},n instanceof Error?n:void 0))}}function Jt(e){return JSON.parse(e)}async function Yt(e,t){let{info:n,req:r,stateDir:i,reject:a}=t,o=r.meta?.requestId,s=Xt(e);if(!n.baseUrl){a(Qt(s,o));return}a(Qt(await Gt(s,{endpoint:{baseUrl:n.baseUrl,token:n.token,tenantId:r.meta?.tenantId},stateDir:i,requestId:o}),o))}function Xt(e){let t=e.data??{},r=Zt(t.cause);return{code:i(t.code==null?void 0:String(t.code),`COMMAND_FAILED`),message:String(t.message??e.message??`Daemon RPC request failed`),cause:r,details:typeof t.details==`object`&&t.details?t.details:void 0,hint:typeof t.hint==`string`?t.hint:void 0,diagnosticId:typeof t.diagnosticId==`string`?t.diagnosticId:void 0,logPath:typeof t.logPath==`string`?t.logPath:void 0,diagnosticsRecord:n(t.diagnosticsRecord),retriable:typeof t.retriable==`boolean`?t.retriable:void 0,supportedOn:typeof t.supportedOn==`string`?t.supportedOn:void 0}}function Zt(e){return r(e)}function Qt(t,n){return new e(i(t.code,`COMMAND_FAILED`),t.message,{...t.details??{},hint:t.hint,diagnosticId:t.diagnosticId,logPath:t.logPath,logPathUnavailable:t.logPathUnavailable,diagnosticsRecord:t.diagnosticsRecord,retriable:t.retriable,supportedOn:t.supportedOn,requestId:n},t.cause)}async function $t(e,t,n,r,i){try{r(e.baseUrl&&n.ok?await pt(e,t,n):n)}catch(e){i(e)}}function en(e,t){let n=e.meta?.requestId??u();return tn(e.command)?{jsonrpc:`2.0`,id:n,method:nn(e.command),params:{...rn(e,e.command,t),...e.command===`lease_allocate`?o(e.flags):{}}}:{jsonrpc:`2.0`,id:n,method:`agent_device.command`,params:e}}function tn(e){return e===`lease_allocate`||e===`lease_heartbeat`||e===`lease_release`}function nn(e){switch(e){case`lease_allocate`:return`agent_device.lease.allocate`;case`lease_heartbeat`:return`agent_device.lease.heartbeat`;case`lease_release`:return`agent_device.lease.release`}}function rn(e,t,n){return s(a(e),t,{includeTokenParam:n.includeTokenParam,token:e.token,session:e.session})}const an=[`xcodebuild .*AgentDeviceRunnerUITests/RunnerTests/testCommand`,String.raw`xcodebuild .*AgentDeviceRunner\.env\.session-`,String.raw`xcodebuild build-for-testing .*apple/runner/AgentDeviceRunner/AgentDeviceRunner\.xcodeproj`],on=new Set([`apple`,`ios`,`macos`]);function sn(e){return e!==void 0&&on.has(e)}function cn(t){let{info:n,statePaths:r,remote:i,timeoutMs:a,requestId:o,command:s,platform:c,session:l,action:u}=t,f=i?{terminated:0}:dn(),p=!i&&ln(s),m=p?fn(n,r):{forcedKill:!1},h=sn(c)||f.terminated>0;return d({level:`error`,phase:`daemon_request_timeout`,data:{timeoutMs:a,requestId:o,command:s,timedOutRunnerPidsTerminated:f.terminated,timedOutRunnerCleanupError:f.error,daemonPidReset:p?n.pid:void 0,daemonPidForceKilled:p?m.forcedKill:void 0,daemonPreservedAfterTimeout:!i&&!p,daemonBaseUrl:n.baseUrl}}),new e(`COMMAND_FAILED`,`Daemon request timed out`,{timeoutMs:a,requestId:o,hint:un({remote:i,resetDaemon:p,command:s,appleCleanupEvidence:h,session:l,action:u})})}function ln(e){return c(e).onTimeout===`reset-daemon`}function un(e){let{remote:t,resetDaemon:n,command:r,appleCleanupEvidence:i,session:a,action:o}=e;if(t)return r===l.record&&o===`stop`?`The remote daemon is still exporting the recording. Run agent-device record stop${a?` --session ${a}`:``} again to wait for that export and receive the completed recording.`:`Retry with --debug and verify the remote daemon URL, auth token, and remote host logs.`;if(!n){let e=i&&r===l.snapshot?` If this was the first Apple-platform snapshot on the device, run agent-device prepare ios-runner with the same --platform before snapshot/test so runner startup is handled explicitly.`:``;return`Retry with --debug and check daemon diagnostics logs. The timed-out ${r??`request`} request was canceled${i?` and Apple runner work was aborted when detected`:``}; the daemon was kept alive so the session can still be closed or inspected.${e}`}return i?`Retry with --debug and check daemon diagnostics logs. Timed-out Apple runner xcodebuild processes were terminated when detected.`:`Retry with --debug and check daemon diagnostics logs. The daemon was reset after the timeout.`}function dn(){let e=0;try{for(let t of an)m(`pkill`,[`-f`,t],{allowFailure:!0}).exitCode===0&&(e+=1);return{terminated:e}}catch(t){return{terminated:e,error:t instanceof Error?t.message:String(t)}}}function fn(e,t){let n=!1;try{C(e.pid,e.processStartTime)&&(process.kill(e.pid,`SIGKILL`),n=!0)}catch{q(e)}finally{U(t.infoPath),W(t.lockPath)}return{forcedKill:n}}const pn=`Daemon HTTP endpoint is unavailable`,mn=`Daemon socket endpoint is unavailable`;async function hn(e,t){let n=Tn(e,t);if(await gn(e,n))return!0;let r=En(e,t,n);return r?await gn(e,r):!1}async function gn(e,t){return t===`http`?await vn(e):await _n(e.port)}function _n(e){return e?new Promise(t=>{let n=!1,r=k.createConnection({host:`127.0.0.1`,port:e},()=>{i(!0)}),i=e=>{n||(n=!0,r.destroy(),t(e))};r.setTimeout(500),r.on(`timeout`,()=>{i(!1)}),r.on(`error`,()=>{i(!1)})}):Promise.resolve(!1)}function vn(e){return bn(e).then(e=>e.reachable)}async function yn(t){let n=await bn(t);if(!t.baseUrl||!n.reachable)return n;let r=[n,n.upstream].find(e=>typeof e?.rpcProtocolVersion==`number`&&e.rpcProtocolVersion!==2);if(r)throw new e(`COMMAND_FAILED`,`Remote daemon RPC protocol is incompatible`,{daemonBaseUrl:t.baseUrl,clientVersion:S(),remoteVersion:r.version,remoteService:r.service,supportedRpcProtocolVersion:2,remoteRpcProtocolVersion:r.rpcProtocolVersion,hint:`Upgrade agent-device on the client or remote host so both support the same daemon RPC protocol.`});return n}async function bn(e){let t=e.baseUrl?_(e.baseUrl,`health`):e.httpPort?`http://127.0.0.1:${e.httpPort}/health`:null;if(!t)return{reachable:!1};let n=new URL(t),r=await v(n.protocol),i=e.baseUrl?3e3:500;return await new Promise(t=>{let a=e.baseUrl?g(e.token):{},o=r.request({protocol:n.protocol,host:n.hostname,port:n.port,path:n.pathname+n.search,method:`GET`,timeout:i,headers:a},e=>{let n=``;e.setEncoding(`utf8`),e.on(`data`,e=>{n+=e}),e.on(`end`,()=>{let r=e.statusCode??500;t({reachable:r<500,statusCode:r,...xn(n)})})});o.on(`timeout`,()=>{o.destroy(),t({reachable:!1})}),o.on(`error`,()=>{t({reachable:!1})}),o.end()})}function xn(e){try{let t=JSON.parse(e),n=t.upstream&&typeof t.upstream==`object`?Sn(t.upstream):void 0;return{...Sn(t),...n?{upstream:n}:{}}}catch{return{}}}function Sn(e){return{service:typeof e.service==`string`?e.service:void 0,version:typeof e.version==`string`?e.version:void 0,rpcProtocolVersion:typeof e.rpcProtocolVersion==`number`?e.rpcProtocolVersion:void 0}}async function Cn(e,t,n,r,i,a={}){let o=Tn(e,n);try{return await wn(e,t,r,i,o,a)}catch(s){let c=En(e,n,o);if(!c||!Dn(s,o))throw s;return await wn(e,t,r,i,c,a)}}async function wn(e,t,n,r,i,a){return i===`http`?await jn(e,t,n,r,a):await An(e,t,n,r,a)}function Tn(t,n){if(t.baseUrl){if(n===`socket`)throw new e(`COMMAND_FAILED`,`Remote daemon endpoint only supports HTTP transport`,{daemonBaseUrl:t.baseUrl});return`http`}if(n===`http`||n===`socket`)return On(t,n);let r=(t.transport===`socket`||t.transport===`dual`?[`socket`,`http`]:[`http`,`socket`]).find(e=>X(t,e));if(r)return r;throw new e(`COMMAND_FAILED`,`Daemon metadata has no reachable transport`)}function X(e,t){return t===`http`?!!e.httpPort:!!e.port}function En(e,t,n){if(t!==`auto`||e.baseUrl)return null;let r=n===`socket`?`http`:`socket`;return X(e,r)?r:null}function Dn(t,n){return n===`socket`&&t instanceof e&&t.code===`COMMAND_FAILED`&&t.message===`Failed to communicate with daemon`&&t.details?.daemonSocketRequestWritten===!1}function On(t,n){if(X(t,n))return n;throw new e(`COMMAND_FAILED`,n===`http`?pn:mn)}function kn(t,n,r,i={}){return d({level:`error`,phase:`daemon_request_socket_error`,data:{requestId:n,message:t instanceof Error?t.message:String(t)}}),new e(`COMMAND_FAILED`,`Failed to communicate with daemon`,{...i,requestId:n,hint:r?`Retry command. If this persists, verify the remote daemon URL, auth token, and remote host reachability.`:`Retry command. If this persists, clean stale daemon metadata and start a fresh session.`},t instanceof Error?t:void 0)}async function An(t,n,r,i,a){let o=t.port;if(!o)throw new e(`COMMAND_FAILED`,mn);return new Promise((e,s)=>{let c=!1,l=k.createConnection({host:`127.0.0.1`,port:o},()=>{c=!0,l.write(`${JSON.stringify(n)}\n`)}),u=!1,d=typeof i==`number`?setTimeout(()=>{u=!0,l.destroy(),s(cn({info:t,statePaths:r,...Z(n,!1,i)}))},i):void 0;zt(l,{req:n,onProgress:a.onProgress,isSettled:()=>u,clearTimeout:()=>{d&&clearTimeout(d)},resolve:t=>{u=!0,e(t)},reject:e=>{u=!0,s(e)}}),l.on(`error`,e=>{u||(u=!0,d&&clearTimeout(d),s(kn(e,n.meta?.requestId,!1,{daemonSocketRequestWritten:c})))})})}function Z(e,t,n){return{remote:t,timeoutMs:n,requestId:e.meta?.requestId,command:e.command,platform:e.flags?.platform,session:e.session,action:e.positionals?.[0]}}async function jn(t,n,r,i,a){let o=t.baseUrl?new URL(_(t.baseUrl,`rpc`)):t.httpPort?new URL(`http://127.0.0.1:${t.httpPort}/rpc`):null;if(!o)throw new e(`COMMAND_FAILED`,pn);let s=JSON.stringify(en(n,{includeTokenParam:!t.baseUrl})),c={"content-type":`application/json`,"content-length":Buffer.byteLength(s)};t.baseUrl&&Object.assign(c,g(t.token));let l=await v(o.protocol);return await new Promise((u,d)=>{let f=l.request({protocol:o.protocol,host:o.hostname,port:o.port,method:`POST`,path:o.pathname+o.search,headers:c},i=>{if(Rt(n,i.headers?.[`content-type`])){Bt(i,{req:n,onProgress:a.onProgress,reject:d,clearTimeout:()=>{m&&clearTimeout(m)},handleResponseBody:e=>qt(e,{info:t,req:n,stateDir:r.baseDir,resolve:u,reject:d})});return}ne(i).then(e=>{m&&clearTimeout(m),qt(e,{info:t,req:n,stateDir:r.baseDir,resolve:u,reject:d})}).catch(t=>{m&&clearTimeout(m),d(new e(`COMMAND_FAILED`,`Failed to read daemon response`,{requestId:n.meta?.requestId},t instanceof Error?t:void 0))})}),p=Mt(t),m=typeof i==`number`?setTimeout(()=>{f.destroy(),d(cn({info:t,statePaths:r,...Z(n,p,i)}))},i):void 0;f.on(`error`,e=>{m&&clearTimeout(m),d(kn(e,n.meta?.requestId,p))}),f.write(s),f.end()})}const Q=15e3,$=new k.BlockList;$.addSubnet(`127.0.0.0`,8,`ipv4`),$.addAddress(`::1`,`ipv6`),$.addSubnet(`::ffff:127.0.0.0`,104,`ipv6`);function Mn(e,t){let n=Nn(e),r=Pn(e,t),i=Fn(e,r.remoteBaseUrl),a=In(e,n,r.rawBaseUrl),o=a?Ln():n;return{paths:de(o),transportPreference:i.preference,serverMode:i.serverMode,ownedStateDir:a,remoteBaseUrl:r.remoteBaseUrl,remoteAuthToken:r.authToken}}function Nn(e){return e.flags?.stateDir??process.env.AGENT_DEVICE_STATE_DIR}function Pn(e,t){let n=e.flags?.daemonBaseUrl??process.env.AGENT_DEVICE_DAEMON_BASE_URL,r=nr(n),i=t??process.env.AGENT_DEVICE_DAEMON_AUTH_TOKEN;return rr(r,i),{rawBaseUrl:n,remoteBaseUrl:r,authToken:i}}function Fn(t,n){let r=t.flags?.daemonTransport??process.env.AGENT_DEVICE_DAEMON_TRANSPORT,i=ue(r);if(n&&i===`socket`)throw new e(`INVALID_ARGS`,`Remote daemon base URL only supports HTTP transport. Remove --daemon-transport socket.`,{daemonBaseUrl:n});let a=t.flags?.daemonServerMode??process.env.AGENT_DEVICE_DAEMON_SERVER_MODE??(r===`dual`?`dual`:void 0);return{preference:i,serverMode:le(a)}}function In(e,t,n){return Yn(e.command)&&!t&&!n}function Ln(){return T.mkdtempSync(w.join(D.tmpdir(),`agent-device-replay-daemon-`))}async function Rn(e){if(e.remoteBaseUrl)return await zn(e);let t=await Bn(e);return t?{info:t,startedByClient:!1}:(At(e.paths),await Wn(e))}async function zn(t){let n={transport:`http`,token:t.remoteAuthToken??``,pid:0,baseUrl:t.remoteBaseUrl};if((await yn(n)).reachable)return{info:n,startedByClient:!1};throw new e(`COMMAND_FAILED`,`Remote daemon is unavailable`,{daemonBaseUrl:t.remoteBaseUrl,hint:`Verify AGENT_DEVICE_DAEMON_BASE_URL points to a reachable daemon with GET /health and POST /rpc. If this CLI was connected with connect proxy, run agent-device disconnect to return to the local daemon.`})}async function Bn(e){let t=z(e.paths.infoPath);if(!t)return null;let n=await xt(t,await Vn(t,e.transportPreference));return n?(Un(t,n,e.paths.baseDir),await q(t),U(e.paths.infoPath),null):t}async function Vn(e,t){try{return await hn(e,t)}catch(e){if(Hn(e))return!1;throw e}}function Hn(t){return t instanceof e&&t.code===`COMMAND_FAILED`&&(t.message===`Daemon HTTP endpoint is unavailable`||t.message===`Daemon socket endpoint is unavailable`)}function Un(e,t,n){try{let r=e.version?`pid ${e.pid}, v${e.version}`:`pid ${e.pid}`;process.stderr.write(`Replacing daemon (${r}) in ${n}: ${t}\n`)}catch{}}async function Wn(t){let n=0,r=[],i,a;for(let e=1;e<=2;e+=1){let o;try{o=$n(t),a={pid:o.pid}}catch(n){if(i=n instanceof Error?n.message:String(n),r.push(await G(t.paths,`start_error`)),e<2){await h(150);continue}break}let s=await Qn(Q,t,o);if(s.kind===`ready`)return{info:s.info,startedByClient:!0};if(s.kind===`early_exit`){if(a=s.exit,i=er(s.exit),r.push(await G(t.paths,`start_error`)),e<2){await h(150);continue}break}if(await jt(t.paths)){n+=1;continue}let c=K(t.paths),l=e<2,u=await G(t.paths,`startup_timeout`,{stopLiveProcesses:!1});if(r.push(u),u.retainedInfoProcess||u.retainedLockProcess){let e=await Qn(Q,t,o);if(e.kind===`ready`)return{info:e.info,startedByClient:!0};e.kind===`early_exit`&&(a=e.exit,i=er(e.exit));break}if(!l)break;!c.hasInfo&&!c.hasLock&&await h(150)}let o=K(t.paths),s=tr(t.paths.logPath);throw new e(`COMMAND_FAILED`,`Failed to start daemon`,{kind:`daemon_startup_failed`,stateDir:t.paths.baseDir,infoPath:t.paths.infoPath,lockPath:t.paths.lockPath,logPath:t.paths.logPath,startupTimeoutMs:Q,startupAttempts:2,lockRecoveryCount:n,cleanupResults:r,startError:i,daemonProcess:a,...s?{daemonLogTail:s}:{},metadataState:o,hint:Nt(o,t.paths)})}async function Gn(e,t,n,r){if(!Yn(e.command)||!t.startedByClient&&!n.ownedStateDir||Mt(t.info)||qn(r)||Xn(e,r))return r;let i={pid:t.info.pid,removedInfo:!1,removedLock:!1,removedStateDir:!1,error:void 0},a=r;try{await q(t.info)}catch(e){i.error=e instanceof Error?e.message:String(e)}finally{let e=T.existsSync(n.paths.infoPath);U(n.paths.infoPath),i.removedInfo=e&&!T.existsSync(n.paths.infoPath);let t=T.existsSync(n.paths.lockPath);if(W(n.paths.lockPath),i.removedLock=t&&!T.existsSync(n.paths.lockPath),n.ownedStateDir){let e=ae(n.paths.sessionsDir);e?a=Kn(r,e):(T.rmSync(n.paths.baseDir,{recursive:!0,force:!0}),i.removedStateDir=!T.existsSync(n.paths.baseDir))}}return d({level:i.error?`warn`:`info`,phase:`daemon_replay_cleanup`,data:i}),a}function Kn(n,r){if(n&&!n.ok)return n;let{sessionName:i,tombstone:a}=r,o=a.sourcePath?`re-run: replay ${a.sourcePath} --save-script`:`re-run your replay <script> --save-script from the start`,s=`The repair transaction for session "${i}" completed, but committing its healed script failed at teardown: ${a.commitFailure.message}. ${o}.`;return{ok:!1,error:t(new e(`REPAIR_COMMIT_FAILED`,s))}}function qn(e){return!e||e.ok||e.error.code!==`REPLAY_DIVERGENCE`?!1:ie(e.error.details?.divergence)?.repairSessionHeld===!0}function Jn(e,t){let n=`This repair session's daemon was kept alive to continue the repair; pass --state-dir ${t} on your next command (press, replay --from, or close --save-script) to reach it.`,r=e.error.hint;return{...e,error:{...e.error,hint:r?`${r} ${n}`:n}}}function Yn(e){return e===l.replay||e===l.test}function Xn(e,t){return e.command!==l.replay||!t||!t.ok?!1:t.data?.sessionActive===!0}function Zn(e,t){let n=e.data??{},r=typeof n.session==`string`?n.session:void 0,i=[...t?[`--state-dir ${x(t)}`]:[],...r?[`--session ${x(r)}`]:[]];if(i.length===0)return e;let a=`This session's daemon was kept alive because its script left the session active; pass ${i.join(` `)} on your next command to reach it.`,o=typeof n.message==`string`?n.message:void 0;return{...e,data:{...n,hint:a,message:o?`${o} ${a}`:a}}}async function Qn(e,t,n){let r=Date.now(),i;for(n.exited.then(e=>{i=e});Date.now()-r<e;){if(i)return{kind:`early_exit`,exit:i};let e=z(t.paths.infoPath);if(e&&await hn(e,t.transportPreference))return{kind:`ready`,info:e};if(i)return{kind:`early_exit`,exit:i};await h(100)}return{kind:`timeout`}}function $n(e){let t=yt(),n=t.useSrc?[`--experimental-strip-types`,t.srcPath]:[t.distPath],r={...process.env,AGENT_DEVICE_STATE_DIR:e.paths.baseDir,AGENT_DEVICE_DAEMON_SERVER_MODE:e.serverMode};T.mkdirSync(e.paths.baseDir,{recursive:!0});let i=T.openSync(e.paths.logPath,`a`),a=T.openSync(e.paths.logPath,`a`);try{return p(process.execPath,n,{env:r,stdio:[`ignore`,i,a]})}finally{T.closeSync(i),T.closeSync(a)}}function er(e){return e.error?`daemon process ${e.pid} failed to start: ${e.error}`:e.signal?`daemon process ${e.pid} exited before readiness with signal ${e.signal}`:`daemon process ${e.pid} exited before readiness with code ${e.exitCode??0}`}function tr(e){try{if(!T.existsSync(e))return;let t=T.statSync(e);if(t.size<=0)return;let n=Math.min(t.size,64e3),r=T.openSync(e,`r`);try{let e=Buffer.alloc(n);T.readSync(r,e,0,n,t.size-n);let i=e.toString(`utf8`).trim();return i.length>0?i:void 0}finally{T.closeSync(r)}}catch{return}}function nr(t){if(!t)return;let n;try{n=new URL(t)}catch(n){throw new e(`INVALID_ARGS`,`Invalid daemon base URL`,{daemonBaseUrl:t},n instanceof Error?n:void 0)}if(n.protocol!==`http:`&&n.protocol!==`https:`)throw new e(`INVALID_ARGS`,`Daemon base URL must use http or https`,{daemonBaseUrl:t});return n.toString().replace(/\/+$/,``)}function rr(t,n){if(!t)return;let r=new URL(t).hostname;if(!ir(r)&&!(typeof n==`string`&&n.trim().length>0))throw new e(`INVALID_ARGS`,`Remote daemon base URL for non-loopback hosts requires daemon authentication`,{daemonBaseUrl:t,hint:`Provide --daemon-auth-token or AGENT_DEVICE_DAEMON_AUTH_TOKEN when using a non-loopback remote daemon URL.`})}function ir(e){let t=e.trim().toLowerCase().replace(/^\[(.*)\]$/,`$1`);return t===`localhost`?!0:k.isIPv4(t)?$.check(t,`ipv4`):k.isIPv6(t)?$.check(t,`ipv6`):!1}export{Xn as a,Cn as c,Rn as i,Ze as l,Jn as n,qn as o,Gn as r,Mn as s,Zn as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{D as e}from"./owner-identity.js";import"./file.js";import t from"node:path";import n from"node:fs";function r(t,r){let i={providerReleases:{released:r.providerReleases.released.map(s),pending:r.providerReleases.pending.map(s)},claims:{released:[...r.claims.released],orphaned:[...r.claims.orphaned],superseded:[...r.claims.superseded]}},a=o(t);try{e({destination:a,contents:`${JSON.stringify(i)}\n`,mode:384}),n.chmodSync(a,384)}catch{}}function i(e){try{let t=JSON.parse(n.readFileSync(o(e),`utf8`));return c(t)?{...t,claims:l(t)}:null}catch{return null}}function a(e){try{n.rmSync(o(e),{force:!0})}catch{}}function o(e){return t.join(e,`daemon-shutdown.json`)}function s(e){return{leaseId:e.leaseId,...e.leaseProvider?{provider:e.leaseProvider}:{}}}function c(e){if(!e||typeof e!=`object`)return!1;let t=e.providerReleases;if(!t||typeof t!=`object`)return!1;let n=t;return Array.isArray(n.released)&&Array.isArray(n.pending)&&n.released.every(f)&&n.pending.every(f)}function l(e){let t=e.claims;if(!t||typeof t!=`object`)return{released:[],orphaned:[],superseded:[]};let n=t;return{released:u(n.released),orphaned:u(n.orphaned),superseded:u(n.superseded)}}function u(e){return Array.isArray(e)?e.filter(d):[]}function d(e){if(!e||typeof e!=`object`)return!1;let t=e;return typeof t.deviceKey==`string`&&typeof t.session==`string`&&typeof t.platform==`string`&&typeof t.deviceId==`string`}function f(e){if(!e||typeof e!=`object`)return!1;let t=e;return typeof t.leaseId==`string`&&t.leaseId.trim().length>0&&(t.provider===void 0||typeof t.provider==`string`)}export{i as n,r,a as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{C as e,T as t,o as n,w as r}from"./sdk-contracts.js";import"./capture.js";import{r as i}from"./sdk-batch-runner.js";import{p as a}from"./android-input-ownership.js";import{c as o,l as s,o as c,v as l}from"./sdk-device.js";import{d as u,l as d,n as f,r as p}from"./lease-scope.js";import{Mr as m,Sr as h,Tr as ee,Wt as te,Xt as ne,Yt as re,tr as ie,zr as g}from"./sdk-batch.js";import{a as ae,n as oe,r as se}from"./script.js";import"./session-store.js";import{r as ce}from"./format.js";import{r as _}from"./diagnostics.js";import"./diagnostics2.js";import{r as le}from"./command.js";import{n as v}from"./runtime-transport-hints.js";import{_ as ue,a as de,c as fe,d as y,f as b,g as pe,h as me,i as he,l as ge,m as _e,n as x,o as ve,p as ye,r as be,s as S,u as xe,v as Se}from"./human-control-contract.js";import{n as Ce,t as we,u as Te}from"./provider-session-ownership.js";import{i as Ee}from"./request-runtime-binding.js";import{r as De}from"./application-lifecycle-runtime.js";import{a as Oe,c as C,l as ke,n as Ae,o as je,r as Me,t as Ne}from"./device-claim-inspection.js";import{b as Pe,c as Fe,g as Ie,i as Le,p as Re,x as w}from"./perf-runtime-plan.js";import{n as ze,r as Be,t as Ve}from"./lease-context.js";import{d as He,g as Ue,u as We}from"./screenshot-runtime.js";import{a as Ge,c as Ke,d as T,l as qe,n as Je,o as Ye,r as Xe,u as E}from"./src8.js";import{n as Ze,t as Qe}from"./compatibility-policy.js";import{o as $e}from"./screen-recording-resource-recovery.js";import D from"node:path";import"node:fs";import et,{createHash as tt}from"node:crypto";import nt from"node:os";import O from"node:fs/promises";function rt(t,n){if(n?.replayBackend&&n.replayBackend!==`maestro`)throw new e(`INVALID_ARGS`,`Unsupported replay backend "${n.replayBackend}".`);return{...oe(t),metadata:se(t)}}function it(e,t){return k(e,t)?t:`${e}:${t}`}function k(e,t){return t.startsWith(`${e}:`)}function at(e,t){return!e.partitioned||k(e.tenant,t)}var ot=class{active=new Map;waiters=new Map;async run(e,t){this.active.set(e,(this.active.get(e)??0)+1);try{return await t()}finally{let t=(this.active.get(e)??1)-1;if(t>0)this.active.set(e,t);else{this.active.delete(e);let t=this.waiters.get(e);this.waiters.delete(e);for(let e of t??[])e()}}}async wait(e,t){if(t?.throwIfAborted(),!this.active.has(e))return;let n=this.waiters.get(e)??new Set,r=()=>{},i=()=>{};try{await new Promise((a,o)=>{r=a,i=()=>o(t?.reason),n.add(r),this.waiters.set(e,n),t?.addEventListener(`abort`,i,{once:!0})})}finally{t?.removeEventListener(`abort`,i),n.delete(r),n.size===0&&this.waiters.get(e)===n&&this.waiters.delete(e)}}},st=class{entriesByLeaseId=new Map;retain(e,t){let n={wanted:t,released:!1},r=this.entriesByLeaseId.get(e)??new Set;return r.add(n),this.entriesByLeaseId.set(e,r),{leaseId:e,release:()=>this.releasePass(e,r,n)}}forget(e){let t=this.entriesByLeaseId.get(e);if(t){for(let e of t)e.released=!0;this.entriesByLeaseId.delete(e)}}isDeferred(e){let t=this.entriesByLeaseId.get(e);if(!t)return!1;for(let e of t)e.wanted()||t.delete(e);return t.size>0||(this.entriesByLeaseId.delete(e),!1)}releasePass(e,t,n){return!n.released&&(n.released=!0,t.delete(n),t.size===0&&this.entriesByLeaseId.delete(e),n.wanted())}},ct=class{holdsByDevice=new Map;mutations=new ot;inFlightWork=new st;leases=new Map;runBindings=new Map;deviceBindings=new Map;maxActiveSimulatorLeases;resolveLeaseTtlMs;now;onLeaseExpired;providerSessionOwnership;constructor(e={}){this.maxActiveSimulatorLeases=Number.isInteger(e.maxActiveSimulatorLeases)?Math.max(0,Number(e.maxActiveSimulatorLeases)):0,this.resolveLeaseTtlMs=ge(e),this.now=e.now??(()=>Date.now()),this.onLeaseExpired=e.onLeaseExpired,this.providerSessionOwnership=new we({now:this.now,retentionMs:e.providerSessionRetentionMs})}allocateLease(e){let t=ye(e);this.cleanupExpiredLeases();let n=this.resolveLeaseTtlMs(t.ttlMs);this.assertHumanControlAdmission(t);let r=this.refreshExistingRunBinding(t,n);if(r)return r;this.assertDeviceAvailable(t),this.enforceCapacity(t.backend);let i=fe(t,n,this.now());return this.leases.set(i.leaseId,i),this.bindLease(i),{...i}}refreshExistingRunBinding(e,t){let n=b(e),r=this.runBindings.get(n);if(!r)return;let i=this.leases.get(r);if(!i){this.runBindings.delete(n);return}if(i.clientId===e.clientId)return this.refreshLease(i,t);if(i.deviceKey)throw xe(i);return S(i,e),this.refreshLease(i,t)}heartbeatLease(e){let t=pe(e.leaseId);this.cleanupExpiredLeases();let n=this.getActiveLease(t);ve(n,e),S(n,e);let r=this.resolveLeaseTtlMs(e.ttlMs);return this.refreshLease(n,r)}retainLeaseWork(e,t){let n=this.inFlightWork.retain(e.leaseId,t);return{leaseId:n.leaseId,release:()=>{let t=n.release();return t&&this.refreshProtectedLease(e.leaseId,this.now()),t}}}releaseLease(e){let t=this.getLease(e);return t?(this.leases.delete(t.leaseId),this.unbindLease(t),this.inFlightWork.forget(t.leaseId),{released:!0,lease:t}):{released:!1}}getLease(e){let t=pe(e.leaseId);this.cleanupExpiredLeases();let n=this.leases.get(t);if(n)return ve(n,e),S(n,e),{...n}}assertLeaseAdmission(e){let t=_e(e);this.cleanupExpiredLeases(),S(this.getActiveLease(t.leaseId),t)}listActiveLeases(){return this.cleanupExpiredLeases(),Array.from(this.leases.values()).map(e=>({...e}))}recordProviderSession(e,t){this.cleanupExpiredLeases();let n=e.expiresAt<=this.now()?e.expiresAt:void 0;this.providerSessionOwnership.record(e,t),this.leases.has(e.leaseId)||this.providerSessionOwnership.markLeaseReleased(e,n)}resolveProviderSession(e){return this.cleanupExpiredLeases(),this.providerSessionOwnership.resolve(e)}listHumanControlHolds(e){this.cleanupExpiredLeases();let t=e.kind===`lease`?y(this.requireHumanControlLease(e.leaseId)):void 0;return[...this.holdsByDevice.entries()].filter(([e])=>t===void 0||t===e).flatMap(([,e])=>[...e.values()].map(({hold:e})=>x(e))).sort((e,t)=>e.id.localeCompare(t.id))}async putHumanControlHold(t,n,r,i){i?.throwIfAborted();let a=he(n),o=de(r);this.cleanupExpiredLeases();let s=this.resolveHumanControlScope(t,o),c=y(s),l=this.findHumanControlHold(a);if(l&&(this.assertHoldAuthority(t,l),y(l.hold.scope)!==c))throw new e(`INVALID_ARGS`,`Release a hold before changing its device scope.`);let u=this.now(),d={...t.kind===`lease`?{ownerLeaseId:t.leaseId}:{},hold:{id:a,scope:s,state:`activating`,...o.reason?{reason:o.reason}:{},createdAt:l?.hold.createdAt??u,updatedAt:u}},f=this.holdsByDevice.get(c)??new Map;return this.holdsByDevice.set(c,f),f.set(a,d),await this.activateHumanControlHold(c,d,o.ttlMs,i)}async activateHumanControlHold(t,n,r,i){let a=this.holdsByDevice.get(t),{id:o}=n.hold;try{if(await this.mutations.wait(t,i),i?.throwIfAborted(),a.get(o)!==n)throw new e(`COMMAND_FAILED`,`Human-control hold changed before activation completed.`,{holdId:o});let s=this.now();return n.hold={...n.hold,state:`active`,updatedAt:s,...r===void 0?{}:{expiresAt:s+r}},this.refreshHeldLease(t,s),x(n.hold)}catch(e){throw a.get(o)===n&&this.deleteHumanControlHold(t,o),e}}removeHumanControlHold(e,t){let n=he(t);this.cleanupExpiredLeases();let r=this.findHumanControlHold(n);if(!r)return;this.assertHoldAuthority(e,r);let i=y(r.hold.scope);return this.deleteHumanControlHold(i,n),x(r.hold)}deleteHumanControlHold(e,t){let n=this.holdsByDevice.get(e);n.delete(t),n.size===0&&(this.holdsByDevice.delete(e),this.refreshHeldLease(e,this.now()))}assertHumanControlAdmission(e){this.expireHumanControlHolds();let t=y(e),n=t===void 0?void 0:this.holdsByDevice.get(t)?.values().next().value;if(n)throw be(n.hold)}async runDeviceMutation(e,t){if(!e)return await t();this.cleanupExpiredLeases();let n=this.getActiveLease(e.leaseId);this.assertHumanControlAdmission(n);let r=y(n);return r===void 0?await t():await this.mutations.run(r,t)}requireHumanControlLease(t){let n=this.getActiveLease(t);if(!n.deviceKey)throw new e(`UNSUPPORTED_OPERATION`,`Human control requires a device-scoped remote lease.`);return{...n,deviceKey:n.deviceKey}}resolveHumanControlScope(t,n){if(t.kind===`host`){if(!n.scope)throw new e(`INVALID_ARGS`,`Host human control requires a lease device scope.`);return n.scope}if(n.scope)throw new e(`INVALID_ARGS`,`Lease-owner human control uses the admitted lease device; do not supply scope.`);let r=this.requireHumanControlLease(t.leaseId);return{backend:r.backend,leaseProvider:r.leaseProvider,deviceKey:r.deviceKey}}assertHoldAuthority(t,n){if(t.kind===`host`)return;let r=this.requireHumanControlLease(t.leaseId);if(n.ownerLeaseId!==r.leaseId||y(r)!==y(n.hold.scope))throw new e(`UNAUTHORIZED`,`Human-control hold does not belong to the admitted lease.`,{reason:`LEASE_SCOPE_MISMATCH`})}findHumanControlHold(e){for(let t of this.holdsByDevice.values()){let n=t.get(e);if(n)return n}}hasHumanControl(e){let t=y(e);return t!==void 0&&this.holdsByDevice.has(t)}isLeaseProtected(e,t){return e.expiresAt>t||this.hasHumanControl(e)||this.inFlightWork.isDeferred(e.leaseId)}expireHumanControlHolds(){let e=this.now();for(let[t,n]of this.holdsByDevice){let r=0;for(let[t,{hold:i}]of n)i.expiresAt===void 0||i.expiresAt>e||(r=Math.max(r,i.expiresAt),n.delete(t));n.size===0&&(this.holdsByDevice.delete(t),this.refreshHeldLease(t,r))}}refreshHeldLease(e,t){this.refreshProtectedLease(this.deviceBindings.get(e),t)}refreshProtectedLease(e,t){let n=e?this.leases.get(e):void 0;n&&this.refreshLease(n,n.expiresAt-n.heartbeatAt,Math.max(t,n.heartbeatAt))}consumeExpiredLeases(){this.expireHumanControlHolds();let e=this.now(),t=[];for(let n of this.leases.values()){if(this.isLeaseProtected(n,e))continue;this.leases.delete(n.leaseId),this.unbindLease(n,n.expiresAt);let r={...n};t.push(r),this.onLeaseExpired?.(r)}return t}consumeExpiredLease(e){this.expireHumanControlHolds();let t=me(e);if(!t)return;let n=this.leases.get(t);if(!n||this.isLeaseProtected(n,this.now()))return;this.leases.delete(n.leaseId),this.unbindLease(n,n.expiresAt);let r={...n};return this.onLeaseExpired?.(r),r}cleanupExpiredLeases(){this.consumeExpiredLeases()}enforceCapacity(t){if(t!==`ios-simulator`||this.maxActiveSimulatorLeases<=0)return;let n=Array.from(this.leases.values()).filter(e=>e.backend===`ios-simulator`).length;if(!(n<this.maxActiveSimulatorLeases))throw new e(`DEVICE_IN_USE`,`No simulator lease capacity available`,{reason:`LEASE_CAPACITY_EXCEEDED`,activeLeases:n,maxActiveLeases:this.maxActiveSimulatorLeases,backend:t,hint:`Retry after releasing another simulator lease.`})}getActiveLease(t){let n=this.leases.get(t);if(n)return n;throw new e(`UNAUTHORIZED`,`Lease is not active`,{reason:`LEASE_NOT_FOUND`})}refreshLease(e,t,n=this.now()){let r={...e,heartbeatAt:n,expiresAt:n+t};return this.leases.set(r.leaseId,r),this.bindLease(r),{...r}}bindLease(e){this.runBindings.set(b(e),e.leaseId);let t=y(e);t&&this.deviceBindings.set(t,e.leaseId)}unbindLease(e,t=this.now()){this.runBindings.delete(b(e));let n=y(e);n&&this.deviceBindings.delete(n),this.providerSessionOwnership.markLeaseReleased(e,t)}assertDeviceAvailable(e){let t=y({backend:e.backend,leaseProvider:e.leaseProvider,deviceKey:e.deviceKey});if(!t)return;let n=this.deviceBindings.get(t);if(!n)return;let r=this.leases.get(n);if(!r){this.deviceBindings.delete(t);return}throw xe(r)}};function lt(t){let n=Se(t.meta?.sessionIsolation??t.flags?.sessionIsolation),r=t.meta?.tenantId??t.flags?.tenant,i=ue(r);if(r&&!i)throw new e(`INVALID_ARGS`,`Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.`);if(n!==`tenant`)return t;if(!i)throw new e(`INVALID_ARGS`,`session isolation mode tenant requires --tenant (or meta.tenantId).`);let a=t.session||`default`;return k(i,a)?{...t,meta:{...t.meta,tenantId:i,sessionIsolation:n}}:{...t,session:it(i,a),meta:{...t.meta,tenantId:i,sessionIsolation:n}}}function ut(t,n,r,i={}){if(He(t.command))return;let a=ze(t);pt(t,a);let o=r?.lease;if(r===void 0&&!a.leaseId&&dt(t,i.providerAppCatalog))return;if(t.command===`human_control`&&!o&&!a.leaseId)throw new e(`UNSUPPORTED_OPERATION`,`Takeover requires an active remote device lease. Local takeover is not supported.`);if(t.command!==`human_control`&&!o&&t.meta?.sessionIsolation!==`tenant`&&(!a.leaseId||!a.tenantId&&!a.runId))return;mt(a,o);let s=Be(t,r),c={...s,leaseTtlMs:s.leaseTtlMs??(p(s)?3e5:void 0)};n.assertLeaseAdmission(d(s));let l=n.heartbeatLease(d(c));return We(t)&&n.assertHumanControlAdmission(l),l}function dt(e,t){let n=Ue(e);return n?.kind===`unconditional`||n?.kind===`provider-app-catalog`&&t?.supports(n.provider)===!0}function ft(e){He(e.command)||pt(e,ze(e))}function pt(t,n){if(t.command!==`open`)return;let r=f(n);if(r.length!==0)throw new e(`INVALID_ARGS`,`Proxy open requires leaseId, tenantId, runId, clientId, and deviceKey lease metadata.`,{missing:r})}function mt(e,t){t&&(A(`leaseId`,e.leaseId,t.leaseId),A(`tenantId`,e.tenantId,t.tenantId),A(`runId`,e.runId,t.runId),A(`leaseProvider`,e.leaseProvider,t.leaseProvider),A(`clientId`,e.clientId,t.clientId),A(`deviceKey`,e.deviceKey,t.deviceKey))}function A(t,n,r){if(!(!n||!r||n===r))throw new e(`UNAUTHORIZED`,`Lease does not match session owner (${t})`,{reason:`LEASE_SESSION_MISMATCH`,field:t})}async function ht(e,t){if(!t.leaseProvider||!e)return!1;try{return await e(t),_({level:`info`,phase:`provider_lease_expired_released`,data:{leaseId:t.leaseId,provider:t.leaseProvider}}),!0}catch(e){return _({level:`error`,phase:`provider_lease_expiry_release_failed`,data:{leaseId:t.leaseId,provider:t.leaseProvider,error:e instanceof Error?e.message:String(e)}}),!1}}function gt(e){ft(e)}async function _t(e){let t=e.sessionStore.get(e.sessionName),n=t?.lease;return!t||!n||!e.leaseRegistry.consumeExpiredLease(n.leaseId)?!1:(_({level:`info`,phase:`leased_session_expired`,data:{reason:`LEASE_EXPIRED`,leaseId:n.leaseId,session:t.name,deviceKey:n.deviceKey}}),await e.teardownSession(t,t.name).catch(e=>{_({level:`debug`,phase:`leased_session_expiry_cleanup_failed`,data:{reason:`LEASE_EXPIRED`,leaseId:n.leaseId,session:t.name,error:e instanceof Error?e.message:String(e)}})}),await Pe(t.deviceClaim).catch(e=>{_({level:`warn`,phase:`leased_session_expiry_device_claim_clear_failed`,data:{session:t.name,deviceKey:t.deviceClaim?.deviceKey,error:e instanceof Error?e.message:String(e)}})}),e.sessionStore.delete(t.name),!0)}function vt(e){let{sessionName:t,sessionStore:n,leaseRegistry:r}=e,i=n.get(t),a=ut(e.req,r,i,{providerAppCatalog:e.providerAppCatalog});if(!a)return e.req;let o={...e.req,internal:{...e.req.internal,admittedLease:a}};return i?.lease&&n.set(t,{...i,lease:{...i.lease,leaseBackend:a.backend,expiresAt:a.expiresAt}}),o}function yt(e){return Ve(e.req,e.req.internal?.admittedLease)??e.existingLease}async function bt(e){let t=e.session.lease;if(!t)return;let n=u({leaseId:t.leaseId,tenantId:t.tenantId,runId:t.runId,leaseBackend:t.leaseBackend,leaseProvider:t.leaseProvider,deviceKey:t.deviceKey,clientId:t.clientId}),r=e.leaseRegistry.getLease(n),i=r?await e.leaseLifecycleProvider?.release?.(r):void 0,a=Ce(i);r&&a&&e.leaseRegistry.recordProviderSession(r,a);let o=e.leaseRegistry.releaseLease(n);return _({level:`info`,phase:`session_lease_released`,data:{session:e.session.name,leaseId:t.leaseId,released:o.released}}),i}const xt=[`platform`,`target`],St=[`iosSimulatorDeviceSet`,`androidDeviceAllowlist`];function Ct(e){return c({deviceName:e?.device,udid:e?.udid,serial:e?.serial})}function wt(e){return Ct(e)||Dt(e,xt)}function Tt(e){return wt(e)||Dt(e,St)}function Et(e){return typeof e==`string`&&e.trim().length>0}function Dt(e,t){return e?t.some(t=>Et(e[t])):!1}function Ot(e){return{appleSimulatorAppTarget:kt(e)}}function kt(e){return e&&!i(e)?e:void 0}function At(e){let t={version:2,platform:e.platform??null,target:e.target??null,runtimeHints:e.runtimeHints??null,initialStaticEnv:e.initialStaticEnv,steps:e.steps};return tt(`sha256`).update(ie(t),`utf8`).digest(`hex`)}function jt(e,t,n){return new Bt(Nt(Mt(t.resolve(e))),n).parse()}function Mt(e){let t=e.trim();return t.startsWith("${")&&t.endsWith(`}`)?t.slice(2,-1).trim():t}function Nt(t){let n=[],r=0;for(;r<t.length;){let i=t.slice(r),a=/^\s+/.exec(i)?.[0].length??0;if(a>0){r+=a;continue}let o=Pt(i);if(!o)throw new e(`INVALID_ARGS`,`Unsupported runFlow.when.true expression near "${i.slice(0,24)}".`);n.push(o.value),r+=o.length}return n}function Pt(e){return Ft(e)??It(e)??Lt(e)??Rt(e)??zt(e)}function Ft(e){return e.startsWith(`maestro.platform`)?{value:{type:`platform`},length:16}:null}function It(e){let t=/^(==|!=|&&|\|\|)/.exec(e)?.[1];return t?{value:{type:`operator`,value:t},length:t.length}:null}function Lt(e){let t=e[0];return t===`(`||t===`)`?{value:{type:`paren`,value:t},length:1}:null}function Rt(e){let t=/^(['"])(.*?)\1/.exec(e);return t?{value:{type:`string`,value:t[2]??``},length:t[0].length}:null}function zt(e){let t=/^(true|false)\b/.exec(e)?.[1];return t?{value:{type:`boolean`,value:t===`true`},length:t.length}:null}var Bt=class{index=0;tokens;platform;constructor(e,t){this.tokens=e,this.platform=t}parse(){let t=this.parseOr();if(this.peek())throw new e(`INVALID_ARGS`,`Unsupported trailing runFlow.when.true expression.`);return t}parseOr(){let e=this.parseAnd();for(;this.consumeOperator(`||`);)e=this.parseAnd()||e;return e}parseAnd(){let e=this.parsePrimary();for(;this.consumeOperator(`&&`);)e=this.parsePrimary()&&e;return e}parsePrimary(){let t=this.peek();if(!t)throw new e(`INVALID_ARGS`,`Incomplete runFlow.when.true expression.`);if(t.type===`boolean`)return this.index+=1,t.value;if(t.type===`paren`&&t.value===`(`){this.index+=1;let t=this.parseOr();if(!this.consumeParen(`)`))throw new e(`INVALID_ARGS`,`Unclosed runFlow.when.true parenthesis.`);return t}return this.parsePlatformComparison()}parsePlatformComparison(){this.consumePlatformToken();let e=this.consumeComparisonOperator(),t=this.consumeStringLiteral(),n=this.platform===t.toLowerCase();return e.value===`==`?n:!n}consumePlatformToken(){if(this.peek()?.type!==`platform`)throw new e(`INVALID_ARGS`,`runFlow.when.true supports maestro.platform comparisons.`);this.index+=1}consumeComparisonOperator(){let t=this.peek();if(t?.type!==`operator`||t.value!==`==`&&t.value!==`!=`)throw new e(`INVALID_ARGS`,`runFlow.when.true comparison requires == or !=.`);return this.index+=1,t}consumeStringLiteral(){let t=this.peek();if(t?.type!==`string`)throw new e(`INVALID_ARGS`,`runFlow.when.true comparison requires a string literal.`);return this.index+=1,t.value}consumeOperator(e){let t=this.peek();return t?.type!==`operator`||t.value!==e?!1:(this.index+=1,!0)}consumeParen(e){let t=this.peek();return t?.type!==`paren`||t.value!==e?!1:(this.index+=1,!0)}peek(){return this.tokens[this.index]}};function Vt(e){switch(e.kind){case`runFlow`:return!(`include`in e);case`repeat`:case`retry`:return!(`commands`in e);default:return!1}}function Ht(e,t){return{...N(e,t),source:e.source}}function j(t,n,r){if(t===void 0)return;let i=r??Ge[n]??{},a=Ye(i),o;if(typeof t==`number`)o=t;else{let r=t.trim();if(r===``)throw new e(`INVALID_ARGS`,`Maestro ${n} must be ${a}.`);o=Number(r)}if(!Number.isFinite(o)||Math.abs(o)>2**53-1||i.integer&&!Number.isSafeInteger(o)||i.nonNegative&&o<0||i.positive&&o<=0)throw new e(`INVALID_ARGS`,`Maestro ${n} must be ${a}.`);return o}function Ut(e,t,n,r){return j(e===void 0?t:n.resolve(String(e)),r)}function M(e){if(e?.aborted)throw t()}async function Wt(t,n){if(t.include.kind===`commands`)return{kind:`program`,source:t.source,config:{},commands:t.include.commands};if(!n.loadProgram)throw new e(`INVALID_ARGS`,`Maestro file runFlow requires a program loader.`);return M(n.signal),n.signal?await n.loadProgram(t.include.path,t.source.path,n.signal):await n.loadProgram(t.include.path,t.source.path)}function Gt(e,t){if(e.include.kind===`file`)return D.resolve(t?D.dirname(t):process.cwd(),e.include.path)}function Kt(e){return e===void 0?void 0:D.resolve(e)}function qt(t,n){let r=Gt(t,t.source.path);if(r&&n.has(r))throw new e(`INVALID_ARGS`,`Maestro runFlow cycle detected at ${r}.`);return r}function Jt(t,n,r,i){let a=t.include.kind===`file`?Kt(n.source.path):void 0,o=new Set([r,a].filter(e=>e!==void 0)),s=[...o].find(e=>i.has(e));if(s)throw new e(`INVALID_ARGS`,`Maestro runFlow cycle detected at ${s}.`);return o.forEach(e=>i.add(e)),o}function Yt(e,t,n){return e.platform&&e.platform!==n.platform?!1:e.true===void 0?!0:typeof e.true==`boolean`?e.true:jt(e.true,t,n.platform)}function Xt(e){return[...e.visible?[{kind:`visible`,selector:e.visible}]:[],...e.notVisible?[{kind:`notVisible`,selector:e.notVisible}]:[]]}function N(e,t){return typeof e==`string`?t.resolve(e):Array.isArray(e)?e.map(e=>N(e,t)):e&&typeof e==`object`?Object.fromEntries(Object.entries(e).map(([e,n])=>[e,N(n,t)])):e}async function Zt(e,t){M(t.signal);let n=Kt(e.source.path),r={options:t,context:Ke(t.defaults,t.env),activeIncludePaths:new Set(n===void 0?[]:[n]),staticallyExecutedControls:0,staticallySkippedControls:0};return{steps:await Qt(e,[],void 0,e.source.path,r),staticallyExecutedControls:r.staticallyExecutedControls,staticallySkippedControls:r.staticallySkippedControls}}async function Qt(e,t,n,r,i){M(i.options.signal);let a=ln(t,e.config.env),o=e.config.appId??n,s=i.context.enter(e.config.env);try{let t=[...e.config.onFlowStart??[],...e.commands,...e.config.onFlowComplete??[]],n=[];for(let s of t)n.push(...await en(s,a,o,e.source.path??r,i));return n}finally{s()}}async function $t(e,t,n,r,i){let a=[];for(let o of e)a.push(...await en(o,t,n,r,i));return a}async function en(e,t,n,r,i){M(i.options.signal);let a=un(e,r);switch(a.kind){case`runFlow`:{let e=nn(a,i);if(e===`omit`)return i.staticallySkippedControls+=1,[];let o=await tn(a,t,n,r,i);return e===`flatten`?(i.staticallyExecutedControls+=1,o):[P(a,t,n,o)]}case`repeat`:return[P(a,t,n,await $t(a.commands,t,n,r,i))];case`retry`:return[P(a,t,n,await $t(a.commands,t,n,r,i))];default:return[sn(a,t,n)]}}async function tn(e,t,n,r,i){let a=an(e,i.context),o=qt(a,i.activeIncludePaths),s=await Wt(a,i.options);M(i.options.signal);let c=Jt(a,s,o,i.activeIncludePaths),l=ln(t,e.env),u=i.context.enter(e.env);try{return await Qt(s,l,n,s.source.path??e.source.path??r,i)}finally{u(),c.forEach(e=>i.activeIncludePaths.delete(e))}}function nn(e,t){let n=e.when;return n?n.platform!==void 0&&n.platform!==t.options.platform?`omit`:rn(n.true,t)||(n.visible||n.notVisible?`opaque`:`flatten`):`flatten`}function rn(e,t){if(e===!1)return`omit`;if(typeof e==`string`)return on(t.context.resolveDeferred(e))?`opaque`:jt(e,t.context,t.options.platform)?void 0:`omit`}function an(e,t){return e.include.kind===`file`?{...e,include:{...e.include,path:t.resolve(e.include.path)}}:e}function on(e){return/\$\{[A-Za-z_][A-Za-z0-9_.]*\}/.test(e)}function sn(e,t,n){return T({kind:`command`,command:e,source:e.source,scopes:t,appId:n})}function P(e,t,n,r){return T({kind:`opaque`,command:cn(e),source:e.source,scopes:t,body:r,appId:n})}function cn(e){switch(e.kind){case`runFlow`:return T({kind:e.kind,source:e.source,when:e.when,label:e.label,...e.include.kind===`file`?{includePath:e.include.path}:{}});case`repeat`:return{kind:e.kind,source:e.source,times:e.times};case`retry`:return T({kind:e.kind,source:e.source,maxRetries:e.maxRetries})}}function ln(e,t){return t===void 0?e:[...e,t]}function un(e,t){return e.source.path||!t?e:{...e,source:{...e.source,path:t}}}async function dn(e,t={}){let{steps:n,staticallyExecutedControls:r,staticallySkippedControls:i}=await Zt(e,t),a=fn(t.runtimeHints),o=T({kind:`maestroReplayPlan`,platform:t.platform,target:t.target,runtimeHints:a,initialStaticEnv:structuredClone({...t.defaults??{},...e.config.env??{},...t.env??{}}),steps:structuredClone(n),total:n.length,compatibility:{staticallyExecutedControls:r,staticallySkippedControls:i}}),s=At(o);return pn({...o,digest:s})}function fn(e){if(!e)return;let t=Object.entries(e).filter(e=>e[1]!==void 0);return t.length===0?void 0:Object.fromEntries(t)}function pn(e){if(!e||typeof e!=`object`||Object.isFrozen(e))return e;for(let t of Object.values(e))pn(t);return Object.freeze(e)}function mn(e,t={}){let{from:n,planDigest:r}=t;if(n===void 0&&r===void 0)return{allowed:!0,startIndex:0};if(n===void 0||r===void 0)return{allowed:!1,reason:`replay --from requires --plan-digest (and --plan-digest requires --from).`};if(!Number.isInteger(n)||n<1||n>e.total)return{allowed:!1,reason:`replay --from ${n} is out of range for a ${e.total}-step plan.`};if(r!==e.digest)return{allowed:!1,reason:`replay --plan-digest does not match the current plan digest.`};if(n===1)return{allowed:!0,startIndex:0};for(let t=0;t<n-1;t+=1){let n=e.steps[t];if(n.kind===`opaque`)return{allowed:!1,reason:`step ${t+1} is opaque runtime control flow (${n.command.kind}) and cannot be skipped safely.`};if(n.command.kind===`runScript`||n.command.kind===`evalScript`)return{allowed:!1,reason:`step ${t+1} (${n.command.kind}) can produce outputEnv values and cannot be skipped safely.`}}let i=e.steps[n-1];return i.kind===`opaque`?{allowed:!1,reason:`step ${n} is opaque runtime control flow (${i.command.kind}) and cannot be resumed into.`}:{allowed:!0,startIndex:n-1}}function hn(t,n={}){let r=mn(t,n);if(!r.allowed)throw new e(`INVALID_ARGS`,r.reason);return r.startIndex}function gn(t,n){if(!Number.isInteger(n)||n<0||n>t.total)throw new e(`INVALID_ARGS`,`Maestro replay startIndex ${n} is out of range for a ${t.total}-step plan.`);return n}const _n=`maestro-test-failure`;function F(t,n={}){return new e(`COMMAND_FAILED`,t,{...n,reason:_n})}function vn(t){return t instanceof e&&t.code===`COMMAND_FAILED`&&t.details?.reason===_n}const yn=new Set([``,`false`,`0`,`null`,`undefined`]);function bn(e){return typeof e==`boolean`?e:typeof e==`number`?e!==0&&!Number.isNaN(e):!yn.has(e)}async function xn(e,t){M(t.options.signal);try{return await Pn(e,t.context,async()=>await Sn(e,t))}catch(t){throw R(t,e)}}async function Sn(e,t){if(e.kind===`command`)return await Cn(e.command,e.appId,t);await kn(e,t)}async function Cn(e,t,n){if(e.kind===`evalScript`)return await En(e,n);let r=Ht(e,n.context);try{return await Dn(r,t,n)}catch(e){if(M(n.options.signal),Tn(r)&&vn(e)){n.warnings.push(wn(r,e)),n.skipped+=1;return}throw Fn(e,r)}}function wn(t,n){let r=`${t.source.path?`${t.source.path}:`:``}line ${t.source.line}`,i=n instanceof e?n.message:String(n);return`Optional Maestro ${t.kind} skipped at ${r}: ${i}`}function Tn(e){return`optional`in e&&e.optional===!0}async function En(t,n){let{evaluateMaestroEvalScript:r}=await import(`./engine-eval-script.js`);if(n.options.trustedScripts===!1)throw new e(`UNAUTHORIZED`,`Maestro evalScript is not permitted for flows received over the remote daemon surface: node:vm is not a security sandbox, so an untrusted expression can escape to the host.`);let i=await r(t.script,n.context.values);n.context.replaceOutput(i),n.executed+=1}async function Dn(e,t,n){switch(e.kind){case`assertVisible`:await L({kind:`visible`,selector:e.target},n.timing.assertVisibleTimeoutMs,n),n.executed+=1;return;case`assertNotVisible`:await L({kind:`notVisible`,selector:e.target},n.timing.assertNotVisibleTimeoutMs,n),n.executed+=1;return;case`assertTrue`:if(!bn(e.condition))throw F(`Maestro assertTrue condition was falsy: ${JSON.stringify(e.condition)}`);n.executed+=1;return;case`extendedWaitUntil`:await L(Nn(e),j(e.timeout,`extendedWaitUntil.timeout`)??n.timing.extendedWaitUntilTimeoutMs,n),n.executed+=1;return;default:return await On(e,t,n)}}async function On(e,t,n){let r=T({command:e,env:n.context.values,appId:t===void 0?void 0:n.context.resolve(t),generation:n.context.generation,invalidateObservation:n.context.invalidateObservation,cachedObservation:n.context.observation,signal:n.options.signal}),i=await n.port.execute(r);return M(n.options.signal),i.observation&&n.context.recordObservation(i.observation),i.outputEnv&&n.context.merge(i.outputEnv),i.artifactPaths?.forEach(e=>n.artifacts.add(e)),n.executed+=1,i}async function kn(e,t){let n=Ht(e.command,t.context);switch(n.kind){case`runFlow`:if(n.when&&!await jn(n.when,t)){t.skipped+=1;return}t.executed+=1,await I(e.body,t);return;case`repeat`:{let r=Ut(n.times,0,t.context,`repeat.times`);t.executed+=1;for(let n=0;n<r;n+=1)M(t.options.signal),await I(e.body,t);return}case`retry`:{let r=Math.min(Ut(n.maxRetries,1,t.context,`retry.maxRetries`),Ze.control.retryMaxRetries);t.executed+=1,await An(e.body,r,t);return}}}async function I(e,t){for(let n of e)await xn(n,t)}async function An(t,n,r){let i;for(let e=0;e<=n;e+=1){M(r.options.signal);try{await I(t,r);return}catch(e){if(M(r.options.signal),!vn(Ln(e)))throw e;i=R(e,t[0])}}throw i||new e(`COMMAND_FAILED`,`Maestro retry commands failed.`)}async function jn(e,t){if(!Yt(e,t.context,t.options))return!1;for(let n of Xt(e))if(M(t.options.signal),!(await Mn(n,t.timing.runFlowConditionTimeoutMs,t)).matched)return!1;return!0}async function L(e,t,n){if(!(await Mn(e,t,n)).matched)throw F(`Maestro ${e.kind} condition did not match.`)}async function Mn(e,t,n){let r={condition:e,timeoutMs:t,generation:n.context.generation,env:n.context.values,...n.context.observation?{cachedObservation:n.context.observation}:{},...n.options.signal?{signal:n.options.signal}:{}},i=await n.port.observe(r);return M(n.options.signal),n.context.recordObservation(i),i}function Nn(t){if(t.visible)return{kind:`visible`,selector:t.visible};if(t.notVisible)return{kind:`notVisible`,selector:t.notVisible};throw new e(`INVALID_ARGS`,`Maestro extendedWaitUntil requires one condition.`)}async function Pn(e,t,n){let r=e.scopes.map(e=>t.enter({...e}));try{return await n()}finally{for(let e=r.length-1;e>=0;--e)r[e]()}}function R(e,t){if(In(e))return e;let n=t?.source??{line:1};return{kind:`maestroPlanStepFailure`,error:Rn(e,t?.command),source:n,...t?{command:t.command}:{}}}function Fn(e,t){return{kind:`maestroPlanStepFailure`,error:Rn(e,t),source:t.source,command:t}}function In(e){return!!(e&&typeof e==`object`&&e.kind===`maestroPlanStepFailure`)}function Ln(e){return In(e)?e.error:e}function Rn(t,n){if(!(t instanceof e)||!n||/\bline \d+\b/.test(t.message))return t;let r=n.source.path?`${n.source.path}:`:``;return new e(t.code,`${t.message} (${r}line ${n.source.line})`,t.details)}async function zn(t,n,r={}){M(r.signal);let i=r.startIndex??0;if(!Number.isInteger(i)||i<0||i>t.total)throw new e(`INVALID_ARGS`,`Maestro replay startIndex ${i} is out of range for a ${t.total}-step plan.`);let a={plan:t,port:n,options:r,context:Ke(r.defaults,r.env?{...r.env}:{}),timing:Qe,artifacts:new Set,warnings:[],executed:t.compatibility.staticallyExecutedControls,skipped:t.compatibility.staticallySkippedControls};for(let e=i;e<t.steps.length;e+=1)try{await Bn(t.steps[e],e,a)}catch(e){throw Ln(e)}return{executed:a.executed,skipped:a.skipped,generation:a.context.generation,artifactPaths:[...a.artifacts],...a.warnings.length>0?{warnings:a.warnings}:{}}}async function Bn(e,t,n){M(n.options.signal);let r=n.options.now??Date.now,i=r(),a=n.port.readMetrics?.(),o=n.context.generation,s={command:e.command,source:e.source,generation:o,stepIndex:t+1,stepTotal:n.plan.total};z(()=>n.options.observer?.commandStarted?.(s));try{let t=await xn(e,n);M(n.options.signal),z(()=>n.options.observer?.commandCompleted?.({...s,durationMs:r()-i,...Vn(a,n.port.readMetrics?.()),...t?.data?{data:t.data}:{}}))}catch(t){let o=R(t,e);throw z(()=>n.options.observer?.commandFailed?.({...s,...o.command?{command:o.command}:{},source:o.source,durationMs:r()-i,...Vn(a,n.port.readMetrics?.()),error:o.error,artifactPaths:[...n.artifacts]})),o}}function Vn(e,t){return!e||!t?{}:{runtimeMetrics:{hierarchyCaptures:t.hierarchyCaptures-e.hierarchyCaptures,screenshotCaptures:t.screenshotCaptures-e.screenshotCaptures,tapRetries:t.tapRetries-e.tapRetries,settleLatches:t.settleLatches-e.settleLatches,settleTimeouts:t.settleTimeouts-e.settleTimeouts}}}function z(e){try{e?.()}catch{}}async function Hn(e,t,n={}){let r=Un(e,n);return await zn(e,t,{...n,startIndex:r})}function Un(e,t){return t.from!==void 0||t.planDigest!==void 0?hn(e,{from:t.from,planDigest:t.planDigest}):gn(e,t.startIndex??0)}function Wn(e){return Vt(e)?{command:e.kind,...e.kind===`runFlow`?V(e.label??e.includePath):{}}:{command:e.kind,...Gn(e)}}function Gn(e){return`label`in e&&e.label?V(e.label):Kn(e)?V($n(e.target)):qn(e)?Jn(e):e.kind===`inputText`?V(`<text>`):Yn(e)}function Kn(e){return e.kind===`tapOn`||e.kind===`doubleTapOn`||e.kind===`longPressOn`}function qn(e){return e.kind===`assertVisible`||e.kind===`assertNotVisible`||e.kind===`extendedWaitUntil`||e.kind===`scrollUntilVisible`}function Jn(e){switch(e.kind){case`assertVisible`:case`assertNotVisible`:return V(B(e.target));case`extendedWaitUntil`:return V(B(e.visible??e.notVisible));case`scrollUntilVisible`:return V(B(e.element))}}function Yn(e){return Xn(e)?Zn(e):e.kind===`swipe`?Qn(e):e.kind===`runFlow`?V(e.label??(e.include.kind===`file`?e.include.path:``)):e.kind===`assertTrue`?V(String(e.condition)):{}}function Xn(e){return e.kind===`openLink`||e.kind===`takeScreenshot`||e.kind===`runScript`||e.kind===`pressKey`}function Zn(e){switch(e.kind){case`openLink`:return V(e.link);case`takeScreenshot`:return V(e.path);case`runScript`:return V(e.file);case`pressKey`:return V(e.key)}}function Qn(e){return V(e.gesture.kind===`coordinates`?`${er(e.gesture.start)} to ${er(e.gesture.end)}`:e.gesture.direction)}function $n(e){return e.space===`target`?B(e.selector):`${e.x},${e.y}${e.space===`percent`?`%`:``}`}function B(e){return e?.id??e?.text}function er(e){return`${e.x},${e.y}${e.space===`percent`?`%`:``}`}function V(e){return e?{value:e}:{}}const tr=new Set(String.raw`^$\.*+?()[]{}|`);function nr(e,t){try{return RegExp(`^(?:${t})$`,`ims`).test(e)}catch{return e.toLocaleLowerCase()===t.toLocaleLowerCase()}}function rr(e){try{new RegExp(e)}catch{return e}let t=``;for(let n=0;n<e.length;n+=1){let r=e[n];if(r!==`\\`){if(tr.has(r))return;t+=r;continue}let i=e[n+1];if(i===void 0||!tr.has(i))return;t+=i,n+=1}return t}function ir(e,t,n){if(n===`android`&&e.visibleToUser===!1)return!1;if(g(e.rect))return t.isVisibleInEffectiveViewport(e);if(e.rect)return!1;if(n!==`android`&&e.hittable===!0)return!0;let r=t.findAncestor(e,e=>ee(e,n)?e:null);return r?g(r.rect)?t.isVisibleInEffectiveViewport(r):n!==`android`&&r.hittable===!0:!1}function ar(e,t,n){return!!n.findAncestor(e,e=>e.index===t.index?e:null)}function or(e,t){let n=[t.id===void 0?void 0:cr(e.identifier,t.id),t.text===void 0?void 0:lr(e,t.text)].filter(e=>e!==void 0);return!(n.length===0&&t.enabled===void 0&&t.selected===void 0||n.some(e=>!e)||t.enabled!==void 0&&e.enabled!==!1!==t.enabled||t.selected!==void 0&&e.selected===!0!==t.selected)}function sr(e){return e.matches.filter(t=>ir(t,e.visibility,e.platform))}function cr(e,t){let n=e??``;return E(n)===E(t)||nr(n,t)}function lr(e,t){return[e.label,qe(e),e.identifier].filter(e=>!!e).some(e=>cr(e,t))}function ur(e){return e.index!==void 0||e.childOf!==void 0||e.below!==void 0||e.above!==void 0||e.leftOf!==void 0||e.rightOf!==void 0||e.containsChild!==void 0||e.containsDescendants!==void 0}function dr(e){return e.text!==void 0||e.id!==void 0||e.enabled!==void 0||e.selected!==void 0}function fr(e,t,n){let r=[],i=0;for(let a of e)for(let e of n){let n=mr(a.rect,e.rect);n===void 0||!pr(t,a.rect,e.rect)||r.push({node:a,distance:n,order:i++})}return r.sort((e,t)=>e.distance-t.distance||e.order-t.order),r.map(({node:e})=>e)}function pr(e,t,n){switch(e){case`below`:return t.y>n.y;case`above`:return t.y<n.y;case`leftOf`:return t.x<n.x;case`rightOf`:return t.x>n.x}}function mr(e,t){if(!(!hr(e)||!hr(t)))return Math.fround(Math.hypot(H(e.x,e.width)-H(t.x,t.width),H(e.y,e.height)-H(t.y,t.height)))}function hr(e){return!!(e&&[e.x,e.y,e.width,e.height].every(Number.isFinite))}function H(e,t){return e+Math.trunc(t/2)}function gr(t,n={},r={}){let i=h(t.nodes,n);n.onVisibilityContextCreated?.();let a=new WeakMap,o=new WeakSet,s=new WeakMap,c=new Map,l=e=>e.parentIndex===void 0?void 0:i.nodeByIndex.get(e.parentIndex)??t.nodes[e.parentIndex],u=e=>{let t=s.get(e);if(t)return t;let n=new Set,r=new Set,i=l(e);for(;i&&!r.has(i.index);)r.add(i.index),n.add(i.index),i=l(i);return s.set(e,n),n},d=(e,r)=>{let i=c.get(e);i||(i=new WeakMap,c.set(e,i));let a=i.get(r);if(a)return a;n.onPositionComputed?.(e,r);let o=fr(t.nodes,e,m(r).indexed),s={ordered:o,candidateIndexes:new Set(o.map(e=>e.index))};return i.set(r,s),s},f=(e,t)=>d(e,t).ordered,p=(e,t)=>d(e,t).candidateIndexes,m=i=>{let s=a.get(i);if(s)return s;if(o.has(i))throw new e(`INVALID_ARGS`,`Maestro selector relations cannot contain cycles.`);o.add(i),n.onSelectorComputed?.(i);try{let e=_r(t,i,l,u,m,p),n={matches:e,indexed:xr(e,i.index,r.orderUnindexed)};return a.set(i,n),n}finally{o.delete(i)}};return{visibility:i,resolve:m,resolvePosition:f}}function _r(e,t,n,r,i,a){let{index:o,childOf:s,below:c,above:l,leftOf:u,rightOf:d,containsChild:f,containsDescendants:p,...m}=t,h=dr(m)?e.nodes.filter(e=>or(e,m)):[...e.nodes];if(s){let e=new Set(i(s).indexed.map(e=>e.index));h=h.filter(t=>yr(r(t),e))}if(f){let e=new Set(i(f).indexed.map(n).filter(e=>e!==void 0).map(e=>e.index));h=h.filter(t=>e.has(t.index))}if(p){let e=p.map(e=>vr(i(e).indexed,r));h=h.filter(t=>e.every(e=>e.has(t.index)))}for(let[e,n]of br(t)){let t=a(e,n);h=h.filter(e=>t.has(e.index))}return h}function vr(e,t){let n=new Set;for(let r of e)for(let e of t(r))n.add(e);return n}function yr(e,t){for(let n of e)if(t.has(n))return!0;return!1}function br(e){return[[`below`,e.below],[`above`,e.above],[`leftOf`,e.leftOf],[`rightOf`,e.rightOf]].filter(e=>e[1]!==void 0)}function xr(e,t,n){if(t===void 0)return n?n(e):[...e];let r=Cr(e)[wr(t)];return r?[r]:[]}function Sr(e,t){return t===void 0?e[0]:Cr(e)[wr(t)]}function Cr(e){return[...e].sort((e,t)=>{let n=U(e.rect?.y),r=U(t.rect?.y);return n===r?U(e.rect?.x)-U(t.rect?.x):n-r})}function U(e){return e!==void 0&&Number.isFinite(e)?e:2**53-1}function wr(t){let n=typeof t==`number`?t:Number(t.trim());if(!Number.isSafeInteger(n)||n<0)throw new e(`INVALID_ARGS`,`Maestro selector.index must be a non-negative integer.`);return n}const Tr={android:{kind:`exact`,provider:`android-helper`},ios:{kind:`divergence`,provider:`apple-xctest`,reason:`maestro-clickable-not-exposed-by-provider`}};function Er(e,t){let n=Tr[t];if(n.kind===`divergence`)return n;let r=a(e);return r?r.kind!==`exact`||r.provider!==n.provider?{kind:`divergence`,provider:n.provider,reason:`unregistered-provider-evidence`}:r:{kind:`divergence`,provider:n.provider,reason:`exact-evidence-not-retained`}}function W(e,t){return t.kind===`exact`?e.map((e,n)=>({node:e,order:n,rank:Dr(t.clickableByNodeIndex.get(e.index))})).sort((e,t)=>t.rank-e.rank||e.order-t.order).map(({node:e})=>e):[...e]}function Dr(e){return e===!0?2:+(e===!1)}function Or(e,t,n,r={}){let i=Er(e,n),a=Ar(e,i,r),o=kr(t,a),s=sr({visibility:a.visibility,matches:o.matches,platform:n});return{...o,visible:s,clickability:i,ranked:jr(s,t,n,a.visibility,i)}}function kr(e,t){return{matches:t.resolve(e).matches,parentMatched:e.childOf===void 0||t.resolve(e.childOf).indexed.length>0}}function Ar(e,t,n={}){return gr(e,n,t?{orderUnindexed:e=>W(e,t)}:{})}function jr(e,t,n,r,i){let a=n!==`ios`||!Fr(t)?e:e.filter(n=>{if(Rr(n))return!0;let i=e.filter(e=>e!==n&&Ir(n,e,t));return!i.some(e=>Rr(e)&&ar(n,e,r))&&!i.some(e=>ar(e,n,r))});return t.index===void 0&&i?W(a,i):a}function Mr(e,t){let n=t===void 0?e.find(G):Nr(e,t);return!n||!G(n)?null:{node:n,rect:n.rect}}function Nr(e,t){return Sr(e,t)}function Pr(e){return G(e)?e.rect:void 0}function G(e){return g(e.rect)}function Fr(e){return e.id!==void 0||e.text!==void 0}function Ir(e,t,n){if(n.id!==void 0&&K(e.identifier)!==K(t.identifier))return!1;if(n.text!==void 0){let n=Lr(e),r=new Set(Lr(t));if(!n.some(e=>r.has(e)))return!1}return!0}function Lr(e){return[e.label,e.value,e.identifier].map(K).filter(e=>e!==void 0)}function K(e){if(e)return E(e)||void 0}function Rr(e){let t=m(e.type??``);return t===`button`||t===`link`||t===`switch`||t===`searchfield`||t===`textfield`||t===`securetextfield`||t===`textview`}const zr=Symbol(`maestroFlowProgram`),Br=Symbol(`maestroFailureCommand`),Vr=Symbol(`maestroFailurePlan`);function Hr(e,t){let n=Xe(e,{sourcePath:t});return{sourcePath:t,name:n.config.name,appTarget:Kr(n),[zr]:n}}async function Ur(e,t,n){let r;try{let i=Je(D.dirname(e.sourcePath),n.readSource),a=await dn(e[zr],{defaults:n.defaults,env:n.env,platform:n.platform,target:n.target,runtimeHints:n.runtimeHints,loadProgram:i,signal:n.signal}),o=hn(a,{from:n.from,planDigest:n.planDigest}),s=await Hn(a,t,{defaults:n.defaults,env:n.env,platform:n.platform,target:n.target,loadProgram:i,signal:n.signal,startIndex:o,trustedScripts:n.trustedScripts,observer:Gr(a,n.observer,e=>{r=e})});return{ok:!0,replayed:a.total-o,planDigest:a.digest,startIndex:o,artifactPaths:s.artifactPaths,...s.warnings?{warnings:s.warnings}:{}}}catch(e){return{ok:!1,error:r?.error??e,...r?{failure:r}:{}}}}function Wr(e,t){let n=Jr(e[Br]),r=e[Vr].platform;return!n||r!==`android`&&r!==`ios`?[]:Or(t,n.selector,r).ranked.map(e=>({node:e,basis:Yr(n.selector,e)}))}function Gr(e,t,n){return{commandStarted:e=>t?.actionStarted?.(q(e)),commandCompleted:e=>t?.actionCompleted?.({...q(e),durationMs:e.durationMs,runtimeMetrics:e.runtimeMetrics,data:e.data}),commandFailed:r=>{let i=mn(e,{from:r.stepIndex,planDigest:e.digest}),a={...q(r),durationMs:r.durationMs,error:r.error,artifactPaths:r.artifactPaths,isControl:Vt(r.command),redactions:r.command.kind===`inputText`&&r.command.text.length>0?[{name:`inputText.text`,value:r.command.text}]:[],resume:i.allowed?{allowed:!0,from:r.stepIndex,planDigest:e.digest}:{allowed:!1,from:r.stepIndex,planDigest:e.digest,reason:i.reason},[Br]:r.command,[Vr]:e};n(a),t?.actionFailed?.(a)}}}function q(e){let t=Wn(e.command);return{action:t.command,...t.value?{value:t.value}:{},source:e.source,generation:e.generation,stepIndex:e.stepIndex,stepTotal:e.stepTotal}}function Kr(e){return[e.config.appId,...[...e.config.onFlowStart??[],...e.commands].filter(e=>e.kind===`launchApp`).map(e=>e.kind===`launchApp`?e.appId:void 0)].find(qr)}function qr(e){return!!(e?.trim()&&!e.includes(`$`)&&!i(e))}function Jr(e){switch(e.kind){case`tapOn`:return e.target.space===`target`?{selector:e.target.selector}:void 0;case`doubleTapOn`:case`longPressOn`:return e.target.space===`target`?{selector:e.target.selector}:void 0;case`assertVisible`:case`assertNotVisible`:return{selector:e.target};case`extendedWaitUntil`:return e.visible?{selector:e.visible}:e.notVisible?{selector:e.notVisible}:void 0;case`scrollUntilVisible`:return{selector:e.element};case`swipe`:return e.gesture.kind===`target`?{selector:e.gesture.from}:void 0;default:return}}function Yr(e,t){return e.id!==void 0||e.text!==void 0&&or({...t,label:void 0,value:void 0},{text:e.text})?`id`:e.text===void 0?`other`:`label`}const Xr=`This replay request carries no script sources. Replay scripts are read by the client and sent with the request; upgrade the agent-device client that issued it to a version that sends script sources.`;function Zr(t,n){let r=t.files[n];if(r===void 0)throw new e(`INVALID_ARGS`,`replay script source is missing ${n}; it was not part of the script sources sent with this request.`,{path:n,entry:t.entry});return r}function Qr(e){if(e.command!==`replay`||e.flags?.replayFrom!==void 0)return;let t=e.flags?.replayScriptSource;if(t)try{let n=t.entry,r=Zr(t,n);if(ce(n,e.flags?.replayBackend)===`maestro`){let t=Hr(r,n);return{flags:e.flags??{},options:$r(t.appTarget,e.flags?.platform)}}let i=rt(r,e.flags),a=ei(i.actions);if(!a.appTarget)return;let o=ti(e.flags,i.actions),s=o.platform??i.metadata.platform;return{flags:s&&o.platform===void 0?{...o,platform:s}:o,options:s===`ios`?ri(a.appTarget):void 0}}catch{return}}function $r(e,t){return t===`ios`?ri(e)??{}:{}}function ei(e){let t=ae(e);for(let n of e){if(n.command!==`open`)continue;let e=n.positionals?.[0];return ni(e)?{appTarget:e,platform:t}:{appTarget:void 0,platform:t}}return{appTarget:void 0,platform:t}}function ti(e,t){let n=ei(t);return e?.platform!==void 0||!n.platform?e??{}:{...e,platform:n.platform}}function ni(e){return!!(e&&e.trim()&&!e.includes(`$`)&&!i(e))}function ri(e){let t=kt(e);return t?{appleSimulatorAppTarget:t}:void 0}const ii={label:`Materialized paths`,plural:!0,expiredHint:`Materialized paths are released automatically when their TTL expires; re-run the command that materialized them if the paths are still needed.`},J=new Map;async function ai(e){let t=await O.mkdtemp(D.join(nt.tmpdir(),`agent-device-materialized-`));try{let n=await li(e.installablePath,D.join(t,`installable`)),r=e.archivePath?await li(e.archivePath,D.join(t,`archive`)):void 0,i=et.randomUUID(),a=e.ttlMs??9e5,o=Date.now()+a,s=setTimeout(()=>{ci(i)},a);return J.set(i,{rootPath:t,installablePath:n,archivePath:r,tenantId:e.tenantId,sessionName:e.sessionName,expiresAt:o,timer:s}),{materializationId:i,installablePath:n,...r?{archivePath:r}:{},expiresAt:new Date(o).toISOString()}}catch(e){throw await O.rm(t,{recursive:!0,force:!0}),e}}async function oi(e,t){await Y(e,Te(J,e,t,ii))}async function si(e){let t=Array.from(J.entries()).filter(([,t])=>t.sessionName===e);await Promise.all(t.map(async([e,t])=>{await Y(e,t)}))}async function ci(e){let t=J.get(e);if(t)try{await Y(e,t)}catch{}}async function Y(e,t){clearTimeout(t.timer),J.delete(e),await O.rm(t.rootPath,{recursive:!0,force:!0})}async function li(e,t){let n=await O.stat(e);await O.mkdir(t,{recursive:!0});let r=D.join(t,D.basename(e));return n.isDirectory()?(await O.cp(e,r,{recursive:!0}),r):(await O.copyFile(e,r),r)}function ui(e){return e.device.platform===`web`}function di(e){return e.toArray().filter(e=>e.device.platform===`web`).map(e=>e.name)}async function fi(e){let{session:t,sessionName:n,sessionStore:r}=e;t.appLog&&await Re({session:t,sessionName:n,sessionStore:r,resourcePath:Ie.resolvePath(r.resolveSessionDir(n))})}async function pi(e){let t=e.sessionStore.get(e.sessionName)??e.session;t.perfCapture&&await Le({...e,session:t,intent:`disposal`})}async function mi(e,t){await t.stopSnapshotHelper(e.device)}async function hi(e){let{session:t,sessionName:n,sessionStore:r,platformCleanup:i}=e;await i.closeManagedBrowser({device:t.device,sessionName:n,stateDir:r.resolveDaemonStateDir(),openSessionNames:()=>di(r)})}async function gi(e){let t=[];for(let{step:n,run:r}of e)try{await r()}catch(e){t.push({step:n,error:e})}return t}function _i(t){if(t.failures.length===0)return;let n=t.failures.map(({step:e})=>e),r=t.failures.map(({step:e,error:t})=>`${e}: ${t instanceof Error?t.message:String(t)}`);return _({level:`error`,phase:t.phase,data:{session:t.sessionName,failedSteps:n,errors:r}}),new e(`COMMAND_FAILED`,`Session cleanup left ${t.failures.length} resource(s) unreleased: ${r.join(`; `)}`,{reason:`session_cleanup_incomplete`,session:t.sessionName,failedSteps:n,hint:`Some session resources failed to release; inspect the session log for per-resource diagnostics. The session was still deleted, so retrying is safe.`})}async function vi(t){let{session:n,sessionName:r,sessionStore:i}=t;if(!t.platformCleanup)throw new e(`INTERNAL_ERROR`,`Platform resource cleanup was not supplied by root runtime composition`);let a=t.platformCleanup,o=[{step:`recording`,run:()=>yi({session:n,sessionName:r,sessionStore:i})},...t.appLog===`run`?[{step:`app_log`,run:()=>fi({session:n,sessionName:r,sessionStore:i})}]:[],{step:`audio_probe`,run:()=>bi({session:n,sessionName:r,sessionStore:i})},{step:`perf_capture`,run:()=>pi({session:n,sessionName:r,sessionStore:i})},{step:`platform_snapshot_helper`,run:()=>mi(n,a)},{step:`web_browser`,run:()=>hi({session:n,sessionName:r,sessionStore:i,platformCleanup:a})}];o.push({step:`materialized_paths`,run:()=>si(r)});let s=_i({sessionName:r,phase:`session_teardown_cleanup_failed`,failures:await gi(o)});if(s)throw s}async function yi(e){let t=e.sessionStore.get(e.sessionName)??e.session;t.screenRecording&&await $e({intent:`disposal`,session:t,sessionName:e.sessionName,sessionStore:e.sessionStore})}async function bi(e){let t=e.sessionStore.get(e.sessionName)??e.session;t.audioProbe&&await Fe({intent:`disposal`,session:t,sessionName:e.sessionName,sessionStore:e.sessionStore})}function xi(e){return s(e)&&e.kind===`simulator`}function Si(e){return e.platform===`android`&&e.kind===`emulator`}const Ci=[`platform`,`metroHost`,`metroPort`,`bundleUrl`,`launchUrl`];function X(e){return e?[e.metroHost,e.metroPort,e.bundleUrl,e.launchUrl].filter(e=>e!==void 0&&e!==``).length:0}function Z(e){if(!e)return{};let t={};return e.metroHost!==void 0&&(t.metroHost=e.metroHost),e.metroPort!==void 0&&(t.metroPort=String(e.metroPort)),e.bundleUrl!==void 0&&(t.bundleUrl=e.bundleUrl),e.launchUrl!==void 0&&(t.launchUrl=e.launchUrl),t}function Q(e){return De(Z(e))}function $(t,n){if(t!==void 0){if(typeof t!=`string`)throw new e(`INVALID_ARGS`,`Invalid open runtime ${n}: expected string.`);return v(t)}}function wi(t){if(t!==void 0){if(!Number.isInteger(t)||t<1||t>65535)throw new e(`INVALID_ARGS`,`Invalid runtime metroPort: ${String(t)}. Use an integer between 1 and 65535.`);return t}}function Ti(t){if(t!==void 0){if(typeof t!=`number`)throw new e(`INVALID_ARGS`,`Invalid open runtime metroPort: expected integer.`);return wi(t)}}function Ei(t,r,i){if(t===void 0)return i;if(!n(t))throw new e(`INVALID_ARGS`,`Invalid open runtime platform: ${String(t)}. Use "ios", "android", or "harmonyos".`);if(i&&t!==i)throw new e(`INVALID_ARGS`,`open runtime targets ${t}, but session "${r}" is bound to ${i}.`);return t}function Di(e){if(n(e))return e}function Oi(e,t){return{platform:t,metroHost:v(e?.metroHost),metroPort:wi(e?.metroPort),bundleUrl:v(e?.bundleUrl),launchUrl:v(e?.launchUrl)}}function ki(e,t){return{platform:t.platform??e?.platform,metroHost:t.metroHost??e?.metroHost,metroPort:t.metroPort??e?.metroPort,bundleUrl:t.bundleUrl??e?.bundleUrl,launchUrl:t.launchUrl??e?.launchUrl}}function Ai(e){if(Si(e))return`10.0.2.2`;if(xi(e))return`127.0.0.1`}function ji(e,t){if(!e||v(e.metroHost)||v(e.bundleUrl)||e.metroPort===void 0)return e;let n=Ai(t);return n?{...e,metroHost:n}:e}function Mi(t){let{runtime:n,sessionName:r,platform:i}=t;if(n===void 0)return;if(!n||typeof n!=`object`||Array.isArray(n))throw new e(`INVALID_ARGS`,`open runtime must be an object.`);let a=n,o=Object.keys(a).find(e=>!Ci.includes(e));if(o)throw new e(`INVALID_ARGS`,`Invalid open runtime field: ${o}. Supported fields are ${Ci.join(`, `)}.`);return{platform:Ei(a.platform,r,i),metroHost:$(a.metroHost,`metroHost`),metroPort:Ti(a.metroPort),bundleUrl:$(a.bundleUrl,`bundleUrl`),launchUrl:$(a.launchUrl,`launchUrl`)}}function Ni(e,t,n){if(n){if(X(n)===0){e.clearRuntimeHints(t);return}return e.setRuntimeHints(t,n),n}}function Pi(t,n,r,i){let a=t.getRuntimeHints(n);if(!a)return;let o=r?l(r):void 0,s=Di(o)??i;if(a.platform&&r&&!s)throw new e(`INVALID_ARGS`,`Session runtime hints are only supported on iOS, Android, and HarmonyOS sessions, but session "${n}" is bound to ${o}.`);if(a.platform&&s&&a.platform!==s)throw new e(`INVALID_ARGS`,`Session runtime hints target ${a.platform}, but session "${n}" is bound to ${o}. Clear the runtime hints or use a different session.`);return s&&a.platform!==s?{...a,platform:s}:a}function Fi(e){let{req:t,sessionStore:n,sessionName:r,device:i}=e,a=i?Di(l(i)):e.platform,o=n.getRuntimeHints(r),s=Mi({runtime:t.runtime,sessionName:r,platform:a});if(t.runtime===void 0){let e=Pi(n,r,i,a);return{runtime:i?ji(e,i):e,previousRuntime:o,replacedStoredRuntime:!1}}let c=s&&X(s)>0?s:void 0;return{runtime:i?ji(c,i):c,previousRuntime:o,replacedStoredRuntime:!0}}function Ii(e){return Fi(e).runtime}function Li(e){try{return{ok:!0,data:Fi(e)}}catch(e){let t=r(e);return Ee(t.code,t.message,t.details)}}async function Ri(e){let{previousRuntime:t,clearRuntimeHints:n}=e;if(!zi(e))return;let r=e.session;r?.appBundleId&&await n({appId:r.appBundleId,values:Z(t)})}function zi(e){return e.replacedStoredRuntime&&!!e.session?.appBundleId&&Q(e.previousRuntime)&&!Q(e.runtime)}function Bi(e){let{device:t,owner:n,stateDir:r,intent:i}=e,a=i.kind===`exact-owner`&&ne(i.owner,n)?te(i.fence):null;if(!a)return{status:`binding-invalid`};let o=C(w(t)),s=Me(ke(o));if(!s)return{status:`missing`};let c=s.allocatorClaim;return!c||!Hi(c.stateDir,r)||!ne(je(c),n)?{status:`conflict`,conflict:s}:c.allocator.identityIncarnationId===a.identityIncarnationId?{status:`covered`}:{status:`incarnation-stale`,heldIncarnationId:c.allocator.identityIncarnationId}}function Vi(e){let t=C(w(e));return Oe(ke(t))}function Hi(e,t){return D.resolve(e)===D.resolve(t)}const Ui=new Set([`DEVICE_CLAIM_LIVE_OWNER`,`DEVICE_CLAIM_RECOVERY_PENDING`,`DEVICE_CLAIM_OWNER_UNCERTAIN`]);function Wi(e){return Ui.has(e)}function Gi(e,t,n=`status`){let r=t.claim??t.allocatorClaim,i=l(r?{platform:r.device.family,appleOs:r.device.appleOs}:e),a=o(e.platform)?`--udid`:`--serial`;return[`agent-device device ${n}`,`--platform ${le(i)}`,`${a} ${le(e.id)}`,...n===`release`||Ae(t.classification)?[`--stale`]:[]].join(` `)}function Ki(t,n){if(n.classification===`allocator-held`)return Ji(t,n);let r=n.claim,i=Gi(t,n,Ne(n.classification)?`release`:`status`),a=l(r?{platform:r.device.family,appleOs:r.device.appleOs}:t);return new e(`DEVICE_IN_USE`,r?`${a} device ${t.id} is owned by session "${r.session}" in workspace "${r.workspace}".`:`${t.name} has an ownership claim that could not be verified.`,{reason:ta(n.classification),classification:n.classification,deviceKey:n.deviceKey,...r?{owner:{session:r.session,workspace:r.workspace,stateDir:r.stateDir}}:{},recovery:{command:i},hint:Ne(n.classification)?`The recorded owner can no longer release this device; settle its resources and release the claim with: ${i}`:`Inspect the owner with: ${i}`,retriable:!1})}function qi(e,t){return ea(Ki(e,t))}function Ji(t,n){let r=n.allocatorClaim,i=l({platform:r.device.family,appleOs:r.device.appleOs}),a=Gi(t,n);return new e(`DEVICE_IN_USE`,`${i} device ${t.id} is held by managed-device allocator "${r.allocator.instanceId}" for installation "${r.stateDir}".`,{reason:`DEVICE_CLAIM_ALLOCATOR_HELD`,classification:n.classification,deviceKey:n.deviceKey,owner:{kind:`allocator`,stateDir:r.stateDir,allocator:r.allocator},recovery:{command:a},hint:`This device belongs to a managed pool and is released only after its allocator proves the identity removed; inspect with: ${a}`,retriable:!1})}function Yi(t,n){return new e(`COMMAND_FAILED`,`${l(t)} device ${t.id} is a managed identity with no allocator-held execution claim for this installation.`,{reason:`allocator-claim-missing`,owner:re(n),deviceKey:C(w(t)),retriable:!1,hint:`A managed identity becomes executable only after its allocator activates it and this installation holds its allocator-held claim.`})}function Xi(t,n,r){return new e(`COMMAND_FAILED`,`${l(t)} device ${t.id} is held for identity incarnation "${r}", which is not the incarnation this binding fences.`,{reason:`allocator-claim-incarnation-stale`,owner:re(n),deviceKey:C(w(t)),heldIncarnationId:r,retriable:!1,hint:`The managed identity was re-provisioned; obtain a new grant from the allocator.`})}function Zi(t,n){return new e(`COMMAND_FAILED`,`A managed local owner executes only under an exact-owner binding that carries a managed binding fence.`,{reason:`runtime-contract-invalid`,owner:re(n),deviceKey:C(w(t)),retriable:!1})}function Qi(e,t,n){switch(n.status){case`binding-invalid`:return{admitted:!1,error:Zi(e,t)};case`missing`:return{admitted:!1,error:Yi(e,t)};case`covered`:return{admitted:!0};case`incarnation-stale`:return{admitted:!1,error:Xi(e,t,n.heldIncarnationId)};case`conflict`:return{admitted:!1,error:Ki(e,n.conflict)}}}function $i(e,t,n){let r=Qi(e,t,n);return r.admitted?void 0:ea(r.error)}function ea(e){let{hint:t,retriable:n,...r}=e.details??{};return Ee(e.code,e.message,r,{hint:t,retriable:n})}function ta(e){switch(e){case`live`:return`DEVICE_CLAIM_LIVE_OWNER`;case`owner-process-dead`:case`owner-daemon-superseded`:return`DEVICE_CLAIM_RECOVERY_PENDING`;case`owner-process-reused`:case`owner-state-dir-gone`:case`unknown`:case`inconsistent`:case`allocator-inconsistent`:return`DEVICE_CLAIM_OWNER_UNCERTAIN`}}function na(e){switch(e.kind){case`local-family`:return`ordinary`;case`managed-local`:return`allocator-held`;case`provider-runtime`:return`none`}}export{rr as $,si as A,Ar as B,fi as C,ui as D,vi as E,Xr as F,Nr as G,Or as H,Zr as I,Er as J,Pr as K,Wr as L,$r as M,ti as N,di as O,Qr as P,ir as Q,Ur as R,_i as S,mi as T,jr as U,kr as V,Mr as W,ur as X,gr as Y,sr as Z,zi as _,Ki as a,Tt as at,bi as b,Bi as c,gt as ct,Q as d,bt as dt,F as et,Ri as f,yt as ft,Ni as g,Z as h,at as ht,Qi as i,Ct as it,ai as j,oi as k,Oi as l,_t as lt,Ii as m,ct as mt,$i as n,Ot as nt,Wi as o,Et as ot,ki as p,lt as pt,W as q,qi as r,wt as rt,Vi as s,vt as st,na as t,j as tt,X as u,ht as ut,Di as v,pi as w,yi as x,Li as y,Hr as z};
|
|
1
|
+
import{C as e,T as t,o as n,w as r}from"./sdk-contracts.js";import"./capture.js";import{r as i}from"./sdk-batch-runner.js";import{p as a}from"./android-input-ownership.js";import{c as o,l as s,o as c,v as l}from"./sdk-device.js";import{d as u,l as d,n as f,r as p}from"./lease-scope.js";import{Mr as m,Sr as h,Tr as ee,Wt as te,Xt as ne,Yt as re,tr as ie,zr as g}from"./sdk-batch.js";import{a as ae,n as oe,r as se}from"./script.js";import"./session-store.js";import{r as ce}from"./format.js";import{r as _}from"./diagnostics.js";import"./diagnostics2.js";import{r as le}from"./command.js";import{n as v}from"./runtime-transport-hints.js";import{_ as ue,a as de,c as fe,d as y,f as b,g as pe,h as me,i as he,l as ge,m as _e,n as x,o as ve,p as ye,r as be,s as S,u as xe,v as Se}from"./human-control-contract.js";import{n as Ce,t as we,u as Te}from"./provider-session-ownership.js";import{i as Ee}from"./request-runtime-binding.js";import{r as De}from"./application-lifecycle-runtime.js";import{a as Oe,c as C,l as ke,n as Ae,o as je,r as Me,t as Ne}from"./device-claim-inspection.js";import{b as Pe,c as Fe,g as Ie,i as Le,p as Re,x as w}from"./perf-runtime-plan.js";import{n as ze,r as Be,t as Ve}from"./lease-context.js";import{d as He,g as Ue,u as We}from"./screenshot-runtime.js";import{a as Ge,c as Ke,d as T,l as qe,n as Je,o as Ye,r as Xe,u as E}from"./src8.js";import{n as Ze,t as Qe}from"./compatibility-policy.js";import{o as $e}from"./screen-recording-resource-recovery.js";import D from"node:path";import"node:fs";import et,{createHash as tt}from"node:crypto";import nt from"node:os";import O from"node:fs/promises";function rt(t,n){if(n?.replayBackend&&n.replayBackend!==`maestro`)throw new e(`INVALID_ARGS`,`Unsupported replay backend "${n.replayBackend}".`);return{...oe(t),metadata:se(t)}}function it(e,t){return k(e,t)?t:`${e}:${t}`}function k(e,t){return t.startsWith(`${e}:`)}function at(e,t){return!e.partitioned||k(e.tenant,t)}var ot=class{active=new Map;waiters=new Map;async run(e,t){this.active.set(e,(this.active.get(e)??0)+1);try{return await t()}finally{let t=(this.active.get(e)??1)-1;if(t>0)this.active.set(e,t);else{this.active.delete(e);let t=this.waiters.get(e);this.waiters.delete(e);for(let e of t??[])e()}}}async wait(e,t){if(t?.throwIfAborted(),!this.active.has(e))return;let n=this.waiters.get(e)??new Set,r=()=>{},i=()=>{};try{await new Promise((a,o)=>{r=a,i=()=>o(t?.reason),n.add(r),this.waiters.set(e,n),t?.addEventListener(`abort`,i,{once:!0})})}finally{t?.removeEventListener(`abort`,i),n.delete(r),n.size===0&&this.waiters.get(e)===n&&this.waiters.delete(e)}}},st=class{entriesByLeaseId=new Map;retain(e,t){let n={wanted:t,released:!1},r=this.entriesByLeaseId.get(e)??new Set;return r.add(n),this.entriesByLeaseId.set(e,r),{leaseId:e,release:()=>this.releasePass(e,r,n)}}forget(e){let t=this.entriesByLeaseId.get(e);if(t){for(let e of t)e.released=!0;this.entriesByLeaseId.delete(e)}}isDeferred(e){let t=this.entriesByLeaseId.get(e);if(!t)return!1;for(let e of t)e.wanted()||t.delete(e);return t.size>0||(this.entriesByLeaseId.delete(e),!1)}releasePass(e,t,n){return!n.released&&(n.released=!0,t.delete(n),t.size===0&&this.entriesByLeaseId.delete(e),n.wanted())}},ct=class{holdsByDevice=new Map;mutations=new ot;inFlightWork=new st;leases=new Map;runBindings=new Map;deviceBindings=new Map;maxActiveSimulatorLeases;resolveLeaseTtlMs;now;onLeaseExpired;providerSessionOwnership;constructor(e={}){this.maxActiveSimulatorLeases=Number.isInteger(e.maxActiveSimulatorLeases)?Math.max(0,Number(e.maxActiveSimulatorLeases)):0,this.resolveLeaseTtlMs=ge(e),this.now=e.now??(()=>Date.now()),this.onLeaseExpired=e.onLeaseExpired,this.providerSessionOwnership=new we({now:this.now,retentionMs:e.providerSessionRetentionMs})}allocateLease(e){let t=ye(e);this.cleanupExpiredLeases();let n=this.resolveLeaseTtlMs(t.ttlMs);this.assertHumanControlAdmission(t);let r=this.refreshExistingRunBinding(t,n);if(r)return r;this.assertDeviceAvailable(t),this.enforceCapacity(t.backend);let i=fe(t,n,this.now());return this.leases.set(i.leaseId,i),this.bindLease(i),{...i}}refreshExistingRunBinding(e,t){let n=b(e),r=this.runBindings.get(n);if(!r)return;let i=this.leases.get(r);if(!i){this.runBindings.delete(n);return}if(i.clientId===e.clientId)return this.refreshLease(i,t);if(i.deviceKey)throw xe(i);return S(i,e),this.refreshLease(i,t)}heartbeatLease(e){let t=pe(e.leaseId);this.cleanupExpiredLeases();let n=this.getActiveLease(t);ve(n,e),S(n,e);let r=this.resolveLeaseTtlMs(e.ttlMs);return this.refreshLease(n,r)}retainLeaseWork(e,t){let n=this.inFlightWork.retain(e.leaseId,t);return{leaseId:n.leaseId,release:()=>{let t=n.release();return t&&this.refreshProtectedLease(e.leaseId,this.now()),t}}}releaseLease(e){let t=this.getLease(e);return t?(this.leases.delete(t.leaseId),this.unbindLease(t),this.inFlightWork.forget(t.leaseId),{released:!0,lease:t}):{released:!1}}getLease(e){let t=pe(e.leaseId);this.cleanupExpiredLeases();let n=this.leases.get(t);if(n)return ve(n,e),S(n,e),{...n}}assertLeaseAdmission(e){let t=_e(e);this.cleanupExpiredLeases(),S(this.getActiveLease(t.leaseId),t)}listActiveLeases(){return this.cleanupExpiredLeases(),Array.from(this.leases.values()).map(e=>({...e}))}recordProviderSession(e,t){this.cleanupExpiredLeases();let n=e.expiresAt<=this.now()?e.expiresAt:void 0;this.providerSessionOwnership.record(e,t),this.leases.has(e.leaseId)||this.providerSessionOwnership.markLeaseReleased(e,n)}resolveProviderSession(e){return this.cleanupExpiredLeases(),this.providerSessionOwnership.resolve(e)}listHumanControlHolds(e){this.cleanupExpiredLeases();let t=e.kind===`lease`?y(this.requireHumanControlLease(e.leaseId)):void 0;return[...this.holdsByDevice.entries()].filter(([e])=>t===void 0||t===e).flatMap(([,e])=>[...e.values()].map(({hold:e})=>x(e))).sort((e,t)=>e.id.localeCompare(t.id))}async putHumanControlHold(t,n,r,i){i?.throwIfAborted();let a=he(n),o=de(r);this.cleanupExpiredLeases();let s=this.resolveHumanControlScope(t,o),c=y(s),l=this.findHumanControlHold(a);if(l&&(this.assertHoldAuthority(t,l),y(l.hold.scope)!==c))throw new e(`INVALID_ARGS`,`Release a hold before changing its device scope.`);let u=this.now(),d={...t.kind===`lease`?{ownerLeaseId:t.leaseId}:{},hold:{id:a,scope:s,state:`activating`,...o.reason?{reason:o.reason}:{},createdAt:l?.hold.createdAt??u,updatedAt:u}},f=this.holdsByDevice.get(c)??new Map;return this.holdsByDevice.set(c,f),f.set(a,d),await this.activateHumanControlHold(c,d,o.ttlMs,i)}async activateHumanControlHold(t,n,r,i){let a=this.holdsByDevice.get(t),{id:o}=n.hold;try{if(await this.mutations.wait(t,i),i?.throwIfAborted(),a.get(o)!==n)throw new e(`COMMAND_FAILED`,`Human-control hold changed before activation completed.`,{holdId:o});let s=this.now();return n.hold={...n.hold,state:`active`,updatedAt:s,...r===void 0?{}:{expiresAt:s+r}},this.refreshHeldLease(t,s),x(n.hold)}catch(e){throw a.get(o)===n&&this.deleteHumanControlHold(t,o),e}}removeHumanControlHold(e,t){let n=he(t);this.cleanupExpiredLeases();let r=this.findHumanControlHold(n);if(!r)return;this.assertHoldAuthority(e,r);let i=y(r.hold.scope);return this.deleteHumanControlHold(i,n),x(r.hold)}deleteHumanControlHold(e,t){let n=this.holdsByDevice.get(e);n.delete(t),n.size===0&&(this.holdsByDevice.delete(e),this.refreshHeldLease(e,this.now()))}assertHumanControlAdmission(e){this.expireHumanControlHolds();let t=y(e),n=t===void 0?void 0:this.holdsByDevice.get(t)?.values().next().value;if(n)throw be(n.hold)}async runDeviceMutation(e,t){if(!e)return await t();this.cleanupExpiredLeases();let n=this.getActiveLease(e.leaseId);this.assertHumanControlAdmission(n);let r=y(n);return r===void 0?await t():await this.mutations.run(r,t)}requireHumanControlLease(t){let n=this.getActiveLease(t);if(!n.deviceKey)throw new e(`UNSUPPORTED_OPERATION`,`Human control requires a device-scoped remote lease.`);return{...n,deviceKey:n.deviceKey}}resolveHumanControlScope(t,n){if(t.kind===`host`){if(!n.scope)throw new e(`INVALID_ARGS`,`Host human control requires a lease device scope.`);return n.scope}if(n.scope)throw new e(`INVALID_ARGS`,`Lease-owner human control uses the admitted lease device; do not supply scope.`);let r=this.requireHumanControlLease(t.leaseId);return{backend:r.backend,leaseProvider:r.leaseProvider,deviceKey:r.deviceKey}}assertHoldAuthority(t,n){if(t.kind===`host`)return;let r=this.requireHumanControlLease(t.leaseId);if(n.ownerLeaseId!==r.leaseId||y(r)!==y(n.hold.scope))throw new e(`UNAUTHORIZED`,`Human-control hold does not belong to the admitted lease.`,{reason:`LEASE_SCOPE_MISMATCH`})}findHumanControlHold(e){for(let t of this.holdsByDevice.values()){let n=t.get(e);if(n)return n}}hasHumanControl(e){let t=y(e);return t!==void 0&&this.holdsByDevice.has(t)}isLeaseProtected(e,t){return e.expiresAt>t||this.hasHumanControl(e)||this.inFlightWork.isDeferred(e.leaseId)}expireHumanControlHolds(){let e=this.now();for(let[t,n]of this.holdsByDevice){let r=0;for(let[t,{hold:i}]of n)i.expiresAt===void 0||i.expiresAt>e||(r=Math.max(r,i.expiresAt),n.delete(t));n.size===0&&(this.holdsByDevice.delete(t),this.refreshHeldLease(t,r))}}refreshHeldLease(e,t){this.refreshProtectedLease(this.deviceBindings.get(e),t)}refreshProtectedLease(e,t){let n=e?this.leases.get(e):void 0;n&&this.refreshLease(n,n.expiresAt-n.heartbeatAt,Math.max(t,n.heartbeatAt))}consumeExpiredLeases(){this.expireHumanControlHolds();let e=this.now(),t=[];for(let n of this.leases.values()){if(this.isLeaseProtected(n,e))continue;this.leases.delete(n.leaseId),this.unbindLease(n,n.expiresAt);let r={...n};t.push(r),this.onLeaseExpired?.(r)}return t}consumeExpiredLease(e){this.expireHumanControlHolds();let t=me(e);if(!t)return;let n=this.leases.get(t);if(!n||this.isLeaseProtected(n,this.now()))return;this.leases.delete(n.leaseId),this.unbindLease(n,n.expiresAt);let r={...n};return this.onLeaseExpired?.(r),r}cleanupExpiredLeases(){this.consumeExpiredLeases()}enforceCapacity(t){if(t!==`ios-simulator`||this.maxActiveSimulatorLeases<=0)return;let n=Array.from(this.leases.values()).filter(e=>e.backend===`ios-simulator`).length;if(!(n<this.maxActiveSimulatorLeases))throw new e(`DEVICE_IN_USE`,`No simulator lease capacity available`,{reason:`LEASE_CAPACITY_EXCEEDED`,activeLeases:n,maxActiveLeases:this.maxActiveSimulatorLeases,backend:t,hint:`Retry after releasing another simulator lease.`})}getActiveLease(t){let n=this.leases.get(t);if(n)return n;throw new e(`UNAUTHORIZED`,`Lease is not active`,{reason:`LEASE_NOT_FOUND`})}refreshLease(e,t,n=this.now()){let r={...e,heartbeatAt:n,expiresAt:n+t};return this.leases.set(r.leaseId,r),this.bindLease(r),{...r}}bindLease(e){this.runBindings.set(b(e),e.leaseId);let t=y(e);t&&this.deviceBindings.set(t,e.leaseId)}unbindLease(e,t=this.now()){this.runBindings.delete(b(e));let n=y(e);n&&this.deviceBindings.delete(n),this.providerSessionOwnership.markLeaseReleased(e,t)}assertDeviceAvailable(e){let t=y({backend:e.backend,leaseProvider:e.leaseProvider,deviceKey:e.deviceKey});if(!t)return;let n=this.deviceBindings.get(t);if(!n)return;let r=this.leases.get(n);if(!r){this.deviceBindings.delete(t);return}throw xe(r)}};function lt(t){let n=Se(t.meta?.sessionIsolation??t.flags?.sessionIsolation),r=t.meta?.tenantId??t.flags?.tenant,i=ue(r);if(r&&!i)throw new e(`INVALID_ARGS`,`Invalid tenant id. Use 1-128 chars: letters, numbers, dot, underscore, hyphen.`);if(n!==`tenant`)return t;if(!i)throw new e(`INVALID_ARGS`,`session isolation mode tenant requires --tenant (or meta.tenantId).`);let a=t.session||`default`;return k(i,a)?{...t,meta:{...t.meta,tenantId:i,sessionIsolation:n}}:{...t,session:it(i,a),meta:{...t.meta,tenantId:i,sessionIsolation:n}}}function ut(t,n,r,i={}){if(He(t.command))return;let a=ze(t);pt(t,a);let o=r?.lease;if(r===void 0&&!a.leaseId&&dt(t,i.providerAppCatalog))return;if(t.command===`human_control`&&!o&&!a.leaseId)throw new e(`UNSUPPORTED_OPERATION`,`Takeover requires an active remote device lease. Local takeover is not supported.`);if(t.command!==`human_control`&&!o&&t.meta?.sessionIsolation!==`tenant`&&(!a.leaseId||!a.tenantId&&!a.runId))return;mt(a,o);let s=Be(t,r),c={...s,leaseTtlMs:s.leaseTtlMs??(p(s)?3e5:void 0)};n.assertLeaseAdmission(d(s));let l=n.heartbeatLease(d(c));return We(t)&&n.assertHumanControlAdmission(l),l}function dt(e,t){let n=Ue(e);return n?.kind===`unconditional`||n?.kind===`provider-app-catalog`&&t?.supports(n.provider)===!0}function ft(e){He(e.command)||pt(e,ze(e))}function pt(t,n){if(t.command!==`open`)return;let r=f(n);if(r.length!==0)throw new e(`INVALID_ARGS`,`Proxy open requires leaseId, tenantId, runId, clientId, and deviceKey lease metadata.`,{missing:r})}function mt(e,t){t&&(A(`leaseId`,e.leaseId,t.leaseId),A(`tenantId`,e.tenantId,t.tenantId),A(`runId`,e.runId,t.runId),A(`leaseProvider`,e.leaseProvider,t.leaseProvider),A(`clientId`,e.clientId,t.clientId),A(`deviceKey`,e.deviceKey,t.deviceKey))}function A(t,n,r){if(!(!n||!r||n===r))throw new e(`UNAUTHORIZED`,`Lease does not match session owner (${t})`,{reason:`LEASE_SESSION_MISMATCH`,field:t})}async function ht(e,t){if(!t.leaseProvider||!e)return!1;try{return await e(t),_({level:`info`,phase:`provider_lease_expired_released`,data:{leaseId:t.leaseId,provider:t.leaseProvider}}),!0}catch(e){return _({level:`error`,phase:`provider_lease_expiry_release_failed`,data:{leaseId:t.leaseId,provider:t.leaseProvider,error:e instanceof Error?e.message:String(e)}}),!1}}function gt(e){ft(e)}async function _t(e){let t=e.sessionStore.get(e.sessionName),n=t?.lease;return!t||!n||!e.leaseRegistry.consumeExpiredLease(n.leaseId)?!1:(_({level:`info`,phase:`leased_session_expired`,data:{reason:`LEASE_EXPIRED`,leaseId:n.leaseId,session:t.name,deviceKey:n.deviceKey}}),await e.teardownSession(t,t.name).catch(e=>{_({level:`debug`,phase:`leased_session_expiry_cleanup_failed`,data:{reason:`LEASE_EXPIRED`,leaseId:n.leaseId,session:t.name,error:e instanceof Error?e.message:String(e)}})}),await Pe(t.deviceClaim).catch(e=>{_({level:`warn`,phase:`leased_session_expiry_device_claim_clear_failed`,data:{session:t.name,deviceKey:t.deviceClaim?.deviceKey,error:e instanceof Error?e.message:String(e)}})}),e.sessionStore.delete(t.name),!0)}function vt(e){let{sessionName:t,sessionStore:n,leaseRegistry:r}=e,i=n.get(t),a=ut(e.req,r,i,{providerAppCatalog:e.providerAppCatalog});if(!a)return e.req;let o={...e.req,internal:{...e.req.internal,admittedLease:a}};return i?.lease&&n.set(t,{...i,lease:{...i.lease,leaseBackend:a.backend,expiresAt:a.expiresAt}}),o}function yt(e){return Ve(e.req,e.req.internal?.admittedLease)??e.existingLease}async function bt(e){let t=e.session.lease;if(!t)return;let n=u({leaseId:t.leaseId,tenantId:t.tenantId,runId:t.runId,leaseBackend:t.leaseBackend,leaseProvider:t.leaseProvider,deviceKey:t.deviceKey,clientId:t.clientId}),r=e.leaseRegistry.getLease(n),i=r?await e.leaseLifecycleProvider?.release?.(r):void 0,a=Ce(i);r&&a&&e.leaseRegistry.recordProviderSession(r,a);let o=e.leaseRegistry.releaseLease(n);return _({level:`info`,phase:`session_lease_released`,data:{session:e.session.name,leaseId:t.leaseId,released:o.released}}),i}const xt=[`platform`,`target`],St=[`iosSimulatorDeviceSet`,`androidDeviceAllowlist`];function Ct(e){return c({deviceName:e?.device,udid:e?.udid,serial:e?.serial})}function wt(e){return Ct(e)||Dt(e,xt)}function Tt(e){return wt(e)||Dt(e,St)}function Et(e){return typeof e==`string`&&e.trim().length>0}function Dt(e,t){return e?t.some(t=>Et(e[t])):!1}function Ot(e){return{appleSimulatorAppTarget:kt(e)}}function kt(e){return e&&!i(e)?e:void 0}function At(e){let t={version:2,platform:e.platform??null,target:e.target??null,runtimeHints:e.runtimeHints??null,initialStaticEnv:e.initialStaticEnv,steps:e.steps};return tt(`sha256`).update(ie(t),`utf8`).digest(`hex`)}function jt(e,t,n){return new Bt(Nt(Mt(t.resolve(e))),n).parse()}function Mt(e){let t=e.trim();return t.startsWith("${")&&t.endsWith(`}`)?t.slice(2,-1).trim():t}function Nt(t){let n=[],r=0;for(;r<t.length;){let i=t.slice(r),a=/^\s+/.exec(i)?.[0].length??0;if(a>0){r+=a;continue}let o=Pt(i);if(!o)throw new e(`INVALID_ARGS`,`Unsupported runFlow.when.true expression near "${i.slice(0,24)}".`);n.push(o.value),r+=o.length}return n}function Pt(e){return Ft(e)??It(e)??Lt(e)??Rt(e)??zt(e)}function Ft(e){return e.startsWith(`maestro.platform`)?{value:{type:`platform`},length:16}:null}function It(e){let t=/^(==|!=|&&|\|\|)/.exec(e)?.[1];return t?{value:{type:`operator`,value:t},length:t.length}:null}function Lt(e){let t=e[0];return t===`(`||t===`)`?{value:{type:`paren`,value:t},length:1}:null}function Rt(e){let t=/^(['"])(.*?)\1/.exec(e);return t?{value:{type:`string`,value:t[2]??``},length:t[0].length}:null}function zt(e){let t=/^(true|false)\b/.exec(e)?.[1];return t?{value:{type:`boolean`,value:t===`true`},length:t.length}:null}var Bt=class{index=0;tokens;platform;constructor(e,t){this.tokens=e,this.platform=t}parse(){let t=this.parseOr();if(this.peek())throw new e(`INVALID_ARGS`,`Unsupported trailing runFlow.when.true expression.`);return t}parseOr(){let e=this.parseAnd();for(;this.consumeOperator(`||`);)e=this.parseAnd()||e;return e}parseAnd(){let e=this.parsePrimary();for(;this.consumeOperator(`&&`);)e=this.parsePrimary()&&e;return e}parsePrimary(){let t=this.peek();if(!t)throw new e(`INVALID_ARGS`,`Incomplete runFlow.when.true expression.`);if(t.type===`boolean`)return this.index+=1,t.value;if(t.type===`paren`&&t.value===`(`){this.index+=1;let t=this.parseOr();if(!this.consumeParen(`)`))throw new e(`INVALID_ARGS`,`Unclosed runFlow.when.true parenthesis.`);return t}return this.parsePlatformComparison()}parsePlatformComparison(){this.consumePlatformToken();let e=this.consumeComparisonOperator(),t=this.consumeStringLiteral(),n=this.platform===t.toLowerCase();return e.value===`==`?n:!n}consumePlatformToken(){if(this.peek()?.type!==`platform`)throw new e(`INVALID_ARGS`,`runFlow.when.true supports maestro.platform comparisons.`);this.index+=1}consumeComparisonOperator(){let t=this.peek();if(t?.type!==`operator`||t.value!==`==`&&t.value!==`!=`)throw new e(`INVALID_ARGS`,`runFlow.when.true comparison requires == or !=.`);return this.index+=1,t}consumeStringLiteral(){let t=this.peek();if(t?.type!==`string`)throw new e(`INVALID_ARGS`,`runFlow.when.true comparison requires a string literal.`);return this.index+=1,t.value}consumeOperator(e){let t=this.peek();return t?.type!==`operator`||t.value!==e?!1:(this.index+=1,!0)}consumeParen(e){let t=this.peek();return t?.type!==`paren`||t.value!==e?!1:(this.index+=1,!0)}peek(){return this.tokens[this.index]}};function Vt(e){switch(e.kind){case`runFlow`:return!(`include`in e);case`repeat`:case`retry`:return!(`commands`in e);default:return!1}}function Ht(e,t){return{...N(e,t),source:e.source}}function j(t,n,r){if(t===void 0)return;let i=r??Ge[n]??{},a=Ye(i),o;if(typeof t==`number`)o=t;else{let r=t.trim();if(r===``)throw new e(`INVALID_ARGS`,`Maestro ${n} must be ${a}.`);o=Number(r)}if(!Number.isFinite(o)||Math.abs(o)>2**53-1||i.integer&&!Number.isSafeInteger(o)||i.nonNegative&&o<0||i.positive&&o<=0)throw new e(`INVALID_ARGS`,`Maestro ${n} must be ${a}.`);return o}function Ut(e,t,n,r){return j(e===void 0?t:n.resolve(String(e)),r)}function M(e){if(e?.aborted)throw t()}async function Wt(t,n){if(t.include.kind===`commands`)return{kind:`program`,source:t.source,config:{},commands:t.include.commands};if(!n.loadProgram)throw new e(`INVALID_ARGS`,`Maestro file runFlow requires a program loader.`);return M(n.signal),n.signal?await n.loadProgram(t.include.path,t.source.path,n.signal):await n.loadProgram(t.include.path,t.source.path)}function Gt(e,t){if(e.include.kind===`file`)return D.resolve(t?D.dirname(t):process.cwd(),e.include.path)}function Kt(e){return e===void 0?void 0:D.resolve(e)}function qt(t,n){let r=Gt(t,t.source.path);if(r&&n.has(r))throw new e(`INVALID_ARGS`,`Maestro runFlow cycle detected at ${r}.`);return r}function Jt(t,n,r,i){let a=t.include.kind===`file`?Kt(n.source.path):void 0,o=new Set([r,a].filter(e=>e!==void 0)),s=[...o].find(e=>i.has(e));if(s)throw new e(`INVALID_ARGS`,`Maestro runFlow cycle detected at ${s}.`);return o.forEach(e=>i.add(e)),o}function Yt(e,t,n){return e.platform&&e.platform!==n.platform?!1:e.true===void 0?!0:typeof e.true==`boolean`?e.true:jt(e.true,t,n.platform)}function Xt(e){return[...e.visible?[{kind:`visible`,selector:e.visible}]:[],...e.notVisible?[{kind:`notVisible`,selector:e.notVisible}]:[]]}function N(e,t){return typeof e==`string`?t.resolve(e):Array.isArray(e)?e.map(e=>N(e,t)):e&&typeof e==`object`?Object.fromEntries(Object.entries(e).map(([e,n])=>[e,N(n,t)])):e}async function Zt(e,t){M(t.signal);let n=Kt(e.source.path),r={options:t,context:Ke(t.defaults,t.env),activeIncludePaths:new Set(n===void 0?[]:[n]),staticallyExecutedControls:0,staticallySkippedControls:0};return{steps:await Qt(e,[],void 0,e.source.path,r),staticallyExecutedControls:r.staticallyExecutedControls,staticallySkippedControls:r.staticallySkippedControls}}async function Qt(e,t,n,r,i){M(i.options.signal);let a=ln(t,e.config.env),o=e.config.appId??n,s=i.context.enter(e.config.env);try{let t=[...e.config.onFlowStart??[],...e.commands,...e.config.onFlowComplete??[]],n=[];for(let s of t)n.push(...await en(s,a,o,e.source.path??r,i));return n}finally{s()}}async function $t(e,t,n,r,i){let a=[];for(let o of e)a.push(...await en(o,t,n,r,i));return a}async function en(e,t,n,r,i){M(i.options.signal);let a=un(e,r);switch(a.kind){case`runFlow`:{let e=nn(a,i);if(e===`omit`)return i.staticallySkippedControls+=1,[];let o=await tn(a,t,n,r,i);return e===`flatten`?(i.staticallyExecutedControls+=1,o):[P(a,t,n,o)]}case`repeat`:return[P(a,t,n,await $t(a.commands,t,n,r,i))];case`retry`:return[P(a,t,n,await $t(a.commands,t,n,r,i))];default:return[sn(a,t,n)]}}async function tn(e,t,n,r,i){let a=an(e,i.context),o=qt(a,i.activeIncludePaths),s=await Wt(a,i.options);M(i.options.signal);let c=Jt(a,s,o,i.activeIncludePaths),l=ln(t,e.env),u=i.context.enter(e.env);try{return await Qt(s,l,n,s.source.path??e.source.path??r,i)}finally{u(),c.forEach(e=>i.activeIncludePaths.delete(e))}}function nn(e,t){let n=e.when;return n?n.platform!==void 0&&n.platform!==t.options.platform?`omit`:rn(n.true,t)||(n.visible||n.notVisible?`opaque`:`flatten`):`flatten`}function rn(e,t){if(e===!1)return`omit`;if(typeof e==`string`)return on(t.context.resolveDeferred(e))?`opaque`:jt(e,t.context,t.options.platform)?void 0:`omit`}function an(e,t){return e.include.kind===`file`?{...e,include:{...e.include,path:t.resolve(e.include.path)}}:e}function on(e){return/\$\{[A-Za-z_][A-Za-z0-9_.]*\}/.test(e)}function sn(e,t,n){return T({kind:`command`,command:e,source:e.source,scopes:t,appId:n})}function P(e,t,n,r){return T({kind:`opaque`,command:cn(e),source:e.source,scopes:t,body:r,appId:n})}function cn(e){switch(e.kind){case`runFlow`:return T({kind:e.kind,source:e.source,when:e.when,label:e.label,...e.include.kind===`file`?{includePath:e.include.path}:{}});case`repeat`:return{kind:e.kind,source:e.source,times:e.times};case`retry`:return T({kind:e.kind,source:e.source,maxRetries:e.maxRetries})}}function ln(e,t){return t===void 0?e:[...e,t]}function un(e,t){return e.source.path||!t?e:{...e,source:{...e.source,path:t}}}async function dn(e,t={}){let{steps:n,staticallyExecutedControls:r,staticallySkippedControls:i}=await Zt(e,t),a=fn(t.runtimeHints),o=T({kind:`maestroReplayPlan`,platform:t.platform,target:t.target,runtimeHints:a,initialStaticEnv:structuredClone({...t.defaults??{},...e.config.env??{},...t.env??{}}),steps:structuredClone(n),total:n.length,compatibility:{staticallyExecutedControls:r,staticallySkippedControls:i}}),s=At(o);return pn({...o,digest:s})}function fn(e){if(!e)return;let t=Object.entries(e).filter(e=>e[1]!==void 0);return t.length===0?void 0:Object.fromEntries(t)}function pn(e){if(!e||typeof e!=`object`||Object.isFrozen(e))return e;for(let t of Object.values(e))pn(t);return Object.freeze(e)}function mn(e,t={}){let{from:n,planDigest:r}=t;if(n===void 0&&r===void 0)return{allowed:!0,startIndex:0};if(n===void 0||r===void 0)return{allowed:!1,reason:`replay --from requires --plan-digest (and --plan-digest requires --from).`};if(!Number.isInteger(n)||n<1||n>e.total)return{allowed:!1,reason:`replay --from ${n} is out of range for a ${e.total}-step plan.`};if(r!==e.digest)return{allowed:!1,reason:`replay --plan-digest does not match the current plan digest.`};if(n===1)return{allowed:!0,startIndex:0};for(let t=0;t<n-1;t+=1){let n=e.steps[t];if(n.kind===`opaque`)return{allowed:!1,reason:`step ${t+1} is opaque runtime control flow (${n.command.kind}) and cannot be skipped safely.`};if(n.command.kind===`runScript`||n.command.kind===`evalScript`)return{allowed:!1,reason:`step ${t+1} (${n.command.kind}) can produce outputEnv values and cannot be skipped safely.`}}let i=e.steps[n-1];return i.kind===`opaque`?{allowed:!1,reason:`step ${n} is opaque runtime control flow (${i.command.kind}) and cannot be resumed into.`}:{allowed:!0,startIndex:n-1}}function hn(t,n={}){let r=mn(t,n);if(!r.allowed)throw new e(`INVALID_ARGS`,r.reason);return r.startIndex}function gn(t,n){if(!Number.isInteger(n)||n<0||n>t.total)throw new e(`INVALID_ARGS`,`Maestro replay startIndex ${n} is out of range for a ${t.total}-step plan.`);return n}const _n=`maestro-test-failure`;function F(t,n={}){return new e(`COMMAND_FAILED`,t,{...n,reason:_n})}function vn(t){return t instanceof e&&t.code===`COMMAND_FAILED`&&t.details?.reason===_n}const yn=new Set([``,`false`,`0`,`null`,`undefined`]);function bn(e){return typeof e==`boolean`?e:typeof e==`number`?e!==0&&!Number.isNaN(e):!yn.has(e)}async function xn(e,t){M(t.options.signal);try{return await Pn(e,t.context,async()=>await Sn(e,t))}catch(t){throw R(t,e)}}async function Sn(e,t){if(e.kind===`command`)return await Cn(e.command,e.appId,t);await kn(e,t)}async function Cn(e,t,n){if(e.kind===`evalScript`)return await En(e,n);let r=Ht(e,n.context);try{return await Dn(r,t,n)}catch(e){if(M(n.options.signal),Tn(r)&&vn(e)){n.warnings.push(wn(r,e)),n.skipped+=1;return}throw Fn(e,r)}}function wn(t,n){let r=`${t.source.path?`${t.source.path}:`:``}line ${t.source.line}`,i=n instanceof e?n.message:String(n);return`Optional Maestro ${t.kind} skipped at ${r}: ${i}`}function Tn(e){return`optional`in e&&e.optional===!0}async function En(t,n){let{evaluateMaestroEvalScript:r}=await import(`./engine-eval-script.js`);if(n.options.trustedScripts===!1)throw new e(`UNAUTHORIZED`,`Maestro evalScript is not permitted for flows received over the remote daemon surface: node:vm is not a security sandbox, so an untrusted expression can escape to the host.`);let i=await r(t.script,n.context.values);n.context.replaceOutput(i),n.executed+=1}async function Dn(e,t,n){switch(e.kind){case`assertVisible`:await L({kind:`visible`,selector:e.target},n.timing.assertVisibleTimeoutMs,n),n.executed+=1;return;case`assertNotVisible`:await L({kind:`notVisible`,selector:e.target},n.timing.assertNotVisibleTimeoutMs,n),n.executed+=1;return;case`assertTrue`:if(!bn(e.condition))throw F(`Maestro assertTrue condition was falsy: ${JSON.stringify(e.condition)}`);n.executed+=1;return;case`extendedWaitUntil`:await L(Nn(e),j(e.timeout,`extendedWaitUntil.timeout`)??n.timing.extendedWaitUntilTimeoutMs,n),n.executed+=1;return;default:return await On(e,t,n)}}async function On(e,t,n){let r=T({command:e,env:n.context.values,appId:t===void 0?void 0:n.context.resolve(t),generation:n.context.generation,invalidateObservation:n.context.invalidateObservation,cachedObservation:n.context.observation,signal:n.options.signal}),i=await n.port.execute(r);return M(n.options.signal),i.observation&&n.context.recordObservation(i.observation),i.outputEnv&&n.context.merge(i.outputEnv),i.artifactPaths?.forEach(e=>n.artifacts.add(e)),n.executed+=1,i}async function kn(e,t){let n=Ht(e.command,t.context);switch(n.kind){case`runFlow`:if(n.when&&!await jn(n.when,t)){t.skipped+=1;return}t.executed+=1,await I(e.body,t);return;case`repeat`:{let r=Ut(n.times,0,t.context,`repeat.times`);t.executed+=1;for(let n=0;n<r;n+=1)M(t.options.signal),await I(e.body,t);return}case`retry`:{let r=Math.min(Ut(n.maxRetries,1,t.context,`retry.maxRetries`),Ze.control.retryMaxRetries);t.executed+=1,await An(e.body,r,t);return}}}async function I(e,t){for(let n of e)await xn(n,t)}async function An(t,n,r){let i;for(let e=0;e<=n;e+=1){M(r.options.signal);try{await I(t,r);return}catch(e){if(M(r.options.signal),!vn(Ln(e)))throw e;i=R(e,t[0])}}throw i||new e(`COMMAND_FAILED`,`Maestro retry commands failed.`)}async function jn(e,t){if(!Yt(e,t.context,t.options))return!1;for(let n of Xt(e))if(M(t.options.signal),!(await Mn(n,t.timing.runFlowConditionTimeoutMs,t)).matched)return!1;return!0}async function L(e,t,n){if(!(await Mn(e,t,n)).matched)throw F(`Maestro ${e.kind} condition did not match.`)}async function Mn(e,t,n){let r={condition:e,timeoutMs:t,generation:n.context.generation,env:n.context.values,...n.context.observation?{cachedObservation:n.context.observation}:{},...n.options.signal?{signal:n.options.signal}:{}},i=await n.port.observe(r);return M(n.options.signal),n.context.recordObservation(i),i}function Nn(t){if(t.visible)return{kind:`visible`,selector:t.visible};if(t.notVisible)return{kind:`notVisible`,selector:t.notVisible};throw new e(`INVALID_ARGS`,`Maestro extendedWaitUntil requires one condition.`)}async function Pn(e,t,n){let r=e.scopes.map(e=>t.enter({...e}));try{return await n()}finally{for(let e=r.length-1;e>=0;--e)r[e]()}}function R(e,t){if(In(e))return e;let n=t?.source??{line:1};return{kind:`maestroPlanStepFailure`,error:Rn(e,t?.command),source:n,...t?{command:t.command}:{}}}function Fn(e,t){return{kind:`maestroPlanStepFailure`,error:Rn(e,t),source:t.source,command:t}}function In(e){return!!(e&&typeof e==`object`&&e.kind===`maestroPlanStepFailure`)}function Ln(e){return In(e)?e.error:e}function Rn(t,n){if(!(t instanceof e)||!n||/\bline \d+\b/.test(t.message))return t;let r=n.source.path?`${n.source.path}:`:``;return new e(t.code,`${t.message} (${r}line ${n.source.line})`,t.details)}async function zn(t,n,r={}){M(r.signal);let i=r.startIndex??0;if(!Number.isInteger(i)||i<0||i>t.total)throw new e(`INVALID_ARGS`,`Maestro replay startIndex ${i} is out of range for a ${t.total}-step plan.`);let a={plan:t,port:n,options:r,context:Ke(r.defaults,r.env?{...r.env}:{}),timing:Qe,artifacts:new Set,warnings:[],executed:t.compatibility.staticallyExecutedControls,skipped:t.compatibility.staticallySkippedControls};for(let e=i;e<t.steps.length;e+=1)try{await Bn(t.steps[e],e,a)}catch(e){throw Ln(e)}return{executed:a.executed,skipped:a.skipped,generation:a.context.generation,artifactPaths:[...a.artifacts],...a.warnings.length>0?{warnings:a.warnings}:{}}}async function Bn(e,t,n){M(n.options.signal);let r=n.options.now??Date.now,i=r(),a=n.port.readMetrics?.(),o=n.context.generation,s={command:e.command,source:e.source,generation:o,stepIndex:t+1,stepTotal:n.plan.total};z(()=>n.options.observer?.commandStarted?.(s));try{let t=await xn(e,n);M(n.options.signal),z(()=>n.options.observer?.commandCompleted?.({...s,durationMs:r()-i,...Vn(a,n.port.readMetrics?.()),...t?.data?{data:t.data}:{}}))}catch(t){let o=R(t,e);throw z(()=>n.options.observer?.commandFailed?.({...s,...o.command?{command:o.command}:{},source:o.source,durationMs:r()-i,...Vn(a,n.port.readMetrics?.()),error:o.error,artifactPaths:[...n.artifacts],warnings:[...n.warnings]})),o}}function Vn(e,t){return!e||!t?{}:{runtimeMetrics:{hierarchyCaptures:t.hierarchyCaptures-e.hierarchyCaptures,screenshotCaptures:t.screenshotCaptures-e.screenshotCaptures,tapRetries:t.tapRetries-e.tapRetries,settleLatches:t.settleLatches-e.settleLatches,settleTimeouts:t.settleTimeouts-e.settleTimeouts}}}function z(e){try{e?.()}catch{}}async function Hn(e,t,n={}){let r=Un(e,n);return await zn(e,t,{...n,startIndex:r})}function Un(e,t){return t.from!==void 0||t.planDigest!==void 0?hn(e,{from:t.from,planDigest:t.planDigest}):gn(e,t.startIndex??0)}function Wn(e){return Vt(e)?{command:e.kind,...e.kind===`runFlow`?V(e.label??e.includePath):{}}:{command:e.kind,...Gn(e)}}function Gn(e){return`label`in e&&e.label?V(e.label):Kn(e)?V($n(e.target)):qn(e)?Jn(e):e.kind===`inputText`?V(`<text>`):Yn(e)}function Kn(e){return e.kind===`tapOn`||e.kind===`doubleTapOn`||e.kind===`longPressOn`}function qn(e){return e.kind===`assertVisible`||e.kind===`assertNotVisible`||e.kind===`extendedWaitUntil`||e.kind===`scrollUntilVisible`}function Jn(e){switch(e.kind){case`assertVisible`:case`assertNotVisible`:return V(B(e.target));case`extendedWaitUntil`:return V(B(e.visible??e.notVisible));case`scrollUntilVisible`:return V(B(e.element))}}function Yn(e){return Xn(e)?Zn(e):e.kind===`swipe`?Qn(e):e.kind===`runFlow`?V(e.label??(e.include.kind===`file`?e.include.path:``)):e.kind===`assertTrue`?V(String(e.condition)):{}}function Xn(e){return e.kind===`openLink`||e.kind===`takeScreenshot`||e.kind===`runScript`||e.kind===`pressKey`}function Zn(e){switch(e.kind){case`openLink`:return V(e.link);case`takeScreenshot`:return V(e.path);case`runScript`:return V(e.file);case`pressKey`:return V(e.key)}}function Qn(e){return V(e.gesture.kind===`coordinates`?`${er(e.gesture.start)} to ${er(e.gesture.end)}`:e.gesture.direction)}function $n(e){return e.space===`target`?B(e.selector):`${e.x},${e.y}${e.space===`percent`?`%`:``}`}function B(e){return e?.id??e?.text}function er(e){return`${e.x},${e.y}${e.space===`percent`?`%`:``}`}function V(e){return e?{value:e}:{}}const tr=new Set(String.raw`^$\.*+?()[]{}|`);function nr(e,t){try{return RegExp(`^(?:${t})$`,`ims`).test(e)}catch{return e.toLocaleLowerCase()===t.toLocaleLowerCase()}}function rr(e){try{new RegExp(e)}catch{return e}let t=``;for(let n=0;n<e.length;n+=1){let r=e[n];if(r!==`\\`){if(tr.has(r))return;t+=r;continue}let i=e[n+1];if(i===void 0||!tr.has(i))return;t+=i,n+=1}return t}function ir(e,t,n){if(n===`android`&&e.visibleToUser===!1)return!1;if(g(e.rect))return t.isVisibleInEffectiveViewport(e);if(e.rect)return!1;if(n!==`android`&&e.hittable===!0)return!0;let r=t.findAncestor(e,e=>ee(e,n)?e:null);return r?g(r.rect)?t.isVisibleInEffectiveViewport(r):n!==`android`&&r.hittable===!0:!1}function ar(e,t,n){return!!n.findAncestor(e,e=>e.index===t.index?e:null)}function or(e,t){let n=[t.id===void 0?void 0:cr(e.identifier,t.id),t.text===void 0?void 0:lr(e,t.text)].filter(e=>e!==void 0);return!(n.length===0&&t.enabled===void 0&&t.selected===void 0||n.some(e=>!e)||t.enabled!==void 0&&e.enabled!==!1!==t.enabled||t.selected!==void 0&&e.selected===!0!==t.selected)}function sr(e){return e.matches.filter(t=>ir(t,e.visibility,e.platform))}function cr(e,t){let n=e??``;return E(n)===E(t)||nr(n,t)}function lr(e,t){return[e.label,qe(e),e.identifier].filter(e=>!!e).some(e=>cr(e,t))}function ur(e){return e.index!==void 0||e.childOf!==void 0||e.below!==void 0||e.above!==void 0||e.leftOf!==void 0||e.rightOf!==void 0||e.containsChild!==void 0||e.containsDescendants!==void 0}function dr(e){return e.text!==void 0||e.id!==void 0||e.enabled!==void 0||e.selected!==void 0}function fr(e,t,n){let r=[],i=0;for(let a of e)for(let e of n){let n=mr(a.rect,e.rect);n===void 0||!pr(t,a.rect,e.rect)||r.push({node:a,distance:n,order:i++})}return r.sort((e,t)=>e.distance-t.distance||e.order-t.order),r.map(({node:e})=>e)}function pr(e,t,n){switch(e){case`below`:return t.y>n.y;case`above`:return t.y<n.y;case`leftOf`:return t.x<n.x;case`rightOf`:return t.x>n.x}}function mr(e,t){if(!(!hr(e)||!hr(t)))return Math.fround(Math.hypot(H(e.x,e.width)-H(t.x,t.width),H(e.y,e.height)-H(t.y,t.height)))}function hr(e){return!!(e&&[e.x,e.y,e.width,e.height].every(Number.isFinite))}function H(e,t){return e+Math.trunc(t/2)}function gr(t,n={},r={}){let i=h(t.nodes,n);n.onVisibilityContextCreated?.();let a=new WeakMap,o=new WeakSet,s=new WeakMap,c=new Map,l=e=>e.parentIndex===void 0?void 0:i.nodeByIndex.get(e.parentIndex)??t.nodes[e.parentIndex],u=e=>{let t=s.get(e);if(t)return t;let n=new Set,r=new Set,i=l(e);for(;i&&!r.has(i.index);)r.add(i.index),n.add(i.index),i=l(i);return s.set(e,n),n},d=(e,r)=>{let i=c.get(e);i||(i=new WeakMap,c.set(e,i));let a=i.get(r);if(a)return a;n.onPositionComputed?.(e,r);let o=fr(t.nodes,e,m(r).indexed),s={ordered:o,candidateIndexes:new Set(o.map(e=>e.index))};return i.set(r,s),s},f=(e,t)=>d(e,t).ordered,p=(e,t)=>d(e,t).candidateIndexes,m=i=>{let s=a.get(i);if(s)return s;if(o.has(i))throw new e(`INVALID_ARGS`,`Maestro selector relations cannot contain cycles.`);o.add(i),n.onSelectorComputed?.(i);try{let e=_r(t,i,l,u,m,p),n={matches:e,indexed:xr(e,i.index,r.orderUnindexed)};return a.set(i,n),n}finally{o.delete(i)}};return{visibility:i,resolve:m,resolvePosition:f}}function _r(e,t,n,r,i,a){let{index:o,childOf:s,below:c,above:l,leftOf:u,rightOf:d,containsChild:f,containsDescendants:p,...m}=t,h=dr(m)?e.nodes.filter(e=>or(e,m)):[...e.nodes];if(s){let e=new Set(i(s).indexed.map(e=>e.index));h=h.filter(t=>yr(r(t),e))}if(f){let e=new Set(i(f).indexed.map(n).filter(e=>e!==void 0).map(e=>e.index));h=h.filter(t=>e.has(t.index))}if(p){let e=p.map(e=>vr(i(e).indexed,r));h=h.filter(t=>e.every(e=>e.has(t.index)))}for(let[e,n]of br(t)){let t=a(e,n);h=h.filter(e=>t.has(e.index))}return h}function vr(e,t){let n=new Set;for(let r of e)for(let e of t(r))n.add(e);return n}function yr(e,t){for(let n of e)if(t.has(n))return!0;return!1}function br(e){return[[`below`,e.below],[`above`,e.above],[`leftOf`,e.leftOf],[`rightOf`,e.rightOf]].filter(e=>e[1]!==void 0)}function xr(e,t,n){if(t===void 0)return n?n(e):[...e];let r=Cr(e)[wr(t)];return r?[r]:[]}function Sr(e,t){return t===void 0?e[0]:Cr(e)[wr(t)]}function Cr(e){return[...e].sort((e,t)=>{let n=U(e.rect?.y),r=U(t.rect?.y);return n===r?U(e.rect?.x)-U(t.rect?.x):n-r})}function U(e){return e!==void 0&&Number.isFinite(e)?e:2**53-1}function wr(t){let n=typeof t==`number`?t:Number(t.trim());if(!Number.isSafeInteger(n)||n<0)throw new e(`INVALID_ARGS`,`Maestro selector.index must be a non-negative integer.`);return n}const Tr={android:{kind:`exact`,provider:`android-helper`},ios:{kind:`divergence`,provider:`apple-xctest`,reason:`maestro-clickable-not-exposed-by-provider`}};function Er(e,t){let n=Tr[t];if(n.kind===`divergence`)return n;let r=a(e);return r?r.kind!==`exact`||r.provider!==n.provider?{kind:`divergence`,provider:n.provider,reason:`unregistered-provider-evidence`}:r:{kind:`divergence`,provider:n.provider,reason:`exact-evidence-not-retained`}}function W(e,t){return t.kind===`exact`?e.map((e,n)=>({node:e,order:n,rank:Dr(t.clickableByNodeIndex.get(e.index))})).sort((e,t)=>t.rank-e.rank||e.order-t.order).map(({node:e})=>e):[...e]}function Dr(e){return e===!0?2:+(e===!1)}function Or(e,t,n,r={}){let i=Er(e,n),a=Ar(e,i,r),o=kr(t,a),s=sr({visibility:a.visibility,matches:o.matches,platform:n});return{...o,visible:s,clickability:i,ranked:jr(s,t,n,a.visibility,i)}}function kr(e,t){return{matches:t.resolve(e).matches,parentMatched:e.childOf===void 0||t.resolve(e.childOf).indexed.length>0}}function Ar(e,t,n={}){return gr(e,n,t?{orderUnindexed:e=>W(e,t)}:{})}function jr(e,t,n,r,i){let a=n!==`ios`||!Fr(t)?e:e.filter(n=>{if(Rr(n))return!0;let i=e.filter(e=>e!==n&&Ir(n,e,t));return!i.some(e=>Rr(e)&&ar(n,e,r))&&!i.some(e=>ar(e,n,r))});return t.index===void 0&&i?W(a,i):a}function Mr(e,t){let n=t===void 0?e.find(G):Nr(e,t);return!n||!G(n)?null:{node:n,rect:n.rect}}function Nr(e,t){return Sr(e,t)}function Pr(e){return G(e)?e.rect:void 0}function G(e){return g(e.rect)}function Fr(e){return e.id!==void 0||e.text!==void 0}function Ir(e,t,n){if(n.id!==void 0&&K(e.identifier)!==K(t.identifier))return!1;if(n.text!==void 0){let n=Lr(e),r=new Set(Lr(t));if(!n.some(e=>r.has(e)))return!1}return!0}function Lr(e){return[e.label,e.value,e.identifier].map(K).filter(e=>e!==void 0)}function K(e){if(e)return E(e)||void 0}function Rr(e){let t=m(e.type??``);return t===`button`||t===`link`||t===`switch`||t===`searchfield`||t===`textfield`||t===`securetextfield`||t===`textview`}const zr=Symbol(`maestroFlowProgram`),Br=Symbol(`maestroFailureCommand`),Vr=Symbol(`maestroFailurePlan`);function Hr(e,t){let n=Xe(e,{sourcePath:t});return{sourcePath:t,name:n.config.name,appTarget:Kr(n),[zr]:n}}async function Ur(e,t,n){let r;try{let i=Je(D.dirname(e.sourcePath),n.readSource),a=await dn(e[zr],{defaults:n.defaults,env:n.env,platform:n.platform,target:n.target,runtimeHints:n.runtimeHints,loadProgram:i,signal:n.signal}),o=hn(a,{from:n.from,planDigest:n.planDigest}),s=await Hn(a,t,{defaults:n.defaults,env:n.env,platform:n.platform,target:n.target,loadProgram:i,signal:n.signal,startIndex:o,trustedScripts:n.trustedScripts,observer:Gr(a,n.observer,e=>{r=e})});return{ok:!0,replayed:a.total-o,planDigest:a.digest,startIndex:o,artifactPaths:s.artifactPaths,...s.warnings?{warnings:s.warnings}:{}}}catch(e){return{ok:!1,error:r?.error??e,...r?{failure:r}:{}}}}function Wr(e,t){let n=Jr(e[Br]),r=e[Vr].platform;return!n||r!==`android`&&r!==`ios`?[]:Or(t,n.selector,r).ranked.map(e=>({node:e,basis:Yr(n.selector,e)}))}function Gr(e,t,n){return{commandStarted:e=>t?.actionStarted?.(q(e)),commandCompleted:e=>t?.actionCompleted?.({...q(e),durationMs:e.durationMs,runtimeMetrics:e.runtimeMetrics,data:e.data}),commandFailed:r=>{let i=mn(e,{from:r.stepIndex,planDigest:e.digest}),a={...q(r),durationMs:r.durationMs,error:r.error,artifactPaths:r.artifactPaths,warnings:[...r.warnings],isControl:Vt(r.command),redactions:r.command.kind===`inputText`&&r.command.text.length>0?[{name:`inputText.text`,value:r.command.text}]:[],resume:i.allowed?{allowed:!0,from:r.stepIndex,planDigest:e.digest}:{allowed:!1,from:r.stepIndex,planDigest:e.digest,reason:i.reason},[Br]:r.command,[Vr]:e};n(a),t?.actionFailed?.(a)}}}function q(e){let t=Wn(e.command);return{action:t.command,...t.value?{value:t.value}:{},source:e.source,generation:e.generation,stepIndex:e.stepIndex,stepTotal:e.stepTotal}}function Kr(e){return[e.config.appId,...[...e.config.onFlowStart??[],...e.commands].filter(e=>e.kind===`launchApp`).map(e=>e.kind===`launchApp`?e.appId:void 0)].find(qr)}function qr(e){return!!(e?.trim()&&!e.includes(`$`)&&!i(e))}function Jr(e){switch(e.kind){case`tapOn`:return e.target.space===`target`?{selector:e.target.selector}:void 0;case`doubleTapOn`:case`longPressOn`:return e.target.space===`target`?{selector:e.target.selector}:void 0;case`assertVisible`:case`assertNotVisible`:return{selector:e.target};case`extendedWaitUntil`:return e.visible?{selector:e.visible}:e.notVisible?{selector:e.notVisible}:void 0;case`scrollUntilVisible`:return{selector:e.element};case`swipe`:return e.gesture.kind===`target`?{selector:e.gesture.from}:void 0;default:return}}function Yr(e,t){return e.id!==void 0||e.text!==void 0&&or({...t,label:void 0,value:void 0},{text:e.text})?`id`:e.text===void 0?`other`:`label`}const Xr=`This replay request carries no script sources. Replay scripts are read by the client and sent with the request; upgrade the agent-device client that issued it to a version that sends script sources.`;function Zr(t,n){let r=t.files[n];if(r===void 0)throw new e(`INVALID_ARGS`,`replay script source is missing ${n}; it was not part of the script sources sent with this request.`,{path:n,entry:t.entry});return r}function Qr(e){if(e.command!==`replay`||e.flags?.replayFrom!==void 0)return;let t=e.flags?.replayScriptSource;if(t)try{let n=t.entry,r=Zr(t,n);if(ce(n,e.flags?.replayBackend)===`maestro`){let t=Hr(r,n);return{flags:e.flags??{},options:$r(t.appTarget,e.flags?.platform)}}let i=rt(r,e.flags),a=ei(i.actions);if(!a.appTarget)return;let o=ti(e.flags,i.actions),s=o.platform??i.metadata.platform;return{flags:s&&o.platform===void 0?{...o,platform:s}:o,options:s===`ios`?ri(a.appTarget):void 0}}catch{return}}function $r(e,t){return t===`ios`?ri(e)??{}:{}}function ei(e){let t=ae(e);for(let n of e){if(n.command!==`open`)continue;let e=n.positionals?.[0];return ni(e)?{appTarget:e,platform:t}:{appTarget:void 0,platform:t}}return{appTarget:void 0,platform:t}}function ti(e,t){let n=ei(t);return e?.platform!==void 0||!n.platform?e??{}:{...e,platform:n.platform}}function ni(e){return!!(e&&e.trim()&&!e.includes(`$`)&&!i(e))}function ri(e){let t=kt(e);return t?{appleSimulatorAppTarget:t}:void 0}const ii={label:`Materialized paths`,plural:!0,expiredHint:`Materialized paths are released automatically when their TTL expires; re-run the command that materialized them if the paths are still needed.`},J=new Map;async function ai(e){let t=await O.mkdtemp(D.join(nt.tmpdir(),`agent-device-materialized-`));try{let n=await li(e.installablePath,D.join(t,`installable`)),r=e.archivePath?await li(e.archivePath,D.join(t,`archive`)):void 0,i=et.randomUUID(),a=e.ttlMs??9e5,o=Date.now()+a,s=setTimeout(()=>{ci(i)},a);return J.set(i,{rootPath:t,installablePath:n,archivePath:r,tenantId:e.tenantId,sessionName:e.sessionName,expiresAt:o,timer:s}),{materializationId:i,installablePath:n,...r?{archivePath:r}:{},expiresAt:new Date(o).toISOString()}}catch(e){throw await O.rm(t,{recursive:!0,force:!0}),e}}async function oi(e,t){await Y(e,Te(J,e,t,ii))}async function si(e){let t=Array.from(J.entries()).filter(([,t])=>t.sessionName===e);await Promise.all(t.map(async([e,t])=>{await Y(e,t)}))}async function ci(e){let t=J.get(e);if(t)try{await Y(e,t)}catch{}}async function Y(e,t){clearTimeout(t.timer),J.delete(e),await O.rm(t.rootPath,{recursive:!0,force:!0})}async function li(e,t){let n=await O.stat(e);await O.mkdir(t,{recursive:!0});let r=D.join(t,D.basename(e));return n.isDirectory()?(await O.cp(e,r,{recursive:!0}),r):(await O.copyFile(e,r),r)}function ui(e){return e.device.platform===`web`}function di(e){return e.toArray().filter(e=>e.device.platform===`web`).map(e=>e.name)}async function fi(e){let{session:t,sessionName:n,sessionStore:r}=e;t.appLog&&await Re({session:t,sessionName:n,sessionStore:r,resourcePath:Ie.resolvePath(r.resolveSessionDir(n))})}async function pi(e){let t=e.sessionStore.get(e.sessionName)??e.session;t.perfCapture&&await Le({...e,session:t,intent:`disposal`})}async function mi(e,t){await t.stopSnapshotHelper(e.device)}async function hi(e){let{session:t,sessionName:n,sessionStore:r,platformCleanup:i}=e;await i.closeManagedBrowser({device:t.device,sessionName:n,stateDir:r.resolveDaemonStateDir(),openSessionNames:()=>di(r)})}async function gi(e){let t=[];for(let{step:n,run:r}of e)try{await r()}catch(e){t.push({step:n,error:e})}return t}function _i(t){if(t.failures.length===0)return;let n=t.failures.map(({step:e})=>e),r=t.failures.map(({step:e,error:t})=>`${e}: ${t instanceof Error?t.message:String(t)}`);return _({level:`error`,phase:t.phase,data:{session:t.sessionName,failedSteps:n,errors:r}}),new e(`COMMAND_FAILED`,`Session cleanup left ${t.failures.length} resource(s) unreleased: ${r.join(`; `)}`,{reason:`session_cleanup_incomplete`,session:t.sessionName,failedSteps:n,hint:`Some session resources failed to release; inspect the session log for per-resource diagnostics. The session was still deleted, so retrying is safe.`})}async function vi(t){let{session:n,sessionName:r,sessionStore:i}=t;if(!t.platformCleanup)throw new e(`INTERNAL_ERROR`,`Platform resource cleanup was not supplied by root runtime composition`);let a=t.platformCleanup,o=[{step:`recording`,run:()=>yi({session:n,sessionName:r,sessionStore:i})},...t.appLog===`run`?[{step:`app_log`,run:()=>fi({session:n,sessionName:r,sessionStore:i})}]:[],{step:`audio_probe`,run:()=>bi({session:n,sessionName:r,sessionStore:i})},{step:`perf_capture`,run:()=>pi({session:n,sessionName:r,sessionStore:i})},{step:`platform_snapshot_helper`,run:()=>mi(n,a)},{step:`web_browser`,run:()=>hi({session:n,sessionName:r,sessionStore:i,platformCleanup:a})}];o.push({step:`materialized_paths`,run:()=>si(r)});let s=_i({sessionName:r,phase:`session_teardown_cleanup_failed`,failures:await gi(o)});if(s)throw s}async function yi(e){let t=e.sessionStore.get(e.sessionName)??e.session;t.screenRecording&&await $e({intent:`disposal`,session:t,sessionName:e.sessionName,sessionStore:e.sessionStore})}async function bi(e){let t=e.sessionStore.get(e.sessionName)??e.session;t.audioProbe&&await Fe({intent:`disposal`,session:t,sessionName:e.sessionName,sessionStore:e.sessionStore})}function xi(e){return s(e)&&e.kind===`simulator`}function Si(e){return e.platform===`android`&&e.kind===`emulator`}const Ci=[`platform`,`metroHost`,`metroPort`,`bundleUrl`,`launchUrl`];function X(e){return e?[e.metroHost,e.metroPort,e.bundleUrl,e.launchUrl].filter(e=>e!==void 0&&e!==``).length:0}function Z(e){if(!e)return{};let t={};return e.metroHost!==void 0&&(t.metroHost=e.metroHost),e.metroPort!==void 0&&(t.metroPort=String(e.metroPort)),e.bundleUrl!==void 0&&(t.bundleUrl=e.bundleUrl),e.launchUrl!==void 0&&(t.launchUrl=e.launchUrl),t}function Q(e){return De(Z(e))}function $(t,n){if(t!==void 0){if(typeof t!=`string`)throw new e(`INVALID_ARGS`,`Invalid open runtime ${n}: expected string.`);return v(t)}}function wi(t){if(t!==void 0){if(!Number.isInteger(t)||t<1||t>65535)throw new e(`INVALID_ARGS`,`Invalid runtime metroPort: ${String(t)}. Use an integer between 1 and 65535.`);return t}}function Ti(t){if(t!==void 0){if(typeof t!=`number`)throw new e(`INVALID_ARGS`,`Invalid open runtime metroPort: expected integer.`);return wi(t)}}function Ei(t,r,i){if(t===void 0)return i;if(!n(t))throw new e(`INVALID_ARGS`,`Invalid open runtime platform: ${String(t)}. Use "ios", "android", or "harmonyos".`);if(i&&t!==i)throw new e(`INVALID_ARGS`,`open runtime targets ${t}, but session "${r}" is bound to ${i}.`);return t}function Di(e){if(n(e))return e}function Oi(e,t){return{platform:t,metroHost:v(e?.metroHost),metroPort:wi(e?.metroPort),bundleUrl:v(e?.bundleUrl),launchUrl:v(e?.launchUrl)}}function ki(e,t){return{platform:t.platform??e?.platform,metroHost:t.metroHost??e?.metroHost,metroPort:t.metroPort??e?.metroPort,bundleUrl:t.bundleUrl??e?.bundleUrl,launchUrl:t.launchUrl??e?.launchUrl}}function Ai(e){if(Si(e))return`10.0.2.2`;if(xi(e))return`127.0.0.1`}function ji(e,t){if(!e||v(e.metroHost)||v(e.bundleUrl)||e.metroPort===void 0)return e;let n=Ai(t);return n?{...e,metroHost:n}:e}function Mi(t){let{runtime:n,sessionName:r,platform:i}=t;if(n===void 0)return;if(!n||typeof n!=`object`||Array.isArray(n))throw new e(`INVALID_ARGS`,`open runtime must be an object.`);let a=n,o=Object.keys(a).find(e=>!Ci.includes(e));if(o)throw new e(`INVALID_ARGS`,`Invalid open runtime field: ${o}. Supported fields are ${Ci.join(`, `)}.`);return{platform:Ei(a.platform,r,i),metroHost:$(a.metroHost,`metroHost`),metroPort:Ti(a.metroPort),bundleUrl:$(a.bundleUrl,`bundleUrl`),launchUrl:$(a.launchUrl,`launchUrl`)}}function Ni(e,t,n){if(n){if(X(n)===0){e.clearRuntimeHints(t);return}return e.setRuntimeHints(t,n),n}}function Pi(t,n,r,i){let a=t.getRuntimeHints(n);if(!a)return;let o=r?l(r):void 0,s=Di(o)??i;if(a.platform&&r&&!s)throw new e(`INVALID_ARGS`,`Session runtime hints are only supported on iOS, Android, and HarmonyOS sessions, but session "${n}" is bound to ${o}.`);if(a.platform&&s&&a.platform!==s)throw new e(`INVALID_ARGS`,`Session runtime hints target ${a.platform}, but session "${n}" is bound to ${o}. Clear the runtime hints or use a different session.`);return s&&a.platform!==s?{...a,platform:s}:a}function Fi(e){let{req:t,sessionStore:n,sessionName:r,device:i}=e,a=i?Di(l(i)):e.platform,o=n.getRuntimeHints(r),s=Mi({runtime:t.runtime,sessionName:r,platform:a});if(t.runtime===void 0){let e=Pi(n,r,i,a);return{runtime:i?ji(e,i):e,previousRuntime:o,replacedStoredRuntime:!1}}let c=s&&X(s)>0?s:void 0;return{runtime:i?ji(c,i):c,previousRuntime:o,replacedStoredRuntime:!0}}function Ii(e){return Fi(e).runtime}function Li(e){try{return{ok:!0,data:Fi(e)}}catch(e){let t=r(e);return Ee(t.code,t.message,t.details)}}async function Ri(e){let{previousRuntime:t,clearRuntimeHints:n}=e;if(!zi(e))return;let r=e.session;r?.appBundleId&&await n({appId:r.appBundleId,values:Z(t)})}function zi(e){return e.replacedStoredRuntime&&!!e.session?.appBundleId&&Q(e.previousRuntime)&&!Q(e.runtime)}function Bi(e){let{device:t,owner:n,stateDir:r,intent:i}=e,a=i.kind===`exact-owner`&&ne(i.owner,n)?te(i.fence):null;if(!a)return{status:`binding-invalid`};let o=C(w(t)),s=Me(ke(o));if(!s)return{status:`missing`};let c=s.allocatorClaim;return!c||!Hi(c.stateDir,r)||!ne(je(c),n)?{status:`conflict`,conflict:s}:c.allocator.identityIncarnationId===a.identityIncarnationId?{status:`covered`}:{status:`incarnation-stale`,heldIncarnationId:c.allocator.identityIncarnationId}}function Vi(e){let t=C(w(e));return Oe(ke(t))}function Hi(e,t){return D.resolve(e)===D.resolve(t)}const Ui=new Set([`DEVICE_CLAIM_LIVE_OWNER`,`DEVICE_CLAIM_RECOVERY_PENDING`,`DEVICE_CLAIM_OWNER_UNCERTAIN`]);function Wi(e){return Ui.has(e)}function Gi(e,t,n=`status`){let r=t.claim??t.allocatorClaim,i=l(r?{platform:r.device.family,appleOs:r.device.appleOs}:e),a=o(e.platform)?`--udid`:`--serial`;return[`agent-device device ${n}`,`--platform ${le(i)}`,`${a} ${le(e.id)}`,...n===`release`||Ae(t.classification)?[`--stale`]:[]].join(` `)}function Ki(t,n){if(n.classification===`allocator-held`)return Ji(t,n);let r=n.claim,i=Gi(t,n,Ne(n.classification)?`release`:`status`),a=l(r?{platform:r.device.family,appleOs:r.device.appleOs}:t);return new e(`DEVICE_IN_USE`,r?`${a} device ${t.id} is owned by session "${r.session}" in workspace "${r.workspace}".`:`${t.name} has an ownership claim that could not be verified.`,{reason:ta(n.classification),classification:n.classification,deviceKey:n.deviceKey,...r?{owner:{session:r.session,workspace:r.workspace,stateDir:r.stateDir}}:{},recovery:{command:i},hint:Ne(n.classification)?`The recorded owner can no longer release this device; settle its resources and release the claim with: ${i}`:`Inspect the owner with: ${i}`,retriable:!1})}function qi(e,t){return ea(Ki(e,t))}function Ji(t,n){let r=n.allocatorClaim,i=l({platform:r.device.family,appleOs:r.device.appleOs}),a=Gi(t,n);return new e(`DEVICE_IN_USE`,`${i} device ${t.id} is held by managed-device allocator "${r.allocator.instanceId}" for installation "${r.stateDir}".`,{reason:`DEVICE_CLAIM_ALLOCATOR_HELD`,classification:n.classification,deviceKey:n.deviceKey,owner:{kind:`allocator`,stateDir:r.stateDir,allocator:r.allocator},recovery:{command:a},hint:`This device belongs to a managed pool and is released only after its allocator proves the identity removed; inspect with: ${a}`,retriable:!1})}function Yi(t,n){return new e(`COMMAND_FAILED`,`${l(t)} device ${t.id} is a managed identity with no allocator-held execution claim for this installation.`,{reason:`allocator-claim-missing`,owner:re(n),deviceKey:C(w(t)),retriable:!1,hint:`A managed identity becomes executable only after its allocator activates it and this installation holds its allocator-held claim.`})}function Xi(t,n,r){return new e(`COMMAND_FAILED`,`${l(t)} device ${t.id} is held for identity incarnation "${r}", which is not the incarnation this binding fences.`,{reason:`allocator-claim-incarnation-stale`,owner:re(n),deviceKey:C(w(t)),heldIncarnationId:r,retriable:!1,hint:`The managed identity was re-provisioned; obtain a new grant from the allocator.`})}function Zi(t,n){return new e(`COMMAND_FAILED`,`A managed local owner executes only under an exact-owner binding that carries a managed binding fence.`,{reason:`runtime-contract-invalid`,owner:re(n),deviceKey:C(w(t)),retriable:!1})}function Qi(e,t,n){switch(n.status){case`binding-invalid`:return{admitted:!1,error:Zi(e,t)};case`missing`:return{admitted:!1,error:Yi(e,t)};case`covered`:return{admitted:!0};case`incarnation-stale`:return{admitted:!1,error:Xi(e,t,n.heldIncarnationId)};case`conflict`:return{admitted:!1,error:Ki(e,n.conflict)}}}function $i(e,t,n){let r=Qi(e,t,n);return r.admitted?void 0:ea(r.error)}function ea(e){let{hint:t,retriable:n,...r}=e.details??{};return Ee(e.code,e.message,r,{hint:t,retriable:n})}function ta(e){switch(e){case`live`:return`DEVICE_CLAIM_LIVE_OWNER`;case`owner-process-dead`:case`owner-daemon-superseded`:return`DEVICE_CLAIM_RECOVERY_PENDING`;case`owner-process-reused`:case`owner-state-dir-gone`:case`unknown`:case`inconsistent`:case`allocator-inconsistent`:return`DEVICE_CLAIM_OWNER_UNCERTAIN`}}function na(e){switch(e.kind){case`local-family`:return`ordinary`;case`managed-local`:return`allocator-held`;case`provider-runtime`:return`none`}}export{rr as $,si as A,Ar as B,fi as C,ui as D,vi as E,Xr as F,Nr as G,Or as H,Zr as I,Er as J,Pr as K,Wr as L,$r as M,ti as N,di as O,Qr as P,ir as Q,Ur as R,_i as S,mi as T,jr as U,kr as V,Mr as W,ur as X,gr as Y,sr as Z,zi as _,Ki as a,Tt as at,bi as b,Bi as c,gt as ct,Q as d,bt as dt,F as et,Ri as f,yt as ft,Ni as g,Z as h,at as ht,Qi as i,Ct as it,ai as j,oi as k,Oi as l,_t as lt,Ii as m,ct as mt,$i as n,Ot as nt,Wi as o,Et as ot,ki as p,lt as pt,W as q,qi as r,wt as rt,Vi as s,vt as st,na as t,j as tt,X as u,ht as ut,Di as v,pi as w,yi as x,Li as y,Hr as z};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { O as Rect } from "./sdk-contracts.js";
|
|
2
|
-
import {
|
|
2
|
+
import { A as PointerTrajectory, M as SinglePointerGesturePlan, j as PointerTrajectorySample, k as MultiTouchGesturePlan } from "./sdk-selectors.js";
|
|
3
3
|
import { Readable, Stream, Writable } from "node:stream";
|
|
4
4
|
//#region packages/platform-android/src/helper-artifacts.d.ts
|
|
5
5
|
type AndroidImeHelperManifest = {
|
|
@@ -31,7 +31,6 @@ type AndroidSnapshotHelperManifest = {
|
|
|
31
31
|
targetSdk?: number;
|
|
32
32
|
outputFormat: 'uiautomator-xml';
|
|
33
33
|
statusProtocol: 'android-snapshot-helper-v1';
|
|
34
|
-
installArgs: string[];
|
|
35
34
|
};
|
|
36
35
|
type AndroidSnapshotHelperArtifact = {
|
|
37
36
|
apkPath: string;
|
|
@@ -81,7 +80,13 @@ type AndroidAdbExecutorResult = {
|
|
|
81
80
|
};
|
|
82
81
|
/** Structural mirror of node's StdioOptions; R13 bars the child_process import that names it. */
|
|
83
82
|
type AndroidAdbStdioOption = 'overlapped' | 'pipe' | 'ignore' | 'inherit';
|
|
84
|
-
|
|
83
|
+
/**
|
|
84
|
+
* A spawned adb process is long-lived — the snapshot helper session rides it for
|
|
85
|
+
* the whole session — so `timeoutMs` is not part of its options: background
|
|
86
|
+
* spawns arm no deadline, and a field that looked like one invited callers to
|
|
87
|
+
* kill their own helper.
|
|
88
|
+
*/
|
|
89
|
+
type AndroidAdbSpawnOptions = Omit<AndroidAdbExecutorOptions, 'timeoutMs'> & {
|
|
85
90
|
cwd?: string;
|
|
86
91
|
detached?: boolean;
|
|
87
92
|
/** Max stdout/stderr bytes for synchronous runs (default Node ~1MB). */
|
|
@@ -131,14 +136,11 @@ type AndroidPortReverseProvider = {
|
|
|
131
136
|
type AndroidAdbTransferOptions = AndroidAdbExecutorOptions;
|
|
132
137
|
type AndroidAdbInstallOptions = AndroidAdbTransferOptions & {
|
|
133
138
|
replace?: boolean;
|
|
134
|
-
allowTestPackages?: boolean;
|
|
135
|
-
allowDowngrade?: boolean;
|
|
136
|
-
grantPermissions?: boolean;
|
|
137
139
|
};
|
|
138
140
|
type AndroidAdbPuller = (remotePath: string, localPath: string, options?: AndroidAdbTransferOptions) => Promise<AndroidAdbExecutorResult>;
|
|
139
141
|
/**
|
|
140
|
-
* Installs an APK path. Implementations are responsible for honoring
|
|
141
|
-
*
|
|
142
|
+
* Installs an APK path. Implementations are responsible for honoring the
|
|
143
|
+
* semantic `replace` option (`adb install -r`).
|
|
142
144
|
*/
|
|
143
145
|
type AndroidAdbInstaller = (apkPath: string, options?: AndroidAdbInstallOptions) => Promise<AndroidAdbExecutorResult>;
|
|
144
146
|
type AndroidBundleInstaller = (bundlePath: string, options: Readonly<{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as e}from"./rolldown-runtime.js";import{
|
|
1
|
+
import{r as e}from"./rolldown-runtime.js";import{C as t,j as n}from"./sdk-contracts.js";import{AsyncLocalStorage as r}from"node:async_hooks";var i=e({listDeviceInventory:()=>l,listLocalDeviceInventory:()=>d,readDeviceInventory:()=>u,readInstalledAppProbe:()=>c,shouldPropagateDeviceInventoryProbeError:()=>m,withDeviceInventoryContext:()=>s});const a=`device_inventory_context_unavailable`,o=new r;async function s(e,t){return await o.run(e,t)}function c(){return o.getStore()?.findInstalledApp}async function l(e){return await f(`providerFirst`,e)}async function u(e){let t=p(),n=await t.providerFirst.discoverWithSource(e,t.requestScope);return{devices:n.devices.map(e=>({...e})),source:n.source}}async function d(e){return await f(`localOnly`,e)}async function f(e,t){let n=p();return(await n[e].discover(t,n.requestScope)).map(e=>({...e}))}function p(){let e=o.getStore();if(!e)throw new t(`COMMAND_FAILED`,`Device inventory gateway is unavailable outside request execution`,{reason:a});return e}function m(e){return n(e)||e instanceof t&&e.code===`COMMAND_FAILED`&&e.details?.reason===a?!0:e instanceof Error&&e.name===`AbortError`}export{m as a,u as i,l as n,s as o,d as r,i as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{C as e}from"./sdk-contracts.js";import{r as t}from"./sdk-batch-runner.js";import{n}from"./app-inventory.js";import"./device.js";import{t as r}from"./request-cancellation.js";import{n as i,t as a}from"./ios-client.js";import{n as o,r as s}from"./snapshot.js";import c from"node:path";import l from"node:fs";import u from"node:os";import{setTimeout as d}from"node:timers/promises";function f(e){return e?.trim()||void 0}async function p(e,t){let n=await i({apiUrl:e.apiUrl,adbUrl:e.adbUrl,token:e.token,logLevel:`warn`}),r={platform:`android`,lease:e.lease,instanceId:e.instanceId,device:e.device,client:n,dependencies:t},a={exec:async(e,t)=>await y(r,e,t),text:async e=>{await n.setText(e.target,e.text)}};return a.reverse=await t.android.createPortReverse(a.exec),Object.assign(r,{adbProvider:a})}function m(e){return e.dependencies.android.createInteractor(e.device,e.adbProvider)}async function h(e,t,n,i,a,o){a?.throwIfAborted();let s=f(i?.packageNameHint);i?.relaunch&&s&&await y(t,[`shell`,`am`,`force-stop`,s],{allowFailure:!0,signal:a});let c=await r(o,e.assets.getOrUpload({path:n,name:T(s,n)},{signal:a}),a);await r(o,t.client.sendAsset(c.signedDownloadUrl),a),a?.throwIfAborted();let l=s?await t.dependencies.android.inferAppName(s):void 0;return{...s?{packageName:s,launchTarget:s}:{},...l?{appName:l}:{}}}async function g(e,t){await e.adbProvider.reverse?.ensure({local:w(t.devicePort),remote:w(t.hostPort),ownerId:t.name})}async function _(e){await e.adbTunnelPromise?.catch(()=>{});let t=e.adbSerial;t&&(await v(e),await e.dependencies.host.runAdb([`disconnect`,t],{allowFailure:!0,timeoutMs:1e4}).catch(()=>{})),e.adbTunnel?.close(),e.adbTunnel=void 0,e.adbSerial=void 0,e.adbTunnelPromise=void 0}async function v(e){let t=e.adbProvider.reverse;if(!t?.list)return;let n=await t.list().catch(()=>[]),r=new Set,i=[];for(let e of n)e.ownerId?r.add(e.ownerId):i.push(e.local);await Promise.allSettled([...[...r].map(async e=>await t.removeAllOwned(e)),...i.map(async e=>await t.remove(e))])}async function y(e,t,n){let{adbArgs:r,result:i}=await b(e,t,n);return await x(r,i,n?.allowFailure,e.dependencies)}async function b(e,t,n){let r=[`-s`,await S(e),...t];return{adbArgs:r,result:await e.dependencies.host.runAdb(r,{allowFailure:n?.allowFailure,binaryStdout:n?.binaryStdout,stdin:n?.stdin,timeoutMs:n?.timeoutMs??3e4,signal:n?.signal})}}async function x(e,t,n,r){if(t.exitCode!==0&&n!==!0)throw await r.android.adbError(`Limrun Android ADB command failed`,t,{command:[`adb`,...e].join(` `)});return t}async function S(e){if(e.adbSerial)return e.adbSerial;let t=e.adbTunnelPromise??C(e);e.adbTunnelPromise=t;try{return await t}catch(n){throw e.adbTunnelPromise===t&&(e.adbTunnelPromise=void 0),n}}async function C(e){let t=await e.client.startAdbTunnel(),n=`${t.address.address}:${t.address.port}`;return e.adbTunnel=t,e.adbSerial=n,n}function w(t){if(!Number.isInteger(t)||t<1||t>65535)throw new e(`INVALID_ARGS`,`Invalid Android tcp reverse port: ${t}`);return`tcp:${t}`}function T(e,t){let n=c.extname(t)||`.apk`;return`${e?.replaceAll(/[^a-zA-Z0-9_.-]+/g,`-`)||`android-app`}${n}`}async function E(e,t){let n=await a({apiUrl:e.apiUrl,token:e.token,logLevel:`warn`});return{platform:`ios`,lease:e.lease,instanceId:e.instanceId,device:e.device,client:n,dependencies:t}}async function D(e,t,n,i,a,o){a?.throwIfAborted();let s=await j(n,t.dependencies);try{a?.throwIfAborted();let n=await r(o,e.assets.getOrUpload({path:s.uploadPath,name:s.assetName},{signal:a}),a),c=(await O(t,n.signedDownloadUrl,{md5:n.md5,relaunch:i?.relaunch,appIdentifierHint:i?.appIdentifierHint},a,o)).appId;return{...c?{bundleId:c,launchTarget:c}:{},...s.appName?{appName:s.appName}:{}}}finally{await s.cleanup()}}async function O(t,n,i,a,o){a?.throwIfAborted();let s=await r(o,t.client.listApps(),a).catch(e=>{if(a?.aborted)throw e}),c=f((await r(o,t.client.installApp(n,{md5:i?.md5,launchMode:i?.relaunch?`RelaunchIfRunning`:`ForegroundIfRunning`}),a)).bundleId),l=f(i?.appIdentifierHint),u=[];for(let e of N){e>0&&await d(e,void 0,{signal:a}),u=await r(o,t.client.listApps(),a);let n=P({resultBundleId:c,requestedBundleId:l,beforeInstallApps:s,afterInstallApps:u});if(n)return{appId:n}}throw new e(`COMMAND_FAILED`,`Limrun iOS app installation could not be verified.`,{resultBundleId:c,requestedBundleId:l,installedUserApps:u.filter(I).map(e=>e.bundleId).sort()})}function k(e){return new A(e)}var A=class{session;constructor(e){this.session=e}async open(e,n){if(n?.url){await this.session.client.launchApp(await this.session.dependencies.ios.resolveAppAlias(e)),await this.session.client.openUrl(n.url);return}if(t(e)){await this.session.client.openUrl(e);return}await this.session.client.launchApp(await this.session.dependencies.ios.resolveAppAlias(e))}async openDevice(){}async close(e){e&&await this.session.client.terminateApp(await this.session.dependencies.ios.resolveAppAlias(e)).catch(()=>{})}async tap(e,t){await this.session.client.tap(e,t)}async tapElementSelector(e){await this.session.client.tapElement(o(e))}async doubleTap(e,t){await this.tap(e,t),await this.tap(e,t)}async longPress(){throw R(`longpress`,`Limrun iOS direct sessions do not expose long press yet.`)}async focus(e,t){await this.tap(e,t)}async type(e,t){if(t&&t>0){for(let n of Array.from(e))await this.session.client.typeText(n),await d(t);return}await this.session.client.typeText(e)}async fill(e,t,n){await this.tap(e,t),await this.session.client.typeText(n)}async scroll(e,t){await this.session.client.scroll(e,t?.pixels??300)}async screenshot(e){let t=await this.session.client.screenshot();await s(e,t.base64)}async snapshot(){let{captureLimrunIosSnapshot:e}=await import(`./ios-snapshot-adapter.js`);return await e(this.session)}async back(){await this.session.client.pressKey(`escape`)}async home(){throw R(`home`,`Limrun iOS direct sessions do not expose home yet.`)}async setOrientation(e){if(e===`portrait-upside-down`)throw R(`orientation`,`Limrun iOS direct sessions support portrait and landscape orientation, not portrait upside-down.`);await this.session.client.setOrientation(e===`portrait`?`Portrait`:`Landscape`)}async performGesture(){throw R(`gesture`,`Limrun iOS direct sessions do not expose portable gesture execution yet.`)}async appSwitcher(){throw R(`app-switcher`,`Limrun iOS direct sessions do not expose app switcher yet.`)}async tvRemote(){throw R(`tv-remote`,`Limrun iOS direct sessions do not expose tv remote control.`)}async readAlert(){throw R(`alert`,L)}async awaitAlert(){throw R(`alert`,L)}async acceptAlert(){throw R(`alert`,L)}async dismissAlert(){throw R(`alert`,L)}async readClipboard(){throw R(`clipboard`,`Limrun iOS direct sessions do not expose clipboard read yet.`)}async writeClipboard(){throw R(`clipboard`,`Limrun iOS direct sessions do not expose clipboard write yet.`)}async setSetting(){throw R(`settings`,`Limrun iOS direct sessions do not expose settings changes yet.`)}};async function j(e,t){if(!(await l.promises.stat(e)).isDirectory())return{uploadPath:e,assetName:c.basename(e),appName:M(e),cleanup:async()=>{}};let n=await l.promises.mkdtemp(c.join(u.tmpdir(),`agent-device-limrun-ios-app-`)),r=c.join(n,`${c.basename(e)}.zip`);try{await t.host.archiveDirectory({sourceDirectory:c.dirname(e),entryName:c.basename(e),archivePath:r})}catch(e){throw await l.promises.rm(n,{recursive:!0,force:!0}),e}return{uploadPath:r,assetName:c.basename(r),appName:await t.ios.readBundleAppName(e)??M(e),cleanup:async()=>{await l.promises.rm(n,{recursive:!0,force:!0})}}}function M(e){return c.basename(e).replace(/\.(?:app|ipa|apk|aab|zip)$/i,``)||void 0}const N=[0,250];function P(e){let t=new Set(e.afterInstallApps.map(e=>e.bundleId));return(e.resultBundleId&&t.has(e.resultBundleId)?e.resultBundleId:void 0)??(e.requestedBundleId&&t.has(e.requestedBundleId)?e.requestedBundleId:void 0)??F(e.beforeInstallApps,e.afterInstallApps)}function F(e,t){if(!e)return;let n=new Set(e.map(e=>e.bundleId)),r=t.filter(e=>I(e)&&!n.has(e.bundleId));return r.length===1?r[0]?.bundleId:void 0}function I(e){return!e.bundleId.startsWith(`com.apple.`)&&!e.installType.toLowerCase().includes(`system`)}const L=`Limrun iOS direct sessions do not expose alert inspection yet.`;function R(t,n){throw new e(`UNSUPPORTED_OPERATION`,n,{command:t})}function z(e){return e.platform===`android`?B(e):V(e)}function B(e){let t=e.adbProvider.exec;return{platform:`android`,device:e.device,interactor:m(e),adb:e.adbProvider,listApps:async r=>await e.dependencies.android.listApps(t,n(r)),getForegroundApp:async n=>await e.dependencies.android.getForegroundApp(e.device,t,n),pressKey:async(t,n)=>{await e.client.pressKey(t,n)},getKeyboardState:async()=>await e.dependencies.android.getKeyboardState(t),dismissKeyboard:async()=>await e.dependencies.android.dismissKeyboard(t),readLogs:async n=>await e.dependencies.android.readLogs(t,n),...H(e.client),installRemoteApp:async t=>{await e.client.sendAsset(t)}}}function V(e){return{platform:`ios`,device:e.device,interactor:k(e),viewport:{width:e.client.deviceInfo.screenWidth,height:e.client.deviceInfo.screenHeight},listApps:async t=>(await e.client.listApps()).filter(e=>n(t)===`all`||I(e)).map(e=>({id:e.bundleId,name:e.name,installType:e.installType})).sort((e,t)=>e.id.localeCompare(t.id)),pressKey:async(t,n)=>{await e.client.pressKey(t,n)},readLogs:async(t,n)=>await e.client.appLogTail(t,n),...H(e.client),installRemoteApp:async(t,n)=>await O(e,t,n),runSimctl:t=>e.client.simctl(t)}}function H(e){return{startRecording:async t=>{await e.startRecording(t)},stopRecording:async({outPath:t})=>await e.stopRecording({localPath:t})}}export{_ as a,p as c,D as i,h as l,k as n,g as o,E as r,m as s,z as t};
|
|
1
|
+
import{C as e}from"./sdk-contracts.js";import{r as t}from"./sdk-batch-runner.js";import{n}from"./app-inventory.js";import"./device.js";import{t as r}from"./request-cancellation.js";import{n as i,t as a}from"./ios-client.js";import{a as o,i as s}from"./snapshot.js";import c from"node:path";import l from"node:fs";import u from"node:os";import{setTimeout as d}from"node:timers/promises";function f(e){return e?.trim()||void 0}async function p(e,t){let n=await i({apiUrl:e.apiUrl,adbUrl:e.adbUrl,token:e.token,logLevel:`warn`}),r={platform:`android`,lease:e.lease,instanceId:e.instanceId,device:e.device,client:n,dependencies:t},a={exec:async(e,t)=>await y(r,e,t),text:async e=>{await n.setText(e.target,e.text)}};return a.reverse=await t.android.createPortReverse(a.exec),Object.assign(r,{adbProvider:a})}function m(e){return e.dependencies.android.createInteractor(e.device,e.adbProvider)}async function h(e,t,n,i,a,o){a?.throwIfAborted();let s=f(i?.packageNameHint);i?.relaunch&&s&&await y(t,[`shell`,`am`,`force-stop`,s],{allowFailure:!0,signal:a});let c=await r(o,e.assets.getOrUpload({path:n,name:T(s,n)},{signal:a}),a);await r(o,t.client.sendAsset(c.signedDownloadUrl),a),a?.throwIfAborted();let l=s?await t.dependencies.android.inferAppName(s):void 0;return{...s?{packageName:s,launchTarget:s}:{},...l?{appName:l}:{}}}async function g(e,t){await e.adbProvider.reverse?.ensure({local:w(t.devicePort),remote:w(t.hostPort),ownerId:t.name})}async function _(e){await e.adbTunnelPromise?.catch(()=>{});let t=e.adbSerial;t&&(await v(e),await e.dependencies.host.runAdb([`disconnect`,t],{allowFailure:!0,timeoutMs:1e4}).catch(()=>{})),e.adbTunnel?.close(),e.adbTunnel=void 0,e.adbSerial=void 0,e.adbTunnelPromise=void 0}async function v(e){let t=e.adbProvider.reverse;if(!t?.list)return;let n=await t.list().catch(()=>[]),r=new Set,i=[];for(let e of n)e.ownerId?r.add(e.ownerId):i.push(e.local);await Promise.allSettled([...[...r].map(async e=>await t.removeAllOwned(e)),...i.map(async e=>await t.remove(e))])}async function y(e,t,n){let{adbArgs:r,result:i}=await b(e,t,n);return await x(r,i,n?.allowFailure,e.dependencies)}async function b(e,t,n){let r=[`-s`,await S(e),...t];return{adbArgs:r,result:await e.dependencies.host.runAdb(r,{allowFailure:n?.allowFailure,binaryStdout:n?.binaryStdout,stdin:n?.stdin,timeoutMs:n?.timeoutMs??3e4,signal:n?.signal})}}async function x(e,t,n,r){if(t.exitCode!==0&&n!==!0)throw await r.android.adbError(`Limrun Android ADB command failed`,t,{command:[`adb`,...e].join(` `)});return t}async function S(e){if(e.adbSerial)return e.adbSerial;let t=e.adbTunnelPromise??C(e);e.adbTunnelPromise=t;try{return await t}catch(n){throw e.adbTunnelPromise===t&&(e.adbTunnelPromise=void 0),n}}async function C(e){let t=await e.client.startAdbTunnel(),n=`${t.address.address}:${t.address.port}`;return e.adbTunnel=t,e.adbSerial=n,n}function w(t){if(!Number.isInteger(t)||t<1||t>65535)throw new e(`INVALID_ARGS`,`Invalid Android tcp reverse port: ${t}`);return`tcp:${t}`}function T(e,t){let n=c.extname(t)||`.apk`;return`${e?.replaceAll(/[^a-zA-Z0-9_.-]+/g,`-`)||`android-app`}${n}`}async function E(e,t){let n=await a({apiUrl:e.apiUrl,token:e.token,logLevel:`warn`});return{platform:`ios`,lease:e.lease,instanceId:e.instanceId,device:e.device,client:n,dependencies:t}}async function D(e,t,n,i,a,o){a?.throwIfAborted();let s=await j(n,t.dependencies);try{a?.throwIfAborted();let n=await r(o,e.assets.getOrUpload({path:s.uploadPath,name:s.assetName},{signal:a}),a),c=(await O(t,n.signedDownloadUrl,{md5:n.md5,relaunch:i?.relaunch,appIdentifierHint:i?.appIdentifierHint},a,o)).appId;return{...c?{bundleId:c,launchTarget:c}:{},...s.appName?{appName:s.appName}:{}}}finally{await s.cleanup()}}async function O(t,n,i,a,o){a?.throwIfAborted();let s=await r(o,t.client.listApps(),a).catch(e=>{if(a?.aborted)throw e}),c=f((await r(o,t.client.installApp(n,{md5:i?.md5,launchMode:i?.relaunch?`RelaunchIfRunning`:`ForegroundIfRunning`}),a)).bundleId),l=f(i?.appIdentifierHint),u=[];for(let e of N){e>0&&await d(e,void 0,{signal:a}),u=await r(o,t.client.listApps(),a);let n=P({resultBundleId:c,requestedBundleId:l,beforeInstallApps:s,afterInstallApps:u});if(n)return{appId:n}}throw new e(`COMMAND_FAILED`,`Limrun iOS app installation could not be verified.`,{resultBundleId:c,requestedBundleId:l,installedUserApps:u.filter(I).map(e=>e.bundleId).sort()})}function k(e){return new A(e)}var A=class{session;constructor(e){this.session=e}async open(e,n){if(n?.url){await this.session.client.launchApp(await this.session.dependencies.ios.resolveAppAlias(e)),await this.session.client.openUrl(n.url);return}if(t(e)){await this.session.client.openUrl(e);return}await this.session.client.launchApp(await this.session.dependencies.ios.resolveAppAlias(e))}async openDevice(){}async close(e){e&&await this.session.client.terminateApp(await this.session.dependencies.ios.resolveAppAlias(e)).catch(()=>{})}async tap(e,t){await this.session.client.tap(e,t)}async tapElementSelector(e){await this.session.client.tapElement(s(e))}async doubleTap(e,t){await this.tap(e,t),await this.tap(e,t)}async longPress(){throw R(`longpress`,`Limrun iOS direct sessions do not expose long press yet.`)}async focus(e,t){await this.tap(e,t)}async type(e,t){await this.enterText(e,t)}async fill(e,t,n,r){let{awaitLimrunTextEntryFocus:i,readLimrunUnambiguousTapTargets:a,readLimrunTextEntryFocus:o}=await import(`./text-entry-focus.js`),s=a(await this.session.client.elementTree(),e,t);await this.tap(e,t);let c=await i({targetsAtPoint:s,readFocus:async()=>o(await this.session.client.elementTree()),sleep:e=>d(e),x:e,y:t});return await this.session.client.pressKey(`a`,[`command`]),n.length===0?(await this.session.client.pressKey(`delete`),{textEntryReadiness:c}):(await this.enterText(n,r),{textEntryReadiness:c})}async enterText(e,t){if(t&&t>0){for(let n of Array.from(e))await this.session.client.typeText(n,!1,{requireFocus:!1}),await d(t);return}await this.session.client.typeText(e,!1,{requireFocus:!1})}async scroll(e,t){await this.session.client.scroll(e,t?.pixels??300)}async screenshot(e){let t=await this.session.client.screenshot();await o(e,t.base64)}async snapshot(){let{captureLimrunIosSnapshot:e}=await import(`./ios-snapshot-adapter.js`);return await e(this.session)}async back(){await this.session.client.pressKey(`escape`)}async home(){throw R(`home`,`Limrun iOS direct sessions do not expose home yet.`)}async setOrientation(e){if(e===`portrait-upside-down`)throw R(`orientation`,`Limrun iOS direct sessions support portrait and landscape orientation, not portrait upside-down.`);await this.session.client.setOrientation(e===`portrait`?`Portrait`:`Landscape`)}async performGesture(){throw R(`gesture`,`Limrun iOS direct sessions do not expose portable gesture execution yet.`)}async appSwitcher(){throw R(`app-switcher`,`Limrun iOS direct sessions do not expose app switcher yet.`)}async tvRemote(){throw R(`tv-remote`,`Limrun iOS direct sessions do not expose tv remote control.`)}async readAlert(){throw R(`alert`,L)}async awaitAlert(){throw R(`alert`,L)}async acceptAlert(){throw R(`alert`,L)}async dismissAlert(){throw R(`alert`,L)}async readClipboard(){throw R(`clipboard`,`Limrun iOS direct sessions do not expose clipboard read yet.`)}async writeClipboard(){throw R(`clipboard`,`Limrun iOS direct sessions do not expose clipboard write yet.`)}async setSetting(){throw R(`settings`,`Limrun iOS direct sessions do not expose settings changes yet.`)}};async function j(e,t){if(!(await l.promises.stat(e)).isDirectory())return{uploadPath:e,assetName:c.basename(e),appName:M(e),cleanup:async()=>{}};let n=await l.promises.mkdtemp(c.join(u.tmpdir(),`agent-device-limrun-ios-app-`)),r=c.join(n,`${c.basename(e)}.zip`);try{await t.host.archiveDirectory({sourceDirectory:c.dirname(e),entryName:c.basename(e),archivePath:r})}catch(e){throw await l.promises.rm(n,{recursive:!0,force:!0}),e}return{uploadPath:r,assetName:c.basename(r),appName:await t.ios.readBundleAppName(e)??M(e),cleanup:async()=>{await l.promises.rm(n,{recursive:!0,force:!0})}}}function M(e){return c.basename(e).replace(/\.(?:app|ipa|apk|aab|zip)$/i,``)||void 0}const N=[0,250];function P(e){let t=new Set(e.afterInstallApps.map(e=>e.bundleId));return(e.resultBundleId&&t.has(e.resultBundleId)?e.resultBundleId:void 0)??(e.requestedBundleId&&t.has(e.requestedBundleId)?e.requestedBundleId:void 0)??F(e.beforeInstallApps,e.afterInstallApps)}function F(e,t){if(!e)return;let n=new Set(e.map(e=>e.bundleId)),r=t.filter(e=>I(e)&&!n.has(e.bundleId));return r.length===1?r[0]?.bundleId:void 0}function I(e){return!e.bundleId.startsWith(`com.apple.`)&&!e.installType.toLowerCase().includes(`system`)}const L=`Limrun iOS direct sessions do not expose alert inspection yet.`;function R(t,n){throw new e(`UNSUPPORTED_OPERATION`,n,{command:t})}function z(e){return e.platform===`android`?B(e):V(e)}function B(e){let t=e.adbProvider.exec;return{platform:`android`,device:e.device,interactor:m(e),adb:e.adbProvider,listApps:async r=>await e.dependencies.android.listApps(t,n(r)),getForegroundApp:async n=>await e.dependencies.android.getForegroundApp(e.device,t,n),pressKey:async(t,n)=>{await e.client.pressKey(t,n)},getKeyboardState:async()=>await e.dependencies.android.getKeyboardState(t),dismissKeyboard:async()=>await e.dependencies.android.dismissKeyboard(t),readLogs:async n=>await e.dependencies.android.readLogs(t,n),...H(e.client),installRemoteApp:async t=>{await e.client.sendAsset(t)}}}function V(e){return{platform:`ios`,device:e.device,interactor:k(e),viewport:{width:e.client.deviceInfo.screenWidth,height:e.client.deviceInfo.screenHeight},listApps:async t=>(await e.client.listApps()).filter(e=>n(t)===`all`||I(e)).map(e=>({id:e.bundleId,name:e.name,installType:e.installType})).sort((e,t)=>e.id.localeCompare(t.id)),pressKey:async(t,n)=>{await e.client.pressKey(t,n)},readLogs:async(t,n)=>await e.client.appLogTail(t,n),...H(e.client),installRemoteApp:async(t,n)=>await O(e,t,n),runSimctl:t=>e.client.simctl(t)}}function H(e){return{startRecording:async t=>{await e.startRecording(t)},stopRecording:async({outPath:t})=>await e.stopRecording({localPath:t})}}export{_ as a,p as c,D as i,h as l,k as n,g as o,E as r,m as s,z as t};
|