agent-device 0.21.22 → 0.21.23
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.22.apk → agent-device-android-ime-helper-0.21.23.apk} +0 -0
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.23.apk.sha256 +1 -0
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.22.manifest.json → agent-device-android-ime-helper-0.21.23.manifest.json} +4 -4
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.23.apk +0 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.23.apk.sha256 +1 -0
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.21.22.manifest.json → agent-device-android-snapshot-helper-0.21.23.manifest.json} +6 -6
- package/dist/src/android-input-ownership.js +1 -1
- package/dist/src/app-log-reconnect.js +1 -1
- package/dist/src/app-log-runtime2.js +3 -3
- package/dist/src/back-mode.js +1 -1
- package/dist/src/client-metro-companion.js +1 -1
- package/dist/src/client-metro.js +1 -1
- package/dist/src/client-options.js +3 -3
- package/dist/src/cloud-artifacts.d.ts +6 -0
- package/dist/src/code-signature-cache.js +1 -1
- package/dist/src/connection-runtime.js +1 -1
- package/dist/src/daemon-registration-owner.js +1 -1
- package/dist/src/device-session.js +3 -1
- package/dist/src/dispatch-resolve.js +1 -1
- package/dist/src/doctor-facade.js +1 -1
- package/dist/src/durable-capture-resource.js +1 -1
- package/dist/src/file.js +1 -1
- package/dist/src/helper.js +2 -2
- package/dist/src/ime-rebind.js +1 -0
- package/dist/src/ime-state.js +1 -0
- package/dist/src/instance-client.js +1 -1
- package/dist/src/internal/bin.js +1 -1
- package/dist/src/internal/daemon.js +1 -1
- package/dist/src/ios-client.js +4 -4
- package/dist/src/ios-snapshot-engine.js +1 -1
- package/dist/src/log-stream.js +33 -0
- package/dist/src/mechanics.js +16 -16
- package/dist/src/node-http.js +1 -0
- package/dist/src/owner-identity.js +1 -1
- package/dist/src/perf-runtime-plan.js +1 -1
- package/dist/src/platform-runtime-app-log-process.js +1 -1
- package/dist/src/platform-runtime-operation-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 +2 -2
- package/dist/src/registry.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-start-budget.js +1 -1
- package/dist/src/runtime10.js +1 -1
- package/dist/src/screenshot-overlay-draw.js +1 -1
- package/dist/src/screenshot-runtime.js +1 -1
- package/dist/src/script.js +1 -1
- package/dist/src/sdk-batch.js +2 -2
- package/dist/src/sdk-contracts.d.ts +5 -4
- package/dist/src/store.js +1 -1
- package/package.json +11 -8
- package/server.json +2 -2
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.22.apk.sha256 +0 -1
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.22.apk +0 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.22.apk.sha256 +0 -1
- package/dist/src/session-stream.js +0 -27
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{P as e}from"./sdk-contracts.js";import{A as t,C as n,D as r,E as i,F as a,M as o,N as s,O as c,P as l,S as u,T as d,_ as f,b as p,f as m,g as h,h as g,j as _,k as v,m as ee,v as te,w as y,x as ne,y as re}from"./session-stream.js";import{i as ie,r as b}from"./ios-client.js";import"./instance-client.js";import{promises as ae}from"fs";import"net";import oe from"os";import x,{basename as se}from"path";import ce,{createHash as le}from"crypto";import"child_process";function S(e,t,n,r,i){if(r===`m`)throw TypeError(`Private method is not writable`);if(r===`a`&&!i)throw TypeError(`Private accessor was defined without a setter`);if(typeof t==`function`?e!==t||!i:!t.has(e))throw TypeError(`Cannot write private member to an object whose class did not declare it`);return r===`a`?i.call(e,n):i?i.value=n:t.set(e,n),n}function C(e,t,n,r){if(n===`a`&&!r)throw TypeError(`Private accessor was defined without a getter`);if(typeof t==`function`?e!==t||!r:!t.has(e))throw TypeError(`Cannot read private member from an object whose class did not declare it`);return n===`m`?r:n===`a`?r.call(e):r?r.value:t.get(e)}let ue=function(){let{crypto:e}=globalThis;if(e?.randomUUID)return ue=e.randomUUID.bind(e),e.randomUUID();let t=new Uint8Array(1),n=e?()=>e.getRandomValues(t)[0]:()=>Math.random()*255&255;return`10000000-1000-4000-8000-100000000000`.replace(/[018]/g,e=>(e^n()&15>>e/4).toString(16))};const de=/^[a-z][a-z0-9+.-]*:/i,fe=e=>de.test(e);let w=e=>(w=Array.isArray,w(e)),pe=w;function me(e){return typeof e==`object`?e??{}:{}}function he(e){if(!e)return!0;for(let t in e)return!1;return!0}function ge(e,t){return Object.prototype.hasOwnProperty.call(e,t)}const _e=(e,t)=>{if(typeof t!=`number`||!Number.isInteger(t))throw new v(`${e} must be an integer`);if(t<0)throw new v(`${e} must be a positive integer`);return t},ve=e=>{try{return JSON.parse(e)}catch{return}},T=`0.49.3`;function ye(){return typeof Deno<`u`&&Deno.build!=null?`deno`:typeof EdgeRuntime<`u`?`edge`:Object.prototype.toString.call(globalThis.process===void 0?0:globalThis.process)===`[object process]`?`node`:`unknown`}const be=()=>{let e=ye();if(e===`deno`)return{"X-Stainless-Lang":`js`,"X-Stainless-Package-Version":T,"X-Stainless-OS":E(Deno.build.os),"X-Stainless-Arch":Se(Deno.build.arch),"X-Stainless-Runtime":`deno`,"X-Stainless-Runtime-Version":typeof Deno.version==`string`?Deno.version:Deno.version?.deno??`unknown`};if(typeof EdgeRuntime<`u`)return{"X-Stainless-Lang":`js`,"X-Stainless-Package-Version":T,"X-Stainless-OS":`Unknown`,"X-Stainless-Arch":`other:${EdgeRuntime}`,"X-Stainless-Runtime":`edge`,"X-Stainless-Runtime-Version":globalThis.process.version};if(e===`node`)return{"X-Stainless-Lang":`js`,"X-Stainless-Package-Version":T,"X-Stainless-OS":E(globalThis.process.platform??`unknown`),"X-Stainless-Arch":Se(globalThis.process.arch??`unknown`),"X-Stainless-Runtime":`node`,"X-Stainless-Runtime-Version":globalThis.process.version??`unknown`};let t=xe();return t?{"X-Stainless-Lang":`js`,"X-Stainless-Package-Version":T,"X-Stainless-OS":`Unknown`,"X-Stainless-Arch":`unknown`,"X-Stainless-Runtime":`browser:${t.browser}`,"X-Stainless-Runtime-Version":t.version}:{"X-Stainless-Lang":`js`,"X-Stainless-Package-Version":T,"X-Stainless-OS":`Unknown`,"X-Stainless-Arch":`unknown`,"X-Stainless-Runtime":`unknown`,"X-Stainless-Runtime-Version":`unknown`}};function xe(){if(typeof navigator>`u`||!navigator)return null;for(let{key:e,pattern:t}of[{key:`edge`,pattern:/Edge(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/},{key:`ie`,pattern:/MSIE(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/},{key:`ie`,pattern:/Trident(?:.*rv\:(\d+)\.(\d+)(?:\.(\d+))?)?/},{key:`chrome`,pattern:/Chrome(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/},{key:`firefox`,pattern:/Firefox(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/},{key:`safari`,pattern:/(?:Version\W+(\d+)\.(\d+)(?:\.(\d+))?)?(?:\W+Mobile\S*)?\W+Safari/}]){let n=t.exec(navigator.userAgent);if(n)return{browser:e,version:`${n[1]||0}.${n[2]||0}.${n[3]||0}`}}return null}const Se=e=>e===`x32`?`x32`:e===`x86_64`||e===`x64`?`x64`:e===`arm`?`arm`:e===`aarch64`||e===`arm64`?`arm64`:e?`other:${e}`:`unknown`,E=e=>(e=e.toLowerCase(),e.includes(`ios`)?`iOS`:e===`android`?`Android`:e===`darwin`?`MacOS`:e===`win32`?`Windows`:e===`freebsd`?`FreeBSD`:e===`openbsd`?`OpenBSD`:e===`linux`?`Linux`:e?`Other:${e}`:`Unknown`);let Ce;const we=()=>Ce??=be();function Te(){if(typeof fetch<`u`)return p.fetch;throw Error("`fetch` is not defined as a global; Either pass `fetch` to the client, `new Limrun({ fetch })` or polyfill the global, `globalThis.fetch = fetch`")}function Ee(...e){let t=globalThis.ReadableStream;if(t===void 0)throw Error("`ReadableStream` is not defined as a global; You will need to polyfill it, `globalThis.ReadableStream = ReadableStream`");return new t(...e)}function De(e){let t=Symbol.asyncIterator in e?e[Symbol.asyncIterator]():e[Symbol.iterator]();return Ee({start(){},async pull(e){let{done:n,value:r}=await t.next();n?e.close():e.enqueue(r)},async cancel(){await t.return?.()}})}async function Oe(e){if(typeof e!=`object`||!e)return;if(e[Symbol.asyncIterator]){await e[Symbol.asyncIterator]().return?.();return}let t=e.getReader(),n=t.cancel();t.releaseLock(),await n}const ke=({headers:e,body:t})=>({bodyHeaders:{"content-type":`application/json`},body:JSON.stringify(t)});function Ae(e){return Object.entries(e).filter(([e,t])=>t!==void 0).map(([e,t])=>{if(typeof t==`string`||typeof t==`number`||typeof t==`boolean`)return`${encodeURIComponent(e)}=${encodeURIComponent(t)}`;if(t===null)return`${encodeURIComponent(e)}=`;throw new v(`Cannot stringify type ${typeof t}; Expected string, number, boolean, or null. If you need to pass nested query parameters, you can manually encode them, e.g. { query: { 'foo[key1]': value1, 'foo[key2]': value2 } }, and please open a GitHub issue requesting better support for your use case.`)}).join(`&`)}const D={off:0,error:200,warn:300,info:400,debug:500},O=(e,t,n)=>{if(e){if(ge(D,e))return e;M(n).warn(`${t} was set to ${JSON.stringify(e)}, expected one of ${JSON.stringify(Object.keys(D))}`)}};function k(){}function A(e,t,n){return!t||D[e]>D[n]?k:t[e].bind(t)}const je={error:k,warn:k,info:k,debug:k};let j=new WeakMap;function M(e){let t=e.logger,n=e.logLevel??`off`;if(!t)return je;let r=j.get(t);if(r&&r[0]===n)return r[1];let i={error:A(`error`,t,n),warn:A(`warn`,t,n),info:A(`info`,t,n),debug:A(`debug`,t,n)};return j.set(t,[n,i]),i}const N=e=>(e.options&&(e.options={...e.options},delete e.options.headers),e.headers&&=Object.fromEntries((e.headers instanceof Headers?[...e.headers]:Object.entries(e.headers)).map(([e,t])=>[e,e.toLowerCase()===`authorization`||e.toLowerCase()===`api-key`||e.toLowerCase()===`x-api-key`||e.toLowerCase()===`cookie`||e.toLowerCase()===`set-cookie`?`***`:t])),`retryOfRequestLogID`in e&&(e.retryOfRequestLogID&&(e.retryOf=e.retryOfRequestLogID),delete e.retryOfRequestLogID),e);async function P(e,t){let{response:n,requestLogID:r,retryOfRequestLogID:i,startTime:a}=t,o=await(async()=>{if(n.status===204)return null;if(t.options.__binaryResponse)return n;let e=n.headers.get(`content-type`)?.split(`;`)[0]?.trim();return e?.includes(`application/json`)||e?.endsWith(`+json`)?n.headers.get(`content-length`)===`0`?void 0:await n.json():await n.text()})();return M(e).debug(`[${r}] response parsed`,N({retryOfRequestLogID:i,url:n.url,status:n.status,body:o,durationMs:Date.now()-a})),o}var F,I=class e extends Promise{constructor(e,t,n=P){super(e=>{e(null)}),this.responsePromise=t,this.parseResponse=n,F.set(this,void 0),S(this,F,e,`f`)}_thenUnwrap(t){return new e(C(this,F,`f`),this.responsePromise,async(e,n)=>t(await this.parseResponse(e,n),n))}asResponse(){return this.responsePromise.then(e=>e.response)}async withResponse(){let[e,t]=await Promise.all([this.parse(),this.asResponse()]);return{data:e,response:t}}parse(){return this.parsedPromise||=this.responsePromise.then(e=>this.parseResponse(C(this,F,`f`),e)),this.parsedPromise}then(e,t){return this.parse().then(e,t)}catch(e){return this.parse().catch(e)}finally(e){return this.parse().finally(e)}};F=new WeakMap;var L,Me=class{constructor(e,t,n,r){L.set(this,void 0),S(this,L,e,`f`),this.options=r,this.response=t,this.body=n}hasNextPage(){return this.getPaginatedItems().length?this.nextPageRequestOptions()!=null:!1}async getNextPage(){let e=this.nextPageRequestOptions();if(!e)throw new v("No next page expected; please check `.hasNextPage()` before calling `.getNextPage()`.");return await C(this,L,`f`).requestAPIList(this.constructor,e)}async*iterPages(){let e=this;for(yield e;e.hasNextPage();)e=await e.getNextPage(),yield e}async*[(L=new WeakMap,Symbol.asyncIterator)](){for await(let e of this.iterPages())for(let t of e.getPaginatedItems())yield t}},Ne=class extends I{constructor(e,t,n){super(e,t,async(e,t)=>new n(e,t.response,await P(e,t),t.options))}async*[Symbol.asyncIterator](){let e=await this;for await(let t of e)yield t}},R=class extends Me{constructor(e,t,n,r){super(e,t,n,r),this.items=n||[]}getPaginatedItems(){return this.items??[]}nextPageRequestOptions(){let e=this.getPaginatedItems();if(!(typeof this.options.query==`object`&&`endingBefore`in(this.options.query||{}))){let t=e[e.length-1]?.metadata.id;return t?{...this.options,query:{...me(this.options.query),startingAfter:t}}:null}let t=e[0]?.metadata.id;return t?{...this.options,query:{...me(this.options.query),endingBefore:t}}:null}};const Pe=()=>{if(typeof File>`u`){let{process:e}=globalThis,t=typeof e?.versions?.node==`string`&&parseInt(e.versions.node.split(`.`))<20;throw Error("`File` is not defined as a global, which is required for file uploads."+(t?" Update to Node 20 LTS or newer, or set `globalThis.File` to `import('node:buffer').File`.":``))}};function z(e,t,n){return Pe(),new File(e,t??`unknown_file`,n)}function Fe(e){return(typeof e==`object`&&!!e&&(`name`in e&&e.name&&String(e.name)||`url`in e&&e.url&&String(e.url)||`filename`in e&&e.filename&&String(e.filename)||`path`in e&&e.path&&String(e.path))||``).split(/[\\/]/).pop()||void 0}const Ie=e=>typeof e==`object`&&!!e&&typeof e[Symbol.asyncIterator]==`function`,Le=e=>typeof e==`object`&&!!e&&typeof e.size==`number`&&typeof e.type==`string`&&typeof e.text==`function`&&typeof e.slice==`function`&&typeof e.arrayBuffer==`function`,Re=e=>typeof e==`object`&&!!e&&typeof e.name==`string`&&typeof e.lastModified==`number`&&Le(e),ze=e=>typeof e==`object`&&!!e&&typeof e.url==`string`&&typeof e.blob==`function`;async function Be(e,t,n){if(Pe(),e=await e,Re(e))return e instanceof File?e:z([await e.arrayBuffer()],e.name);if(ze(e)){let r=await e.blob();return t||=new URL(e.url).pathname.split(/[\\/]/).pop(),z(await B(r),t,n)}let r=await B(e);if(t||=Fe(e),!n?.type){let e=r.find(e=>typeof e==`object`&&`type`in e&&e.type);typeof e==`string`&&(n={...n,type:e})}return z(r,t,n)}async function B(e){let t=[];if(typeof e==`string`||ArrayBuffer.isView(e)||e instanceof ArrayBuffer)t.push(e);else if(Le(e))t.push(e instanceof Blob?e:await e.arrayBuffer());else if(Ie(e))for await(let n of e)t.push(...await B(n));else{let t=e?.constructor?.name;throw Error(`Unexpected data type: ${typeof e}${t?`; constructor: ${t}`:``}${Ve(e)}`)}return t}function Ve(e){return typeof e!=`object`||!e?``:`; props: [${Object.getOwnPropertyNames(e).map(e=>`"${e}"`).join(`, `)}]`}var V=class{constructor(e){this._client=e}},He=class extends V{get(e,t){return this._client.get(`/v1/analytics`,{query:e,...t})}getInstances(e,t){return this._client.get(`/v1/analytics/instances`,{query:e,...t})}};const Ue=Symbol(`brand.privateNullableHeaders`);function*We(e){if(!e)return;if(Ue in e){let{values:t,nulls:n}=e;yield*t.entries();for(let e of n)yield[e,null];return}let t=!1,n;e instanceof Headers?n=e.entries():pe(e)?n=e:(t=!0,n=Object.entries(e??{}));for(let e of n){let n=e[0];if(typeof n!=`string`)throw TypeError(`expected header name to be a string`);let r=pe(e[1])?e[1]:[e[1]],i=!1;for(let e of r)e!==void 0&&(t&&!i&&(i=!0,yield[n,null]),yield[n,e])}}const H=e=>{let t=new Headers,n=new Set;for(let r of e){let e=new Set;for(let[i,a]of We(r)){let r=i.toLowerCase();e.has(r)||(t.delete(i),e.add(r)),a===null?(t.delete(i),n.add(r)):(t.append(i,a),n.delete(r))}}return{[Ue]:!0,values:t,nulls:n}};function Ge(e){return e.replace(/[^A-Za-z0-9\-._~!$&'()*+,;=:@]+/g,encodeURIComponent)}const Ke=Object.freeze(Object.create(null)),U=((e=Ge)=>function(t,...n){if(t.length===1)return t[0];let r=!1,i=[],a=t.reduce((t,a,o)=>{/[?#]/.test(a)&&(r=!0);let s=n[o],c=(r?encodeURIComponent:e)(``+s);return o!==n.length&&(s==null||typeof s==`object`&&s.toString===Object.getPrototypeOf(Object.getPrototypeOf(s.hasOwnProperty??Ke)??Ke)?.toString)&&(c=s+``,i.push({start:t.length+a.length,length:c.length,error:`Value of type ${Object.prototype.toString.call(s).slice(8,-1)} is not a valid path parameter`})),t+a+(o===n.length?``:c)},``),o=a.split(/[?#]/,1)[0],s=/(?<=^|\/)(?:\.|%2e){1,2}(?=\/|$)/gi,c;for(;(c=s.exec(o))!==null;)i.push({start:c.index,length:c[0].length,error:`Value "${c[0]}" can\'t be safely passed as a path parameter`});if(i.sort((e,t)=>e.start-t.start),i.length>0){let e=0,t=i.reduce((t,n)=>{let r=` `.repeat(n.start-e),i=`^`.repeat(n.length);return e=n.start+n.length,t+r+i},``);throw new v(`Path parameters result in path with invalid segments:\n${i.map(e=>e.error).join(`
|
|
2
|
-
`)}\n${a}\n${t}`)}return a})(Ge);var W=class extends V{create(e,t){let{reuseIfExists:n,wait:r,...i}=e;return this._client.post(`/v1/gradle_instances`,{query:{reuseIfExists:n,wait:r},body:i,...t})}list(e={},t){return this._client.getAPIList(`/v1/gradle_instances`,R,{query:e,...t})}delete(e,t){return this._client.delete(U`/v1/gradle_instances/${e}`,{...t,headers:H([{Accept:`*/*`},t?.headers])})}get(e,t){return this._client.get(U`/v1/gradle_instances/${e}`,t)}},qe=class extends V{create(e,t){return this._client.post(`/v1/scoped_tokens`,{body:e,...t})}},Je=class extends V{list(e={},t){return this._client.get(`/v1/assets`,{query:e,...t})}delete(e,t){return this._client.delete(U`/v1/assets/${e}`,{...t,headers:H([{Accept:`*/*`},t?.headers])})}get(e,t={},n){return this._client.get(U`/v1/assets/${e}`,{query:t,...n})}getOrCreate(e,t){return this._client.put(`/v1/assets`,{body:e,...t})}};function Ye(e,t){if(!t)return{body:e};let n=0;return{body:new ReadableStream({pull(r){if(n>=e.length){r.close();return}let i=e.subarray(n,Math.min(n+262144,e.length));n+=i.length,r.enqueue(i),t(n,e.length)}}),duplex:`half`}}var Xe=class extends Je{async getOrUpload(e,t){let n=await this.getOrCreate({name:e.name??se(e.path),kind:e.kind??`App`,...e.platform&&{platform:e.platform},...e.ttl&&{ttl:e.ttl},...e.uploadOptions},t),r=await ae.readFile(e.path),i=le(`md5`).update(r).digest(`hex`);if(n.md5&&n.md5===i)return{id:n.id,name:n.name,signedDownloadUrl:n.signedDownloadUrl,kind:n.kind,...n.platform&&{platform:n.platform},md5:n.md5,...n.expiresAt&&{expiresAt:n.expiresAt}};let a=await p.fetch(n.signedUploadUrl,{headers:{...e.onUploadProgress&&{"Content-Length":r.length.toString()},"Content-Type":`application/octet-stream`},method:`PUT`,...Ye(r,e.onUploadProgress)});if(a.status!==200)throw Error(`Failed to upload asset: ${a.status} ${await a.text()}`);return{id:n.id,name:n.name,signedDownloadUrl:n.signedDownloadUrl,kind:n.kind,...n.platform&&{platform:n.platform},md5:i,...n.expiresAt&&{expiresAt:n.expiresAt}}}},Ze=class extends V{create(e,t){let{reuseIfExists:n,wait:r,...i}=e;return this._client.post(`/v1/ios_instances`,{query:{reuseIfExists:n,wait:r},body:i,...t})}list(e={},t){return this._client.getAPIList(`/v1/ios_instances`,R,{query:e,...t})}delete(e,t){return this._client.delete(U`/v1/ios_instances/${e}`,{...t,headers:H([{Accept:`*/*`},t?.headers])})}get(e,t){return this._client.get(U`/v1/ios_instances/${e}`,t)}},Qe=class extends Ze{listSessionArtifacts(e,t,n){return this._client.get(U`/v1/ios_instances/${e}/session_artifacts`,{query:t?{kind:t}:void 0,...n})}listRecordings(e,t){return this.listSessionArtifacts(e,`recording`,t)}listAppLogs(e,t){return this.listSessionArtifacts(e,`appLog`,t)}listEvents(e,t){return this.listSessionArtifacts(e,`eventLog`,t)}},$e=class extends V{create(e,t){let{reuseIfExists:n,wait:r,...i}=e;return this._client.post(`/v1/android_instances`,{query:{reuseIfExists:n,wait:r},body:i,...t})}list(e={},t){return this._client.getAPIList(`/v1/android_instances`,R,{query:e,...t})}delete(e,t){return this._client.delete(U`/v1/android_instances/${e}`,{...t,headers:H([{Accept:`*/*`},t?.headers])})}get(e,t){return this._client.get(U`/v1/android_instances/${e}`,t)}},et=class extends $e{listSessionArtifacts(e,t,n){return this._client.get(U`/v1/android_instances/${e}/session_artifacts`,{query:t?{kind:t}:void 0,...n})}listRecordings(e,t){return this.listSessionArtifacts(e,`recording`,t)}listAppLogs(e,t){return this.listSessionArtifacts(e,`appLog`,t)}listEvents(e,t){return this.listSessionArtifacts(e,`eventLog`,t)}},tt=class extends V{create(e,t){let{reuseIfExists:n,wait:r,...i}=e;return this._client.post(`/v1/xcode_instances`,{query:{reuseIfExists:n,wait:r},body:i,...t})}list(e={},t){return this._client.getAPIList(`/v1/xcode_instances`,R,{query:e,...t})}delete(e,t){return this._client.delete(U`/v1/xcode_instances/${e}`,{...t,headers:H([{Accept:`*/*`},t?.headers])})}get(e,t){return this._client.get(U`/v1/xcode_instances/${e}`,t)}},nt=class extends Error{constructor(e){super(`Instance ${e} was gone before it reported any cache status`),this.instanceId=e,this.name=`XcodeCacheGoneError`}},rt=class extends Error{constructor(e,t,n){super(`Timed out after ${Math.round(t/1e3)}s waiting for the cache ${e} to finish`+(n?` (last phase: ${n[e].phase})`:``)),this.side=e,this.timeoutMs=t,this.cache=n,this.name=`XcodeCacheTimeoutError`}};const it={restore:12e5,save:72e4};function at(e){return e===`disabled`||e===`unsupported`||e===`restored`||e===`skipped`||e===`failed`}function ot(e){return e===`disabled`||e===`published`||e===`skipped`||e===`failed`||e===`timed_out`}function st(e,t){return t===`restore`?at(e.restore.phase):ot(e.save.phase)}function ct(e,t={}){let n=t.side??`restore`,r=t.timeoutMs??it[n],i=e.baseURL;for(;i.endsWith(`/`);)i=i.slice(0,-1);let a=`${i}/v1/xcode_instances/${encodeURIComponent(e.instanceId)}/cache`;return new Promise((i,o)=>{let s,c=``,l=!1,u=e=>{if(!l){l=!0,clearTimeout(d),t.signal?.removeEventListener(`abort`,f);try{g.close()}catch{}e()}},d=setTimeout(()=>u(()=>o(new rt(n,r,s))),r),f=()=>u(()=>o(t.signal?.reason??Error(`aborted`))),m=!1,h=()=>{m||l||(m=!0,p.fetch(a,{headers:{Authorization:`Bearer ${e.apiKey}`,Accept:`application/json`}}).then(async t=>{if(m=!1,t.status!==404){await t.text().catch(()=>void 0);return}u(()=>s?i({cache:s,gone:!0}):o(new nt(e.instanceId)))}).catch(()=>{m=!1}))},g=re({url:a,fetch:async(t,n)=>{let r=await p.fetch(t,n);return r.status===404&&u(()=>s?i({cache:s,gone:!0}):o(new nt(e.instanceId))),r},onConnect:()=>t.onOpen?.(),headers:{Authorization:`Bearer ${e.apiKey}`,Accept:`text/event-stream`},onMessage:e=>{if(e.event!==`cache`&&e.event!==`gone`)return;let r;try{r=JSON.parse(typeof e.data==`string`?e.data:String(e.data))}catch(e){u(()=>o(Error(`Cache stream sent unreadable data: ${e}`)));return}if(s=r,e.event===`gone`){h();return}let a=`${r.restore.phase}/${r.restore.reason??``}|${r.save.phase}/${r.save.reason??``}`;a!==c&&(c=a,t.onUpdate?.(r)),st(r,n)&&u(()=>i({cache:r,gone:!1}))}});if(t.signal?.aborted){f();return}t.signal?.addEventListener(`abort`,f,{once:!0})})}function lt(e,t){let n=x.resolve(e),r=`limsync-cache-${x.basename(n)}-${ce.createHash(`sha1`).update(n).digest(`hex`).slice(0,8)}`;return{cacheKey:r,basisCacheDir:t??x.join(oe.tmpdir(),r)}}function G(e,t,n,r){return e.getOrCreate({name:t,ttl:n||`336h`,...r}).catch(e=>{let n=`Failed to create upload URL for asset '${t}': ${e instanceof Error?e.message:e}`;throw Error(n,{cause:e})})}const ut=[`none`,`error`,`warn`,`info`,`debug`];function dt(e,t){let n=ut.indexOf(t),r=e=>n>=ut.indexOf(e);return(t,n)=>{r(t)&&(t===`error`||t===`warn`?console[t](e,n):console.log(e,n))}}const ft=/^[A-Z0-9_]+$/,pt=4096,mt=65536;function ht(e){let t=Object.entries(e);if(t.length>32)throw Error(`too many build settings: got ${t.length}, max 32`);let n=0;for(let[e,r]of t){if(!ft.test(e))throw Error(`invalid build setting key "${e}": keys must match ^[A-Z0-9_]+$`);if(typeof r!=`string`)throw Error(`invalid build setting value for "${e}": value must be a string`);let t=Buffer.byteLength(r,`utf8`);if(t>pt)throw Error(`build setting value for "${e}" is too large: got ${t} bytes, max ${pt} bytes`);if(n+=Buffer.byteLength(e,`utf8`)+t,n>mt)throw Error(`build settings payload is too large: max ${mt} bytes`)}}const gt=e=>new Promise(t=>setTimeout(t,e)),_t=/failed: (?:502|503|504)\b|\bEOF\b|ECONNRESET|ECONNREFUSED|socket hang up|fetch failed/i;function vt(e){let t=e instanceof Error?e.message:String(e);return _t.test(t)}async function yt(e,t={}){let n=t.sleep??gt,r=t.attempts??5,i=t.retryOn??vt,a;for(let o=1;o<=r;o++)try{return await e()}catch(e){if(!i(e))throw e;if(a=e,o<r){let r=e instanceof Error?e.message:String(e);t.log?.(`Retrying after error (${r.trim()})...`),await n(2e3*o)}}throw a}function bt(e){if(e===``||e.startsWith(`/`)||e.includes(`\\`)||e.includes(`\0`))throw Error(`invalid sandbox home path from server: ${e}`);let t=e.split(`/`);if(t.some(e=>e===``||e===`.`||e===`..`))throw Error(`invalid sandbox home path from server: ${e}`);return t.join(`/`)}async function xt(e,t){let n=await J(await p.fetch(`${e}/info`,{method:`GET`,headers:{Authorization:`Bearer ${t}`}}),`GET /info`);if(!n.homeDir)throw Error(`GET /info response is missing homeDir`);return{homeDir:bt(n.homeDir),...n.xcode?{xcode:n.xcode}:{}}}function St(e){let t=new URL(e);if(t.protocol===`https:`)t.protocol=`wss:`;else if(t.protocol===`http:`)t.protocol=`ws:`;else throw Error(`Unsupported apiUrl protocol for rbe tunnel: ${t.protocol}`);return t.pathname=`${t.pathname.replace(/\/+$/,``)}/rbe/tunnel`,t.search=``,t.hash=``,t.toString()}var Ct=class extends v{constructor(e){super(`Remote build execution is not available on this Xcode instance (${e} returned 404). Its limbuild may predate RBE support, or you may be targeting the wrong environment (for example production instead of staging).`),this.name=`RbeUnsupportedError`}},wt=class extends v{constructor(e){super(`Xcode version selection is not available on this sandbox (${e} returned 404): its daemon predates Xcode selection. Create a new sandbox, or omit the Xcode version to build with its default.`),this.name=`XcodeSelectionUnsupportedError`}};function Tt(e,t){return q(e,t,e=>new wt(e))}function K(e,t){return q(e,t,e=>new Ct(e))}async function q(e,t,n){if(e.status===404)throw await e.text().catch(()=>void 0),n(t);return J(e,t)}async function J(e,t){let n=await e.text();if(!e.ok)throw g(t,e.status,n,e.headers);if(!n.trim())throw Error(`${t} returned an empty response`);return JSON.parse(n)}var Et=class extends tt{listBuildLogs(e,t){return this._client.get(U`/v1/xcode_instances/${e}/build_logs`,t)}listBazelBuildLogs(e,t){return this._client.get(U`/v1/xcode_instances/${e}/bazel_build_logs`,t)}create(e,t){return super.create(e,t)}getCache(e,t){return this._client.get(U`/v1/xcode_instances/${e}/cache`,t)}bindCacheKey(e,t,n){return this._client.put(U`/v1/xcode_instances/${e}/cache`,{body:{key:t},...n})}followCache(e,t){let n=this._client.apiKey;if(!n)throw Error(`Following cache status needs an API key on the client`);return ct({baseURL:this._client.baseURL,apiKey:n,instanceId:e},t)}async createClient(e){let t,n;if(`instance`in e){if(!e.instance.status.apiUrl)throw Error(`Instance not ready: apiUrl is not available`);t=e.instance.status.apiUrl,n=e.instance.status.token}else t=e.apiUrl,n=e.token;let r=dt(`[XcodeInstance]`,e.logLevel??`info`),i=this._client,a,o=()=>(a??=xt(t,n),a),s=async e=>{let r,i;if(`status`in e){if(!e.status.apiUrl)throw Error(`Simulator instance not ready: apiUrl is not available`);r=e.status.apiUrl,i=e.status.token}else r=e.apiUrl,i=e.token;return J(await p.fetch(`${t}/simulator`,{method:`POST`,headers:{"Content-Type":`application/json`,Authorization:`Bearer ${n}`},body:JSON.stringify({apiUrl:r,token:i})}),`POST /simulator`)},c=async e=>{try{return await i.iosInstances.delete(e),!0}catch{return!1}};return{async sync(e,i){let{cacheKey:a,basisCacheDir:s}=lt(e,i?.basisCacheDir),c=i?.additionalFiles&&i.additionalFiles.length>0?await o():void 0,l=i?.additionalFiles?.map(e=>({localPath:e.localPath,remotePath:c&&e.remotePath.startsWith(`~/`)?`${c.homeDir}/${e.remotePath.slice(2)}`:e.remotePath})),u={apiUrl:t,token:n,udid:a,install:i?.install??!0,ignoreFn:await b(e,{basisCacheDir:s,log:r,xcodeDefaults:!0,...i?.include?{include:i.include}:{},...i?.ignore?{additional:i.ignore}:{}}),basisCacheDir:s,watch:i?.watch??!0,launchMode:`ForegroundIfRunning`,log:r,syncSymlinks:!0,...l?{additionalFiles:l}:{},...i?.onSyncComplete?{onSyncComplete:i.onSyncComplete}:{}},d=await ee(e,u),f={};return d.bytesSent!==void 0&&(f.bytesSent=d.bytesSent),d.stopWatching&&(f.stopWatching=d.stopWatching),f},xcodebuild(e,a){if(a?.reactNative?.devServerURL&&e?.configuration===`Release`)throw Error(`reactNative.devServerURL is only supported for Debug builds`);if(e?.onlyTesting?.length&&e?.skipTesting?.length)throw Error(`onlyTesting and skipTesting are mutually exclusive; pass one`);if((e?.onlyTesting?.length||e?.skipTesting?.length)&&e?.action!==`build-for-testing`)throw Error(`onlyTesting/skipTesting require action: 'build-for-testing'`);if(e?.runTests===!1&&e?.action!==`build-for-testing`)throw Error(`runTests: false requires action: 'build-for-testing'`);if(e?.action===`build-for-testing`&&e.sdk!==void 0&&e.sdk!==`iphonesimulator`)throw Error(`action: 'build-for-testing' requires the iphonesimulator sdk`);a?.buildSettings&&ht(a.buildSettings);let o={command:`xcodebuild`,...e&&{xcodebuild:e},...a?.xcodegen&&{xcodegen:a.xcodegen},...a?.reactNative&&{reactNative:a.reactNative},...a?.signing&&{signing:a.signing},...a?.cloudSigning&&{cloudSigning:a.cloudSigning},...a?.appstore&&{testflight:a.appstore},...a?.buildSettings&&{buildSettings:a.buildSettings},...a?.env?.length&&{env:a.env},...a?.gitInit!==void 0&&{gitInit:a.gitInit},...a?.logProcessor&&{logProcessor:a.logProcessor},...a?.webhook&&{webhook:a.webhook}},s={apiUrl:t,token:n,log:r,...a?.onXctestEvent&&{onXctestEvent:a.onXctestEvent}};if(a?.upload&&`assetName`in a.upload){let e=G(i.assets,a.upload.assetName,a.upload.ttl,a.upload.uploadOptions).then(e=>(o.signedUploadUrl=e.signedUploadUrl,o.assetId=e.id,o.additionalMetadata={signedDownloadUrl:e.signedDownloadUrl},o));return f(e,s)}return a?.upload&&`signedUploadUrl`in a.upload&&(o.signedUploadUrl=a.upload.signedUploadUrl),f(o,s)},run(e,i){if(e.trim()===``)throw Error(`commandLine must not be empty`);if(i?.timeoutSeconds!==void 0&&(!Number.isInteger(i.timeoutSeconds)||i.timeoutSeconds<1||i.timeoutSeconds>21600))throw Error(`timeoutSeconds must be an integer between 1 and 21600`);let a={command:`run`,commandLine:e,cwd:i?.cwd??`.`,...i?.env&&{env:i.env},...i?.timeoutSeconds!==void 0&&{timeoutSeconds:i.timeoutSeconds}};return f(a,{apiUrl:t,token:n,log:r})},async getSimulator(){return J(await p.fetch(`${t}/simulator`,{method:`GET`,headers:{Authorization:`Bearer ${n}`}}),`GET /simulator`)},attachSimulator:s,attachNewSimulator:async()=>{let e=await i.iosInstances.create({wait:!0});try{await s(e)}catch(t){throw await c(e.metadata.id),t}return{iosInstanceId:e.metadata.id,simulator:e}},deleteSimulator:c,async getXcode(){return Tt(await p.fetch(`${t}/xcode`,{method:`GET`,headers:{Authorization:`Bearer ${n}`}}),`GET /xcode`)},async setXcode(e){return Tt(await p.fetch(`${t}/xcode`,{method:`POST`,headers:{"Content-Type":`application/json`,Authorization:`Bearer ${n}`},body:JSON.stringify({version:e})}),`POST /xcode`)},getInfo:()=>xt(t,n),async startRbe(e){return K(await p.fetch(`${t}/rbe`,{method:`POST`,headers:{"Content-Type":`application/json`,Authorization:`Bearer ${n}`},body:JSON.stringify(e??{})}),`POST /rbe`)},async getRbe(){return K(await p.fetch(`${t}/rbe`,{method:`GET`,headers:{Authorization:`Bearer ${n}`}}),`GET /rbe`)},async stopRbe(){return K(await p.fetch(`${t}/rbe`,{method:`DELETE`,headers:{Authorization:`Bearer ${n}`}}),`DELETE /rbe`)},async startRbeTunnel(r){return m(St(t),n,r?.host??`127.0.0.1`,r?.port??8980,{mode:`multiplexed`,logLevel:r?.logLevel??e.logLevel??`info`})},async uploadLatestRbeBuild(e){let r,a;if(e.assetName!==void 0){if(!e.assetName)throw Error(`assetName must not be empty`);let t=await G(i.assets,e.assetName,e.ttl);r=t.signedUploadUrl,a=t.signedDownloadUrl}else r=e.signedUploadUrl;return{...await yt(async()=>{let e=await p.fetchLongRequest(`${t}/rbe/upload`,{method:`POST`,headers:{"Content-Type":`application/json`,Authorization:`Bearer ${n}`},body:JSON.stringify({signedUploadUrl:r})});if(e.status===404)throw await e.text().catch(()=>void 0),Error(`POST /rbe/upload returned 404: the instance may no longer exist, or its limbuild predates RBE upload support. Recreate the instance and retry.`);return J(e,`POST /rbe/upload`)},{retryOn:e=>vt(e)||h(e,400)&&/no successful RBE app build/i.test(e.body)}),...a&&{signedDownloadUrl:a}}},async getActiveRbeBuilds(){return K(await p.fetch(`${t}/rbe/builds/active`,{method:`GET`,headers:{Authorization:`Bearer ${n}`}}),`GET /rbe/builds/active`)},async getRecentRbeBuilds(){return K(await p.fetch(`${t}/rbe/builds/recent`,{method:`GET`,headers:{Authorization:`Bearer ${n}`}}),`GET /rbe/builds/recent`)},waitForRbeBuildEnd(e,r){return new Promise((i,a)=>{if(r?.signal?.aborted){a(Error(`waiting for build ${e} was aborted`));return}let o=!1,s=()=>{d.close(),r?.signal?.removeEventListener(`abort`,u)},c=e=>{o||(o=!0,s(),i(e))},l=e=>{o||(o=!0,s(),a(e))},u=()=>l(Error(`waiting for build ${e} was aborted`)),d=re({url:`${t}/exec/${e}/events`,fetch:te(p.fetch,t=>l(Error(`build event stream for ${e} is unreachable: ${t instanceof Error?t.message:t}`))),headers:{Authorization:`Bearer ${n}`},onMessage:t=>{if(t.event!==`end`)return;let n;try{n=JSON.parse(t.data)}catch(t){l(Error(`invalid build end event for ${e}: ${t}`));return}c(n)},onDisconnect:()=>{l(Error(`build event stream for ${e} ended without a terminal event (the build may have finished and its live stream been removed)`))}});r?.signal?.addEventListener(`abort`,u,{once:!0})})}}}};function Dt(e){let t=e.endsWith(`/`)?e.slice(0,-1):e,n=t.split(`/`);return n[n.length-1]===`local.properties`||n.length===1&&(t===`.gradle`||t===`.kotlin`||t===`build`)}var Ot=class extends W{listBuildLogs(e,t){return this._client.get(U`/v1/gradle_instances/${e}/build_logs`,t)}async createClient(e){let t,n;if(`instance`in e){if(!e.instance.status.apiUrl)throw Error(`Instance not ready: apiUrl is not available`);t=e.instance.status.apiUrl,n=e.instance.status.token}else t=e.apiUrl,n=e.token;let r=dt(`[GradleInstance]`,e.logLevel??`info`),i=this._client;return{async sync(e,i){let{cacheKey:a,basisCacheDir:o}=lt(e,i?.basisCacheDir),s=i?.ignore,c={apiUrl:t,token:n,udid:a,install:!1,ignoreFn:await b(e,{basisCacheDir:o,log:r,xcodeDefaults:!1,nestedGitignore:!0,additional:s?e=>Dt(e)||s(e):Dt,...i?.include?{include:i.include}:{}}),basisCacheDir:o,watch:!1,launchMode:`ForegroundIfRunning`,log:r,syncSymlinks:!0},l=await ee(e,c),u={};return l.bytesSent!==void 0&&(u.bytesSent=l.bytesSent),u},gradlebuild(e){let a={command:`gradlebuild`,...e?.tasks?.length&&{tasks:e.tasks},...e?.projectPath&&{projectPath:e.projectPath},...e?.reactNative&&{reactNative:e.reactNative},...e?.signing&&{signing:e.signing},...e?.webhook&&{webhook:e.webhook},...e?.playstore&&{playstore:e.playstore}};if(e?.upload&&`assetName`in e.upload){let o=G(i.assets,e.upload.assetName,e.upload.ttl).then(e=>(a.signedUploadUrl=e.signedUploadUrl,a.additionalMetadata={signedDownloadUrl:e.signedDownloadUrl},a));return f(o,{apiUrl:t,token:n,log:r})}return e?.upload&&`signedUploadUrl`in e.upload&&(a.signedUploadUrl=e.upload.signedUploadUrl),f(a,{apiUrl:t,token:n,log:r})}}}};W.prototype.listBuildLogs=Ot.prototype.listBuildLogs,W.prototype.createClient=Ot.prototype.createClient;const Y=e=>{if(globalThis.process!==void 0)return globalThis.process.env?.[e]?.trim()||void 0;if(globalThis.Deno!==void 0)return globalThis.Deno.env?.get?.(e)?.trim()||void 0};var X,Z,Q,kt,$=class{constructor({baseURL:e=Y(`LIMRUN_BASE_URL`),apiKey:t=Y(`LIM_API_KEY`)??null,...n}={}){X.add(this),Q.set(this,void 0),this.androidInstances=new et(this),this.assets=new Xe(this),this.iosInstances=new Qe(this),this.xcodeInstances=new Et(this),this.gradleInstances=new W(this),this.analytics=new He(this),this.scopedTokens=new qe(this);let r={apiKey:t,...n,baseURL:e||`https://api.limrun.com`};this.baseURL=r.baseURL,this.timeout=r.timeout??Z.DEFAULT_TIMEOUT,this.logger=r.logger??console;let i=`warn`;this.logLevel=i,this.logLevel=O(r.logLevel,`ClientOptions.logLevel`,this)??O(Y(`LIMRUN_LOG`),`process.env['LIMRUN_LOG']`,this)??i,this.fetchOptions=r.fetchOptions,this.maxRetries=r.maxRetries??2,this.fetch=r.fetch??Te(),S(this,Q,ke,`f`);let a=Y(`LIMRUN_CUSTOM_HEADERS`);if(a){let e={};for(let t of a.split(`
|
|
3
|
-
`)){let n=t.indexOf(`:`);n>=0&&(e[t.substring(0,n).trim()]=t.substring(n+1).trim())}r.defaultHeaders={...e,...r.defaultHeaders}}this._options=r,this.apiKey=t}withOptions(e){return new this.constructor({...this._options,baseURL:this.baseURL,maxRetries:this.maxRetries,timeout:this.timeout,logger:this.logger,logLevel:this.logLevel,fetch:this.fetch,fetchOptions:this.fetchOptions,apiKey:this.apiKey,...e})}defaultQuery(){return this._options.defaultQuery}validateHeaders({values:e,nulls:t}){if(!(this.apiKey&&e.get(`authorization`))&&!t.has(`authorization`))throw Error(`Could not resolve authentication method. Expected the apiKey to be set. Or for the "Authorization" headers to be explicitly omitted`)}async authHeaders(e){if(this.apiKey!=null)return
|
|
1
|
+
import{P as e}from"./sdk-contracts.js";import{A as t,C as n,D as r,E as i,F as a,I as o,L as s,M as c,N as l,O as u,P as d,R as f,S as p,T as m,_ as h,b as g,g as _,j as v,k as ee,m as te,v as y,w as ne,x as re,y as ie}from"./log-stream.js";import{i as ae,r as oe}from"./ios-client.js";import"./instance-client.js";import{promises as se}from"fs";import"net";import ce from"os";import b,{basename as le}from"path";import ue,{createHash as de}from"crypto";import"child_process";function x(e,t,n,r,i){if(r===`m`)throw TypeError(`Private method is not writable`);if(r===`a`&&!i)throw TypeError(`Private accessor was defined without a setter`);if(typeof t==`function`?e!==t||!i:!t.has(e))throw TypeError(`Cannot write private member to an object whose class did not declare it`);return r===`a`?i.call(e,n):i?i.value=n:t.set(e,n),n}function S(e,t,n,r){if(n===`a`&&!r)throw TypeError(`Private accessor was defined without a getter`);if(typeof t==`function`?e!==t||!r:!t.has(e))throw TypeError(`Cannot read private member from an object whose class did not declare it`);return n===`m`?r:n===`a`?r.call(e):r?r.value:t.get(e)}let fe=function(){let{crypto:e}=globalThis;if(e?.randomUUID)return fe=e.randomUUID.bind(e),e.randomUUID();let t=new Uint8Array(1),n=e?()=>e.getRandomValues(t)[0]:()=>Math.random()*255&255;return`10000000-1000-4000-8000-100000000000`.replace(/[018]/g,e=>(e^n()&15>>e/4).toString(16))};const pe=/^[a-z][a-z0-9+.-]*:/i,me=e=>pe.test(e);let C=e=>(C=Array.isArray,C(e)),he=C;function ge(e){return typeof e==`object`?e??{}:{}}function _e(e){if(!e)return!0;for(let t in e)return!1;return!0}function ve(e,t){return Object.prototype.hasOwnProperty.call(e,t)}const ye=(e,t)=>{if(typeof t!=`number`||!Number.isInteger(t))throw new c(`${e} must be an integer`);if(t<0)throw new c(`${e} must be a positive integer`);return t},be=e=>{try{return JSON.parse(e)}catch{return}},w=`0.59.0`;function xe(){return typeof Deno<`u`&&Deno.build!=null?`deno`:typeof EdgeRuntime<`u`?`edge`:Object.prototype.toString.call(globalThis.process===void 0?0:globalThis.process)===`[object process]`?`node`:`unknown`}const Se=()=>{let e=xe();if(e===`deno`)return{"X-Stainless-Lang":`js`,"X-Stainless-Package-Version":w,"X-Stainless-OS":Te(Deno.build.os),"X-Stainless-Arch":we(Deno.build.arch),"X-Stainless-Runtime":`deno`,"X-Stainless-Runtime-Version":typeof Deno.version==`string`?Deno.version:Deno.version?.deno??`unknown`};if(typeof EdgeRuntime<`u`)return{"X-Stainless-Lang":`js`,"X-Stainless-Package-Version":w,"X-Stainless-OS":`Unknown`,"X-Stainless-Arch":`other:${EdgeRuntime}`,"X-Stainless-Runtime":`edge`,"X-Stainless-Runtime-Version":globalThis.process.version};if(e===`node`)return{"X-Stainless-Lang":`js`,"X-Stainless-Package-Version":w,"X-Stainless-OS":Te(globalThis.process.platform??`unknown`),"X-Stainless-Arch":we(globalThis.process.arch??`unknown`),"X-Stainless-Runtime":`node`,"X-Stainless-Runtime-Version":globalThis.process.version??`unknown`};let t=Ce();return t?{"X-Stainless-Lang":`js`,"X-Stainless-Package-Version":w,"X-Stainless-OS":`Unknown`,"X-Stainless-Arch":`unknown`,"X-Stainless-Runtime":`browser:${t.browser}`,"X-Stainless-Runtime-Version":t.version}:{"X-Stainless-Lang":`js`,"X-Stainless-Package-Version":w,"X-Stainless-OS":`Unknown`,"X-Stainless-Arch":`unknown`,"X-Stainless-Runtime":`unknown`,"X-Stainless-Runtime-Version":`unknown`}};function Ce(){if(typeof navigator>`u`||!navigator)return null;for(let{key:e,pattern:t}of[{key:`edge`,pattern:/Edge(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/},{key:`ie`,pattern:/MSIE(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/},{key:`ie`,pattern:/Trident(?:.*rv\:(\d+)\.(\d+)(?:\.(\d+))?)?/},{key:`chrome`,pattern:/Chrome(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/},{key:`firefox`,pattern:/Firefox(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/},{key:`safari`,pattern:/(?:Version\W+(\d+)\.(\d+)(?:\.(\d+))?)?(?:\W+Mobile\S*)?\W+Safari/}]){let n=t.exec(navigator.userAgent);if(n)return{browser:e,version:`${n[1]||0}.${n[2]||0}.${n[3]||0}`}}return null}const we=e=>e===`x32`?`x32`:e===`x86_64`||e===`x64`?`x64`:e===`arm`?`arm`:e===`aarch64`||e===`arm64`?`arm64`:e?`other:${e}`:`unknown`,Te=e=>(e=e.toLowerCase(),e.includes(`ios`)?`iOS`:e===`android`?`Android`:e===`darwin`?`MacOS`:e===`win32`?`Windows`:e===`freebsd`?`FreeBSD`:e===`openbsd`?`OpenBSD`:e===`linux`?`Linux`:e?`Other:${e}`:`Unknown`);let Ee;const De=()=>Ee??=Se();function Oe(){if(typeof fetch<`u`)return n.fetch;throw Error("`fetch` is not defined as a global; Either pass `fetch` to the client, `new Limrun({ fetch })` or polyfill the global, `globalThis.fetch = fetch`")}function ke(...e){let t=globalThis.ReadableStream;if(t===void 0)throw Error("`ReadableStream` is not defined as a global; You will need to polyfill it, `globalThis.ReadableStream = ReadableStream`");return new t(...e)}function Ae(e){let t=Symbol.asyncIterator in e?e[Symbol.asyncIterator]():e[Symbol.iterator]();return ke({start(){},async pull(e){let{done:n,value:r}=await t.next();n?e.close():e.enqueue(r)},async cancel(){await t.return?.()}})}async function je(e){if(typeof e!=`object`||!e)return;if(e[Symbol.asyncIterator]){await e[Symbol.asyncIterator]().return?.();return}let t=e.getReader(),n=t.cancel();t.releaseLock(),await n}const Me=({headers:e,body:t})=>({bodyHeaders:{"content-type":`application/json`},body:JSON.stringify(t)});function Ne(e){return Object.entries(e).filter(([e,t])=>t!==void 0).map(([e,t])=>{if(typeof t==`string`||typeof t==`number`||typeof t==`boolean`)return`${encodeURIComponent(e)}=${encodeURIComponent(t)}`;if(t===null)return`${encodeURIComponent(e)}=`;throw new c(`Cannot stringify type ${typeof t}; Expected string, number, boolean, or null. If you need to pass nested query parameters, you can manually encode them, e.g. { query: { 'foo[key1]': value1, 'foo[key2]': value2 } }, and please open a GitHub issue requesting better support for your use case.`)}).join(`&`)}const T={off:0,error:200,warn:300,info:400,debug:500},E=(e,t,n)=>{if(e){if(ve(T,e))return e;A(n).warn(`${t} was set to ${JSON.stringify(e)}, expected one of ${JSON.stringify(Object.keys(T))}`)}};function D(){}function O(e,t,n){return!t||T[e]>T[n]?D:t[e].bind(t)}const Pe={error:D,warn:D,info:D,debug:D};let k=new WeakMap;function A(e){let t=e.logger,n=e.logLevel??`off`;if(!t)return Pe;let r=k.get(t);if(r&&r[0]===n)return r[1];let i={error:O(`error`,t,n),warn:O(`warn`,t,n),info:O(`info`,t,n),debug:O(`debug`,t,n)};return k.set(t,[n,i]),i}const j=e=>(e.options&&(e.options={...e.options},delete e.options.headers),e.headers&&=Object.fromEntries((e.headers instanceof Headers?[...e.headers]:Object.entries(e.headers)).map(([e,t])=>[e,e.toLowerCase()===`authorization`||e.toLowerCase()===`api-key`||e.toLowerCase()===`x-api-key`||e.toLowerCase()===`cookie`||e.toLowerCase()===`set-cookie`?`***`:t])),`retryOfRequestLogID`in e&&(e.retryOfRequestLogID&&(e.retryOf=e.retryOfRequestLogID),delete e.retryOfRequestLogID),e);async function Fe(e,t){let{response:n,requestLogID:r,retryOfRequestLogID:i,startTime:a}=t,o=await(async()=>{if(n.status===204)return null;if(t.options.__binaryResponse)return n;let e=n.headers.get(`content-type`)?.split(`;`)[0]?.trim();return e?.includes(`application/json`)||e?.endsWith(`+json`)?n.headers.get(`content-length`)===`0`?void 0:await n.json():await n.text()})();return A(e).debug(`[${r}] response parsed`,j({retryOfRequestLogID:i,url:n.url,status:n.status,body:o,durationMs:Date.now()-a})),o}var M,Ie=class e extends Promise{constructor(e,t,n=Fe){super(e=>{e(null)}),this.responsePromise=t,this.parseResponse=n,M.set(this,void 0),x(this,M,e,`f`)}_thenUnwrap(t){return new e(S(this,M,`f`),this.responsePromise,async(e,n)=>t(await this.parseResponse(e,n),n))}asResponse(){return this.responsePromise.then(e=>e.response)}async withResponse(){let[e,t]=await Promise.all([this.parse(),this.asResponse()]);return{data:e,response:t}}parse(){return this.parsedPromise||=this.responsePromise.then(e=>this.parseResponse(S(this,M,`f`),e)),this.parsedPromise}then(e,t){return this.parse().then(e,t)}catch(e){return this.parse().catch(e)}finally(e){return this.parse().finally(e)}};M=new WeakMap;var N,Le=class{constructor(e,t,n,r){N.set(this,void 0),x(this,N,e,`f`),this.options=r,this.response=t,this.body=n}hasNextPage(){return this.getPaginatedItems().length?this.nextPageRequestOptions()!=null:!1}async getNextPage(){let e=this.nextPageRequestOptions();if(!e)throw new c("No next page expected; please check `.hasNextPage()` before calling `.getNextPage()`.");return await S(this,N,`f`).requestAPIList(this.constructor,e)}async*iterPages(){let e=this;for(yield e;e.hasNextPage();)e=await e.getNextPage(),yield e}async*[(N=new WeakMap,Symbol.asyncIterator)](){for await(let e of this.iterPages())for(let t of e.getPaginatedItems())yield t}},Re=class extends Ie{constructor(e,t,n){super(e,t,async(e,t)=>new n(e,t.response,await Fe(e,t),t.options))}async*[Symbol.asyncIterator](){let e=await this;for await(let t of e)yield t}},P=class extends Le{constructor(e,t,n,r){super(e,t,n,r),this.items=n||[]}getPaginatedItems(){return this.items??[]}nextPageRequestOptions(){let e=this.getPaginatedItems();if(!(typeof this.options.query==`object`&&`endingBefore`in(this.options.query||{}))){let t=e[e.length-1]?.metadata.id;return t?{...this.options,query:{...ge(this.options.query),startingAfter:t}}:null}let t=e[0]?.metadata.id;return t?{...this.options,query:{...ge(this.options.query),endingBefore:t}}:null}};const ze=()=>{if(typeof File>`u`){let{process:e}=globalThis,t=typeof e?.versions?.node==`string`&&parseInt(e.versions.node.split(`.`))<20;throw Error("`File` is not defined as a global, which is required for file uploads."+(t?" Update to Node 20 LTS or newer, or set `globalThis.File` to `import('node:buffer').File`.":``))}};function F(e,t,n){return ze(),new File(e,t??`unknown_file`,n)}function Be(e){return(typeof e==`object`&&!!e&&(`name`in e&&e.name&&String(e.name)||`url`in e&&e.url&&String(e.url)||`filename`in e&&e.filename&&String(e.filename)||`path`in e&&e.path&&String(e.path))||``).split(/[\\/]/).pop()||void 0}const Ve=e=>typeof e==`object`&&!!e&&typeof e[Symbol.asyncIterator]==`function`,He=e=>typeof e==`object`&&!!e&&typeof e.size==`number`&&typeof e.type==`string`&&typeof e.text==`function`&&typeof e.slice==`function`&&typeof e.arrayBuffer==`function`,Ue=e=>typeof e==`object`&&!!e&&typeof e.name==`string`&&typeof e.lastModified==`number`&&He(e),We=e=>typeof e==`object`&&!!e&&typeof e.url==`string`&&typeof e.blob==`function`;async function Ge(e,t,n){if(ze(),e=await e,Ue(e))return e instanceof File?e:F([await e.arrayBuffer()],e.name);if(We(e)){let r=await e.blob();return t||=new URL(e.url).pathname.split(/[\\/]/).pop(),F(await I(r),t,n)}let r=await I(e);if(t||=Be(e),!n?.type){let e=r.find(e=>typeof e==`object`&&`type`in e&&e.type);typeof e==`string`&&(n={...n,type:e})}return F(r,t,n)}async function I(e){let t=[];if(typeof e==`string`||ArrayBuffer.isView(e)||e instanceof ArrayBuffer)t.push(e);else if(He(e))t.push(e instanceof Blob?e:await e.arrayBuffer());else if(Ve(e))for await(let n of e)t.push(...await I(n));else{let t=e?.constructor?.name;throw Error(`Unexpected data type: ${typeof e}${t?`; constructor: ${t}`:``}${Ke(e)}`)}return t}function Ke(e){return typeof e!=`object`||!e?``:`; props: [${Object.getOwnPropertyNames(e).map(e=>`"${e}"`).join(`, `)}]`}var L=class{constructor(e){this._client=e}},qe=class extends L{get(e,t){return this._client.get(`/v1/analytics`,{query:Je(e),...t})}getInstances(e,t){return this._client.get(`/v1/analytics/instances`,{query:Je(e),...t})}};function Je(e){let{startedAt:t,stoppedAt:n,...r}=e,i={...r};for(let[e,r]of Object.entries({startedAt:t,stoppedAt:n}))if(r!==void 0)for(let[t,n]of Object.entries(r))n!==void 0&&(i[`${e}[${t}]`]=n);return i}const Ye=Symbol(`brand.privateNullableHeaders`);function*Xe(e){if(!e)return;if(Ye in e){let{values:t,nulls:n}=e;yield*t.entries();for(let e of n)yield[e,null];return}let t=!1,n;e instanceof Headers?n=e.entries():he(e)?n=e:(t=!0,n=Object.entries(e??{}));for(let e of n){let n=e[0];if(typeof n!=`string`)throw TypeError(`expected header name to be a string`);let r=he(e[1])?e[1]:[e[1]],i=!1;for(let e of r)e!==void 0&&(t&&!i&&(i=!0,yield[n,null]),yield[n,e])}}const R=e=>{let t=new Headers,n=new Set;for(let r of e){let e=new Set;for(let[i,a]of Xe(r)){let r=i.toLowerCase();e.has(r)||(t.delete(i),e.add(r)),a===null?(t.delete(i),n.add(r)):(t.append(i,a),n.delete(r))}}return{[Ye]:!0,values:t,nulls:n}};function Ze(e){return e.replace(/[^A-Za-z0-9\-._~!$&'()*+,;=:@]+/g,encodeURIComponent)}const Qe=Object.freeze(Object.create(null)),z=((e=Ze)=>function(t,...n){if(t.length===1)return t[0];let r=!1,i=[],a=t.reduce((t,a,o)=>{/[?#]/.test(a)&&(r=!0);let s=n[o],c=(r?encodeURIComponent:e)(``+s);return o!==n.length&&(s==null||typeof s==`object`&&s.toString===Object.getPrototypeOf(Object.getPrototypeOf(s.hasOwnProperty??Qe)??Qe)?.toString)&&(c=s+``,i.push({start:t.length+a.length,length:c.length,error:`Value of type ${Object.prototype.toString.call(s).slice(8,-1)} is not a valid path parameter`})),t+a+(o===n.length?``:c)},``),o=a.split(/[?#]/,1)[0],s=/(?<=^|\/)(?:\.|%2e){1,2}(?=\/|$)/gi,l;for(;(l=s.exec(o))!==null;)i.push({start:l.index,length:l[0].length,error:`Value "${l[0]}" can\'t be safely passed as a path parameter`});if(i.sort((e,t)=>e.start-t.start),i.length>0){let e=0,t=i.reduce((t,n)=>{let r=` `.repeat(n.start-e),i=`^`.repeat(n.length);return e=n.start+n.length,t+r+i},``);throw new c(`Path parameters result in path with invalid segments:\n${i.map(e=>e.error).join(`
|
|
2
|
+
`)}\n${a}\n${t}`)}return a})(Ze);var B=class extends L{create(e,t){let{reuseIfExists:n,wait:r,...i}=e;return this._client.post(`/v1/gradle_instances`,{query:{reuseIfExists:n,wait:r},body:i,...t})}list(e={},t){return this._client.getAPIList(`/v1/gradle_instances`,P,{query:e,...t})}delete(e,t){return this._client.delete(z`/v1/gradle_instances/${e}`,{...t,headers:R([{Accept:`*/*`},t?.headers])})}get(e,t){return this._client.get(z`/v1/gradle_instances/${e}`,t)}},V=class extends L{create(e,t){return this._client.post(`/v1/scoped_tokens`,{body:e,...t})}},$e=class extends L{list(e={},t){return this._client.get(`/v1/assets`,{query:e,...t})}delete(e,t){return this._client.delete(z`/v1/assets/${e}`,{...t,headers:R([{Accept:`*/*`},t?.headers])})}get(e,t={},n){return this._client.get(z`/v1/assets/${e}`,{query:t,...n})}getOrCreate(e,t){return this._client.put(`/v1/assets`,{body:e,...t})}};function et(e,t){if(!t)return{body:e};let n=0;return{body:new ReadableStream({pull(r){if(n>=e.length){r.close();return}let i=e.subarray(n,Math.min(n+262144,e.length));n+=i.length,r.enqueue(i),t(n,e.length)}}),duplex:`half`}}var tt=class extends $e{async getOrUpload(e,t){let r=await this.getOrCreate({name:e.name??le(e.path),kind:e.kind??`App`,...e.platform&&{platform:e.platform},...e.ttl&&{ttl:e.ttl},...e.uploadOptions},t),i=await se.readFile(e.path),a=de(`md5`).update(i).digest(`hex`);if(r.md5&&r.md5===a)return{id:r.id,name:r.name,signedDownloadUrl:r.signedDownloadUrl,kind:r.kind,...r.platform&&{platform:r.platform},md5:r.md5,...r.expiresAt&&{expiresAt:r.expiresAt}};let o=await n.fetch(r.signedUploadUrl,{headers:{...e.onUploadProgress&&{"Content-Length":i.length.toString()},"Content-Type":`application/octet-stream`},method:`PUT`,...et(i,e.onUploadProgress)});if(o.status!==200)throw Error(`Failed to upload asset: ${o.status} ${await o.text()}`);return{id:r.id,name:r.name,signedDownloadUrl:r.signedDownloadUrl,kind:r.kind,...r.platform&&{platform:r.platform},md5:a,...r.expiresAt&&{expiresAt:r.expiresAt}}}},nt=class extends L{create(e,t){let{reuseIfExists:n,wait:r,...i}=e;return this._client.post(`/v1/ios_instances`,{query:{reuseIfExists:n,wait:r},body:i,...t})}list(e={},t){return this._client.getAPIList(`/v1/ios_instances`,P,{query:e,...t})}delete(e,t){return this._client.delete(z`/v1/ios_instances/${e}`,{...t,headers:R([{Accept:`*/*`},t?.headers])})}get(e,t){return this._client.get(z`/v1/ios_instances/${e}`,t)}},rt=class extends nt{listSessionArtifacts(e,t,n){return this._client.get(z`/v1/ios_instances/${e}/session_artifacts`,{query:t?{kind:t}:void 0,...n})}listRecordings(e,t){return this.listSessionArtifacts(e,`recording`,t)}listAppLogs(e,t){return this.listSessionArtifacts(e,`appLog`,t)}listEvents(e,t){return this.listSessionArtifacts(e,`eventLog`,t)}},it=class extends L{create(e,t){let{reuseIfExists:n,wait:r,...i}=e;return this._client.post(`/v1/android_instances`,{query:{reuseIfExists:n,wait:r},body:i,...t})}list(e={},t){return this._client.getAPIList(`/v1/android_instances`,P,{query:e,...t})}delete(e,t){return this._client.delete(z`/v1/android_instances/${e}`,{...t,headers:R([{Accept:`*/*`},t?.headers])})}get(e,t){return this._client.get(z`/v1/android_instances/${e}`,t)}},at=class extends it{listSessionArtifacts(e,t,n){return this._client.get(z`/v1/android_instances/${e}/session_artifacts`,{query:t?{kind:t}:void 0,...n})}listRecordings(e,t){return this.listSessionArtifacts(e,`recording`,t)}listAppLogs(e,t){return this.listSessionArtifacts(e,`appLog`,t)}listEvents(e,t){return this.listSessionArtifacts(e,`eventLog`,t)}},ot=class extends L{create(e,t){let{reuseIfExists:n,wait:r,...i}=e;return this._client.post(`/v1/xcode_instances`,{query:{reuseIfExists:n,wait:r},body:i,...t})}list(e={},t){return this._client.getAPIList(`/v1/xcode_instances`,P,{query:e,...t})}delete(e,t){return this._client.delete(z`/v1/xcode_instances/${e}`,{...t,headers:R([{Accept:`*/*`},t?.headers])})}get(e,t){return this._client.get(z`/v1/xcode_instances/${e}`,t)}};function H(e){let t=e.status.token;if(!t)throw Error(`Instance ${e.metadata.id} came back without its token: the credential used can read it but not control it.`);return t}var U=class extends Error{constructor(e){super(`Instance ${e} was gone before it reported any cache status`),this.instanceId=e,this.name=`XcodeCacheGoneError`}},W=class extends Error{constructor(e,t,n){super(`Timed out after ${Math.round(t/1e3)}s waiting for the cache ${e} to finish`+(n?` (last phase: ${n[e].phase})`:``)),this.side=e,this.timeoutMs=t,this.cache=n,this.name=`XcodeCacheTimeoutError`}};const st={restore:12e5,save:72e4};function ct(e){return e===`disabled`||e===`unsupported`||e===`restored`||e===`skipped`||e===`failed`}function lt(e){return e===`disabled`||e===`published`||e===`skipped`||e===`failed`||e===`timed_out`}function ut(e,t){return t===`restore`?ct(e.restore.phase):lt(e.save.phase)}function dt(e,t={}){let r=t.side??`restore`,i=t.timeoutMs??st[r],a=e.baseURL;for(;a.endsWith(`/`);)a=a.slice(0,-1);let o=`${a}/v1/xcode_instances/${encodeURIComponent(e.instanceId)}/cache`;return new Promise((a,s)=>{let c,l=``,u=!1,d=e=>{if(!u){u=!0,clearTimeout(f),t.signal?.removeEventListener(`abort`,m);try{_.close()}catch{}e()}},f=setTimeout(()=>d(()=>s(new W(r,i,c))),i),m=()=>d(()=>s(t.signal?.reason??Error(`aborted`))),h=!1,g=()=>{h||u||(h=!0,n.fetch(o,{headers:{Authorization:`Bearer ${e.apiKey}`,Accept:`application/json`}}).then(async t=>{if(h=!1,t.status!==404){await t.text().catch(()=>void 0);return}d(()=>c?a({cache:c,gone:!0}):s(new U(e.instanceId)))}).catch(()=>{h=!1}))},_=p({url:o,fetch:async(t,r)=>{let i=await n.fetch(t,r);return i.status===404&&d(()=>c?a({cache:c,gone:!0}):s(new U(e.instanceId))),i},onConnect:()=>t.onOpen?.(),headers:{Authorization:`Bearer ${e.apiKey}`,Accept:`text/event-stream`},onMessage:e=>{if(e.event!==`cache`&&e.event!==`gone`)return;let n;try{n=JSON.parse(typeof e.data==`string`?e.data:String(e.data))}catch(e){d(()=>s(Error(`Cache stream sent unreadable data: ${e}`)));return}if(c=n,e.event===`gone`){g();return}let i=`${n.restore.phase}/${n.restore.reason??``}|${n.save.phase}/${n.save.reason??``}`;i!==l&&(l=i,t.onUpdate?.(n)),ut(n,r)&&d(()=>a({cache:n,gone:!1}))}});if(t.signal?.aborted){m();return}t.signal?.addEventListener(`abort`,m,{once:!0})})}var ft=class extends U{constructor(e){super(e),this.name=`XcodeSnapshotGoneError`,this.message=`Instance ${e} was gone before it reported any disk snapshot status`}},pt=class extends W{constructor(e){super(e.side,e.timeoutMs,e.cache),this.name=`XcodeSnapshotTimeoutError`,this.message=e.message.replace(`the cache `,`the disk snapshot `),this.snapshot=e.cache?G(e.cache):void 0}};function G(e){let{cacheKey:t,...n}=e.save;return{...e,save:{...n,...t===void 0?{}:{snapshotKey:t}}}}async function mt(e,t={}){let{onUpdate:n,...r}=t;try{let t=await dt(e,{...r,...n?{onUpdate:e=>n(G(e))}:{}});return{snapshot:G(t.cache),gone:t.gone}}catch(e){throw e instanceof U?new ft(e.instanceId):e instanceof W?new pt(e):e}}function ht(e,t){let n=b.resolve(e),r=`limsync-cache-${b.basename(n)}-${ue.createHash(`sha1`).update(n).digest(`hex`).slice(0,8)}`;return{cacheKey:r,basisCacheDir:t??b.join(ce.tmpdir(),r)}}function K(e,t,n,r){return e.getOrCreate({name:t,ttl:n||`336h`,...r}).catch(e=>{let n=`Failed to create upload URL for asset '${t}': ${e instanceof Error?e.message:e}`;throw Error(n,{cause:e})})}const gt=[`none`,`error`,`warn`,`info`,`debug`];function _t(e,t){let n=gt.indexOf(t),r=e=>n>=gt.indexOf(e);return(t,n)=>{r(t)&&(t===`error`||t===`warn`?console[t](e,n):console.log(e,n))}}function vt(e){return(t,n)=>{if(t.trim()===``)throw Error(`commandLine must not be empty`);if(n?.timeoutSeconds!==void 0&&(!Number.isInteger(n.timeoutSeconds)||n.timeoutSeconds<1||n.timeoutSeconds>21600))throw Error(`timeoutSeconds must be an integer between 1 and 21600`);let r={command:`run`,commandLine:t,cwd:n?.cwd??`.`,...n?.env?.length&&{env:n.env},...n?.timeoutSeconds!==void 0&&{timeoutSeconds:n.timeoutSeconds}};return h(r,e)}}const yt=/^[A-Z0-9_]+$/,bt=4096,xt=65536;function St(e){let t=Object.entries(e);if(t.length>32)throw Error(`too many build settings: got ${t.length}, max 32`);let n=0;for(let[e,r]of t){if(!yt.test(e))throw Error(`invalid build setting key "${e}": keys must match ^[A-Z0-9_]+$`);if(typeof r!=`string`)throw Error(`invalid build setting value for "${e}": value must be a string`);let t=Buffer.byteLength(r,`utf8`);if(t>bt)throw Error(`build setting value for "${e}" is too large: got ${t} bytes, max ${bt} bytes`);if(n+=Buffer.byteLength(e,`utf8`)+t,n>xt)throw Error(`build settings payload is too large: max ${xt} bytes`)}}const Ct=e=>new Promise(t=>setTimeout(t,e)),wt=/failed: (?:502|503|504)\b|\bEOF\b|ECONNRESET|ECONNREFUSED|socket hang up|fetch failed/i;function Tt(e){let t=e instanceof Error?e.message:String(e);return wt.test(t)}async function Et(e,t={}){let n=t.sleep??Ct,r=t.attempts??5,i=t.retryOn??Tt,a;for(let o=1;o<=r;o++)try{return await e()}catch(e){if(!i(e))throw e;if(a=e,o<r){let r=e instanceof Error?e.message:String(e);t.log?.(`Retrying after error (${r.trim()})...`),await n(2e3*o)}}throw a}function Dt(e){if(e===``||e.startsWith(`/`)||e.includes(`\\`)||e.includes(`\0`))throw Error(`invalid sandbox home path from server: ${e}`);let t=e.split(`/`);if(t.some(e=>e===``||e===`.`||e===`..`))throw Error(`invalid sandbox home path from server: ${e}`);return t.join(`/`)}async function Ot(e,t){let r=await J(await n.fetch(`${e}/info`,{method:`GET`,headers:{Authorization:`Bearer ${t}`}}),`GET /info`);if(!r.homeDir)throw Error(`GET /info response is missing homeDir`);return{homeDir:Dt(r.homeDir),...r.xcode?{xcode:r.xcode}:{}}}function kt(e){let t=new URL(e);if(t.protocol===`https:`)t.protocol=`wss:`;else if(t.protocol===`http:`)t.protocol=`ws:`;else throw Error(`Unsupported apiUrl protocol for rbe tunnel: ${t.protocol}`);return t.pathname=`${t.pathname.replace(/\/+$/,``)}/rbe/tunnel`,t.search=``,t.hash=``,t.toString()}var At=class extends c{constructor(e){super(`Remote build execution is not available on this Xcode instance (${e} returned 404). Its limbuild may predate RBE support, or you may be targeting the wrong environment (for example production instead of staging).`),this.name=`RbeUnsupportedError`}},jt=class extends c{constructor(e){super(`Xcode version selection is not available on this sandbox (${e} returned 404): its daemon predates Xcode selection. Create a new sandbox, or omit the Xcode version to build with its default.`),this.name=`XcodeSelectionUnsupportedError`}};function Mt(e,t){return Nt(e,t,e=>new jt(e))}function q(e,t){return Nt(e,t,e=>new At(e))}async function Nt(e,t,n){if(e.status===404)throw await e.text().catch(()=>void 0),n(t);return J(e,t)}async function J(e,t){let n=await e.text();if(!e.ok)throw ie(t,e.status,n,e.headers);if(!n.trim())throw Error(`${t} returned an empty response`);return JSON.parse(n)}var Pt=class extends ot{listBuildLogs(e,t){return this._client.get(z`/v1/xcode_instances/${e}/build_logs`,t)}listBazelBuildLogs(e,t){return this._client.get(z`/v1/xcode_instances/${e}/bazel_build_logs`,t)}create(e,t){if(e.spec?.snapshot!==void 0){let{snapshot:n,cache:r,...i}=e.spec;if(r!==void 0)throw Error(`Use either spec.snapshot or the legacy spec.cache, not both.`);return super.create({...e,spec:{...i,cache:n}},t)}return super.create(e,t)}getSnapshot(e,t){return this.getCache(e,t)._thenUnwrap(G)}bindSnapshotKey(e,t,n){return this.bindCacheKey(e,t,n)._thenUnwrap(G)}followSnapshot(e,t){let n=this._client.apiKey;if(!n)throw Error(`Following disk snapshot status needs an API key on the client`);return mt({baseURL:this._client.baseURL,apiKey:n,instanceId:e},t)}getCache(e,t){return this._client.get(z`/v1/xcode_instances/${e}/cache`,t)}bindCacheKey(e,t,n){return this._client.put(z`/v1/xcode_instances/${e}/cache`,{body:{key:t},...n})}followCache(e,t){let n=this._client.apiKey;if(!n)throw Error(`Following cache status needs an API key on the client`);return dt({baseURL:this._client.baseURL,apiKey:n,instanceId:e},t)}async createClient(e){let t,r;if(`instance`in e){if(!e.instance.status.apiUrl)throw Error(`Instance not ready: apiUrl is not available`);t=e.instance.status.apiUrl,r=H(e.instance)}else t=e.apiUrl,r=e.token;let i=_t(`[XcodeInstance]`,e.logLevel??`info`),a=this._client,o,s=()=>(o??=Ot(t,r),o),c=async e=>{let i,a;if(`status`in e){if(!e.status.apiUrl)throw Error(`Simulator instance not ready: apiUrl is not available`);i=e.status.apiUrl,a=H(e)}else i=e.apiUrl,a=e.token;return J(await n.fetch(`${t}/simulator`,{method:`POST`,headers:{"Content-Type":`application/json`,Authorization:`Bearer ${r}`},body:JSON.stringify({apiUrl:i,token:a})}),`POST /simulator`)},l=async e=>{try{return await a.iosInstances.delete(e),!0}catch{return!1}};return{async sync(e,n){let{cacheKey:a,basisCacheDir:o}=ht(e,n?.basisCacheDir),c=n?.additionalFiles&&n.additionalFiles.length>0?await s():void 0,l=n?.additionalFiles?.map(e=>({localPath:e.localPath,remotePath:c&&e.remotePath.startsWith(`~/`)?`${c.homeDir}/${e.remotePath.slice(2)}`:e.remotePath})),u={apiUrl:t,token:r,udid:a,install:n?.install??!0,ignoreFn:await oe(e,{basisCacheDir:o,log:i,xcodeDefaults:!0,...n?.include?{include:n.include}:{},...n?.ignore?{additional:n.ignore}:{}}),basisCacheDir:o,watch:n?.watch??!0,launchMode:`ForegroundIfRunning`,log:i,syncSymlinks:!0,...l?{additionalFiles:l}:{},...n?.onSyncComplete?{onSyncComplete:n.onSyncComplete}:{}},d=await _(e,u),f={};return d.bytesSent!==void 0&&(f.bytesSent=d.bytesSent),d.stopWatching&&(f.stopWatching=d.stopWatching),f},xcodebuild(e,n){if(n?.reactNative?.devServerURL&&e?.configuration===`Release`)throw Error(`reactNative.devServerURL is only supported for Debug builds`);if(e?.onlyTesting?.length&&e?.skipTesting?.length)throw Error(`onlyTesting and skipTesting are mutually exclusive; pass one`);if((e?.onlyTesting?.length||e?.skipTesting?.length)&&e?.action!==`build-for-testing`)throw Error(`onlyTesting/skipTesting require action: 'build-for-testing'`);if(e?.runTests===!1&&e?.action!==`build-for-testing`)throw Error(`runTests: false requires action: 'build-for-testing'`);if(e?.action===`build-for-testing`&&e.sdk!==void 0&&e.sdk!==`iphonesimulator`)throw Error(`action: 'build-for-testing' requires the iphonesimulator sdk`);n?.buildSettings&&St(n.buildSettings);let o={command:`xcodebuild`,...e&&{xcodebuild:e},...n?.xcodegen&&{xcodegen:n.xcodegen},...n?.reactNative&&{reactNative:n.reactNative},...n?.signing&&{signing:n.signing},...n?.cloudSigning&&{cloudSigning:n.cloudSigning},...n?.appstore&&{testflight:n.appstore},...n?.buildSettings&&{buildSettings:n.buildSettings},...n?.env?.length&&{env:n.env},...n?.gitInit!==void 0&&{gitInit:n.gitInit},...n?.logProcessor&&{logProcessor:n.logProcessor},...n?.webhook&&{webhook:n.webhook}},s={apiUrl:t,token:r,log:i,...n?.onXctestEvent&&{onXctestEvent:n.onXctestEvent}};if(n?.upload&&`assetName`in n.upload){let e=K(a.assets,n.upload.assetName,n.upload.ttl,n.upload.uploadOptions).then(e=>(o.signedUploadUrl=e.signedUploadUrl,o.assetId=e.id,o.additionalMetadata={signedDownloadUrl:e.signedDownloadUrl},o));return h(e,s)}return n?.upload&&`signedUploadUrl`in n.upload&&(o.signedUploadUrl=n.upload.signedUploadUrl),h(o,s)},run:vt({apiUrl:t,token:r,log:i}),observeBuildLogs(e,n){return y(e,{apiUrl:t,token:r,log:i,...n})},async getSimulator(){return J(await n.fetch(`${t}/simulator`,{method:`GET`,headers:{Authorization:`Bearer ${r}`}}),`GET /simulator`)},attachSimulator:c,attachNewSimulator:async()=>{let e=await a.iosInstances.create({wait:!0});try{await c(e)}catch(t){throw await l(e.metadata.id),t}return{iosInstanceId:e.metadata.id,simulator:e}},deleteSimulator:l,async getXcode(){return Mt(await n.fetch(`${t}/xcode`,{method:`GET`,headers:{Authorization:`Bearer ${r}`}}),`GET /xcode`)},async setXcode(e){return Mt(await n.fetch(`${t}/xcode`,{method:`POST`,headers:{"Content-Type":`application/json`,Authorization:`Bearer ${r}`},body:JSON.stringify({version:e})}),`POST /xcode`)},getInfo:()=>Ot(t,r),async startRbe(e){return q(await n.fetch(`${t}/rbe`,{method:`POST`,headers:{"Content-Type":`application/json`,Authorization:`Bearer ${r}`},body:JSON.stringify(e??{})}),`POST /rbe`)},async getRbe(){return q(await n.fetch(`${t}/rbe`,{method:`GET`,headers:{Authorization:`Bearer ${r}`}}),`GET /rbe`)},async stopRbe(){return q(await n.fetch(`${t}/rbe`,{method:`DELETE`,headers:{Authorization:`Bearer ${r}`}}),`DELETE /rbe`)},async startRbeTunnel(n){return te(kt(t),r,n?.host??`127.0.0.1`,n?.port??8980,{mode:`multiplexed`,logLevel:n?.logLevel??e.logLevel??`info`})},async uploadLatestRbeBuild(e){let i,o;if(e.assetName!==void 0){if(!e.assetName)throw Error(`assetName must not be empty`);let t=await K(a.assets,e.assetName,e.ttl);i=t.signedUploadUrl,o=t.signedDownloadUrl}else i=e.signedUploadUrl;return{...await Et(async()=>{let e=await n.fetchLongRequest(`${t}/rbe/upload`,{method:`POST`,headers:{"Content-Type":`application/json`,Authorization:`Bearer ${r}`},body:JSON.stringify({signedUploadUrl:i})});if(e.status===404)throw await e.text().catch(()=>void 0),Error(`POST /rbe/upload returned 404: the instance may no longer exist, or its limbuild predates RBE upload support. Recreate the instance and retry.`);return J(e,`POST /rbe/upload`)},{retryOn:e=>Tt(e)||g(e,400)&&/no successful RBE app build/i.test(e.body)}),...o&&{signedDownloadUrl:o}}},async getActiveRbeBuilds(){return q(await n.fetch(`${t}/rbe/builds/active`,{method:`GET`,headers:{Authorization:`Bearer ${r}`}}),`GET /rbe/builds/active`)},async getRecentRbeBuilds(){return q(await n.fetch(`${t}/rbe/builds/recent`,{method:`GET`,headers:{Authorization:`Bearer ${r}`}}),`GET /rbe/builds/recent`)},waitForRbeBuildEnd(e,i){return new Promise((a,o)=>{if(i?.signal?.aborted){o(Error(`waiting for build ${e} was aborted`));return}let s=!1,c=()=>{f.close(),i?.signal?.removeEventListener(`abort`,d)},l=e=>{s||(s=!0,c(),a(e))},u=e=>{s||(s=!0,c(),o(e))},d=()=>u(Error(`waiting for build ${e} was aborted`)),f=p({url:`${t}/exec/${e}/events`,fetch:re(n.fetch,t=>u(Error(`build event stream for ${e} is unreachable: ${t instanceof Error?t.message:t}`))),headers:{Authorization:`Bearer ${r}`},onMessage:t=>{if(t.event!==`end`)return;let n;try{n=JSON.parse(t.data)}catch(t){u(Error(`invalid build end event for ${e}: ${t}`));return}l(n)},onDisconnect:()=>{u(Error(`build event stream for ${e} ended without a terminal event (the build may have finished and its live stream been removed)`))}});i?.signal?.addEventListener(`abort`,d,{once:!0})})}}}};function Ft(e){let t=e.endsWith(`/`)?e.slice(0,-1):e,n=t.split(`/`);return n[n.length-1]===`local.properties`||n.length===1&&(t===`.gradle`||t===`.kotlin`||t===`build`)}var It=class extends B{listBuildLogs(e,t){return this._client.get(z`/v1/gradle_instances/${e}/build_logs`,t)}async createClient(e){let t,n;if(`instance`in e){if(!e.instance.status.apiUrl)throw Error(`Instance not ready: apiUrl is not available`);t=e.instance.status.apiUrl,n=H(e.instance)}else t=e.apiUrl,n=e.token;let r=_t(`[GradleInstance]`,e.logLevel??`info`),i=this._client;return{async sync(e,i){let{cacheKey:a,basisCacheDir:o}=ht(e,i?.basisCacheDir),s=i?.ignore,c={apiUrl:t,token:n,udid:a,install:!1,ignoreFn:await oe(e,{basisCacheDir:o,log:r,xcodeDefaults:!1,nestedGitignore:!0,additional:s?e=>Ft(e)||s(e):Ft,...i?.include?{include:i.include}:{}}),basisCacheDir:o,watch:i?.watch??!1,launchMode:`ForegroundIfRunning`,log:r,syncSymlinks:!0,...i?.additionalFiles&&{additionalFiles:i.additionalFiles},...i?.onSyncComplete&&{onSyncComplete:i.onSyncComplete}},l=await _(e,c),u={};return l.bytesSent!==void 0&&(u.bytesSent=l.bytesSent),l.stopWatching&&(u.stopWatching=l.stopWatching),u},run:vt({apiUrl:t,token:n,log:r}),gradlebuild(e){let a={command:`gradlebuild`,...e?.env?.length&&{env:e.env},...e?.tasks?.length&&{tasks:e.tasks},...e?.projectPath&&{projectPath:e.projectPath},...e?.reactNative&&{reactNative:e.reactNative},...e?.signing&&{signing:e.signing},...e?.webhook&&{webhook:e.webhook},...e?.playstore&&{playstore:e.playstore}};if(e?.upload&&`assetName`in e.upload){let o=K(i.assets,e.upload.assetName,e.upload.ttl).then(e=>(a.signedUploadUrl=e.signedUploadUrl,a.additionalMetadata={signedDownloadUrl:e.signedDownloadUrl},a));return h(o,{apiUrl:t,token:n,log:r})}return e?.upload&&`signedUploadUrl`in e.upload&&(a.signedUploadUrl=e.upload.signedUploadUrl),h(a,{apiUrl:t,token:n,log:r})},observeBuildLogs(e,i){return y(e,{apiUrl:t,token:n,log:r,...i})}}}};B.prototype.listBuildLogs=It.prototype.listBuildLogs,B.prototype.createClient=It.prototype.createClient;const Y=e=>{if(globalThis.process!==void 0)return globalThis.process.env?.[e]?.trim()||void 0;if(globalThis.Deno!==void 0)return globalThis.Deno.env?.get?.(e)?.trim()||void 0};var X,Z,Q,Lt,$=class{constructor({baseURL:e=Y(`LIMRUN_BASE_URL`),apiKey:t=Y(`LIM_API_KEY`)??null,...n}={}){X.add(this),Q.set(this,void 0),this.androidInstances=new at(this),this.assets=new tt(this),this.iosInstances=new rt(this),this.xcodeInstances=new Pt(this),this.gradleInstances=new B(this),this.analytics=new qe(this),this.scopedTokens=new V(this);let r={apiKey:t,...n,baseURL:e||`https://api.limrun.com`};this.baseURL=r.baseURL,this.timeout=r.timeout??Z.DEFAULT_TIMEOUT,this.logger=r.logger??console;let i=`warn`;this.logLevel=i,this.logLevel=E(r.logLevel,`ClientOptions.logLevel`,this)??E(Y(`LIMRUN_LOG`),`process.env['LIMRUN_LOG']`,this)??i,this.fetchOptions=r.fetchOptions,this.maxRetries=r.maxRetries??2,this.fetch=r.fetch??Oe(),x(this,Q,Me,`f`);let a=Y(`LIMRUN_CUSTOM_HEADERS`);if(a){let e={};for(let t of a.split(`
|
|
3
|
+
`)){let n=t.indexOf(`:`);n>=0&&(e[t.substring(0,n).trim()]=t.substring(n+1).trim())}r.defaultHeaders={...e,...r.defaultHeaders}}this._options=r,this.apiKey=t}withOptions(e){return new this.constructor({...this._options,baseURL:this.baseURL,maxRetries:this.maxRetries,timeout:this.timeout,logger:this.logger,logLevel:this.logLevel,fetch:this.fetch,fetchOptions:this.fetchOptions,apiKey:this.apiKey,...e})}defaultQuery(){return this._options.defaultQuery}validateHeaders({values:e,nulls:t}){if(!(this.apiKey&&e.get(`authorization`))&&!t.has(`authorization`))throw Error(`Could not resolve authentication method. Expected the apiKey to be set. Or for the "Authorization" headers to be explicitly omitted`)}async authHeaders(e){if(this.apiKey!=null)return R([{Authorization:`Bearer ${this.apiKey}`}])}stringifyQuery(e){return Ne(e)}getUserAgent(){return`${this.constructor.name}/JS ${w}`}defaultIdempotencyKey(){return`stainless-node-retry-${fe()}`}makeStatusError(e,t,n,r){return i.generate(e,t,n,r)}buildURL(e,t,n){let r=!S(this,X,`m`,Lt).call(this)&&n||this.baseURL,i=me(e)?new URL(e):new URL(r+(r.endsWith(`/`)&&e.startsWith(`/`)?e.slice(1):e)),a=this.defaultQuery(),o=Object.fromEntries(i.searchParams);return(!_e(a)||!_e(o))&&(t={...o,...a,...t}),typeof t==`object`&&t&&!Array.isArray(t)&&(i.search=this.stringifyQuery(t)),i.toString()}async prepareOptions(e){}async prepareRequest(e,{url:t,options:n}){}get(e,t){return this.methodRequest(`get`,e,t)}post(e,t){return this.methodRequest(`post`,e,t)}patch(e,t){return this.methodRequest(`patch`,e,t)}put(e,t){return this.methodRequest(`put`,e,t)}delete(e,t){return this.methodRequest(`delete`,e,t)}methodRequest(e,t,n){return this.request(Promise.resolve(n).then(n=>({method:e,path:t,...n})))}request(e,t=null){return new Ie(this,this.makeRequest(e,t,void 0))}async makeRequest(e,t,n){let i=await e,a=i.maxRetries??this.maxRetries;t??=a,await this.prepareOptions(i);let{req:o,url:c,timeout:l}=await this.buildRequest(i,{retryCount:a-t});await this.prepareRequest(o,{url:c,options:i});let u=`log_`+(Math.random()*(1<<24)|0).toString(16).padStart(6,`0`),d=n===void 0?``:`, retryOf: ${n}`,p=Date.now();if(A(this).debug(`[${u}] sending request`,j({retryOfRequestLogID:n,method:i.method,url:c,options:i,headers:o.headers})),i.signal?.aborted)throw new r;let h=new AbortController,g=await this.fetchWithTimeout(c,o,l,h).catch(s),_=Date.now();if(g instanceof globalThis.Error){let e=`retrying, ${t} attempts remaining`;if(i.signal?.aborted)throw new r;let a=f(g)||/timed? ?out/i.test(String(g)+(`cause`in g?String(g.cause):``));if(t)return A(this).info(`[${u}] connection ${a?`timed out`:`failed`} - ${e}`),A(this).debug(`[${u}] connection ${a?`timed out`:`failed`} (${e})`,j({retryOfRequestLogID:n,url:c,durationMs:_-p,message:g.message})),this.retryRequest(i,t,n??u);throw A(this).info(`[${u}] connection ${a?`timed out`:`failed`} - error; no more retries left`),A(this).debug(`[${u}] connection ${a?`timed out`:`failed`} (error; no more retries left)`,j({retryOfRequestLogID:n,url:c,durationMs:_-p,message:g.message})),a?new m:new ne({cause:g})}let v=`[${u}${d}] ${o.method} ${c} ${g.ok?`succeeded`:`failed`} with status ${g.status} in ${_-p}ms`;if(!g.ok){let e=await this.shouldRetry(g);if(t&&e){let e=`retrying, ${t} attempts remaining`;return await je(g.body),A(this).info(`${v} - ${e}`),A(this).debug(`[${u}] response error (${e})`,j({retryOfRequestLogID:n,url:g.url,status:g.status,headers:g.headers,durationMs:_-p})),this.retryRequest(i,t,n??u,g.headers)}let r=e?`error; no more retries left`:`error; not retryable`;A(this).info(`${v} - ${r}`);let a=await g.text().catch(e=>s(e).message),o=be(a),c=o?void 0:a;throw A(this).debug(`[${u}] response error (${r})`,j({retryOfRequestLogID:n,url:g.url,status:g.status,headers:g.headers,message:c,durationMs:Date.now()-p})),this.makeStatusError(g.status,o,c,g.headers)}return A(this).info(v),A(this).debug(`[${u}] response start`,j({retryOfRequestLogID:n,url:g.url,status:g.status,headers:g.headers,durationMs:_-p})),{response:g,options:i,controller:h,requestLogID:u,retryOfRequestLogID:n,startTime:p}}getAPIList(e,t,n){return this.requestAPIList(t,n&&`then`in n?n.then(t=>({method:`get`,path:e,...t})):{method:`get`,path:e,...n})}requestAPIList(e,t){let n=this.makeRequest(t,null,void 0);return new Re(this,n,e)}async fetchWithTimeout(e,t,n,r){let{signal:i,method:a,...o}=t||{},s=this._makeAbort(r);i&&i.addEventListener(`abort`,s,{once:!0});let c=setTimeout(s,n),l=globalThis.ReadableStream&&o.body instanceof globalThis.ReadableStream||typeof o.body==`object`&&o.body!==null&&Symbol.asyncIterator in o.body,u={signal:r.signal,...l?{duplex:`half`}:{},method:`GET`,...o};a&&(u.method=a.toUpperCase());try{return await this.fetch.call(void 0,e,u)}finally{clearTimeout(c)}}async shouldRetry(e){let t=e.headers.get(`x-should-retry`);return t===`true`?!0:t===`false`?!1:e.status===408||e.status===409||e.status===429||e.status>=500}async retryRequest(e,t,n,r){let i,a=r?.get(`retry-after-ms`);if(a){let e=parseFloat(a);Number.isNaN(e)||(i=e)}let o=r?.get(`retry-after`);if(o&&!i){let e=parseFloat(o);i=Number.isNaN(e)?Date.parse(o)-Date.now():e*1e3}if(i===void 0){let n=e.maxRetries??this.maxRetries;i=this.calculateDefaultRetryTimeoutMillis(t,n)}return await ae(i),this.makeRequest(e,t-1,n)}calculateDefaultRetryTimeoutMillis(e,t){let n=t-e;return Math.min(.5*2**n,8)*(1-Math.random()*.25)*1e3}async buildRequest(e,{retryCount:t=0}={}){let n={...e},{method:r,path:i,query:a,defaultBaseURL:o}=n,s=this.buildURL(i,a,o);`timeout`in n&&ye(`timeout`,n.timeout),n.timeout=n.timeout??this.timeout;let{bodyHeaders:c,body:l}=this.buildBody({options:n});return{req:{method:r,headers:await this.buildHeaders({options:e,method:r,bodyHeaders:c,retryCount:t}),...n.signal&&{signal:n.signal},...globalThis.ReadableStream&&l instanceof globalThis.ReadableStream&&{duplex:`half`},...l&&{body:l},...this.fetchOptions??{},...n.fetchOptions??{}},url:s,timeout:n.timeout}}async buildHeaders({options:e,method:t,bodyHeaders:n,retryCount:r}){let i={};this.idempotencyHeader&&t!==`get`&&(e.idempotencyKey||=this.defaultIdempotencyKey(),i[this.idempotencyHeader]=e.idempotencyKey);let a=R([i,{Accept:`application/json`,"User-Agent":this.getUserAgent(),"X-Stainless-Retry-Count":String(r),...e.timeout?{"X-Stainless-Timeout":String(Math.trunc(e.timeout/1e3))}:{},...De()},await this.authHeaders(e),this._options.defaultHeaders,n,e.headers]);return this.validateHeaders(a),a.values}_makeAbort(e){return()=>e.abort()}buildBody({options:e}){let{body:t,headers:n}=e;if(!t)return t==null&&`body`in e?S(this,Q,`f`).call(this,{body:t,headers:R([n])}):{bodyHeaders:void 0,body:void 0};let r=R([n]);return ArrayBuffer.isView(t)||t instanceof ArrayBuffer||t instanceof DataView||typeof t==`string`&&r.values.has(`content-type`)||globalThis.Blob&&t instanceof globalThis.Blob||t instanceof FormData||t instanceof URLSearchParams||globalThis.ReadableStream&&t instanceof globalThis.ReadableStream?{bodyHeaders:void 0,body:t}:typeof t==`object`&&(Symbol.asyncIterator in t||Symbol.iterator in t&&`next`in t&&typeof t.next==`function`)?{bodyHeaders:void 0,body:Ae(t)}:typeof t==`object`&&r.values.get(`content-type`)===`application/x-www-form-urlencoded`?{bodyHeaders:{"content-type":`application/x-www-form-urlencoded`},body:this.stringifyQuery(t)}:S(this,Q,`f`).call(this,{body:t,headers:r})}};Z=$,Q=new WeakMap,X=new WeakSet,Lt=function(){return this.baseURL!==`https://api.limrun.com`},$.Limrun=Z,$.DEFAULT_TIMEOUT=3e5,$.LimrunError=c,$.APIError=i,$.APIConnectionError=ne,$.APIConnectionTimeoutError=m,$.APIUserAbortError=r,$.NotFoundError=l,$.ConflictError=t,$.RateLimitError=a,$.BadRequestError=ee,$.AuthenticationError=u,$.InternalServerError=v,$.PermissionDeniedError=d,$.UnprocessableEntityError=o,$.toFile=Ge,$.AndroidInstances=at,$.Assets=tt,$.IosInstances=rt,$.XcodeInstances=Pt,$.GradleInstances=B,$.Analytics=qe,$.ScopedTokens=V,process.platform;const Rt=`agent-device-cli`;function zt(e){return{apiKey:e.apiKey,defaultHeaders:{"x-agent-device-client":Rt,"x-agent-device-version":e.clientVersion}}}function Bt(t,n,r=`This daemon drives an existing Limrun instance with its own token. Set LIMRUN_API_KEY, or ask the instance owner to do this.`){if(t)return t;throw new e(`UNSUPPORTED_OPERATION`,`${n} requires a Limrun API key.`,{hint:r})}export{$ as i,zt as n,Bt as r,Rt as t};
|
|
@@ -319,6 +319,12 @@ type AndroidSnapshotBackendMetadata = {
|
|
|
319
319
|
captureMode?: string;
|
|
320
320
|
systemSurfaceOnly?: boolean;
|
|
321
321
|
windowCount?: number;
|
|
322
|
+
/**
|
|
323
|
+
* `AccessibilityWindowInfo` types of the listed windows the helper could not serialize because
|
|
324
|
+
* reading their root returned null or threw (`2` is an input method window); `windowCount` counts
|
|
325
|
+
* only the roots it serialized. Empty when every listed window was read. Absent on an older helper.
|
|
326
|
+
*/
|
|
327
|
+
missingRootWindowTypes?: number[];
|
|
322
328
|
nodeCount?: number;
|
|
323
329
|
helperTruncated?: boolean;
|
|
324
330
|
elapsedMs?: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{j as e}from"./owner-identity.js";import"./file.js";import{a as t,r as n,s as r,t as i}from"./code-signature.js";import a from"node:crypto";import o from"node:fs";import s from"node:os";import c from"node:path";function l(e,a){let o=t(a),s=t(e),c=v(s,o),l=i(o,s),d=u(c,o,l);if(d)return n(d.files);let p;try{p=r(s,o)}catch{return`unknown`}return f(p.files,l)&&_(c,p),n(p.files)}function u(e,t,n){let r=p(e);if(!(!r||!f(r.files,n))){for(let[e,n,i]of r.files){let r=d(c.resolve(t,e));if(!r?.isFile()||r.size!==n||Math.trunc(r.mtimeMs)!==i)return}for(let e of r.absentPaths)if(d(c.resolve(t,e))?.isFile())return;return r}}function d(e){try{return o.statSync(e)}catch{return}}function f(e,t){return e.some(([e])=>e===t)}function p(e){let t=m(e);if(!t)return;let n=[];for(let e of t.files){let t=g(e);if(!t)return;n.push(t)}if(t.absent.every(e=>typeof e==`string`))return{files:n,absentPaths:t.absent}}function m(e){let t=h(e);if(t===void 0)return;let n;try{n=JSON.parse(t)}catch{return}if(!n||typeof n!=`object`)return;let r=n;if(r.version===2&&!(!Array.isArray(r.files)||!Array.isArray(r.absent)))return{files:r.files,absent:r.absent}}function h(e){let t;try{t=o.openSync(e,`r`)}catch{return}try{let e=process.getuid?.();return e!==void 0&&o.fstatSync(t).uid!==e?void 0:o.readFileSync(t,`utf8`)}catch{return}finally{o.closeSync(t)}}function g(e){if(!Array.isArray(e)||e.length!==3)return;let[t,n,r]=e;if(typeof t==`string`&&typeof n==`number`&&typeof r==`number`)return[t,n,r]}function _(t,n){let r={version:2,files:[...n.files],absent:[...n.absentPaths]};try{o.mkdirSync(c.dirname(t),{recursive:!0,mode:448}),e({destination:t,contents:JSON.stringify(r),mode:384})}catch{}}function v(e,t){let n=a.createHash(`sha1`).update(`${t} ${e}`).digest(`hex`),r=`agent-device-code-signature-${process.getuid?.()??`user`}`;return c.join(s.tmpdir(),r,`${n}.json`)}export{l as resolveCachedDaemonCodeSignature};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{P as e,d as t,l as n,p as r}from"./sdk-contracts.js";import{r as i}from"./diagnostics.js";import"./diagnostics2.js";import{C as a,D as o,o as s,s as c,w as l}from"./sdk-device.js";import{a as u,c as d,l as f,r as p}from"./lease-scope.js";import{n as m,t as h}from"./catalog.js";import{t as g}from"./sdk-remote-config.js";import{t as _}from"./prepare-kind.js";import{A as v}from"./owner-identity.js";import{p as y}from"./exec.js";import"./file.js";import"./command.js";import{t as ee}from"./daemon-resolution.js";import{_ as b}from"./base-url.js";import{i as te,r as ne}from"./client-metro-companion.js";import{n as re}from"./metro2.js";import{n as ie,r as x,t as ae}from"./remote-config2.js";import{a as S,n as C}from"./providers.js";import w from"node:crypto";import T from"node:fs";import E from"node:path";const D={slug:`react-devtools-companion`,runArg:b,displayName:`React DevTools companion`};async function oe(e){return await ne({...e,definition:D,localBaseUrl:e.localBaseUrl??`http://127.0.0.1:8097`,registerPath:`/api/react-devtools/companion/register`,unregisterPath:`/api/react-devtools/companion/unregister`,devicePort:e.devicePort??8097})}async function O(e){return await te({...e,definition:D})}function se(e){return e===`android-instance`||e===`ios-instance`}function ce(e){return[`exec`,`--yes`,`--package`,`agent-cdp@1.6.1`,`--`,`agent-cdp`,...e]}function le(e){return e.some(e=>e===`--url`||e.startsWith(`--url=`))}function ue(e){return e[0]===`target`&&(e[1]===`list`||e[1]===`select`)&&!le(e)}function de(e){let t=new URL(e);t.search=``,t.hash=``;let n=t.pathname.replace(/\/+$/,``);return t.pathname=n.endsWith(`/index.bundle`)?n.slice(0,-13)||`/`:n||`/`,t.toString().replace(/\/+$/,``)}function fe(e){let t=e?.metroPublicBaseUrl?.trim();return t?de(t):null}function pe(t,n={}){if(!ue(t)||!n.flags?.metroProxyBaseUrl||!se(n.flags.leaseBackend))return t;let r=fe(n.flags);if(!r)throw new e(`INVALID_ARGS`,`cdp remote bridge target discovery requires a React Native dev-server public base URL.`,{hint:`Include metroPublicBaseUrl in the remote config so cdp can reach the local or tunneled Metro/Re.Pack CDP endpoint without bridge proxy authentication.`});return[...t,`--url`,r]}async function me(e,t={}){let n=pe(e,t);return(await y(`npm`,ce(n),{cwd:t.cwd??process.cwd(),env:t.env??process.env,allowFailure:!0,onStdoutChunk:e=>{process.stdout.write(e)},onStderrChunk:e=>{process.stderr.write(e)}})).exitCode}function k(e){let n=l(e),r=t(n);return{platform:n,target:e.target,leaseBackend:r,identityFlag:r?c(n):void 0,id:e.id}}function he(e){return`${e.platform}:${e.target??`mobile`}:${e.id}`}function A(e){let t=[e.leaseBackend?r(e.leaseBackend):void 0,e.recordedPlatform].filter(e=>e!==void 0);if(t.some(e=>t.some(t=>a(e,t)))||a(e.requestedPlatform,t[0]??e.recordedPlatform))return{ok:!1,boundPlatform:t[0],requestedPlatform:e.requestedPlatform};let n=[...t,e.requestedPlatform].filter(e=>e!==void 0);return{ok:!0,platform:n.find(e=>e!==`apple`)??n[0]}}function ge(e,t){return t!==void 0&&e.platform===void 0?!1:A({leaseBackend:e.leaseBackend,recordedPlatform:e.platform,requestedPlatform:t}).ok}function j(e){let t=R(e);if(!T.existsSync(t))return null;let n;try{n=JSON.parse(T.readFileSync(t,`utf8`))}catch(t){return U(e,t),null}return Ce(n)?n:(U(e),null)}function M(e){let t=R({stateDir:e.stateDir,session:e.state.session});T.mkdirSync(E.dirname(t),{recursive:!0}),H(t,e.state),H(z(e.stateDir),{session:e.state.session})}function N(e){return{baseUrl:xe(e.daemonBaseUrl),transport:e.daemonTransport,serverMode:e.daemonServerMode}}function P(e){T.rmSync(R(e),{force:!0});let t=z(e.stateDir);V(e.stateDir)===e.session&&T.rmSync(t,{force:!0})}function _e(t){let n=t.validateRemoteConfigHash??!0,r=t.remoteConfig?ie({configPath:t.remoteConfig,cwd:t.cwd,env:t.env}):void 0,i=j(t)??(t.allowActiveFallback?B({stateDir:t.stateDir}):null);if(!i||r&&i.remoteConfigPath!==r)return null;if(n&&L(i.remoteConfigPath)!==i.remoteConfigHash)throw new e(`INVALID_ARGS`,`Active remote connection config changed. Run agent-device connect --force to refresh it.`,{remoteConfig:i.remoteConfigPath});let a=be(i,t),o=u(i);return{runtime:i.runtime,connection:f(o),flags:{...a,remoteConfig:i.remoteConfigPath,daemonBaseUrl:i.daemon?.baseUrl??a.daemonBaseUrl,daemonAuthToken:a.daemonAuthToken,daemonTransport:i.daemon?.transport??a.daemonTransport,daemonServerMode:i.daemon?.serverMode??a.daemonServerMode,...d(o),sessionIsolation:`tenant`,session:i.session,platform:i.platform??a.platform,target:i.target??a.target}}}function F(e){return f(u(e))}function I(e,t){return{leaseProvider:e.leaseProvider??t.leaseProvider,clientId:e.clientId??t.clientId,deviceKey:e.deviceKey??t.deviceKey}}function ve(e,t){return!t||(t.leaseProvider===void 0||e.leaseProvider===t.leaseProvider)&&(t.clientId===void 0||e.clientId===t.clientId)}function L(t){try{return w.createHash(`sha256`).update(T.readFileSync(t)).digest(`hex`)}catch(n){throw new e(`INVALID_ARGS`,`Remote config file not found: ${t}`,{cause:n instanceof Error?n.message:String(n)})}}function R(e){return E.join(e.stateDir,`remote-connections`,`${Se(e.session)}.json`)}function z(e){return E.join(e,`remote-connections`,`.active-session.json`)}function B(e){let t=V(e.stateDir);return t?j({stateDir:e.stateDir,session:t}):null}function V(e){let t=z(e);if(T.existsSync(t))try{let e=JSON.parse(T.readFileSync(t,`utf8`));return typeof e.session==`string`?e.session:void 0}catch{return}}function ye(e){if(e)return w.createHash(`sha256`).update(e).digest(`hex`).slice(0,12)}function be(e,t){try{return x({configPath:e.remoteConfigPath,cwd:t.cwd,env:t.env}).profile}catch(e){if(t.validateRemoteConfigHash===!1)return{};throw e}}function H(e,t){v({destination:e,contents:`${JSON.stringify(t,null,2)}\n`,mode:384})}function xe(e){if(!e)return;let t=new URL(e);t.username=``,t.password=``;for(let e of Array.from(t.searchParams.keys()))/(auth|key|password|secret|token)/i.test(e)&&t.searchParams.delete(e);return t.toString().replace(/\/+$/,``)}function U(e,t){i({level:`warn`,phase:`remote_connection_state_invalid`,data:{session:e.session,cause:t instanceof Error?t.message:t?String(t):void 0}}),P(e)}function Se(e){let t=e.replaceAll(/[^a-zA-Z0-9._-]/g,`_`);return t?t===e?t:`${t}-${w.createHash(`sha256`).update(e).digest(`hex`).slice(0,8)}`:`default`}function Ce(e){if(!e||typeof e!=`object`||Array.isArray(e))return!1;let t=e;return t.version===1&&we(t,[`session`,`remoteConfigPath`,`remoteConfigHash`,`tenant`,`runId`,`connectedAt`,`updatedAt`])&&Te(t,[`leaseId`,`leaseBackend`,`leaseProvider`,`deviceKey`,`clientId`])&&Ee(t.daemon)}function we(e,t){return t.every(t=>typeof e[t]==`string`)}function Te(e,t){return t.every(t=>e[t]===void 0||typeof e[t]==`string`)}function Ee(e){return e===void 0?!0:!e||typeof e!=`object`||Array.isArray(e)?!1:De(e)}function De(e){let t=e;return(t.baseUrl===void 0||typeof t.baseUrl==`string`)&&(t.authToken===void 0||typeof t.authToken==`string`)&&(t.transport===void 0||typeof t.transport==`string`)&&(t.serverMode===void 0||typeof t.serverMode==`string`)}const Oe=g.map(e=>e.key);function W(e){let t={};for(let n of Oe){let r=e[n];r!==void 0&&(t[n]=r)}return t}function ke(e){return e.remoteConfig?{...W(x({configPath:e.remoteConfig,cwd:e.cwd,env:e.env}).profile),remoteConfig:e.remoteConfig}:{}}function Ae(e){return e===`cloud`||e===`proxy`||G(e)}function G(e){return e===`limrun`||S(e)}function je(){return[`cloud`,`proxy`,C.browserStack,C.awsDeviceFarm,`limrun`].join(`, `)}function K(e){let t=G(e),n=S(e);return{leaseKind:e===`proxy`?`proxy`:t?`direct-device-provider`:`remote-provider`,requiresAppAttachment:e===C.awsDeviceFarm,requiresRemoteDaemon:!t,supportsArtifacts:n,supportsDeferredAppSelection:e===`limrun`,supportsDirectPortReverse:e===`limrun`,usesCloudWebDriverLease:n}}function q(e){return{providerDeviceOrientation:e.providerDeviceOrientation,providerGeoLocation:e.providerGeoLocation,providerTimezone:e.providerTimezone,providerAppiumVersion:e.providerAppiumVersion,providerLanguage:e.providerLanguage,providerLocale:e.providerLocale,providerNetworkProfile:e.providerNetworkProfile,providerCustomNetwork:e.providerCustomNetwork,providerNoResignApp:e.providerNoResignApp}}function Me(e){return{metroProjectRoot:e.metroProjectRoot,metroKind:e.metroKind,metroPublicBaseUrl:e.metroPublicBaseUrl,metroProxyBaseUrl:e.metroProxyBaseUrl,metroPreparePort:e.metroPreparePort,metroListenHost:e.metroListenHost,metroStatusHost:e.metroStatusHost,metroStartupTimeoutMs:e.metroStartupTimeoutMs,metroProbeTimeoutMs:e.metroProbeTimeoutMs,metroRuntimeFile:e.metroRuntimeFile,metroNoReuseExisting:e.metroNoReuseExisting,metroNoInstallDeps:e.metroNoInstallDeps,launchUrl:e.launchUrl}}const J=new Set([`artifacts`,`connect`,`connection`,`close`,`disconnect`,`metro`,`session`]),Ne=new Set([`open`]),Pe=new Set([m.open,m.install,m.reinstall,h.installSource]);async function Fe(t){let{command:n,flags:r,client:i}=t;if(!r.remoteConfig)return{flags:r,runtime:t.runtime};let a=ee(r.stateDir).baseDir,o=x({configPath:r.remoteConfig,cwd:process.cwd(),env:process.env}),s={...W(o.profile),...r,remoteConfig:o.resolvedPath},c=j({stateDir:a,session:s.session??`default`});if(c&&c.remoteConfigPath!==o.resolvedPath)throw new e(`INVALID_ARGS`,`A different remote connection is already active for this session. Run connect --force or disconnect before using a different --remote-config.`,{session:c.session,activeRemoteConfig:c.remoteConfigPath,requestedRemoteConfig:o.resolvedPath});let l=c??lt(s,o.resolvedPath,o.profile),u={...s,session:l.session},d=K(l.leaseProvider).supportsDeferredAppSelection,f=d&&n===m.open?t.positionals?.[0]:void 0;d&&delete u.providerApp;let p=ct(l.runtime,u.platform)??t.runtime,h=l,g=!c,_,v=Ue(h);if(v.shouldAllocate(n)){let e=await Be({command:n,client:i,state:l,nextState:h,nextFlags:u,initialApp:f,policy:v});h=e.state,g||=e.changed,_=e.acquiredLeaseForCleanup}let y=A({leaseBackend:h.leaseBackend,recordedPlatform:h.platform,requestedPlatform:u.platform});if(!y.ok)throw $({session:l.session,leaseBackend:h.leaseBackend,boundPlatform:y.boundPlatform,requestedPlatform:y.requestedPlatform,detail:`bound-connection`});h={...h,platform:y.platform},u.platform=y.platform;let b=await Ie({command:n,flags:u,client:i,state:l,nextState:h,runtime:p,positionals:t.positionals,batchSteps:t.batchSteps,forceRuntimePrepare:t.forceRuntimePrepare});return h=b.state,p=b.runtime,g||=b.changed,await ze({changed:g,stateDir:a,state:h,client:i,acquiredLeaseForCleanup:_,preparedMetroCleanupOnFailure:b.preparedMetroCleanupOnFailure,metroCleanupToStop:b.metroCleanupToStop}),{flags:{...u,session:h.session,leaseId:h.leaseId,leaseBackend:h.leaseBackend,platform:h.platform??u.platform,target:h.target??u.target},runtime:p,connection:F(h)}}async function Ie(t){let{command:n,flags:r,state:i,client:a}=t,o=Le(t.nextState,r),s=t.runtime;if(!ot(n,r,t.batchSteps,t.positionals)||!Z(r)||!Re(t.forceRuntimePrepare,s,r.platform))return{state:o,runtime:s,changed:!1};if(!o.leaseId)throw new e(`INVALID_ARGS`,`${n} requires a resolved remote lease before Metro runtime can be prepared.`);let c=await Ye(r,a,i.remoteConfigPath,i.session,{tenantId:i.tenant,runId:i.runId,leaseId:o.leaseId}),l=!st(o.metro,c.cleanup);return o={...o,runtime:c.runtime,metro:c.cleanup,updatedAt:new Date().toISOString()},{state:o,runtime:c.runtime,changed:!0,metroCleanupToStop:l?t.nextState.metro:void 0,preparedMetroCleanupOnFailure:l?c.cleanup:void 0}}function Le(e,t){return e.leaseId||!t.leaseId?e:{...e,leaseId:t.leaseId,leaseBackend:t.leaseBackend}}function Re(e,t,n){return e===!0||!t||!Q(t,n)}async function ze(e){if(e.changed)try{M({stateDir:e.stateDir,state:e.state})}catch(t){throw await Y(e.preparedMetroCleanupOnFailure),await it(e.client,e.state,e.acquiredLeaseForCleanup),t}await Y(e.metroCleanupToStop)}async function Be(e){let{command:t,client:n,state:r,nextFlags:i,policy:a}=e,o=r.leaseBackend??X(i),s=e.nextState,c=await a.resolveLeaseState({command:t,client:n,state:s,flags:i,leaseBackend:o});s=c.state,c.device&&ft(i,c.device);let l=s.leaseBackend??o??at(i,t);mt(r,l);let u=A({leaseBackend:l,recordedPlatform:s.platform,requestedPlatform:i.platform});if(!u.ok)throw $({session:r.session,leaseBackend:l,boundPlatform:u.boundPlatform,requestedPlatform:u.requestedPlatform,detail:`bound-connection`});ht(r,i),s={...s,platform:u.platform},i.platform=u.platform;let d=await ut(n,s,l,a,i,e.initialApp),f=d.lease;return i.leaseId=f.leaseId,i.leaseBackend=l,i.target=s.target??i.target,Ve(s,f,l)?{state:s,changed:!1,acquiredLeaseForCleanup:d.acquired?f:void 0}:{state:He(s,f,l,i),changed:!0,acquiredLeaseForCleanup:d.acquired?f:void 0}}function Ve(e,t,n){return e.leaseId===t.leaseId&&e.leaseBackend===n&&e.deviceKey===(t.deviceKey??e.deviceKey)}function He(e,t,n,r){let i=I(t,e);return{...e,leaseId:t.leaseId,leaseBackend:n,...i,platform:e.platform??r.platform,target:e.target??r.target,updatedAt:new Date().toISOString()}}function Ue(e){if(e.leaseBackend===`macos-app`)return qe;let t=K(e.leaseProvider);return t.leaseKind===`proxy`?Ke:t.supportsDeferredAppSelection?We:t.usesCloudWebDriverLease?Je:Ge}const We={shouldAllocate:e=>e!==m.apps&&!J.has(e),ttlMs:()=>void 0,resolveLeaseState:async e=>({state:e.state})},Ge={shouldAllocate:e=>!J.has(e),ttlMs:()=>void 0,resolveLeaseState:async e=>({state:e.state})},Ke={shouldAllocate:e=>e!==`devices`&&!J.has(e),ttlMs:()=>3e5,resolveLeaseState:dt},qe={shouldAllocate:e=>e!==`devices`&&!J.has(e),ttlMs:()=>void 0,resolveLeaseState:async({state:t})=>{if(!t.leaseId||!t.deviceKey)throw new e(`INVALID_ARGS`,`A macos-app connection needs the leaseId and deviceKey the host allocated in its remote config.`);return{state:{...t,platform:`macos`}}}},Je={shouldAllocate:e=>!J.has(e),ttlMs:()=>6e5,resolveLeaseState:async e=>({state:e.state})};async function Ye(t,n,r,i,a){if(!t.metroProjectRoot&&!t.metroPublicBaseUrl&&!t.metroProxyBaseUrl)return{};if(t.platform!==`ios`&&t.platform!==`android`)throw new e(`INVALID_ARGS`,`Deferred Metro preparation requires platform "ios" or "android".`);if(!t.metroPublicBaseUrl&&!t.metroProxyBaseUrl)throw new e(`INVALID_ARGS`,`Deferred Metro preparation requires metroPublicBaseUrl or metroProxyBaseUrl when Metro settings are provided.`);let o=await n.metro.prepare({projectRoot:t.metroProjectRoot,kind:_(t.metroKind),publicBaseUrl:t.metroPublicBaseUrl,proxyBaseUrl:t.metroProxyBaseUrl,bearerToken:t.metroBearerToken,bridgeScope:a,launchUrl:t.launchUrl,companionProfileKey:r,companionConsumerKey:i,port:t.metroPreparePort,listenHost:t.metroListenHost,statusHost:t.metroStatusHost,startupTimeoutMs:t.metroStartupTimeoutMs,probeTimeoutMs:t.metroProbeTimeoutMs,reuseExisting:!t.metroNoReuseExisting&&void 0,installDependenciesIfNeeded:!t.metroNoInstallDeps&&void 0,runtimeFilePath:t.metroRuntimeFile});return{runtime:t.platform===`ios`?o.iosRuntime:o.androidRuntime,cleanup:t.metroProxyBaseUrl?{projectRoot:o.projectRoot,profileKey:r,consumerKey:i}:void 0}}async function Y(e){if(e)try{await re(e)}catch{}}async function Xe(e){try{await O({projectRoot:process.cwd(),stateDir:e.stateDir,profileKey:e.state.remoteConfigPath,consumerKey:e.state.session})}catch{}}function Ze(e){return e.leaseBackend===`macos-app`}async function Qe(e,t,n){return!t.leaseId||Ze(t)?{released:!1}:await e.leases.release({tenant:t.tenant,runId:t.runId,leaseId:t.leaseId,leaseBackend:t.leaseBackend,daemonBaseUrl:t.daemon?.baseUrl,daemonAuthToken:n,daemonTransport:t.daemon?.transport,daemonServerMode:t.daemon?.serverMode,...F(t)})}function $e(e){let t=et(e.previous,e.cwd,e.env);return t?{canAuthenticate:!0,daemonAuthToken:t}:e.previous.daemon?.baseUrl===e.nextDaemonBaseUrl?{canAuthenticate:!0,daemonAuthToken:e.ambientDaemonAuthToken}:{canAuthenticate:!1}}function et(e,t,n){try{let{profile:r}=ae({configPath:e.remoteConfigPath,cwd:t,env:n});return r.daemonAuthToken&&tt(e,r.daemonBaseUrl)?r.daemonAuthToken:void 0}catch{return}}function tt(e,t){let n=N({daemonBaseUrl:t})?.baseUrl;return n!==void 0&&n===e.daemon?.baseUrl}async function nt(e,t,n){if(!t.leaseId||Ze(t))return;let r=$e({previous:t,nextDaemonBaseUrl:n.nextDaemonBaseUrl,ambientDaemonAuthToken:n.ambientDaemonAuthToken,cwd:n.cwd,env:n.env});if(!r.canAuthenticate)return rt(t,`no credential known to belong to that endpoint was available`);try{await Qe(e,t,r.daemonAuthToken);return}catch{return rt(t,`the release request failed`)}}function rt(e,t){return{status:`unreleased`,message:`Could not release the previous lease ${e.leaseId} (tenant ${e.tenant}, run ${e.runId}) at ${e.daemon?.baseUrl??`its daemon`}: ${t}. It was left in place — release it manually if it is still active.`}}async function it(e,t,n){if(n)try{let r=I(t,n);await e.leases.release({tenant:t.tenant,runId:t.runId,leaseId:n.leaseId,leaseBackend:t.leaseBackend??n.backend,...r})}catch{}}function X(e){return e.leaseBackend??t(e.platform)}function at(t,n){let r=X(t);if(r)return r;throw new e(`INVALID_ARGS`,`${n} requires --platform ios|android|harmonyos or --lease-backend when the remote connection has not resolved a lease yet.`)}function ot(e,t,n,r=[]){return e===`cdp`?ue(r)&&!!t.metroPublicBaseUrl:Ne.has(e)?!0:e!==`batch`||!n?!1:n.some(e=>{let t=e.command.trim().toLowerCase();return Ne.has(t)&&e.runtime===void 0})}function Z(e){let t=e.metroKind;return!!(e.metroPublicBaseUrl||e.metroProxyBaseUrl||e.metroProjectRoot||t)}function Q(e,t){return!e.platform||!t||!n(t)||e.platform===t}function st(e,t){return e?.projectRoot===t?.projectRoot&&e?.profileKey===t?.profileKey&&e?.consumerKey===t?.consumerKey}function ct(e,t){if(e)return Q(e,t)?e:void 0}function lt(t,n,r={}){if(!t.tenant)throw new e(`INVALID_ARGS`,`remote command requires tenant in remote config or via --tenant <id>.`);if(!t.runId)throw new e(`INVALID_ARGS`,`remote command requires runId in remote config or via --run-id <id>.`);if(!t.daemonBaseUrl&&K(r.leaseProvider).requiresRemoteDaemon)throw new e(`INVALID_ARGS`,`remote command requires daemonBaseUrl in remote config, config, env, or --daemon-base-url.`);let i=new Date().toISOString();return{version:1,session:t.session??`default`,remoteConfigPath:n,remoteConfigHash:L(n),daemon:N(t),tenant:t.tenant,runId:t.runId,leaseId:t.leaseId,leaseBackend:t.leaseBackend??X(t),leaseProvider:r.leaseProvider,clientId:r.clientId,deviceKey:r.deviceKey,platform:t.platform,target:t.target,connectedAt:i,updatedAt:i}}async function ut(t,n,r,i,a,o){let s=F(n);if(n.leaseId&&n.leaseBackend===r){let e=await gt(t,n.leaseId,{tenant:n.tenant,runId:n.runId,leaseBackend:r,...s,ttlMs:i.ttlMs(n)});if(e)return{lease:e,acquired:!1}}if(r===`macos-app`)throw new e(`UNAUTHORIZED`,`The host-allocated macos-app lease is no longer active.`,{reason:`LEASE_NOT_FOUND`,leaseId:n.leaseId,hint:`Ask the host for a new macos-app lease and update the remote config.`});return{lease:await t.leases.allocate({tenant:n.tenant,runId:n.runId,leaseBackend:r,...s,ttlMs:i.ttlMs(n),platform:n.platform??a.platform,target:n.target??a.target,device:a.device,udid:a.udid,serial:a.serial,providerApp:o??a.providerApp,providerOsVersion:a.providerOsVersion,providerProject:a.providerProject,providerBuild:a.providerBuild,providerSessionName:a.providerSessionName,...q(a),awsProjectArn:a.awsProjectArn,awsDeviceArn:a.awsDeviceArn,awsAppArn:a.awsAppArn,awsRegion:a.awsRegion,awsInteractionMode:a.awsInteractionMode}),acquired:!0}}async function dt(t){if(!Pe.has(t.command)){if(t.state.leaseId&&t.state.deviceKey)return{state:t.state};throw new e(`INVALID_ARGS`,`No active proxy device lease for this session; run open first.`)}let n=await pt(t.client,t.flags),r=k(n);return{state:{...t.state,deviceKey:he(r),leaseBackend:t.state.leaseBackend??t.leaseBackend??r.leaseBackend,platform:r.platform,target:t.state.target??r.target,updatedAt:new Date().toISOString()},device:n}}function ft(e,t){let n=k(t);e.platform=n.platform,e.target=n.target??e.target,n.identityFlag===`udid`&&(e.udid=n.id),n.identityFlag===`serial`&&(e.serial=n.id)}async function pt(e,t){let n=await e.devices.list({platform:t.platform,target:t.target,device:t.device,udid:t.udid,serial:t.serial,iosSimulatorDeviceSet:t.iosSimulatorDeviceSet,androidDeviceAllowlist:t.androidDeviceAllowlist});return await o(n.map(e=>({...s(e.platform),id:e.id,name:e.name,kind:e.kind,target:e.target,booted:e.booted})),{platform:t.platform,target:t.target,deviceName:t.device,udid:t.udid,serial:t.serial})}function $(t){return new e(`INVALID_ARGS`,t.detail===`bound-connection`?`Active remote connection is already bound to a different platform. Re-run connect --force to replace it.`:`The requested platform does not match the device this lease backend rents.`,{session:t.session,leaseBackend:t.leaseBackend,platform:t.boundPlatform,requestedPlatform:t.requestedPlatform,reason:`CONNECTION_PLATFORM_CONFLICT`})}function mt(t,n){if(t.leaseBackend&&t.leaseBackend!==n)throw new e(`INVALID_ARGS`,`Active remote connection is already bound to a different lease backend. Re-run connect --force to replace it.`,{session:t.session,leaseBackend:t.leaseBackend})}function ht(t,n){if(t.target&&n.target&&t.target!==n.target)throw new e(`INVALID_ARGS`,`Active remote connection is already bound to a different target. Re-run connect --force to replace it.`,{session:t.session,target:t.target})}async function gt(e,t,n){try{return await e.leases.heartbeat({...n,leaseId:t})}catch(e){if(p(e))return;throw e}}export{se as A,B as C,_e as D,P as E,O as M,M as O,A as S,ve as T,F as _,Qe as a,L as b,Xe as c,je as d,K as f,N as g,ke as h,nt as i,oe as j,me as k,q as l,W as m,Z as n,X as o,Ae as p,Fe as r,Y as s,$ as t,Me as u,ge as v,j as w,I as x,ye as y};
|
|
1
|
+
import{P as e,d as t,l as n,p as r}from"./sdk-contracts.js";import{r as i}from"./diagnostics.js";import"./diagnostics2.js";import{C as a,D as o,o as s,s as c,w as l}from"./sdk-device.js";import{a as u,c as d,l as f,r as p}from"./lease-scope.js";import{n as m,t as h}from"./catalog.js";import{t as g}from"./sdk-remote-config.js";import{t as _}from"./prepare-kind.js";import{j as v}from"./owner-identity.js";import{p as y}from"./exec.js";import"./file.js";import"./command.js";import{t as ee}from"./daemon-resolution.js";import{_ as b}from"./base-url.js";import{i as te,r as ne}from"./client-metro-companion.js";import{n as re}from"./metro2.js";import{n as ie,r as x,t as ae}from"./remote-config2.js";import{a as S,n as C}from"./providers.js";import w from"node:crypto";import T from"node:fs";import E from"node:path";const D={slug:`react-devtools-companion`,runArg:b,displayName:`React DevTools companion`};async function oe(e){return await ne({...e,definition:D,localBaseUrl:e.localBaseUrl??`http://127.0.0.1:8097`,registerPath:`/api/react-devtools/companion/register`,unregisterPath:`/api/react-devtools/companion/unregister`,devicePort:e.devicePort??8097})}async function O(e){return await te({...e,definition:D})}function se(e){return e===`android-instance`||e===`ios-instance`}function ce(e){return[`exec`,`--yes`,`--package`,`agent-cdp@1.6.1`,`--`,`agent-cdp`,...e]}function le(e){return e.some(e=>e===`--url`||e.startsWith(`--url=`))}function ue(e){return e[0]===`target`&&(e[1]===`list`||e[1]===`select`)&&!le(e)}function de(e){let t=new URL(e);t.search=``,t.hash=``;let n=t.pathname.replace(/\/+$/,``);return t.pathname=n.endsWith(`/index.bundle`)?n.slice(0,-13)||`/`:n||`/`,t.toString().replace(/\/+$/,``)}function fe(e){let t=e?.metroPublicBaseUrl?.trim();return t?de(t):null}function pe(t,n={}){if(!ue(t)||!n.flags?.metroProxyBaseUrl||!se(n.flags.leaseBackend))return t;let r=fe(n.flags);if(!r)throw new e(`INVALID_ARGS`,`cdp remote bridge target discovery requires a React Native dev-server public base URL.`,{hint:`Include metroPublicBaseUrl in the remote config so cdp can reach the local or tunneled Metro/Re.Pack CDP endpoint without bridge proxy authentication.`});return[...t,`--url`,r]}async function me(e,t={}){let n=pe(e,t);return(await y(`npm`,ce(n),{cwd:t.cwd??process.cwd(),env:t.env??process.env,allowFailure:!0,onStdoutChunk:e=>{process.stdout.write(e)},onStderrChunk:e=>{process.stderr.write(e)}})).exitCode}function k(e){let n=l(e),r=t(n);return{platform:n,target:e.target,leaseBackend:r,identityFlag:r?c(n):void 0,id:e.id}}function he(e){return`${e.platform}:${e.target??`mobile`}:${e.id}`}function A(e){let t=[e.leaseBackend?r(e.leaseBackend):void 0,e.recordedPlatform].filter(e=>e!==void 0);if(t.some(e=>t.some(t=>a(e,t)))||a(e.requestedPlatform,t[0]??e.recordedPlatform))return{ok:!1,boundPlatform:t[0],requestedPlatform:e.requestedPlatform};let n=[...t,e.requestedPlatform].filter(e=>e!==void 0);return{ok:!0,platform:n.find(e=>e!==`apple`)??n[0]}}function ge(e,t){return t!==void 0&&e.platform===void 0?!1:A({leaseBackend:e.leaseBackend,recordedPlatform:e.platform,requestedPlatform:t}).ok}function j(e){let t=R(e);if(!T.existsSync(t))return null;let n;try{n=JSON.parse(T.readFileSync(t,`utf8`))}catch(t){return U(e,t),null}return Ce(n)?n:(U(e),null)}function M(e){let t=R({stateDir:e.stateDir,session:e.state.session});T.mkdirSync(E.dirname(t),{recursive:!0}),H(t,e.state),H(z(e.stateDir),{session:e.state.session})}function N(e){return{baseUrl:xe(e.daemonBaseUrl),transport:e.daemonTransport,serverMode:e.daemonServerMode}}function P(e){T.rmSync(R(e),{force:!0});let t=z(e.stateDir);V(e.stateDir)===e.session&&T.rmSync(t,{force:!0})}function _e(t){let n=t.validateRemoteConfigHash??!0,r=t.remoteConfig?ie({configPath:t.remoteConfig,cwd:t.cwd,env:t.env}):void 0,i=j(t)??(t.allowActiveFallback?B({stateDir:t.stateDir}):null);if(!i||r&&i.remoteConfigPath!==r)return null;if(n&&L(i.remoteConfigPath)!==i.remoteConfigHash)throw new e(`INVALID_ARGS`,`Active remote connection config changed. Run agent-device connect --force to refresh it.`,{remoteConfig:i.remoteConfigPath});let a=be(i,t),o=u(i);return{runtime:i.runtime,connection:f(o),flags:{...a,remoteConfig:i.remoteConfigPath,daemonBaseUrl:i.daemon?.baseUrl??a.daemonBaseUrl,daemonAuthToken:a.daemonAuthToken,daemonTransport:i.daemon?.transport??a.daemonTransport,daemonServerMode:i.daemon?.serverMode??a.daemonServerMode,...d(o),sessionIsolation:`tenant`,session:i.session,platform:i.platform??a.platform,target:i.target??a.target}}}function F(e){return f(u(e))}function I(e,t){return{leaseProvider:e.leaseProvider??t.leaseProvider,clientId:e.clientId??t.clientId,deviceKey:e.deviceKey??t.deviceKey}}function ve(e,t){return!t||(t.leaseProvider===void 0||e.leaseProvider===t.leaseProvider)&&(t.clientId===void 0||e.clientId===t.clientId)}function L(t){try{return w.createHash(`sha256`).update(T.readFileSync(t)).digest(`hex`)}catch(n){throw new e(`INVALID_ARGS`,`Remote config file not found: ${t}`,{cause:n instanceof Error?n.message:String(n)})}}function R(e){return E.join(e.stateDir,`remote-connections`,`${Se(e.session)}.json`)}function z(e){return E.join(e,`remote-connections`,`.active-session.json`)}function B(e){let t=V(e.stateDir);return t?j({stateDir:e.stateDir,session:t}):null}function V(e){let t=z(e);if(T.existsSync(t))try{let e=JSON.parse(T.readFileSync(t,`utf8`));return typeof e.session==`string`?e.session:void 0}catch{return}}function ye(e){if(e)return w.createHash(`sha256`).update(e).digest(`hex`).slice(0,12)}function be(e,t){try{return x({configPath:e.remoteConfigPath,cwd:t.cwd,env:t.env}).profile}catch(e){if(t.validateRemoteConfigHash===!1)return{};throw e}}function H(e,t){v({destination:e,contents:`${JSON.stringify(t,null,2)}\n`,mode:384})}function xe(e){if(!e)return;let t=new URL(e);t.username=``,t.password=``;for(let e of Array.from(t.searchParams.keys()))/(auth|key|password|secret|token)/i.test(e)&&t.searchParams.delete(e);return t.toString().replace(/\/+$/,``)}function U(e,t){i({level:`warn`,phase:`remote_connection_state_invalid`,data:{session:e.session,cause:t instanceof Error?t.message:t?String(t):void 0}}),P(e)}function Se(e){let t=e.replaceAll(/[^a-zA-Z0-9._-]/g,`_`);return t?t===e?t:`${t}-${w.createHash(`sha256`).update(e).digest(`hex`).slice(0,8)}`:`default`}function Ce(e){if(!e||typeof e!=`object`||Array.isArray(e))return!1;let t=e;return t.version===1&&we(t,[`session`,`remoteConfigPath`,`remoteConfigHash`,`tenant`,`runId`,`connectedAt`,`updatedAt`])&&Te(t,[`leaseId`,`leaseBackend`,`leaseProvider`,`deviceKey`,`clientId`])&&Ee(t.daemon)}function we(e,t){return t.every(t=>typeof e[t]==`string`)}function Te(e,t){return t.every(t=>e[t]===void 0||typeof e[t]==`string`)}function Ee(e){return e===void 0?!0:!e||typeof e!=`object`||Array.isArray(e)?!1:De(e)}function De(e){let t=e;return(t.baseUrl===void 0||typeof t.baseUrl==`string`)&&(t.authToken===void 0||typeof t.authToken==`string`)&&(t.transport===void 0||typeof t.transport==`string`)&&(t.serverMode===void 0||typeof t.serverMode==`string`)}const Oe=g.map(e=>e.key);function W(e){let t={};for(let n of Oe){let r=e[n];r!==void 0&&(t[n]=r)}return t}function ke(e){return e.remoteConfig?{...W(x({configPath:e.remoteConfig,cwd:e.cwd,env:e.env}).profile),remoteConfig:e.remoteConfig}:{}}function Ae(e){return e===`cloud`||e===`proxy`||G(e)}function G(e){return e===`limrun`||S(e)}function je(){return[`cloud`,`proxy`,C.browserStack,C.awsDeviceFarm,`limrun`].join(`, `)}function K(e){let t=G(e),n=S(e);return{leaseKind:e===`proxy`?`proxy`:t?`direct-device-provider`:`remote-provider`,requiresAppAttachment:e===C.awsDeviceFarm,requiresRemoteDaemon:!t,supportsArtifacts:n,supportsDeferredAppSelection:e===`limrun`,supportsDirectPortReverse:e===`limrun`,usesCloudWebDriverLease:n}}function q(e){return{providerDeviceOrientation:e.providerDeviceOrientation,providerGeoLocation:e.providerGeoLocation,providerTimezone:e.providerTimezone,providerAppiumVersion:e.providerAppiumVersion,providerLanguage:e.providerLanguage,providerLocale:e.providerLocale,providerNetworkProfile:e.providerNetworkProfile,providerCustomNetwork:e.providerCustomNetwork,providerNoResignApp:e.providerNoResignApp}}function Me(e){return{metroProjectRoot:e.metroProjectRoot,metroKind:e.metroKind,metroPublicBaseUrl:e.metroPublicBaseUrl,metroProxyBaseUrl:e.metroProxyBaseUrl,metroPreparePort:e.metroPreparePort,metroListenHost:e.metroListenHost,metroStatusHost:e.metroStatusHost,metroStartupTimeoutMs:e.metroStartupTimeoutMs,metroProbeTimeoutMs:e.metroProbeTimeoutMs,metroRuntimeFile:e.metroRuntimeFile,metroNoReuseExisting:e.metroNoReuseExisting,metroNoInstallDeps:e.metroNoInstallDeps,launchUrl:e.launchUrl}}const J=new Set([`artifacts`,`connect`,`connection`,`close`,`disconnect`,`metro`,`session`]),Ne=new Set([`open`]),Pe=new Set([m.open,m.install,m.reinstall,h.installSource]);async function Fe(t){let{command:n,flags:r,client:i}=t;if(!r.remoteConfig)return{flags:r,runtime:t.runtime};let a=ee(r.stateDir).baseDir,o=x({configPath:r.remoteConfig,cwd:process.cwd(),env:process.env}),s={...W(o.profile),...r,remoteConfig:o.resolvedPath},c=j({stateDir:a,session:s.session??`default`});if(c&&c.remoteConfigPath!==o.resolvedPath)throw new e(`INVALID_ARGS`,`A different remote connection is already active for this session. Run connect --force or disconnect before using a different --remote-config.`,{session:c.session,activeRemoteConfig:c.remoteConfigPath,requestedRemoteConfig:o.resolvedPath});let l=c??lt(s,o.resolvedPath,o.profile),u={...s,session:l.session},d=K(l.leaseProvider).supportsDeferredAppSelection,f=d&&n===m.open?t.positionals?.[0]:void 0;d&&delete u.providerApp;let p=ct(l.runtime,u.platform)??t.runtime,h=l,g=!c,_,v=Ue(h);if(v.shouldAllocate(n)){let e=await Be({command:n,client:i,state:l,nextState:h,nextFlags:u,initialApp:f,policy:v});h=e.state,g||=e.changed,_=e.acquiredLeaseForCleanup}let y=A({leaseBackend:h.leaseBackend,recordedPlatform:h.platform,requestedPlatform:u.platform});if(!y.ok)throw $({session:l.session,leaseBackend:h.leaseBackend,boundPlatform:y.boundPlatform,requestedPlatform:y.requestedPlatform,detail:`bound-connection`});h={...h,platform:y.platform},u.platform=y.platform;let b=await Ie({command:n,flags:u,client:i,state:l,nextState:h,runtime:p,positionals:t.positionals,batchSteps:t.batchSteps,forceRuntimePrepare:t.forceRuntimePrepare});return h=b.state,p=b.runtime,g||=b.changed,await ze({changed:g,stateDir:a,state:h,client:i,acquiredLeaseForCleanup:_,preparedMetroCleanupOnFailure:b.preparedMetroCleanupOnFailure,metroCleanupToStop:b.metroCleanupToStop}),{flags:{...u,session:h.session,leaseId:h.leaseId,leaseBackend:h.leaseBackend,platform:h.platform??u.platform,target:h.target??u.target},runtime:p,connection:F(h)}}async function Ie(t){let{command:n,flags:r,state:i,client:a}=t,o=Le(t.nextState,r),s=t.runtime;if(!ot(n,r,t.batchSteps,t.positionals)||!Z(r)||!Re(t.forceRuntimePrepare,s,r.platform))return{state:o,runtime:s,changed:!1};if(!o.leaseId)throw new e(`INVALID_ARGS`,`${n} requires a resolved remote lease before Metro runtime can be prepared.`);let c=await Ye(r,a,i.remoteConfigPath,i.session,{tenantId:i.tenant,runId:i.runId,leaseId:o.leaseId}),l=!st(o.metro,c.cleanup);return o={...o,runtime:c.runtime,metro:c.cleanup,updatedAt:new Date().toISOString()},{state:o,runtime:c.runtime,changed:!0,metroCleanupToStop:l?t.nextState.metro:void 0,preparedMetroCleanupOnFailure:l?c.cleanup:void 0}}function Le(e,t){return e.leaseId||!t.leaseId?e:{...e,leaseId:t.leaseId,leaseBackend:t.leaseBackend}}function Re(e,t,n){return e===!0||!t||!Q(t,n)}async function ze(e){if(e.changed)try{M({stateDir:e.stateDir,state:e.state})}catch(t){throw await Y(e.preparedMetroCleanupOnFailure),await it(e.client,e.state,e.acquiredLeaseForCleanup),t}await Y(e.metroCleanupToStop)}async function Be(e){let{command:t,client:n,state:r,nextFlags:i,policy:a}=e,o=r.leaseBackend??X(i),s=e.nextState,c=await a.resolveLeaseState({command:t,client:n,state:s,flags:i,leaseBackend:o});s=c.state,c.device&&ft(i,c.device);let l=s.leaseBackend??o??at(i,t);mt(r,l);let u=A({leaseBackend:l,recordedPlatform:s.platform,requestedPlatform:i.platform});if(!u.ok)throw $({session:r.session,leaseBackend:l,boundPlatform:u.boundPlatform,requestedPlatform:u.requestedPlatform,detail:`bound-connection`});ht(r,i),s={...s,platform:u.platform},i.platform=u.platform;let d=await ut(n,s,l,a,i,e.initialApp),f=d.lease;return i.leaseId=f.leaseId,i.leaseBackend=l,i.target=s.target??i.target,Ve(s,f,l)?{state:s,changed:!1,acquiredLeaseForCleanup:d.acquired?f:void 0}:{state:He(s,f,l,i),changed:!0,acquiredLeaseForCleanup:d.acquired?f:void 0}}function Ve(e,t,n){return e.leaseId===t.leaseId&&e.leaseBackend===n&&e.deviceKey===(t.deviceKey??e.deviceKey)}function He(e,t,n,r){let i=I(t,e);return{...e,leaseId:t.leaseId,leaseBackend:n,...i,platform:e.platform??r.platform,target:e.target??r.target,updatedAt:new Date().toISOString()}}function Ue(e){if(e.leaseBackend===`macos-app`)return qe;let t=K(e.leaseProvider);return t.leaseKind===`proxy`?Ke:t.supportsDeferredAppSelection?We:t.usesCloudWebDriverLease?Je:Ge}const We={shouldAllocate:e=>e!==m.apps&&!J.has(e),ttlMs:()=>void 0,resolveLeaseState:async e=>({state:e.state})},Ge={shouldAllocate:e=>!J.has(e),ttlMs:()=>void 0,resolveLeaseState:async e=>({state:e.state})},Ke={shouldAllocate:e=>e!==`devices`&&!J.has(e),ttlMs:()=>3e5,resolveLeaseState:dt},qe={shouldAllocate:e=>e!==`devices`&&!J.has(e),ttlMs:()=>void 0,resolveLeaseState:async({state:t})=>{if(!t.leaseId||!t.deviceKey)throw new e(`INVALID_ARGS`,`A macos-app connection needs the leaseId and deviceKey the host allocated in its remote config.`);return{state:{...t,platform:`macos`}}}},Je={shouldAllocate:e=>!J.has(e),ttlMs:()=>6e5,resolveLeaseState:async e=>({state:e.state})};async function Ye(t,n,r,i,a){if(!t.metroProjectRoot&&!t.metroPublicBaseUrl&&!t.metroProxyBaseUrl)return{};if(t.platform!==`ios`&&t.platform!==`android`)throw new e(`INVALID_ARGS`,`Deferred Metro preparation requires platform "ios" or "android".`);if(!t.metroPublicBaseUrl&&!t.metroProxyBaseUrl)throw new e(`INVALID_ARGS`,`Deferred Metro preparation requires metroPublicBaseUrl or metroProxyBaseUrl when Metro settings are provided.`);let o=await n.metro.prepare({projectRoot:t.metroProjectRoot,kind:_(t.metroKind),publicBaseUrl:t.metroPublicBaseUrl,proxyBaseUrl:t.metroProxyBaseUrl,bearerToken:t.metroBearerToken,bridgeScope:a,launchUrl:t.launchUrl,companionProfileKey:r,companionConsumerKey:i,port:t.metroPreparePort,listenHost:t.metroListenHost,statusHost:t.metroStatusHost,startupTimeoutMs:t.metroStartupTimeoutMs,probeTimeoutMs:t.metroProbeTimeoutMs,reuseExisting:!t.metroNoReuseExisting&&void 0,installDependenciesIfNeeded:!t.metroNoInstallDeps&&void 0,runtimeFilePath:t.metroRuntimeFile});return{runtime:t.platform===`ios`?o.iosRuntime:o.androidRuntime,cleanup:t.metroProxyBaseUrl?{projectRoot:o.projectRoot,profileKey:r,consumerKey:i}:void 0}}async function Y(e){if(e)try{await re(e)}catch{}}async function Xe(e){try{await O({projectRoot:process.cwd(),stateDir:e.stateDir,profileKey:e.state.remoteConfigPath,consumerKey:e.state.session})}catch{}}function Ze(e){return e.leaseBackend===`macos-app`}async function Qe(e,t,n){return!t.leaseId||Ze(t)?{released:!1}:await e.leases.release({tenant:t.tenant,runId:t.runId,leaseId:t.leaseId,leaseBackend:t.leaseBackend,daemonBaseUrl:t.daemon?.baseUrl,daemonAuthToken:n,daemonTransport:t.daemon?.transport,daemonServerMode:t.daemon?.serverMode,...F(t)})}function $e(e){let t=et(e.previous,e.cwd,e.env);return t?{canAuthenticate:!0,daemonAuthToken:t}:e.previous.daemon?.baseUrl===e.nextDaemonBaseUrl?{canAuthenticate:!0,daemonAuthToken:e.ambientDaemonAuthToken}:{canAuthenticate:!1}}function et(e,t,n){try{let{profile:r}=ae({configPath:e.remoteConfigPath,cwd:t,env:n});return r.daemonAuthToken&&tt(e,r.daemonBaseUrl)?r.daemonAuthToken:void 0}catch{return}}function tt(e,t){let n=N({daemonBaseUrl:t})?.baseUrl;return n!==void 0&&n===e.daemon?.baseUrl}async function nt(e,t,n){if(!t.leaseId||Ze(t))return;let r=$e({previous:t,nextDaemonBaseUrl:n.nextDaemonBaseUrl,ambientDaemonAuthToken:n.ambientDaemonAuthToken,cwd:n.cwd,env:n.env});if(!r.canAuthenticate)return rt(t,`no credential known to belong to that endpoint was available`);try{await Qe(e,t,r.daemonAuthToken);return}catch{return rt(t,`the release request failed`)}}function rt(e,t){return{status:`unreleased`,message:`Could not release the previous lease ${e.leaseId} (tenant ${e.tenant}, run ${e.runId}) at ${e.daemon?.baseUrl??`its daemon`}: ${t}. It was left in place — release it manually if it is still active.`}}async function it(e,t,n){if(n)try{let r=I(t,n);await e.leases.release({tenant:t.tenant,runId:t.runId,leaseId:n.leaseId,leaseBackend:t.leaseBackend??n.backend,...r})}catch{}}function X(e){return e.leaseBackend??t(e.platform)}function at(t,n){let r=X(t);if(r)return r;throw new e(`INVALID_ARGS`,`${n} requires --platform ios|android|harmonyos or --lease-backend when the remote connection has not resolved a lease yet.`)}function ot(e,t,n,r=[]){return e===`cdp`?ue(r)&&!!t.metroPublicBaseUrl:Ne.has(e)?!0:e!==`batch`||!n?!1:n.some(e=>{let t=e.command.trim().toLowerCase();return Ne.has(t)&&e.runtime===void 0})}function Z(e){let t=e.metroKind;return!!(e.metroPublicBaseUrl||e.metroProxyBaseUrl||e.metroProjectRoot||t)}function Q(e,t){return!e.platform||!t||!n(t)||e.platform===t}function st(e,t){return e?.projectRoot===t?.projectRoot&&e?.profileKey===t?.profileKey&&e?.consumerKey===t?.consumerKey}function ct(e,t){if(e)return Q(e,t)?e:void 0}function lt(t,n,r={}){if(!t.tenant)throw new e(`INVALID_ARGS`,`remote command requires tenant in remote config or via --tenant <id>.`);if(!t.runId)throw new e(`INVALID_ARGS`,`remote command requires runId in remote config or via --run-id <id>.`);if(!t.daemonBaseUrl&&K(r.leaseProvider).requiresRemoteDaemon)throw new e(`INVALID_ARGS`,`remote command requires daemonBaseUrl in remote config, config, env, or --daemon-base-url.`);let i=new Date().toISOString();return{version:1,session:t.session??`default`,remoteConfigPath:n,remoteConfigHash:L(n),daemon:N(t),tenant:t.tenant,runId:t.runId,leaseId:t.leaseId,leaseBackend:t.leaseBackend??X(t),leaseProvider:r.leaseProvider,clientId:r.clientId,deviceKey:r.deviceKey,platform:t.platform,target:t.target,connectedAt:i,updatedAt:i}}async function ut(t,n,r,i,a,o){let s=F(n);if(n.leaseId&&n.leaseBackend===r){let e=await gt(t,n.leaseId,{tenant:n.tenant,runId:n.runId,leaseBackend:r,...s,ttlMs:i.ttlMs(n)});if(e)return{lease:e,acquired:!1}}if(r===`macos-app`)throw new e(`UNAUTHORIZED`,`The host-allocated macos-app lease is no longer active.`,{reason:`LEASE_NOT_FOUND`,leaseId:n.leaseId,hint:`Ask the host for a new macos-app lease and update the remote config.`});return{lease:await t.leases.allocate({tenant:n.tenant,runId:n.runId,leaseBackend:r,...s,ttlMs:i.ttlMs(n),platform:n.platform??a.platform,target:n.target??a.target,device:a.device,udid:a.udid,serial:a.serial,providerApp:o??a.providerApp,providerOsVersion:a.providerOsVersion,providerProject:a.providerProject,providerBuild:a.providerBuild,providerSessionName:a.providerSessionName,...q(a),awsProjectArn:a.awsProjectArn,awsDeviceArn:a.awsDeviceArn,awsAppArn:a.awsAppArn,awsRegion:a.awsRegion,awsInteractionMode:a.awsInteractionMode}),acquired:!0}}async function dt(t){if(!Pe.has(t.command)){if(t.state.leaseId&&t.state.deviceKey)return{state:t.state};throw new e(`INVALID_ARGS`,`No active proxy device lease for this session; run open first.`)}let n=await pt(t.client,t.flags),r=k(n);return{state:{...t.state,deviceKey:he(r),leaseBackend:t.state.leaseBackend??t.leaseBackend??r.leaseBackend,platform:r.platform,target:t.state.target??r.target,updatedAt:new Date().toISOString()},device:n}}function ft(e,t){let n=k(t);e.platform=n.platform,e.target=n.target??e.target,n.identityFlag===`udid`&&(e.udid=n.id),n.identityFlag===`serial`&&(e.serial=n.id)}async function pt(e,t){let n=await e.devices.list({platform:t.platform,target:t.target,device:t.device,udid:t.udid,serial:t.serial,iosSimulatorDeviceSet:t.iosSimulatorDeviceSet,androidDeviceAllowlist:t.androidDeviceAllowlist});return await o(n.map(e=>({...s(e.platform),id:e.id,name:e.name,kind:e.kind,target:e.target,booted:e.booted})),{platform:t.platform,target:t.target,deviceName:t.device,udid:t.udid,serial:t.serial})}function $(t){return new e(`INVALID_ARGS`,t.detail===`bound-connection`?`Active remote connection is already bound to a different platform. Re-run connect --force to replace it.`:`The requested platform does not match the device this lease backend rents.`,{session:t.session,leaseBackend:t.leaseBackend,platform:t.boundPlatform,requestedPlatform:t.requestedPlatform,reason:`CONNECTION_PLATFORM_CONFLICT`})}function mt(t,n){if(t.leaseBackend&&t.leaseBackend!==n)throw new e(`INVALID_ARGS`,`Active remote connection is already bound to a different lease backend. Re-run connect --force to replace it.`,{session:t.session,leaseBackend:t.leaseBackend})}function ht(t,n){if(t.target&&n.target&&t.target!==n.target)throw new e(`INVALID_ARGS`,`Active remote connection is already bound to a different target. Re-run connect --force to replace it.`,{session:t.session,target:t.target})}async function gt(e,t,n){try{return await e.leases.heartbeat({...n,leaseId:t})}catch(e){if(p(e))return;throw e}}export{se as A,B as C,_e as D,P as E,O as M,M as O,A as S,ve as T,F as _,Qe as a,L as b,Xe as c,je as d,K as f,N as g,ke as h,nt as i,oe as j,me as k,q as l,W as m,Z as n,X as o,Ae as p,Fe as r,Y as s,$ as t,Me as u,ge as v,j as w,I as x,ye as y};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as e}from"./rolldown-runtime.js";import{J as t,P as n}from"./sdk-contracts.js";import{i as r,l as i,r as a}from"./diagnostics.js";import"./diagnostics2.js";import{
|
|
1
|
+
import{r as e}from"./rolldown-runtime.js";import{J as t,P as n}from"./sdk-contracts.js";import{i as r,l as i,r as a}from"./diagnostics.js";import"./diagnostics2.js";import{S as o,j as s,m as c,o as l,r as u,w as d,x as f}from"./owner-identity.js";import{f as p}from"./exec.js";import{t as m}from"./timeouts.js";import{i as h,n as g,r as _}from"./file.js";import"./command.js";import"./process.js";import{t as v}from"./daemon-resolution.js";import"./retry.js";import{n as y}from"./session-repair-tombstone.js";import{i as b,n as x,r as S}from"./daemon-registration.js";import{r as C,t as w}from"./daemon-shutdown-report.js";import T from"node:fs";import E from"node:os";import D from"node:path";async function O(e,t){let{logPath:n,command:a=`daemon`,debug:o=!0}=e;return await i({command:a,session:`daemon`,logPath:n,debug:o},async()=>{try{return await t()}finally{r({force:!0})}})}const k=[/\/dist\/src\/daemon\.js($|[\s"'])/,/\/dist\/src\/internal\/daemon\.js($|[\s"'])/,/\/src\/daemon\.ts($|[\s"'])/];function A(e){let t=e.toLowerCase().replaceAll(`\\`,`/`);return k.some(e=>e.test(t))}function ee(e,t){if(!t||!c(e))return!1;let n=d(e);if(!n||n!==t)return!1;let r=o(e);return r?A(r):!1}function te(e,t){try{return process.kill(e,t),!0}catch(e){let t=e.code;if(t===`ESRCH`||t===`EPERM`)return!1;throw e}}async function j(e,t){if(!u(e.pid))return{exited:!1,elapsedMs:0};let n=Date.now(),r=n+t.timeoutMs,i=t.pollMs??100,a=()=>{if(!c(e.pid))return!0;let t=f([e.pid]).get(e.pid);return!!(t?.state.startsWith(`Z`)||t?.startTime&&t.startTime!==e.startTime)},o=a();for(;!o&&Date.now()<r;)await m(Math.min(i,Math.max(0,r-Date.now()))),o=a();return{exited:o,elapsedMs:Date.now()-n}}async function M(e,t){if(!u(e.pid))return{status:`retained`,reason:`identity-unverified`};if(!e.startTime?.trim())return c(e.pid)?{status:`retained`,reason:`missing-start-time`}:{status:`not-running`};let n={pid:e.pid,startTime:e.startTime};if((await j(n,{timeoutMs:0})).exited)return{status:`exited`,identity:n,mode:`already-exited`};let r;if(t.mode===`graceful`){let e=await N(n,{signal:`SIGTERM`,timeoutMs:t.termTimeoutMs});if(e.status!==`survived`)return e;r=`SIGTERM`}let i=await N(n,{signal:`SIGKILL`,timeoutMs:t.killTimeoutMs,previousSignal:r});return i.status===`survived`?{status:`retained`,reason:`exit-timeout`}:i}async function N(e,t){let n=ee(e.pid,e.startTime),r=n&&te(e.pid,t.signal),i=r?t.signal===`SIGTERM`?`graceful`:`forced`:t.previousSignal?`graceful`:`already-exited`;return(await j(e,{timeoutMs:i===`already-exited`?0:t.timeoutMs})).exited?{status:`exited`,identity:e,mode:i}:r?{status:`survived`}:{status:`retained`,signal:t.signal,reason:n?`signal-failed`:`identity-unverified`}}var P=e({DAEMON_STARTUP_EXIT_CODES:()=>F,createOwnedReplayStateDir:()=>H,launchDaemonProcess:()=>U,recoverAbandonedDaemonRegistration:()=>Y,stopAndRetireDaemon:()=>K,tryAcquireDaemonRegistration:()=>I});const F=Object.freeze({busy:75,unproven:78});async function I(e){let t={...e},n=l(),r=h({lockDirPath:t.lockPath,owner:{...n,acquiredAtMs:Date.now()},description:`daemon registration`});if(r.status!==`acquired`)return r;let{acquisition:i}=r;try{i.assertHeld(),T.rmSync(C(t.baseDir),{force:!0})}catch(e){await R(i,e,t.logPath)}return{status:`acquired`,owner:Object.freeze({publish({socketPort:e,httpPort:r,...a}){i.assertHeld(),B(t.logPath);let o=e&&r?`dual`:r?`http`:`socket`;i.assertHeld(),s({destination:t.infoPath,contents:JSON.stringify({...a,port:e,httpPort:r,transport:o,pid:n.pid,processStartTime:n.startTime??void 0,stateDir:t.baseDir},null,2),mode:384})},async finish(e){let r;try{e&&z(t.baseDir,e,i),r=L(t.infoPath,n,i)}catch(e){return await R(i,e,t.logPath)}return await i.release(),r}})}}function L(e,t,n){n.assertHeld();let r=b(e,t);if(r.state!==`match`)return r;n.assertHeld();try{T.unlinkSync(e)}catch(e){if(e.code!==`ENOENT`)throw e}return{state:`removed`}}async function R(e,t,n){try{await e.release()}catch(e){await Q(n,`daemon_registration_release_failed`,e)}throw t}function z(e,t,n){let r=C(e),i=`${JSON.stringify(w(t))}\n`;n.assertHeld();try{s({destination:r,contents:i,mode:384})}catch{return}}function B(e){let t=T.openSync(e,`a`,384);try{T.ftruncateSync(t,0)}finally{T.closeSync(t)}}const V=new WeakMap;function H(){let e=Object.freeze(v(T.mkdtempSync(D.join(E.tmpdir(),`agent-device-replay-daemon-`)))),t=Object.freeze({paths:e});return V.set(t,{paths:e,startups:[],sealed:!1}),t}function U(e){let t=e.ownedStateDir&&G(e.ownedStateDir,e.paths);if(t?.sealed)throw new n(`COMMAND_FAILED`,`Replay daemon startup admission is closed.`,{reason:`daemon_startup_admission_closed`});T.mkdirSync(e.paths.baseDir,{recursive:!0});let r=T.openSync(e.paths.logPath,`a`);try{let n=p(process.execPath,e.args,{env:{...process.env,AGENT_DEVICE_STATE_DIR:e.paths.baseDir,AGENT_DEVICE_DAEMON_SERVER_MODE:e.serverMode},stdio:[`ignore`,r,r]}),i={...e.paths},a={launch:Object.freeze({...n,get startTime(){return a.startTime},readIdentity(){return W(i,a),{pid:n.pid,startTime:a.startTime??null}}}),joined:!1};return t&&t.startups.push(a),n.exited.then(()=>{a.joined=!0}),a.startTime=d(n.pid)??void 0,a.launch}finally{T.closeSync(r)}}function W(e,t){if(t.startTime||t.joined)return;let n=S(e.infoPath);if(n?.pid!==t.launch.pid||!n.startTime)return;let r=_(e.lockPath);x(r,n)&&(t.startTime=n.startTime)}function G(e,t){let r=V.get(e);if(!r||Object.entries(r.paths).some(([e,n])=>t[e]!==n))throw new n(`COMMAND_FAILED`,`Private replay directory ownership could not be verified.`,{reason:`daemon_private_state_unowned`});return r}async function K(e){let n,r=e.observed;try{if(e.ownedStateDir&&(n=G(e.ownedStateDir,e.paths),n.sealed=!0,r=q(n,r),n.retirement))return await n.retirement}catch(r){return await $(n,e.startupJoinTimeoutMs??1e3),{status:`retained`,reason:`ownership-unproven`,removedInfo:!1,error:t(r)}}let i=X({...e,observed:r},t=>M(t,{mode:e.mode,termTimeoutMs:e.termTimeoutMs??3e3,killTimeoutMs:e.killTimeoutMs??1e3}),n,e.startupJoinTimeoutMs??1e3);n&&(n.retirement=i);let a=await i;return n&&(a.status===`absent`||!a.removedStateDir)&&(n.retirement=void 0),a}function q(e,t){if(!t){if(e.startups.length===0)return null;throw J()}let n=e.startups.find(({launch:e})=>e.pid===t.pid);if(!n)throw J();let{launch:r}=n,i=t.startTime?t:r.readIdentity();if(r.startTime&&r.startTime===i.startTime)return i;throw J()}function J(){return new n(`COMMAND_FAILED`,`The observed daemon is not an owned startup lifetime.`,{reason:`daemon_private_startup_unowned`})}async function Y(e){return await X(e,async e=>{if(!e.startTime?.trim())return{status:`retained`,reason:`missing-start-time`};let t={pid:e.pid,startTime:e.startTime};return(await j(t,{timeoutMs:0})).exited?{status:`exited`,identity:t,mode:`already-exited`}:{status:`retained`,reason:`identity-unverified`}})}async function X(e,n,r,i=1e3){let a={...e.paths},o=e.observed&&{...e.observed},s,c;if(o)try{s=await n(o)}catch(e){c=t(e)}let l=await $(r,i);return c?{status:`retained`,reason:`stop-failed`,removedInfo:!1,error:c}:s&&s.status!==`exited`?{status:`retained`,reason:`exit-unconfirmed`,termination:s,removedInfo:!1}:l?await Z({...e,paths:a},s,r):{status:`retained`,reason:`startup-unconfirmed`,termination:s,removedInfo:!1}}async function Z(e,n,r){let i=e.paths,a;try{a=await g({lockDirPath:i.lockPath,owner:{...l(),acquiredAtMs:Date.now()},description:`daemon registration retirement`,timeoutMs:e.lockTimeoutMs??1e3})}catch(e){let r=t(e);return{status:`retained`,reason:r.details?.reason===`process_lock_timeout`?`lock-busy`:`retirement-unconfirmed`,termination:n,removedInfo:!1,error:r}}let o={status:`retained`,reason:`retirement-unconfirmed`,removedInfo:!1};try{o=re(L(i.infoPath,n?.identity??null,a),n),o=ie(r,a,o)}catch(e){o={status:`retained`,reason:`retirement-unconfirmed`,termination:n,removedInfo:o.removedInfo,error:t(e)}}return await ne(a,o,i.logPath)}async function ne(e,n,r){try{await e.release()}catch(e){let i=n.status===`retained`?n.error:void 0;i&&await Q(r,`daemon_retirement_release_failed`,e),n={...n,status:`retained`,reason:`retirement-unconfirmed`,error:i??t(e)}}return n}function re(e,t){return t&&(e.state===`removed`||e.state===`absent`)?{status:`retired`,termination:t,removedInfo:e.state===`removed`}:e.state===`absent`?{status:`absent`,removedInfo:!1}:{status:`retained`,termination:t,removedInfo:!1,reason:e.state===`replaced`?`registration-replaced`:e.state===`unreadable`?`metadata-unreadable`:`ownership-unproven`}}async function Q(e,n,r){await O({logPath:e},()=>{a({level:`warn`,phase:n,data:{error:t(r)}})})}async function $(e,t){if(!e||e.startups.every(e=>e.joined))return!0;let n;try{return await Promise.race([Promise.all(e.startups.map(({launch:e})=>e.exited)).then(()=>!0),new Promise(e=>{n=setTimeout(()=>e(!1),t)})])}finally{n&&clearTimeout(n)}}function ie(e,n,r){if(!e||r.status!==`retired`&&(r.status!==`absent`||e.startups.length!==0))return r;try{n.assertHeld();let t=y(e.paths.sessionsDir);return t?r.status===`retired`?{...r,removedStateDir:!1,repairCommitFailure:t}:{status:`retained`,reason:`retirement-unconfirmed`,removedInfo:!1,removedStateDir:!1,repairCommitFailure:t}:(n.assertHeld(),T.rmSync(e.paths.baseDir,{recursive:!0,force:!0}),{...r,removedStateDir:!0})}catch(e){return{...r,status:`retained`,reason:`retirement-unconfirmed`,removedStateDir:!1,error:t(e)}}}export{Y as a,O as c,U as i,H as n,K as o,P as r,I as s,F as t};
|
|
@@ -1 +1,3 @@
|
|
|
1
|
-
import{B as e,P as t}from"./sdk-contracts.js";import{i as n}from"./sdk-batch-runner.js";import{n as r}from"./app-inventory.js";import"./device.js";import{t as i}from"./ios-client.js";import{t as a}from"./instance-client.js";import{t as o}from"./request-cancellation.js";import{i as s}from"./snapshot.js";import c from"node:fs";import l from"node:os";import u from"node:path";import{setTimeout as d}from"node:timers/promises";function f(e){return e?.trim()||void 0}async function p(e,t){let n=await a({apiUrl:e.apiUrl,adbUrl:e.adbUrl,token:e.token,logLevel:`warn`}),r={platform:`android`,lease:e.lease,instanceId:e.instanceId,ownership:e.ownership,device:e.device,client:n,token:e.token,dependencies:t},i={exec:async(e,t)=>await y(r,e,t),text:async e=>{await n.setText(e.target,e.text)}};return i.reverse=await t.android.createPortReverse(i.exec,{noRebind:e.ownership===`attached`}),Object.assign(r,{adbProvider:i})}function m(e){return e.dependencies.android.createInteractor(e.device,e.adbProvider)}async function h(e,t,n,r,i,a){i?.throwIfAborted();let s=f(r?.packageNameHint);r?.relaunch&&s&&await t.dependencies.android.forceStopApp(async(e,n)=>await y(t,e,n),s,i);let c=await o(a,e.assets.getOrUpload({path:n,name:T(s,n)},{signal:i}),i);await o(a,t.client.sendAsset(c.signedDownloadUrl),i),i?.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(e.dependencies.android.hostAdbInvocation([`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=[],a=e.ownership===`attached`;for(let e of n)e.ownerId?r.add(e.ownerId):a||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{invocation: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=await S(e),i=e.dependencies.android.deviceAdbInvocation(r,t);return{invocation:i,result:await e.dependencies.host.runAdb(i,{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,e);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(e){if(!Number.isInteger(e)||e<1||e>65535)throw new t(`INVALID_ARGS`,`Invalid Android tcp reverse port: ${e}`);return`tcp:${e}`}function T(e,t){let n=u.extname(t)||`.apk`;return`${e?.replaceAll(/[^a-zA-Z0-9_.-]+/g,`-`)||`android-app`}${n}`}async function E(e,t){let n=await i({apiUrl:e.apiUrl,token:e.token,logLevel:`warn`});return{platform:`ios`,lease:e.lease,instanceId:e.instanceId,ownership:e.ownership,device:e.device,client:n,token:e.token,dependencies:t}}async function D(e,t,n,r,i,a){i?.throwIfAborted();let s=await j(n,t.dependencies);try{i?.throwIfAborted();let n=await o(a,e.assets.getOrUpload({path:s.uploadPath,name:s.assetName},{signal:i}),i),c=(await O(t,n.signedDownloadUrl,{md5:n.md5,relaunch:r?.relaunch,appIdentifierHint:r?.appIdentifierHint},i,a)).appId;return{...c?{bundleId:c,launchTarget:c}:{},...s.appName?{appName:s.appName}:{}}}finally{await s.cleanup()}}async function O(e,n,r,i,a){i?.throwIfAborted();let s=await o(a,e.client.listApps(),i).catch(e=>{if(i?.aborted)throw e}),c=f((await o(a,e.client.installApp(n,{md5:r?.md5,launchMode:r?.relaunch?`RelaunchIfRunning`:`ForegroundIfRunning`}),i)).bundleId),l=f(r?.appIdentifierHint),u=[];for(let t of N){t>0&&await d(t,void 0,{signal:i}),u=await o(a,e.client.listApps(),i);let n=I({resultBundleId:c,requestedBundleId:l,beforeInstallApps:s,afterInstallApps:u});if(n)return{appId:n}}throw new t(`COMMAND_FAILED`,`Limrun iOS app installation could not be verified.`,{resultBundleId:c,requestedBundleId:l,installedUserApps:u.filter(R).map(e=>e.bundleId).sort()})}function k(e){return new A(e)}var A=class{session;constructor(e){this.session=e}async open(e,t){if(t?.url){await this.launch(e,t.launchArgs),await this.session.client.openUrl(t.url);return}if(n(e)){await this.session.client.openUrl(e);return}await this.launch(e,t?.launchArgs)}async launch(e,n=[]){let r=await this.session.dependencies.ios.resolveAppAlias(e);if(n.length===0){await this.session.client.launchApp(r);return}let i=await this.session.client.simctl([`launch`,`--terminate-running-process`,`booted`,r,...n]).wait();if(i.code!==0)throw new t(`COMMAND_FAILED`,`Limrun iOS could not launch ${r} with arguments.`,{bundleId:r,exitCode:i.code,stderr:i.stderr.trim()})}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.session.client.performActions([{type:`tap`,x:e,y:t},{type:`wait`,durationMs:F},{type:`tap`,x:e,y:t}])}async longPress(e,t,n=P){await this.session.client.performActions([{type:`touchDown`,x:e,y:t},{type:`wait`,durationMs:n},{type:`touchUp`,x:e,y:t}])}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(t,n){if(n&&n>0){let r=0;try{for(let e of Array.from(t))await this.session.client.typeText(e,!1,{requireFocus:!1}),r+=1,await d(n)}catch(t){throw e(t,r)}return}await this.session.client.typeText(t,!1,{requireFocus:!1})}async scroll(e,t){await this.session.client.scroll(e,t?.pixels??300)}async screenshot(e){let{transcodeScreenshotToPngAsync:t}=await import(`./png-worker-client.js`).then(e=>e.s),n=await this.session.client.screenshot(),r=await t(Buffer.from(n.base64,`base64`),`Limrun iOS screenshot`);c.mkdirSync(u.dirname(e),{recursive:!0}),await c.promises.writeFile(e,r)}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 setOrientation(e){if(e===`portrait-upside-down`)throw z(`orientation`,`Limrun iOS direct sessions support portrait and landscape orientation, not portrait upside-down.`);await this.session.client.setOrientation(e===`portrait`?`Portrait`:`Landscape`)}async setSetting(e,t,n,r){let{setLimrunIosSetting:i}=await import(`./ios-settings.js`);return await i(this.session,e,t,n,r)}};async function j(e,t){if(!(await c.promises.stat(e)).isDirectory())return{uploadPath:e,assetName:u.basename(e),appName:M(e),cleanup:async()=>{}};let n=await c.promises.mkdtemp(u.join(l.tmpdir(),`agent-device-limrun-ios-app-`)),r=u.join(n,`${u.basename(e)}.zip`);try{await t.host.archiveDirectory({sourceDirectory:u.dirname(e),entryName:u.basename(e),archivePath:r})}catch(e){throw await c.promises.rm(n,{recursive:!0,force:!0}),e}return{uploadPath:r,assetName:u.basename(r),appName:await t.ios.readBundleAppName(e)??M(e),cleanup:async()=>{await c.promises.rm(n,{recursive:!0,force:!0})}}}function M(e){return u.basename(e).replace(/\.(?:app|ipa|apk|aab|zip)$/i,``)||void 0}const N=[0,250],P=800,F=80;function I(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)??L(e.beforeInstallApps,e.afterInstallApps)}function L(e,t){if(!e)return;let n=new Set(e.map(e=>e.bundleId)),r=t.filter(e=>R(e)&&!n.has(e.bundleId));return r.length===1?r[0]?.bundleId:void 0}function R(e){return!e.bundleId.startsWith(`com.apple.`)&&!e.installType.toLowerCase().includes(`system`)}function z(e,n){throw new t(`UNSUPPORTED_OPERATION`,n,{command:e})}function B(e){return e.platform===`android`?V(e):H(e)}function V(e){let t=e.adbProvider.exec;return{platform:`android`,device:e.device,interactor:m(e),adb:e.adbProvider,listApps:async n=>await e.dependencies.android.listApps(t,r(n)),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),...U(e.client,e.token,e.dependencies.host),installRemoteApp:async t=>{await e.client.sendAsset(t)}}}function H(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=>r(t)===`all`||R(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),...U(e.client,e.token,e.dependencies.host),installRemoteApp:async(t,n)=>await O(e,t,n),runSimctl:t=>e.client.simctl(t)}}function U(e,t,n){return{startRecording:async t=>{await e.startRecording(t)},stopRecording:async()=>({downloadUrl:await e.stopRecording({})}),downloadRecording:async e=>{await n.downloadFile({url:e.downloadUrl,headers:{Authorization:`Bearer ${t}`},destinationPath:e.outPath,timeoutMs:6e4})}}}export{_ as a,p as c,D as i,h as l,k as n,g as o,E as r,m as s,B as t};
|
|
1
|
+
import{B as e,P as t}from"./sdk-contracts.js";import{i as n}from"./sdk-batch-runner.js";import{n as r}from"./app-inventory.js";import"./device.js";import{t as i}from"./ios-client.js";import{t as a}from"./instance-client.js";import{t as o}from"./request-cancellation.js";import{i as s}from"./snapshot.js";import c from"node:fs";import l from"node:os";import u from"node:path";import{setTimeout as d}from"node:timers/promises";function f(e){return e?.trim()||void 0}async function p(e,t){let n=await a({apiUrl:e.apiUrl,adbUrl:e.adbUrl,token:e.token,logLevel:`warn`}),r={platform:`android`,lease:e.lease,instanceId:e.instanceId,ownership:e.ownership,device:e.device,client:n,token:e.token,dependencies:t},i={exec:async(e,t)=>await y(r,e,t),text:async e=>{await n.setText(e.target,e.text)}};return i.reverse=await t.android.createPortReverse(i.exec,{noRebind:e.ownership===`attached`}),Object.assign(r,{adbProvider:i})}function m(e){return e.dependencies.android.createInteractor(e.device,e.adbProvider)}async function h(e,t,n,r,i,a){i?.throwIfAborted();let s=f(r?.packageNameHint);r?.relaunch&&s&&await t.dependencies.android.forceStopApp(async(e,n)=>await y(t,e,n),s,i);let c=await o(a,e.assets.getOrUpload({path:n,name:T(s,n)},{signal:i}),i);await o(a,t.client.sendAsset(c.signedDownloadUrl),i),i?.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(e.dependencies.android.hostAdbInvocation([`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=[],a=e.ownership===`attached`;for(let e of n)e.ownerId?r.add(e.ownerId):a||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{invocation: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=await S(e),i=e.dependencies.android.deviceAdbInvocation(r,t);return{invocation:i,result:await e.dependencies.host.runAdb(i,{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,e);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(e){if(!Number.isInteger(e)||e<1||e>65535)throw new t(`INVALID_ARGS`,`Invalid Android tcp reverse port: ${e}`);return`tcp:${e}`}function T(e,t){let n=u.extname(t)||`.apk`;return`${e?.replaceAll(/[^a-zA-Z0-9_.-]+/g,`-`)||`android-app`}${n}`}async function E(e,t){let n=await i({apiUrl:e.apiUrl,token:e.token,logLevel:`warn`});return{platform:`ios`,lease:e.lease,instanceId:e.instanceId,ownership:e.ownership,device:e.device,client:n,token:e.token,dependencies:t}}async function D(e,t,n,r,i,a){i?.throwIfAborted();let s=await j(n,t.dependencies);try{i?.throwIfAborted();let n=await o(a,e.assets.getOrUpload({path:s.uploadPath,name:s.assetName},{signal:i}),i),c=(await O(t,n.signedDownloadUrl,{md5:n.md5,relaunch:r?.relaunch,appIdentifierHint:r?.appIdentifierHint},i,a)).appId;return{...c?{bundleId:c,launchTarget:c}:{},...s.appName?{appName:s.appName}:{}}}finally{await s.cleanup()}}async function O(e,n,r,i,a){i?.throwIfAborted();let s=await o(a,e.client.listApps(),i).catch(e=>{if(i?.aborted)throw e}),c=f((await o(a,e.client.installApp(n,{md5:r?.md5,launchMode:r?.relaunch?`RelaunchIfRunning`:`ForegroundIfRunning`}),i)).bundleId),l=f(r?.appIdentifierHint),u=[];for(let t of N){t>0&&await d(t,void 0,{signal:i}),u=await o(a,e.client.listApps(),i);let n=I({resultBundleId:c,requestedBundleId:l,beforeInstallApps:s,afterInstallApps:u});if(n)return{appId:n}}throw new t(`COMMAND_FAILED`,`Limrun iOS app installation could not be verified.`,{resultBundleId:c,requestedBundleId:l,installedUserApps:u.filter(R).map(e=>e.bundleId).sort()})}function k(e){return new A(e)}var A=class{session;constructor(e){this.session=e}async open(e,t){if(t?.url){await this.launch(e,t.launchArgs),await this.session.client.openUrl(t.url);return}if(n(e)){await this.session.client.openUrl(e);return}await this.launch(e,t?.launchArgs)}async launch(e,n=[]){let r=await this.session.dependencies.ios.resolveAppAlias(e);if(n.length===0){await this.session.client.launchApp(r);return}let i=await this.session.client.simctl([`launch`,`--terminate-running-process`,`booted`,r,...n]).wait();if(i.code!==0)throw new t(`COMMAND_FAILED`,`Limrun iOS could not launch ${r} with arguments.`,{bundleId:r,exitCode:i.code,stderr:i.stderr.trim()})}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.session.client.performActions([{type:`tap`,x:e,y:t},{type:`wait`,durationMs:F},{type:`tap`,x:e,y:t}])}async longPress(e,t,n=P){await this.session.client.performActions([{type:`touchDown`,x:e,y:t},{type:`wait`,durationMs:n},{type:`touchUp`,x:e,y:t}])}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(t,n){if(n&&n>0){let r=0;try{for(let e of Array.from(t))await this.session.client.typeText(e,!1,{requireFocus:!1}),r+=1,await d(n)}catch(t){throw e(t,r)}return}await this.session.client.typeText(t,!1,{requireFocus:!1})}async scroll(e,t){await this.session.client.scroll(e,t?.pixels??300)}async screenshot(e){let{transcodeScreenshotToPngAsync:t}=await import(`./png-worker-client.js`).then(e=>e.s),n=await this.session.client.screenshot(),r=await t(Buffer.from(n.base64,`base64`),`Limrun iOS screenshot`);c.mkdirSync(u.dirname(e),{recursive:!0}),await c.promises.writeFile(e,r)}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(){await this.session.client.performActions([{type:`buttonDown`,button:`home`},{type:`buttonUp`,button:`home`}])}async readClipboard(){return(await this.pasteboard([`pbpaste`,`booted`])).stdout.replaceAll(`\r
|
|
2
|
+
`,`
|
|
3
|
+
`).replace(/\n$/,``)}async writeClipboard(e){await this.pasteboard([`pbcopy`,`booted`],e)}async pasteboard(e,n){let r=await this.session.client.simctl(e,n===void 0?void 0:{stdin:n}).wait();if(r.code!==0)throw new t(`COMMAND_FAILED`,`Limrun iOS could not access the clipboard.`,{command:e[0],exitCode:r.code,stderr:r.stderr.trim()});return r}async setOrientation(e){if(e===`portrait-upside-down`)throw z(`orientation`,`Limrun iOS direct sessions support portrait and landscape orientation, not portrait upside-down.`);await this.session.client.setOrientation(e===`portrait`?`Portrait`:`Landscape`)}async setSetting(e,t,n,r){let{setLimrunIosSetting:i}=await import(`./ios-settings.js`);return await i(this.session,e,t,n,r)}};async function j(e,t){if(!(await c.promises.stat(e)).isDirectory())return{uploadPath:e,assetName:u.basename(e),appName:M(e),cleanup:async()=>{}};let n=await c.promises.mkdtemp(u.join(l.tmpdir(),`agent-device-limrun-ios-app-`)),r=u.join(n,`${u.basename(e)}.zip`);try{await t.host.archiveDirectory({sourceDirectory:u.dirname(e),entryName:u.basename(e),archivePath:r})}catch(e){throw await c.promises.rm(n,{recursive:!0,force:!0}),e}return{uploadPath:r,assetName:u.basename(r),appName:await t.ios.readBundleAppName(e)??M(e),cleanup:async()=>{await c.promises.rm(n,{recursive:!0,force:!0})}}}function M(e){return u.basename(e).replace(/\.(?:app|ipa|apk|aab|zip)$/i,``)||void 0}const N=[0,250],P=800,F=80;function I(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)??L(e.beforeInstallApps,e.afterInstallApps)}function L(e,t){if(!e)return;let n=new Set(e.map(e=>e.bundleId)),r=t.filter(e=>R(e)&&!n.has(e.bundleId));return r.length===1?r[0]?.bundleId:void 0}function R(e){return!e.bundleId.startsWith(`com.apple.`)&&!e.installType.toLowerCase().includes(`system`)}function z(e,n){throw new t(`UNSUPPORTED_OPERATION`,n,{command:e})}function B(e){return e.platform===`android`?V(e):H(e)}function V(e){let t=e.adbProvider.exec;return{platform:`android`,device:e.device,interactor:m(e),adb:e.adbProvider,listApps:async n=>await e.dependencies.android.listApps(t,r(n)),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),...U(e.client,e.token,e.dependencies.host),installRemoteApp:async t=>{await e.client.sendAsset(t)}}}function H(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=>r(t)===`all`||R(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),...U(e.client,e.token,e.dependencies.host),installRemoteApp:async(t,n)=>await O(e,t,n),runSimctl:t=>e.client.simctl(t)}}function U(e,t,n){return{startRecording:async t=>{await e.startRecording(t)},stopRecording:async()=>({downloadUrl:await e.stopRecording({})}),downloadRecording:async e=>{await n.downloadFile({url:e.downloadUrl,headers:{Authorization:`Bearer ${t}`},destinationPath:e.outPath,timeoutMs:6e4})}}}export{_ as a,p as c,D as i,h as l,k as n,g as o,E as r,m as s,B as t};
|