@appetize/cli 0.24.0 → 0.25.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # @appetize/cli
2
2
 
3
+ ## 0.25.1
4
+
5
+ ### Patch Changes
6
+
7
+ - fix: webserver API errors include the webserver's reason
8
+
9
+ ## 0.25.0
10
+
11
+ ### Minor Changes
12
+
13
+ - feat(session): `session start` takes `--launch-app`, `--launch-url`, `--launch-params`, `--launch-permissions` and `--launch-ios-args`, with `--open` kept as an alias
14
+
15
+ ### Patch Changes
16
+
17
+ - fix(session): cancelling `session start` while connecting no longer crashes the daemon
18
+
3
19
  ## 0.24.0
4
20
 
5
21
  ### Minor Changes
package/cli.js CHANGED
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env node
2
- import He from"sade";import{p as u,a as h,f as _,U as a,d as R,b as Ye,i as Je,c as Qe,e as et,r as te,g as E,h as T,j as tt,D as ot,s as nt,k as it,l as oe,m as ne,S as U,n as ie,o as re,q as se,v as rt,t as st,u as ae,w as at,x as ce,y as ct,z as pt,A as dt,B as lt,C as pe,E as de,F as ut,G as ft,H as mt,I as ht,J as gt,K as wt}from"./stream-BowDfEJS.js";import{existsSync as le,openAsBlob as yt,openSync as vt,closeSync as xt}from"node:fs";import{basename as z,extname as St,resolve as ue,dirname as bt,join as x,relative as Et}from"node:path";import{writeFile as fe,stat as At,rm as Ot,cp as It}from"node:fs/promises";import{spawn as Pt}from"node:child_process";import{fileURLToPath as me}from"node:url";import{humanId as Tt}from"human-id";import{homedir as $t}from"node:os";import kt from"debug";import Lt from"yocto-spinner";import Dt from"cli-table3";import"json-rpc-2.0";import"zod/mini";import"stream";import"module";import"node:net";const j=["closed","fullyOpen","partiallyOpen"],he=["back","menu","unlock","volumeDown","volumeUp"],ge=["home","lock"],we=[...ge,...he],F=["down","left","right","up"],ye=[{header:"Target",key:"id"},{header:"App",key:"appId"},{header:"Platform",key:"platform"},{header:"Version",key:"versionName"},{header:"Build",key:"buildNumber"},{header:"Uploaded",key:"created"}];function C({appId:e,buildNumber:t,created:o,id:n,platform:i,versionName:r}){return{appId:e,buildNumber:t,created:o,id:n,platform:i,versionName:r}}const Nt=["app"],_t=10,Rt=[{fields:ye,key:"builds"},{header:"Total",key:"total"},{header:"Next page",key:"nextPage"}];async function Ut({options:e,signal:t}){const o=u(e.app,"--app"),n=h(e.limit,"--limit")??_t,i=h(e.page,"--page"),r={limit:String(n)};o!==void 0&&(r.appId=o),i!==void 0&&(r.page=String(i));const s=await _("/api/v2/builds",{commandOptions:e,query:r,signal:t});return{builds:s.builds.map(C),nextPage:s.nextPage,total:s.total}}const zt=["note","tags"],ve=12e4,jt=2e3,M=[".apk",".apks",".zip",".tar.gz",".tgz"],Ft={".apk":"android",".apks":"android",".tar.gz":"ios",".tgz":"ios",".zip":"ios"},Ct=ye;async function Mt({options:e,positionals:[t],progress:o,signal:n}){const i=Gt(t),r=z(t);o.status(`Uploading ${r}`);const s=await Kt(t,i,e,n);if(e.wait!==!0)return o.status(`Uploaded ${r}`),C(s);o.step(`Uploaded ${r}`),o.status("Waiting for build metadata");const p=await Bt(s.id,e,n);return o.status(`Processed ${r}`),C(p)}async function Bt(e,t,o){const n=h(t.timeout,"--timeout")??ve,i=Date.now()+n;for(;;){const r=await _(`/api/v2/builds/${e}`,{commandOptions:t,signal:o});if(r.appId!==void 0)return r;if(Date.now()>=i)throw new Error(`Build ${e} is still being processed after ${String(n)}ms; find it with 'appetize build list'`);await R(jt,o)}}async function qt(e){if(!le(e))throw new Error(`No build file at ${e}`);return await yt(e)}function Gt(e){const t=e.toLowerCase(),o=M.find(n=>t.endsWith(n));if(o===void 0)throw new a(`Cannot tell the platform of ${z(e)}; upload a ${M.join(", ")} file`);return Ft[o]}async function Kt(e,t,o,n){const i=new FormData;i.set("platform",t);const r=u(o.note,"--note");r!==void 0&&i.set("note",r);const s=u(o.tags,"--tags");return s!==void 0&&i.set("tags",s),i.set("file",await qt(e),z(e)),await _("/api/v2/builds",{body:i,commandOptions:o,method:"POST",signal:n})}const Zt=["platform"],Vt=[{fields:[{header:"ID",key:"id"},{header:"Name",key:"name"},{header:"Platform",key:"platform"},{header:"OS versions",key:"osVersions"}],key:"devices"}];async function Wt({options:e,signal:t}){const o=Xt(e.platform);return{devices:(await Ye(e,t)).filter(i=>o===void 0||i.platform===o).map(Ht)}}function Xt(e){const t=u(e,"--platform");if(t!==void 0){if(!Je(t))throw new a(`--platform expects one of: ${Qe.join(", ")}`);return t}}function Ht({id:e,name:t,osVersions:o,platform:n}){return{id:e,name:t,osVersions:o,platform:n}}const Yt="cli-fold",Jt=async({device:e,positionals:[t]})=>{if(!Qt(t))throw new a(`Hinge must be one of: ${j.join(", ")}`);await e.fold(t)};function Qt(e){return j.some(t=>t===e)}const eo=async({device:e,options:t,positionals:[o]})=>{await e.gesture(oo(o),to(t))};function to(e){const t=h(e.timeout,"--timeout");return t===void 0?void 0:{timeout:t}}function oo(e){let t;try{t=et(e)}catch(o){throw o instanceof SyntaxError?new a(o.message):o}if(t.length===0)throw new a("Expected at least one gesture step");return t}const no="APPETIZE_OUTPUT";function io(e,t,o){return{format:ro(e,t),progress:so(e,o)}}function B(e,{extension:t,strict:o=!1}){const n=St(e);if(n==="")return`${e}${t}`;if(o&&n!==t)throw new a(`The output must be a path ending in ${t}`);return e}function ro(e,t){if(e.json===!0)return"json";if(e.json===!1)return"text";const o=process.env[no]?.trim();return o==="json"||o==="text"?o:t.isTTY===!0?"text":"json"}function so(e,t){return e.quiet===!0?"silent":t.isTTY===!0&&process.env.TERM!=="dumb"&&!("CI"in process.env)?"interactive":"silent"}const S=["text","testId"],g="select",A={testId:{help:"Test id to match by exact string",suffix:"test-id"},text:{help:'Text to match by exact string or regex (e.g., "Sign in" or "/sign in/i")',suffix:"text"}},q="index",$="position",G="x",K="y";function xe(e,{prefix:t=g}={}){return S.reduce((o,n)=>{const{help:i,suffix:r}=A[n];return o.option(`--${d(t,r)}`,i)},e).option(`--${d(t,q)}`,"Which match when multiple (0-based)")}function Z(e,t={}){const{prefix:o=g}=t;return xe(e,t).option(`--${d(o,$)}`,"Screen position to use as x,y (0-1), e.g., 0.5,0.75").option(`--${d(o,G)}`,"Horizontal position within the element (0-1, outside allowed)").option(`--${d(o,K)}`,"Vertical position within the element (0-1, outside allowed)")}function Se(e,{prefix:t=g}={}){const o=W(e,t);if(o.length===0)throw new a(`A selector is required: pass one of ${L(S,t)}`);if(o.length>1)throw new a(`Only one selector may be given, got ${L(o,t)}`);const[n]=o,i=Pe(e,d(t,A[n].suffix)),r=h(e[d(t,q)],`--${d(t,q)}`);switch(n){case"testId":return{by:"testId",index:r,testId:i};case"text":return{by:"text",index:r,text:po(i)}}}function be(e){const t=h(e.timeout,"--timeout");return t===void 0?void 0:{timeout:t}}function ao(e,{prefix:t=g}={}){return Oe(e,t)?Se(e,{prefix:t}):void 0}function k(e,{prefix:t=g}={}){return Oe(e,t)?Ee(e,{prefix:t}):void 0}function Ee(e,{prefix:t=g}={}){const o=d(t,$),n=e[o],i=Ie(e,d(t,G)),r=Ie(e,d(t,K));if(n===void 0){if(W(e,t).length===0)throw new a(`A selector is required: pass one of ${O({prefix:t})}`);return{...Se(e,{prefix:t}),x:i,y:r}}if(W(e,t).length>0)throw new a(`--${o} may not be combined with ${L(S,t)}`);if(i!==void 0||r!==void 0)throw new a(`--${o} may not be combined with --${d(t,G)} or --${d(t,K)}`);return co(Pe(e,o),o)}function O(e={}){const{prefix:t=g}=e;return`${L(S,t)}, --${d(t,$)}`}function V(e={}){const{prefix:t=g}=e;return[...Ae(e),d(t,$)]}function Ae({prefix:e=g}={}){return S.map(t=>d(e,A[t].suffix))}function W(e,t){return S.filter(o=>e[d(t,A[o].suffix)]!==void 0)}function d(...e){return e.filter(Boolean).join("-")}function L(e,t){return e.map(o=>`--${d(t,A[o].suffix)}`).join(", ")}function Oe(e,t){return Object.entries(e).some(([o,n])=>n!==void 0&&o.startsWith(`${t}-`))}function Ie(e,t){return h(e[t],`--${t}`)}function co(e,t){const o=e.split(",");if(o.length!==2)throw new a(`--${t} expects x,y (0-1), e.g., 0.5,0.75`);const[n,i]=o.map(r=>Number(r.trim()));return{by:"position",x:te(n,`--${t}`),y:te(i,`--${t}`)}}function po(e){const t=/^\/(.*)\/([a-z]*)$/s.exec(e);return t?new RegExp(t[1],t[2]):e}function Pe(e,t){return E(e[t],`--${t}`)}const lo=Ae(),uo=async({device:e,options:t,positionals:[o]})=>{const n=fo(o),i=ao(t),r=await e.inspect(i,be(t)),s=mo(r,t.pretty===!0);await fe(n,s);const p=Buffer.byteLength(s),c=Te(r.roots);return i?{bytes:p,matches:r.roots.length,nodes:c,output:n}:{bytes:p,nodes:c,output:n}};function Te(e){return e.reduce((t,o)=>t+1+Te(o.children),0)}function fo(e="inspect"){return B(e,{extension:".json"})}function mo(e,t){return`${JSON.stringify(e,null,t?2:void 0)}
3
- `}const ho=async({device:e})=>{await e.clearKeychain()},go=async({device:e,positionals:[t]})=>{await e.open(wo(t))};function wo(e){if(typeof e=="string")try{return new URL(e),e}catch{throw new a("<url> expects a URL, e.g., myapp://orders/42")}throw new a("<url> expects a URL, e.g., myapp://orders/42")}const yo=new Set(we),vo=async({device:e,positionals:[t]})=>{if(!xo(t))throw new a(`Button must be one of: ${we.join(", ")}`);await e.press(t)};function xo(e){return typeof e=="string"&&yo.has(e)}const So=async({control:e,options:t,positionals:[o]})=>{const{path:n}=await e.recordStart({force:t.force===!0,path:Eo(o)});return{path:n}},bo=async({control:e})=>{const{path:t}=await e.recordStop();return{path:t}};function Eo(e){const t=ue(B(e,{extension:".mp4",strict:!0})),o=bt(t);if(!le(o))throw new a(`No such directory: ${o}`);return t}const Ao=async({device:e,positionals:[t]})=>{if(!Oo(t))throw new a(`Orientation must be one of: ${T.join(", ")}`);await e.rotate(t)};function Oo(e){return T.some(t=>t===e)}const Io=async({device:e,positionals:[t]})=>{const o=await e.screenshot(),n=To(o.mimeType,t);return await fe(n,o.data),{bytes:o.data.byteLength,output:n}};function Po(e){const t=e.split("/").at(1);return`.${t==="jpeg"?"jpg":t??"png"}`}function To(e,t="screenshot"){return B(t,{extension:Po(e)})}function $o(e){const t=me(new URL("./daemon.js",import.meta.url)),o=vt(tt(e.sessionId),"a"),n=Pt(process.execPath,[t],{detached:!0,env:{...process.env,[ot]:nt(e),DEBUG:ko(process.env.DEBUG)},stdio:["ignore",o,o]});if(xt(o),n.unref(),n.pid===void 0)throw new Error("Failed to spawn the session daemon");return n.pid}function ko(e){return e?`${e},appetize:daemon`:"appetize:daemon"}const Lo=/^[a-z0-9](?:[a-z0-9._-]{0,62}[a-z0-9])?$/i;function Do(){return Tt({capitalize:!1,separator:"-"})}function No(e){if(!Lo.test(e))throw new a('--session-id must use letters, digits, ".", "-" or "_"');return e}const $e=1e4;function ke(e){if(!it(e))return!1;try{process.kill(e.pid,"SIGTERM")}catch{}return!0}async function Le(e,t){(ke(e)||Ro(e))&&await _o(e,t)}async function _o({pid:e,sessionId:t},o){const n=ne(e);try{await R($e,AbortSignal.any([o,n]))}catch(i){if(n.aborted||!oe(e))return;throw i}throw new U(`Session ${t} did not stop in time`,{sessionId:t})}function Ro({endedAt:e,pid:t}){return e!==void 0&&Date.now()-Date.parse(e)<$e&&oe(t)}const Uo=["device-android-shell","device-appearance","device-font-size","device-ios-keyboards","device-locale","device-location","device-orientation","device-os-version","device-timezone"];function zo(e,t){const o=De({shell:u(e["device-android-shell"],"--device-android-shell"),softKeyboard:ie(e["device-android-soft-keyboard"],{defaultValue:!0})}),n=De({autocorrect:ie(e["device-ios-autocorrect"],{defaultValue:!0}),keyboards:Co(e["device-ios-keyboards"],"--device-ios-keyboards")});return{android:o,appearance:X(e["device-appearance"],se,"--device-appearance"),fontSize:X(e["device-font-size"],re,"--device-font-size"),id:t,ios:n,locale:u(e["device-locale"],"--device-locale"),location:Fo(e["device-location"]),orientation:X(e["device-orientation"],T,"--device-orientation"),osVersion:u(e["device-os-version"],"--device-os-version"),timezone:u(e["device-timezone"],"--device-timezone")}}function jo(e){return e!==""&&Number.isFinite(Number(e))}function De(e){return Object.values(e).some(t=>t!==void 0)?e:void 0}function X(e,t,o){const n=u(e,o);if(n===void 0)return;const i=t.find(r=>r===n);if(i===void 0)throw new a(`${o} expects one of ${t.join(", ")}`);return i}function Fo(e){const t=u(e,"--device-location");if(t===void 0)return;const o=t.split(",").map(r=>r.trim());if(o.length!==2||!o.every(jo))throw new a("--device-location expects <lat>,<lng>, e.g., 43.65,-79.38");const[n,i]=o.map(Number);return{latitude:n,longitude:i}}function Co(e,t){return e===void 0?void 0:(Array.isArray(e)?e:[e]).map(n=>E(n,t))}const Ne={"device.id":"<device>","device.location.latitude":"--device-location latitude","device.location.longitude":"--device-location longitude","launch.url":"--open"};function Mo(e,{endpointFromEnv:t=!1}={}){const o=t?{...Ne,endpoint:"APPETIZE_ENDPOINT"}:Ne;try{rt(e)}catch(n){throw n instanceof st?new a(n.issues.map(i=>Bo(i,o)).join(`
4
- `)):n}}function Bo({code:e,message:t,path:o},n){const i=qo(o,n);switch(e){case"invalidValue":return`${i} ${t.replace(/^expected /,"expects ")}`;case"needsLaunchApp":return`${i} has no effect without --target, or with --no-launch-app`;case"needsTarget":return`${i} has no effect without --target`}}function qo(e,t){return t[e]??`--${e.split(".").filter(o=>!/^\d+$/.test(o)).map(o=>o.replaceAll(/([A-Z])/g,"-$1").toLowerCase()).join("-")}`}const Go=[...Uo,"open","proxy","target"],Ko=150,Zo={downloadingApp:"Downloading the app",installingApp:"Installing the app",launchingApp:"Launching the app",queued:"Queued",ready:"Device ready",requesting:"Requesting a device",starting:"Starting the device"},Vo=[{header:"Session ID",key:"sessionId"},{header:"Web view",key:"viewerUrl"},{format:e=>`adb connect ${e}`,header:"adb",key:"adbSerial"},{header:"Host",key:"baseUrl"},{fields:[{header:"Device",key:"device"},{header:"Daemon",key:"daemon"},{header:"Network",key:"network"}],header:"Logs",key:"logs"},{hidden:!0,key:"controlSocket"}];async function Wo(e,{onPhase:t,signal:o}){let n;for(;;){const i=ce(e),r=i?.state?.phase;if(r&&r!==n&&(n=r,t?.(r)),i&&r==="ready"&&i.controlSocket!==void 0)return{...i,controlSocket:i.controlSocket};if(r==="error")throw new Error(i?.endedReason??"The session failed to start");if(r==="ended")throw new Error(i?.endedReason??"The session ended");await R(Ko,o)}}function Xo(e){const t=u(e,"--open");if(t!==void 0){try{new URL(t)}catch{throw new a("--open expects a URL, e.g., myapp://orders/42")}return t}}function Ho(e){if(!(e===void 0||e===!1)){if(e===""||e==="intercept")return"intercept";if(typeof e!="string"||!Jo(e))throw new a("--proxy expects 'intercept' or an http:// url, e.g., http://proxy:8080");return e}}async function Yo({options:e,positionals:t,progress:o,signal:n}){const[i]=t,r=u(e.target,"--target")??en(e);if(r===void 0&&!process.env.APPETIZE_API_TOKEN)throw new a("APPETIZE_API_TOKEN must be set without a target",["Set APPETIZE_API_TOKEN, or pass --target"]);const s=u(e["session-id"],"--session-id"),p=e.force===!0;if(p&&s===void 0)throw new a("--force needs --session-id");const c=s===void 0?Do():No(s),l={device:zo(e,i),endpoint:at(e),featureFlags:ae(),launch:tn(Xo(e.open)),proxy:Ho(e.proxy),sessionId:c,target:r};Mo(l,{endpointFromEnv:e.endpoint===void 0});const f=ce(c);if(f!==void 0){if(!p)throw new ct(c);o.status(`Replacing session ${c}`),await Le(f,n),pt(c)}$o(l),o.step(`Session ${c}`);const v=dt(c,l.proxy);if(e.wait===!1)return{logs:v,sessionId:c};const I=await Wo(c,{onPhase:P=>{Qo(P)&&o.status(Zo[P]??"Starting the session")},signal:n}).catch(P=>{throw U.wrap(P,c)});return{adbSerial:I.adbSerial,baseUrl:I.baseUrl,controlSocket:I.controlSocket,logs:v,sessionId:c,viewerUrl:I.viewerUrl}}function Jo(e){return e.startsWith("http://")}function Qo(e){return e!=="ended"&&e!=="error"}function en(e){const t=e._;return Array.isArray(t)&&typeof t[0]=="string"?t[0]:void 0}function tn(e){return e===void 0?void 0:{url:e}}const on=async({options:e,progress:t,record:o,signal:n})=>(e.wait===!1?ke(o):(t.status(`Stopping session ${o.sessionId}`),await Le(o,n)),{sessionId:o.sessionId}),_e="appetize",nn=me(new URL(`./skills/${_e}/`,import.meta.url)),H=["agents","claude","codex","copilot","cursor"],Re=["project","user"],rn={agents:".agents",claude:".claude",codex:".codex",copilot:".copilot",cursor:".cursor"},sn=x(".agents","skills"),an=["claude","agents"];function cn(e){return H.some(t=>t===e)}function pn(e){return Re.some(t=>t===e)}async function dn(e){const t=e.agents??await ln(e),o=await Promise.all(t.map(n=>Ue(n,e)));return[...new Set(o.flat())]}async function Ue(e,t){const o=ze(e,t);if(e==="claude")return[x(o,"skills")];const n=x(t.root,sn);return t.scope==="project"?[n]:await je(o)?[n,x(o,"skills")]:[n]}function ze(e,t){if(e==="claude"&&t.scope==="user"){const o=process.env.CLAUDE_CONFIG_DIR?.trim();if(o)return ue(o)}return x(t.root,rn[e])}async function ln(e){const o=(await Promise.all(H.map(async n=>await un(n,e)?n:void 0))).filter(n=>n!==void 0);return o.length>0?o:an}async function un(e,t){const o=[ze(e,t),...await Ue(e,t)];return(await Promise.all(o.map(i=>je(i)))).includes(!0)}async function je(e){try{return(await At(e)).isDirectory()}catch{return!1}}const fn=["agent","scope"];async function mn({options:e,signal:t}){const o=wn(e.scope),n=gn(e.agent),i=o==="user"?$t():process.cwd(),r=await dn({agents:n,root:i,scope:o}),s=[];for(const p of r){t.throwIfAborted();const c=x(p,_e);await Ot(c,{force:!0,recursive:!0}),await It(nn,c,{recursive:!0}),s.push(o==="user"?c:Et(i,c))}return{installed:s}}function hn(e){const t=E(e,"--agent");if(!cn(t))throw new a(`--agent expects one of ${H.join(", ")}`);return t}function gn(e){return e===void 0?void 0:(Array.isArray(e)?e:[e]).map(o=>hn(o))}function wn(e){if(e===void 0)return"project";const t=E(e,"--scope");if(!pn(t))throw new a(`--scope expects one of ${Re.join(", ")}`);return t}const w="from",y="to",yn=[...V({prefix:w}),...V({prefix:y})],vn=async({device:e,options:t})=>{await e.swipe(En(t),On(t))};function xn(e){return F.some(t=>t===e)}function Sn(e){if(e===void 0)return;const t=E(e,"--direction");if(!xn(t))throw new a(`--direction expects one of ${F.join(", ")}`);return t}function bn(e,t){const o=lt(e.distance,"--distance");if(k(e,{prefix:y})!==void 0)throw new a(`--direction may not be combined with --${y}-*`);return{direction:t,distance:o,from:k(e,{prefix:w})}}function En(e){const t=Sn(e.direction);return t===void 0?An(e):bn(e,t)}function An(e){if(e.distance!==void 0)throw new a("--distance is only valid with --direction");return{from:Fe(k(e,{prefix:w}),w),to:Fe(k(e,{prefix:y}),y)}}function On(e){const t=h(e.duration,"--duration"),o=h(e.timeout,"--timeout");return t===void 0&&o===void 0?void 0:{duration:t,timeout:o}}function Fe(e,t){if(e===void 0)throw new a(`A swipe needs --direction, or both endpoints: pass one of ${O({prefix:t})}`);return e}const In=V(),Pn=async({device:e,options:t})=>{const o=Ee(t);await e.tap(o,be(t))},Tn=async({device:e,options:t,positionals:[o]})=>{await e.type(o,$n(t))};function $n(e){const t=h(e.delay,"--delay");return t===void 0?void 0:{delay:t}}const Y=kt("appetize:cli"),kn={fail:()=>{},status:()=>{},step:()=>{},succeed:()=>{}};function Ln(e,t,o){return e==="interactive"?Dn(t,o):kn}function Dn(e,t){const o=Lt({handleSignals:!1,stream:e});let n=0;const i=()=>{o.stop()};t.addEventListener("abort",i,{once:!0});const r=()=>(process.off("exit",i),o.isSpinning);return{fail:()=>{r()&&o.stop()},status:s=>{if(!t.aborted){if(o.isSpinning){o.text=s;return}n=Date.now(),process.once("exit",i),o.start(s)}},step:s=>{e.write(`\u25B8 ${s}
5
- `)},succeed:()=>{if(!r())return;const s=Math.round((Date.now()-n)/1e3);o.success(`${o.text} (${String(s)}s)`)}}}const Nn=new Set(["adb","api","apk","id","os","url"]),_n={bottom:"","bottom-left":"","bottom-mid":"","bottom-right":"",left:"","left-mid":"",mid:"","mid-mid":"",middle:" ",right:"","right-mid":"",top:"","top-left":"","top-mid":"","top-right":""},Ce=2,Rn=10;function Un(e){return e.split(/(?=[A-Z])/).map((t,o)=>{const n=t.toLowerCase();return Nn.has(n)?n.toUpperCase():o===0?n.charAt(0).toUpperCase()+n.slice(1):n}).join(" ")}function zn(e,t,o){return Q(e)?Ze(e,t,o):D(e,{fields:t,key:""},o)}function jn(e,t){const o=[];for(let n=0;n<e.length;n+=t)o.push(e.slice(n,n+t));return o.length===0?[e]:o}function Me(e){return new Dt({chars:_n,head:e,style:{border:[],head:[],"padding-left":0,"padding-right":Ce}})}function Be(e,t){return e.find(o=>o.key===t)}function qe(e,t){return t?.header??Un(e)}function J(e){return e!=null}function Q(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function Ge(e){return["boolean","number","string"].includes(typeof e)}function Ke(e,t){const o=new Set(t),n=e.map(r=>r.key).filter(r=>o.has(r)),i=new Set(e.filter(r=>r.hidden).map(r=>r.key));return[...new Set([...n,...t])].filter(r=>!i.has(r))}function Ze(e,t,o){const n=new Map(Object.entries(e)),i=Ke(t,[...n.keys()]).filter(f=>J(n.get(f))),r=i.map(f=>Be(t,f)),s=i.map((f,v)=>qe(f,r[v])),p=Math.max(0,...s.map(f=>f.length))+Ce,c=o===void 0?void 0:o-p-1,l=Me();return l.push(...i.map((f,v)=>[s[v],D(n.get(f),r[v],c)])),Ve(l.toString())}function Fn(e,t){const o=e.map(s=>new Map(Object.entries(s))),n=Ke(t,o.flatMap(s=>[...s.keys()])),i=n.map(s=>Be(t,s)),r=Me(n.map((s,p)=>qe(s,i[p])));for(const s of o)r.push(n.map((p,c)=>{const l=s.get(p);return J(l)?D(l,i[c]):""}));return Ve(r.toString())}function D(e,t,o){if(t?.format)return N(t.format(e),o);if(Ge(e))return N(pe(e),o);if(Array.isArray(e)){const n=e.filter(J);return n.every(Ge)?N(pe(n),o):n.every(Q)?Fn(n,t?.fields??[]):n.map(i=>D(i,t,o)).join(`
6
- `)}return Q(e)?Ze(e,t?.fields??[],o):N(String(e),o)}function Ve(e){return e.split(`
2
+ import Ye from"sade";import{p as u,a as h,f as R,U as a,d as z,b as Qe,i as et,c as tt,e as nt,r as oe,g as I,h as k,j as ot,D as it,s as st,k as rt,l as ie,m as se,S as U,n as j,o as re,q as F,t as T,u as ae,v as ce,w as pe,x as at,y as ct,z as de,A as pt,B as le,C as dt,E as lt,F as ut,G as ft,H as ue,I as fe,J as mt,K as ht,L as gt,M as wt,N as yt,O as vt}from"./stream-C4JjU85l.js";import{existsSync as me,openAsBlob as xt,openSync as St,closeSync as bt}from"node:fs";import{basename as C,extname as Et,resolve as he,dirname as Ot,join as x,relative as At}from"node:path";import{writeFile as ge,stat as Pt,rm as It,cp as kt}from"node:fs/promises";import{spawn as Tt}from"node:child_process";import{fileURLToPath as we}from"node:url";import{humanId as $t}from"human-id";import{homedir as Lt}from"node:os";import Dt from"debug";import Nt from"yocto-spinner";import _t from"cli-table3";import"json-rpc-2.0";import"zod/mini";import"stream";import"module";import"node:net";const M=["closed","fullyOpen","partiallyOpen"],ye=["back","menu","unlock","volumeDown","volumeUp"],ve=["home","lock"],xe=[...ve,...ye],B=["down","left","right","up"],Se=[{header:"Target",key:"id"},{header:"App",key:"appId"},{header:"Platform",key:"platform"},{header:"Version",key:"versionName"},{header:"Build",key:"buildNumber"},{header:"Uploaded",key:"created"}];function q({appId:e,buildNumber:t,created:n,id:o,platform:i,versionName:s}){return{appId:e,buildNumber:t,created:n,id:o,platform:i,versionName:s}}const Rt=["app"],zt=10,Ut=[{fields:Se,key:"builds"},{header:"Total",key:"total"},{header:"Next page",key:"nextPage"}];async function jt({options:e,signal:t}){const n=u(e.app,"--app"),o=h(e.limit,"--limit")??zt,i=h(e.page,"--page"),s={limit:String(o)};n!==void 0&&(s.appId=n),i!==void 0&&(s.page=String(i));const r=await R("/api/v2/builds",{commandOptions:e,query:s,signal:t});return{builds:r.builds.map(q),nextPage:r.nextPage,total:r.total}}const Ft=["note","tags"],be=12e4,Ct=2e3,G=[".apk",".apks",".zip",".tar.gz",".tgz"],Mt={".apk":"android",".apks":"android",".tar.gz":"ios",".tgz":"ios",".zip":"ios"},Bt=Se;async function qt({options:e,positionals:[t],progress:n,signal:o}){const i=Zt(t),s=C(t);n.status(`Uploading ${s}`);const r=await Vt(t,i,e,o);if(e.wait!==!0)return n.status(`Uploaded ${s}`),q(r);n.step(`Uploaded ${s}`),n.status("Waiting for build metadata");const p=await Gt(r.id,e,o);return n.status(`Processed ${s}`),q(p)}async function Gt(e,t,n){const o=h(t.timeout,"--timeout")??be,i=Date.now()+o;for(;;){const s=await R(`/api/v2/builds/${e}`,{commandOptions:t,signal:n});if(s.appId!==void 0)return s;if(Date.now()>=i)throw new Error(`Build ${e} is still being processed after ${String(o)}ms; find it with 'appetize build list'`);await z(Ct,n)}}async function Kt(e){if(!me(e))throw new Error(`No build file at ${e}`);return await xt(e)}function Zt(e){const t=e.toLowerCase(),n=G.find(o=>t.endsWith(o));if(n===void 0)throw new a(`Cannot tell the platform of ${C(e)}; upload a ${G.join(", ")} file`);return Mt[n]}async function Vt(e,t,n,o){const i=new FormData;i.set("platform",t);const s=u(n.note,"--note");s!==void 0&&i.set("note",s);const r=u(n.tags,"--tags");return r!==void 0&&i.set("tags",r),i.set("file",await Kt(e),C(e)),await R("/api/v2/builds",{body:i,commandOptions:n,method:"POST",signal:o})}const Wt=["platform"],Xt=[{fields:[{header:"ID",key:"id"},{header:"Name",key:"name"},{header:"Platform",key:"platform"},{header:"OS versions",key:"osVersions"}],key:"devices"}];async function Ht({options:e,signal:t}){const n=Jt(e.platform);return{devices:(await Qe(e,t)).filter(i=>n===void 0||i.platform===n).map(Yt)}}function Jt(e){const t=u(e,"--platform");if(t!==void 0){if(!et(t))throw new a(`--platform expects one of: ${tt.join(", ")}`);return t}}function Yt({id:e,name:t,osVersions:n,platform:o}){return{id:e,name:t,osVersions:n,platform:o}}const Qt="cli-fold",en=async({device:e,positionals:[t]})=>{if(!tn(t))throw new a(`Hinge must be one of: ${M.join(", ")}`);await e.fold(t)};function tn(e){return M.some(t=>t===e)}const nn=async({device:e,options:t,positionals:[n]})=>{await e.gesture(sn(n),on(t))};function on(e){const t=h(e.timeout,"--timeout");return t===void 0?void 0:{timeout:t}}function sn(e){let t;try{t=nt(e)}catch(n){throw n instanceof SyntaxError?new a(n.message):n}if(t.length===0)throw new a("Expected at least one gesture step");return t}const rn="APPETIZE_OUTPUT";function an(e,t,n){return{format:cn(e,t),progress:pn(e,n)}}function K(e,{extension:t,strict:n=!1}){const o=Et(e);if(o==="")return`${e}${t}`;if(n&&o!==t)throw new a(`The output must be a path ending in ${t}`);return e}function cn(e,t){if(e.json===!0)return"json";if(e.json===!1)return"text";const n=process.env[rn]?.trim();return n==="json"||n==="text"?n:t.isTTY===!0?"text":"json"}function pn(e,t){return e.quiet===!0?"silent":t.isTTY===!0&&process.env.TERM!=="dumb"&&!("CI"in process.env)?"interactive":"silent"}const S=["text","testId"],g="select",E={testId:{help:"Test id to match by exact string",suffix:"test-id"},text:{help:'Text to match by exact string or regex (e.g., "Sign in" or "/sign in/i")',suffix:"text"}},Z="index",$="position",V="x",W="y";function Ee(e,{prefix:t=g}={}){return S.reduce((n,o)=>{const{help:i,suffix:s}=E[o];return n.option(`--${d(t,s)}`,i)},e).option(`--${d(t,Z)}`,"Which match when multiple (0-based)")}function X(e,t={}){const{prefix:n=g}=t;return Ee(e,t).option(`--${d(n,$)}`,"Screen position to use as x,y (0-1), e.g., 0.5,0.75").option(`--${d(n,V)}`,"Horizontal position within the element (0-1, outside allowed)").option(`--${d(n,W)}`,"Vertical position within the element (0-1, outside allowed)")}function Oe(e,{prefix:t=g}={}){const n=J(e,t);if(n.length===0)throw new a(`A selector is required: pass one of ${D(S,t)}`);if(n.length>1)throw new a(`Only one selector may be given, got ${D(n,t)}`);const[o]=n,i=$e(e,d(t,E[o].suffix)),s=h(e[d(t,Z)],`--${d(t,Z)}`);switch(o){case"testId":return{by:"testId",index:s,testId:i};case"text":return{by:"text",index:s,text:un(i)}}}function Ae(e){const t=h(e.timeout,"--timeout");return t===void 0?void 0:{timeout:t}}function dn(e,{prefix:t=g}={}){return ke(e,t)?Oe(e,{prefix:t}):void 0}function L(e,{prefix:t=g}={}){return ke(e,t)?Pe(e,{prefix:t}):void 0}function Pe(e,{prefix:t=g}={}){const n=d(t,$),o=e[n],i=Te(e,d(t,V)),s=Te(e,d(t,W));if(o===void 0){if(J(e,t).length===0)throw new a(`A selector is required: pass one of ${O({prefix:t})}`);return{...Oe(e,{prefix:t}),x:i,y:s}}if(J(e,t).length>0)throw new a(`--${n} may not be combined with ${D(S,t)}`);if(i!==void 0||s!==void 0)throw new a(`--${n} may not be combined with --${d(t,V)} or --${d(t,W)}`);return ln($e(e,n),n)}function O(e={}){const{prefix:t=g}=e;return`${D(S,t)}, --${d(t,$)}`}function H(e={}){const{prefix:t=g}=e;return[...Ie(e),d(t,$)]}function Ie({prefix:e=g}={}){return S.map(t=>d(e,E[t].suffix))}function J(e,t){return S.filter(n=>e[d(t,E[n].suffix)]!==void 0)}function d(...e){return e.filter(Boolean).join("-")}function D(e,t){return e.map(n=>`--${d(t,E[n].suffix)}`).join(", ")}function ke(e,t){return Object.entries(e).some(([n,o])=>o!==void 0&&n.startsWith(`${t}-`))}function Te(e,t){return h(e[t],`--${t}`)}function ln(e,t){const n=e.split(",");if(n.length!==2)throw new a(`--${t} expects x,y (0-1), e.g., 0.5,0.75`);const[o,i]=n.map(s=>Number(s.trim()));return{by:"position",x:oe(o,`--${t}`),y:oe(i,`--${t}`)}}function un(e){const t=/^\/(.*)\/([a-z]*)$/s.exec(e);return t?new RegExp(t[1],t[2]):e}function $e(e,t){return I(e[t],`--${t}`)}const fn=Ie(),mn=async({device:e,options:t,positionals:[n]})=>{const o=hn(n),i=dn(t),s=await e.inspect(i,Ae(t)),r=gn(s,t.pretty===!0);await ge(o,r);const p=Buffer.byteLength(r),c=Le(s.roots);return i?{bytes:p,matches:s.roots.length,nodes:c,output:o}:{bytes:p,nodes:c,output:o}};function Le(e){return e.reduce((t,n)=>t+1+Le(n.children),0)}function hn(e="inspect"){return K(e,{extension:".json"})}function gn(e,t){return`${JSON.stringify(e,null,t?2:void 0)}
3
+ `}const wn=async({device:e})=>{await e.clearKeychain()},yn=async({device:e,positionals:[t]})=>{await e.open(vn(t))};function vn(e){if(typeof e=="string")try{return new URL(e),e}catch{throw new a("<url> expects a URL, e.g., myapp://orders/42")}throw new a("<url> expects a URL, e.g., myapp://orders/42")}const xn=new Set(xe),Sn=async({device:e,positionals:[t]})=>{if(!bn(t))throw new a(`Button must be one of: ${xe.join(", ")}`);await e.press(t)};function bn(e){return typeof e=="string"&&xn.has(e)}const En=async({control:e,options:t,positionals:[n]})=>{const{path:o}=await e.recordStart({force:t.force===!0,path:An(n)});return{path:o}},On=async({control:e})=>{const{path:t}=await e.recordStop();return{path:t}};function An(e){const t=he(K(e,{extension:".mp4",strict:!0})),n=Ot(t);if(!me(n))throw new a(`No such directory: ${n}`);return t}const Pn=async({device:e,positionals:[t]})=>{if(!In(t))throw new a(`Orientation must be one of: ${k.join(", ")}`);await e.rotate(t)};function In(e){return k.some(t=>t===e)}const kn=async({device:e,positionals:[t]})=>{const n=await e.screenshot(),o=$n(n.mimeType,t);return await ge(o,n.data),{bytes:n.data.byteLength,output:o}};function Tn(e){const t=e.split("/").at(1);return`.${t==="jpeg"?"jpg":t??"png"}`}function $n(e,t="screenshot"){return K(t,{extension:Tn(e)})}function Ln(e){const t=we(new URL("./daemon.js",import.meta.url)),n=St(ot(e.sessionId),"a"),o=Tt(process.execPath,[t],{detached:!0,env:{...process.env,[it]:st(e),DEBUG:Dn(process.env.DEBUG)},stdio:["ignore",n,n]});if(bt(n),o.unref(),o.pid===void 0)throw new Error("Failed to spawn the session daemon");return o.pid}function Dn(e){return e?`${e},appetize:daemon`:"appetize:daemon"}const Nn=/^[a-z0-9](?:[a-z0-9._-]{0,62}[a-z0-9])?$/i;function _n(){return $t({capitalize:!1,separator:"-"})}function Rn(e){if(!Nn.test(e))throw new a('--session-id must use letters, digits, ".", "-" or "_"');return e}const De=1e4;function Ne(e){if(!rt(e))return!1;try{process.kill(e.pid,"SIGTERM")}catch{}return!0}async function _e(e,t){(Ne(e)||Un(e))&&await zn(e,t)}async function zn({pid:e,sessionId:t},n){const o=se(e);try{await z(De,AbortSignal.any([n,o]))}catch(i){if(o.aborted||!ie(e))return;throw i}throw new U(`Session ${t} did not stop in time`,{sessionId:t})}function Un({endedAt:e,pid:t}){return e!==void 0&&Date.now()-Date.parse(e)<De&&ie(t)}const jn=["device-android-shell","device-appearance","device-font-size","device-ios-keyboards","device-locale","device-location","device-orientation","device-os-version","device-timezone"];function Fn(e,t){const n=j({shell:u(e["device-android-shell"],"--device-android-shell"),softKeyboard:re(e["device-android-soft-keyboard"],{defaultValue:!0})}),o=j({autocorrect:re(e["device-ios-autocorrect"],{defaultValue:!0}),keyboards:F(e["device-ios-keyboards"],"--device-ios-keyboards")});return{android:n,appearance:T(e["device-appearance"],ce,"--device-appearance"),fontSize:T(e["device-font-size"],ae,"--device-font-size"),id:t,ios:o,locale:u(e["device-locale"],"--device-locale"),location:Mn(e["device-location"]),orientation:T(e["device-orientation"],k,"--device-orientation"),osVersion:u(e["device-os-version"],"--device-os-version"),timezone:u(e["device-timezone"],"--device-timezone")}}function Cn(e){return e!==""&&Number.isFinite(Number(e))}function Mn(e){const t=u(e,"--device-location");if(t===void 0)return;const n=t.split(",").map(s=>s.trim());if(n.length!==2||!n.every(Cn))throw new a("--device-location expects <lat>,<lng>, e.g., 43.65,-79.38");const[o,i]=n.map(Number);return{latitude:o,longitude:i}}const Bn=["launch-app","launch-ios-args","launch-params","launch-permissions","launch-url","open"];function qn(e){const t=F(e["launch-ios-args"],"--launch-ios-args");return j({app:Gn(e["launch-app"]),ios:t===void 0?void 0:{args:t},params:Kn(e["launch-params"]),permissions:T(e["launch-permissions"],pe,"--launch-permissions"),url:u(e["launch-url"],"--launch-url")??u(e.open,"--open")})}function Gn(e){return e===!1?!1:u(e,"--launch-app")}function Kn(e){const t=F(e,"--launch-params");if(t!==void 0)return Object.fromEntries(t.map(Zn))}function Zn(e){const t=e.indexOf("=");if(t<1)throw new a("--launch-params expects key=value, e.g., --launch-params debug=true");return[e.slice(0,t),Vn(e.slice(t+1))]}function Vn(e){try{return JSON.parse(e)}catch{return e}}const Re={"device.id":"<device>","device.location.latitude":"--device-location latitude","device.location.longitude":"--device-location longitude"};function Wn(e,{endpointFromEnv:t=!1}={}){const n=t?{...Re,endpoint:"APPETIZE_ENDPOINT"}:Re;try{at(e)}catch(o){throw o instanceof ct?new a(o.issues.map(i=>Xn(i,n)).join(`
4
+ `)):o}}function Xn({code:e,message:t,path:n},o){const i=Hn(n,o);switch(e){case"invalidValue":return`${i} ${t.replace(/^expected /,"expects ")}`;case"needsLaunchApp":return`${i} has no effect without --target, or with --no-launch-app`;case"needsTarget":return`${i} has no effect without --target`}}function Hn(e,t){return t[e]??`--${e.split(".").filter(n=>!/^\d+$/.test(n)).map(n=>n.replaceAll(/([A-Z])/g,"-$1").toLowerCase()).join("-")}`}const Jn=[...jn,...Bn,"proxy","target"],Yn=150,Qn={downloadingApp:"Downloading the app",installingApp:"Installing the app",launchingApp:"Launching the app",queued:"Queued",ready:"Device ready",requesting:"Requesting a device",starting:"Starting the device"},eo=[{header:"Session ID",key:"sessionId"},{header:"Web view",key:"viewerUrl"},{format:e=>`adb connect ${e}`,header:"adb",key:"adbSerial"},{header:"Host",key:"baseUrl"},{fields:[{header:"Device",key:"device"},{header:"Daemon",key:"daemon"},{header:"Network",key:"network"}],header:"Logs",key:"logs"},{hidden:!0,key:"controlSocket"}];async function to(e,{onPhase:t,signal:n}){let o;for(;;){const i=le(e),s=i?.state?.phase;if(s&&s!==o&&(o=s,t?.(s)),i&&s==="ready"&&i.controlSocket!==void 0)return{...i,controlSocket:i.controlSocket};if(s==="error")throw new Error(i?.endedReason??"The session failed to start");if(s==="ended")throw new Error(i?.endedReason??"The session ended");await z(Yn,n)}}function no(e){if(!(e===void 0||e===!1)){if(e===""||e==="intercept")return"intercept";if(typeof e!="string"||!io(e))throw new a("--proxy expects 'intercept' or an http:// url, e.g., http://proxy:8080");return e}}async function oo({options:e,positionals:t,progress:n,signal:o}){const[i]=t,s=u(e.target,"--target")??ro(e);if(s===void 0&&!process.env.APPETIZE_API_TOKEN)throw new a("APPETIZE_API_TOKEN must be set without a target",["Set APPETIZE_API_TOKEN, or pass --target"]);const r=u(e["session-id"],"--session-id"),p=e.force===!0;if(p&&r===void 0)throw new a("--force needs --session-id");const c=r===void 0?_n():Rn(r),l={device:Fn(e,i),endpoint:pt(e),featureFlags:de(),launch:qn(e),proxy:no(e.proxy),sessionId:c,target:s};Wn(l,{endpointFromEnv:e.endpoint===void 0});const f=le(c);if(f!==void 0){if(!p)throw new dt(c);n.status(`Replacing session ${c}`),await _e(f,o),lt(c)}Ln(l),n.step(`Session ${c}`);const v=ut(c,l.proxy);if(e.wait===!1)return{logs:v,sessionId:c};const A=await to(c,{onPhase:P=>{so(P)&&n.status(Qn[P]??"Starting the session")},signal:o}).catch(P=>{throw U.wrap(P,c)});return{adbSerial:A.adbSerial,baseUrl:A.baseUrl,controlSocket:A.controlSocket,logs:v,sessionId:c,viewerUrl:A.viewerUrl}}function io(e){return e.startsWith("http://")}function so(e){return e!=="ended"&&e!=="error"}function ro(e){const t=e._;return Array.isArray(t)&&typeof t[0]=="string"?t[0]:void 0}const ao=async({options:e,progress:t,record:n,signal:o})=>(e.wait===!1?Ne(n):(t.status(`Stopping session ${n.sessionId}`),await _e(n,o)),{sessionId:n.sessionId}),ze="appetize",co=we(new URL(`./skills/${ze}/`,import.meta.url)),Y=["agents","claude","codex","copilot","cursor"],Ue=["project","user"],po={agents:".agents",claude:".claude",codex:".codex",copilot:".copilot",cursor:".cursor"},lo=x(".agents","skills"),uo=["claude","agents"];function fo(e){return Y.some(t=>t===e)}function mo(e){return Ue.some(t=>t===e)}async function ho(e){const t=e.agents??await go(e),n=await Promise.all(t.map(o=>je(o,e)));return[...new Set(n.flat())]}async function je(e,t){const n=Fe(e,t);if(e==="claude")return[x(n,"skills")];const o=x(t.root,lo);return t.scope==="project"?[o]:await Ce(n)?[o,x(n,"skills")]:[o]}function Fe(e,t){if(e==="claude"&&t.scope==="user"){const n=process.env.CLAUDE_CONFIG_DIR?.trim();if(n)return he(n)}return x(t.root,po[e])}async function go(e){const n=(await Promise.all(Y.map(async o=>await wo(o,e)?o:void 0))).filter(o=>o!==void 0);return n.length>0?n:uo}async function wo(e,t){const n=[Fe(e,t),...await je(e,t)];return(await Promise.all(n.map(i=>Ce(i)))).includes(!0)}async function Ce(e){try{return(await Pt(e)).isDirectory()}catch{return!1}}const yo=["agent","scope"];async function vo({options:e,signal:t}){const n=bo(e.scope),o=So(e.agent),i=n==="user"?Lt():process.cwd(),s=await ho({agents:o,root:i,scope:n}),r=[];for(const p of s){t.throwIfAborted();const c=x(p,ze);await It(c,{force:!0,recursive:!0}),await kt(co,c,{recursive:!0}),r.push(n==="user"?c:At(i,c))}return{installed:r}}function xo(e){const t=I(e,"--agent");if(!fo(t))throw new a(`--agent expects one of ${Y.join(", ")}`);return t}function So(e){return e===void 0?void 0:(Array.isArray(e)?e:[e]).map(n=>xo(n))}function bo(e){if(e===void 0)return"project";const t=I(e,"--scope");if(!mo(t))throw new a(`--scope expects one of ${Ue.join(", ")}`);return t}const w="from",y="to",Eo=[...H({prefix:w}),...H({prefix:y})],Oo=async({device:e,options:t})=>{await e.swipe(ko(t),$o(t))};function Ao(e){return B.some(t=>t===e)}function Po(e){if(e===void 0)return;const t=I(e,"--direction");if(!Ao(t))throw new a(`--direction expects one of ${B.join(", ")}`);return t}function Io(e,t){const n=ft(e.distance,"--distance");if(L(e,{prefix:y})!==void 0)throw new a(`--direction may not be combined with --${y}-*`);return{direction:t,distance:n,from:L(e,{prefix:w})}}function ko(e){const t=Po(e.direction);return t===void 0?To(e):Io(e,t)}function To(e){if(e.distance!==void 0)throw new a("--distance is only valid with --direction");return{from:Me(L(e,{prefix:w}),w),to:Me(L(e,{prefix:y}),y)}}function $o(e){const t=h(e.duration,"--duration"),n=h(e.timeout,"--timeout");return t===void 0&&n===void 0?void 0:{duration:t,timeout:n}}function Me(e,t){if(e===void 0)throw new a(`A swipe needs --direction, or both endpoints: pass one of ${O({prefix:t})}`);return e}const Lo=H(),Do=async({device:e,options:t})=>{const n=Pe(t);await e.tap(n,Ae(t))},No=async({device:e,options:t,positionals:[n]})=>{await e.type(n,_o(t))};function _o(e){const t=h(e.delay,"--delay");return t===void 0?void 0:{delay:t}}const Q=Dt("appetize:cli"),Ro={fail:()=>{},status:()=>{},step:()=>{},succeed:()=>{}};function zo(e,t,n){return e==="interactive"?Uo(t,n):Ro}function Uo(e,t){const n=Nt({handleSignals:!1,stream:e});let o=0;const i=()=>{n.stop()};t.addEventListener("abort",i,{once:!0});const s=()=>(process.off("exit",i),n.isSpinning);return{fail:()=>{s()&&n.stop()},status:r=>{if(!t.aborted){if(n.isSpinning){n.text=r;return}o=Date.now(),process.once("exit",i),n.start(r)}},step:r=>{e.write(`\u25B8 ${r}
5
+ `)},succeed:()=>{if(!s())return;const r=Math.round((Date.now()-o)/1e3);n.success(`${n.text} (${String(r)}s)`)}}}const jo=new Set(["adb","api","apk","id","os","url"]),Fo={bottom:"","bottom-left":"","bottom-mid":"","bottom-right":"",left:"","left-mid":"",mid:"","mid-mid":"",middle:" ",right:"","right-mid":"",top:"","top-left":"","top-mid":"","top-right":""},Be=2,Co=10;function Mo(e){return e.split(/(?=[A-Z])/).map((t,n)=>{const o=t.toLowerCase();return jo.has(o)?o.toUpperCase():n===0?o.charAt(0).toUpperCase()+o.slice(1):o}).join(" ")}function Bo(e,t,n){return te(e)?We(e,t,n):N(e,{fields:t,key:""},n)}function qo(e,t){const n=[];for(let o=0;o<e.length;o+=t)n.push(e.slice(o,o+t));return n.length===0?[e]:n}function qe(e){return new _t({chars:Fo,head:e,style:{border:[],head:[],"padding-left":0,"padding-right":Be}})}function Ge(e,t){return e.find(n=>n.key===t)}function Ke(e,t){return t?.header??Mo(e)}function ee(e){return e!=null}function te(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function Ze(e){return["boolean","number","string"].includes(typeof e)}function Ve(e,t){const n=new Set(t),o=e.map(s=>s.key).filter(s=>n.has(s)),i=new Set(e.filter(s=>s.hidden).map(s=>s.key));return[...new Set([...o,...t])].filter(s=>!i.has(s))}function We(e,t,n){const o=new Map(Object.entries(e)),i=Ve(t,[...o.keys()]).filter(f=>ee(o.get(f))),s=i.map(f=>Ge(t,f)),r=i.map((f,v)=>Ke(f,s[v])),p=Math.max(0,...r.map(f=>f.length))+Be,c=n===void 0?void 0:n-p-1,l=qe();return l.push(...i.map((f,v)=>[r[v],N(o.get(f),s[v],c)])),Xe(l.toString())}function Go(e,t){const n=e.map(r=>new Map(Object.entries(r))),o=Ve(t,n.flatMap(r=>[...r.keys()])),i=o.map(r=>Ge(t,r)),s=qe(o.map((r,p)=>Ke(r,i[p])));for(const r of n)s.push(o.map((p,c)=>{const l=r.get(p);return ee(l)?N(l,i[c]):""}));return Xe(s.toString())}function N(e,t,n){if(t?.format)return _(t.format(e),n);if(Ze(e))return _(ue(e),n);if(Array.isArray(e)){const o=e.filter(ee);return o.every(Ze)?_(ue(o),n):o.every(te)?Go(o,t?.fields??[]):o.map(i=>N(i,t,n)).join(`
6
+ `)}return te(e)?We(e,t?.fields??[],n):_(String(e),n)}function Xe(e){return e.split(`
7
7
  `).map(t=>t.trimEnd()).join(`
8
- `)}function N(e,t){return t===void 0||t<Rn?e:e.split(`
9
- `).flatMap(o=>Cn(o,t)).join(`
10
- `)}function Cn(e,t){const o=[];let n="";for(const i of e.split(" ").flatMap(r=>jn(r,t)))n===""?n=i:n.length+1+i.length<=t?n=`${n} ${i}`:(o.push(n),n=i);return o.push(n),o}async function Mn(e,t={}){const o=await de(e,{signal:t.signal});return new ut(o,{...t,onClose:()=>{o.close(),t.onClose?.()}})}function Bn(e,t){if(e.controlSocket===void 0)throw new Error("Session is not ready");return Mn(e.controlSocket,{baseUrl:e.baseUrl,signal:t})}async function qn(e,t){if(e.controlSocket===void 0)throw new Error("Session is not ready");const o=await de(e.controlSocket,{signal:t}),{client:n}=ft(o,{});return{close:()=>{o.close()},recordStart:async i=>await n.request("appetizeio.cli.record.start",i),recordStop:async()=>await n.request("appetizeio.cli.record.stop")}}function Gn(e){return async({options:t,positionals:o,progress:n,signal:i})=>{const r=t["session-id"],s=mt(typeof r=="string"?r:void 0);try{return await e({options:t,positionals:o,progress:n,record:s,signal:AbortSignal.any([i,ne(s.pid)])})}catch(p){throw U.wrap(p,s.sessionId)}}}function Kn(e){return async({options:t,positionals:o,progress:n,record:i,signal:r})=>{const s=await Bn(i,r);try{return await e({device:s,options:t,positionals:o,progress:n,signal:r})}finally{s.close()}}}function Zn(e){return async({options:t,positionals:o,progress:n,record:i,signal:r})=>{const s=await qn(i,r);try{return await e({control:s,options:t,positionals:o,progress:n,signal:r})}finally{s.close()}}}const Vn=["session-id",...Nt,...zt,...Zt,...lo,...fn,...Go,...yn,...In],Wn=["json","quiet"];function Xn(e){const t=He("appetize").version(e).option("--json","Print the result as JSON").option("--quiet","Hide progress");return b(t,"session start <device>",o=>o.describe(["Start a device session and wait until it is ready","","Environment variables:","APPETIZE_API_TOKEN: Authorizes private APIs and targets; required with no target","APPETIZE_ENDPOINT: Appetize URL used when --endpoint is omitted"]).option("--device-android-shell","Android only: adb shell command run at start; needs --target").option("--device-appearance",`Device appearance: ${se.join(" or ")}`).option("--device-font-size",`Device font size: ${re.join(", ")}`).option("--device-ios-keyboards","iOS only: keyboard layout (e.g., en_US@sw=QWERTY); repeatable").option("--device-locale","Device locale as a BCP 47 tag (e.g., fr-CA)").option("--device-location","Device location as <lat>,<lng>; use = if latitude is negative").option("--device-orientation",`Initial orientation: ${T.join(", ")}`).option("--device-os-version","Device OS version (e.g., 17 for iOS, 14 for Android)").option("--device-timezone","Device IANA timezone (e.g., America/Toronto)").option("--endpoint","Appetize URL (e.g., https://appetize.io); overrides APPETIZE_ENDPOINT").option("--force","Replace a session with the same id",!1).option("--no-device-android-soft-keyboard","Android only: hide the on-screen keyboard").option("--no-device-ios-autocorrect","iOS only: keep autocorrect off, its default").option("--no-wait","Return without waiting for the device session to be ready").option("--open","URL opened once the session is ready").option("--proxy","Route traffic through a proxy: 'intercept' to capture it, or an http url").option("--session-id","Session id; defaults to a generated 3-word id").option("--target","App, build or app group id to run").example("session start iphone15pro --target app_a1b2c3").example("session start iphone15pro").example("session start pixel7 --target app_a1b2c3 --device-os-version 14").example("session start iphone15pro --target app_a1b2c3 --open myapp://orders/42").example("session start iphone15pro --device-orientation landscapeLeft --device-appearance dark").example("session start pixel7 --device-locale fr-CA --device-timezone America/Toronto").example("session start iphone15pro --target app_a1b2c3 --session-id demo --force"),Yo,{fields:Vo}),ee(t,"session stop",o=>o.describe("Stop a device session and await its exit").option("--no-wait","Return without waiting for the session to exit").example("session stop --no-wait"),on),b(t,"build list",o=>o.describe(["List uploaded builds, printing session start targets","","Environment variables:","APPETIZE_API_TOKEN: Authorizes the listing request","APPETIZE_ENDPOINT: Appetize URL used when --endpoint is omitted"]).option("--app","App id to filter by (bundle or package id)").option("--endpoint","Appetize URL (e.g., https://appetize.io); overrides APPETIZE_ENDPOINT").option("--limit","Builds per page (default 10, max 200)").option("--page","Page of results to fetch (default 1)").example("build list").example("build list --app com.example.app").example("build list --app com.example.app --page 2"),Ut,{fields:Rt}),b(t,"build upload <file>",o=>o.describe([`Upload a build (${M.join(", ")}) as a session start target`,"","Environment variables:","APPETIZE_API_TOKEN: Authorizes the upload","APPETIZE_ENDPOINT: Appetize URL used when --endpoint is omitted"]).option("--endpoint","Appetize URL (e.g., https://appetize.io); overrides APPETIZE_ENDPOINT").option("--note","Note to store with the build").option("--tags","Comma separated tags to store with the build").option("--timeout",`Milliseconds to wait with --wait (default ${String(ve)})`).option("--wait","Wait for the app id and version metadata to resolve").example("build upload ./app.apk").example("build upload ./app.zip").example("build upload ./app.apk --wait").example('build upload ./app.apk --tags beta,latest --note "PR 42"'),Mt,{fields:Ct}),b(t,"device list",o=>o.describe(["List device models and their supported OS versions","","Environment variables:","APPETIZE_ENDPOINT: Appetize URL used when --endpoint is omitted"]).option("--endpoint","Appetize URL (e.g., https://appetize.io); overrides APPETIZE_ENDPOINT").option("--platform","Platform to filter by: ios or android").example("device list").example("device list --platform ios"),Wt,{fields:Vt}),m(t,"press <button>",o=>o.describe(`Press a device button: ${ge.join(", ")}; Android only: ${he.join(", ")}`).example("press home").example("press volumeUp"),vo),m(t,"rotate <orientation>",o=>o.describe("Rotate the device to an orientation: portrait, landscapeLeft, landscapeRight or upsideDown").example("rotate portrait").example("rotate landscapeLeft"),Ao),Yt in ae()&&m(t,"fold <hinge>",o=>o.describe(`Fold a foldable device: ${j.join(", ")}`).example("fold closed").example("fold fullyOpen"),Jt),m(t,"open <url>",o=>o.describe("Open a URL or deep link on the device").example("open myapp://orders/42").example("open https://example.com"),go),m(t,"keychain clear",o=>o.describe("Clear the entire device keychain (iOS only)").example("keychain clear"),ho),m(t,"screenshot [output]",o=>o.describe("Take a screenshot of the current device screen").example("screenshot").example("screenshot home-screen").example("screenshot ./shots/checkout.png"),Io),m(t,"tap",o=>Z(o.describe(["Tap an element matched by a selector, or a screen position","",`Pick one of: ${O()}`])).option("--timeout","Milliseconds to wait for the element").example("tap --select-text 'Log in'").example("tap --select-test-id save").example("tap --select-text '/^Item \\d+/i' --select-index 2").example("tap --select-position 0.5,0.75").example("tap --select-test-id slider --select-x 0.9").example("tap --select-test-id dialog --select-x=-0.1").example("tap --select-test-id row --select-y=1.2"),Pn),m(t,"swipe",o=>Z(Z(o.describe(["Swipe in a direction, or along a path between two points","",`Pick a --direction with an optional --${w} starting point,`,`or both a --${w}-* and a --${y}-* point to form a path`,"",`Pick one per point: ${O({prefix:w})}`,` ${O({prefix:y})}`]).option("--direction",`Direction to travel: ${F.join(", ")}`).option("--distance","Travel as a fraction of the screen (0-1)"),{prefix:w}),{prefix:y}).option("--duration","Milliseconds the gesture travels for").option("--timeout",`Milliseconds to wait for any --${w}/--${y} elements`).example("swipe --direction up").example("swipe --direction up --distance 0.25").example("swipe --direction left --from-test-id card --from-index 1").example("swipe --from-position 0.5,0.75 --to-position 0.5,0.3").example("swipe --from-text 'Drag me' --from-y 0.9 --to-test-id drop-zone"),vn),m(t,"gesture <syntax>",o=>o.describe(["Play a single-pointer gesture",""," > press the pointer down"," / lift it"," {wait} pause 400 ms"," {wait=ms} pause ms"," {...} move the pointer:"," byText=Photo to the element with exactly that text"," byText=/photo/i to the element matching the regex",' byText="My photos" quote values with spaces'," byTestId=card to the element with that test id"," index=1 to the second match, from 0"," x=0 y=0 to a point in it; 0-1 spans it"," 0.5,0.6 to a screen position, each 0-1"," x=0.5 y=0.6 the same screen position"," duration=ms glide time while down; default 400","","Single-quote the gesture. A pointer still down at the end lifts.","Double taps need {wait=100} between taps; Android drops faster ones."]).option("--timeout","Milliseconds to wait for any elements").example("gesture '{byText=Photo}>/' # tap").example("gesture '{byText=Photo}>{wait=800}/' # long-press").example("gesture '{0.5,0.5}>/{wait=100}>/' # double tap").example("gesture '{byTestId=card}>{byTestId=drop-zone duration=600}/' # drag").example(`gesture '{byText="My photos" x=0 y=0}>{wait}/' # top-left corner`).example("gesture '{byText=/photo/i index=1}>{wait=800}/' # 2nd match").example("gesture '{byTestId=slider x=0}>{byTestId=slider x=1 duration=1000}/' # slide").example("gesture '{0.5,0.8}>{0.5,0.6}{0.8,0.6}{0.8,0.2}/' # path").example("gesture '{0.2,0.4}>{0.5,0.6 duration=300}/{0.2,0.7}>{0.8,0.7}/' # 2 strokes").example("gesture '{byTestId=card}>{wait=800}/' --timeout 5000 # wait for card"),eo),m(t,"inspect [output]",o=>xe(o.describe("Capture the view hierarchy of the screen, or of every element a selector matches")).option("--timeout","Milliseconds to wait for a match").option("--pretty","Pretty-print the JSON",!1).example("inspect").example("inspect --select-text 'Log in'").example("inspect hierarchy.json --pretty"),uo),m(t,"type <text>",o=>o.describe(`Type text; {...} presses a named key: ${wt.join(", ")}`).option("--delay","Milliseconds to wait between steps").example("type 'hello{Enter}'").example("type '{Backspace>16/}'").example("type 'user@example.com{Tab}hunter2{Enter}' --delay 50"),Tn),We(t,"recording start <output>",o=>o.describe("Start recording the device video to an mp4 file").option("--force","Overwrite the file if it already exists",!1).example("recording start login-flow").example("recording start ./captures/checkout.mp4").example("recording start login-flow --force"),So),We(t,"recording stop",o=>o.describe("Stop recording the device video and close the file").example("recording stop"),bo),b(t,"skill install",o=>o.describe("Install the Appetize agent skill for coding agents").option("--agent","Agent to install for, repeatable; defaults to the agents detected").option("--scope","Install for the project (default) or the user").example("skill install").example("skill install --scope user").example("skill install --agent claude --agent cursor"),mn),t}function b(e,t,o,n,{fields:i}={}){const r=t.split(" ").filter(s=>!/^[<[]/.test(s)).join(" ");return o(e.command(t)).action(Jn({action:n,fields:i,name:r}))}function ee(e,t,o,n){return b(e,t,i=>o(i).option("--session-id","Target session id; defaults to the sole active session"),Gn(n))}function m(e,t,o,n){return ee(e,t,o,Kn(n))}function We(e,t,o,n){return ee(e,t,o,Zn(n))}function Xe(e){return`${String(Date.now()-e)}ms`}function Hn(e,t,o){if(e==="json")return JSON.stringify(t===void 0?{}:t,null,2);const n=t===void 0?"":zn(t,o,process.stdout.columns);return n===""?void 0:n}async function Yn({action:e,fields:t=[],name:o},n){const i=Date.now();Y(`invoked: ${process.argv.slice(2).join(" ")}`);const r=ht(n),{format:s,progress:p}=io(r.options,process.stdout,process.stderr),c=Ln(p,process.stderr,r.signal);try{const l=Hn(s,await e({...r,progress:c}),t);c.succeed(),l!==void 0&&process.stdout.write(`${l}
11
- `),Y(`ok in ${Xe(i)}`)}catch(l){c.fail(),process.stderr.write(`${gt(s,l,{command:o})}
12
- `),Y(`failed after ${Xe(i)}:`,l),process.exitCode=1}}function Jn(e){return(...t)=>{Yn(e,t)}}Xn("0.24.0").parse(process.argv,{boolean:Wn,string:Vn});
8
+ `)}function _(e,t){return t===void 0||t<Co?e:e.split(`
9
+ `).flatMap(n=>Ko(n,t)).join(`
10
+ `)}function Ko(e,t){const n=[];let o="";for(const i of e.split(" ").flatMap(s=>qo(s,t)))o===""?o=i:o.length+1+i.length<=t?o=`${o} ${i}`:(n.push(o),o=i);return n.push(o),n}async function Zo(e,t={}){const n=await fe(e,{signal:t.signal});return new mt(n,{...t,onClose:()=>{n.close(),t.onClose?.()}})}function Vo(e,t){if(e.controlSocket===void 0)throw new Error("Session is not ready");return Zo(e.controlSocket,{baseUrl:e.baseUrl,signal:t})}async function Wo(e,t){if(e.controlSocket===void 0)throw new Error("Session is not ready");const n=await fe(e.controlSocket,{signal:t}),{client:o}=ht(n,{});return{close:()=>{n.close()},recordStart:async i=>await o.request("appetizeio.cli.record.start",i),recordStop:async()=>await o.request("appetizeio.cli.record.stop")}}function Xo(e){return async({options:t,positionals:n,progress:o,signal:i})=>{const s=t["session-id"],r=gt(typeof s=="string"?s:void 0);try{return await e({options:t,positionals:n,progress:o,record:r,signal:AbortSignal.any([i,se(r.pid)])})}catch(p){throw U.wrap(p,r.sessionId)}}}function Ho(e){return async({options:t,positionals:n,progress:o,record:i,signal:s})=>{const r=await Vo(i,s);try{return await e({device:r,options:t,positionals:n,progress:o,signal:s})}finally{r.close()}}}function Jo(e){return async({options:t,positionals:n,progress:o,record:i,signal:s})=>{const r=await Wo(i,s);try{return await e({control:r,options:t,positionals:n,progress:o,signal:s})}finally{r.close()}}}const Yo=["session-id",...Rt,...Ft,...Wt,...fn,...yo,...Jn,...Eo,...Lo],Qo=["json","quiet"];function ei(e){const t=Ye("appetize").version(e).option("--json","Print the result as JSON").option("--quiet","Hide progress");return b(t,"session start <device>",n=>n.describe(["Start a device session and wait until it is ready","","Environment variables:","APPETIZE_API_TOKEN: Authorizes private APIs and targets; required with no target","APPETIZE_ENDPOINT: Appetize URL used when --endpoint is omitted"]).option("--device-android-shell","Android only: adb shell command run at start; needs --target").option("--device-appearance",`Device appearance: ${ce.join(" or ")}`).option("--device-font-size",`Device font size: ${ae.join(", ")}`).option("--device-ios-keyboards","iOS only: keyboard layout (e.g., en_US@sw=QWERTY); repeatable").option("--device-locale","Device locale as a BCP 47 tag (e.g., fr-CA)").option("--device-location","Device location as <lat>,<lng>; use = if latitude is negative").option("--device-orientation",`Initial orientation: ${k.join(", ")}`).option("--device-os-version","Device OS version (e.g., 17 for iOS, 14 for Android)").option("--device-timezone","Device IANA timezone (e.g., America/Toronto)").option("--endpoint","Appetize URL (e.g., https://appetize.io); overrides APPETIZE_ENDPOINT").option("--force","Replace a session with the same id",!1).option("--launch-app","App id to launch instead of the target app; needs --target").option("--launch-ios-args","iOS only: app launch argument, joined with = if it starts with -; repeatable; needs --target").option("--launch-params","App launch parameter as key=value, JSON when valid; repeatable; needs --target").option("--launch-permissions",`Grant app permissions: ${pe.join(", ")}; needs --target`).option("--launch-url","URL opened once the session is ready").option("--no-device-android-soft-keyboard","Android only: hide the on-screen keyboard").option("--no-device-ios-autocorrect","iOS only: keep autocorrect off, its default").option("--no-launch-app","Skip launching the app; needs --target").option("--no-wait","Return without waiting for the device session to be ready").option("--proxy","Route traffic through a proxy: 'intercept' to capture it, or an http url").option("--session-id","Session id; defaults to a generated 3-word id").option("--target","App, build or app group id to run").example("session start iphone15pro --target app_a1b2c3").example("session start iphone15pro").example("session start pixel7 --target app_a1b2c3 --device-os-version 14").example("session start iphone15pro --target app_a1b2c3 --launch-url myapp://orders/42").example("session start iphone15pro --target app_a1b2c3 --launch-params debug=true --launch-params retries=3").example(`session start iphone15pro --target app_a1b2c3 --launch-params 'zip="90210"'`).example(`session start iphone15pro --target app_a1b2c3 --launch-params 'tags=["beta","qa"]'`).example("session start iphone15pro --device-orientation landscapeLeft --device-appearance dark").example("session start pixel7 --device-locale fr-CA --device-timezone America/Toronto").example("session start iphone15pro --target app_a1b2c3 --session-id demo --force"),oo,{fields:eo}),ne(t,"session stop",n=>n.describe("Stop a device session and await its exit").option("--no-wait","Return without waiting for the session to exit").example("session stop --no-wait"),ao),b(t,"build list",n=>n.describe(["List uploaded builds, printing session start targets","","Environment variables:","APPETIZE_API_TOKEN: Authorizes the listing request","APPETIZE_ENDPOINT: Appetize URL used when --endpoint is omitted"]).option("--app","App id to filter by (bundle or package id)").option("--endpoint","Appetize URL (e.g., https://appetize.io); overrides APPETIZE_ENDPOINT").option("--limit","Builds per page (default 10, max 200)").option("--page","Page of results to fetch (default 1)").example("build list").example("build list --app com.example.app").example("build list --app com.example.app --page 2"),jt,{fields:Ut}),b(t,"build upload <file>",n=>n.describe([`Upload a build (${G.join(", ")}) as a session start target`,"","Environment variables:","APPETIZE_API_TOKEN: Authorizes the upload","APPETIZE_ENDPOINT: Appetize URL used when --endpoint is omitted"]).option("--endpoint","Appetize URL (e.g., https://appetize.io); overrides APPETIZE_ENDPOINT").option("--note","Note to store with the build").option("--tags","Comma separated tags to store with the build").option("--timeout",`Milliseconds to wait with --wait (default ${String(be)})`).option("--wait","Wait for the app id and version metadata to resolve").example("build upload ./app.apk").example("build upload ./app.zip").example("build upload ./app.apk --wait").example('build upload ./app.apk --tags beta,latest --note "PR 42"'),qt,{fields:Bt}),b(t,"device list",n=>n.describe(["List device models and their supported OS versions","","Environment variables:","APPETIZE_ENDPOINT: Appetize URL used when --endpoint is omitted"]).option("--endpoint","Appetize URL (e.g., https://appetize.io); overrides APPETIZE_ENDPOINT").option("--platform","Platform to filter by: ios or android").example("device list").example("device list --platform ios"),Ht,{fields:Xt}),m(t,"press <button>",n=>n.describe(`Press a device button: ${ve.join(", ")}; Android only: ${ye.join(", ")}`).example("press home").example("press volumeUp"),Sn),m(t,"rotate <orientation>",n=>n.describe("Rotate the device to an orientation: portrait, landscapeLeft, landscapeRight or upsideDown").example("rotate portrait").example("rotate landscapeLeft"),Pn),Qt in de()&&m(t,"fold <hinge>",n=>n.describe(`Fold a foldable device: ${M.join(", ")}`).example("fold closed").example("fold fullyOpen"),en),m(t,"open <url>",n=>n.describe("Open a URL or deep link on the device").example("open myapp://orders/42").example("open https://example.com"),yn),m(t,"keychain clear",n=>n.describe("Clear the entire device keychain (iOS only)").example("keychain clear"),wn),m(t,"screenshot [output]",n=>n.describe("Take a screenshot of the current device screen").example("screenshot").example("screenshot home-screen").example("screenshot ./shots/checkout.png"),kn),m(t,"tap",n=>X(n.describe(["Tap an element matched by a selector, or a screen position","",`Pick one of: ${O()}`])).option("--timeout","Milliseconds to wait for the element").example("tap --select-text 'Log in'").example("tap --select-test-id save").example("tap --select-text '/^Item \\d+/i' --select-index 2").example("tap --select-position 0.5,0.75").example("tap --select-test-id slider --select-x 0.9").example("tap --select-test-id dialog --select-x=-0.1").example("tap --select-test-id row --select-y=1.2"),Do),m(t,"swipe",n=>X(X(n.describe(["Swipe in a direction, or along a path between two points","",`Pick a --direction with an optional --${w} starting point,`,`or both a --${w}-* and a --${y}-* point to form a path`,"",`Pick one per point: ${O({prefix:w})}`,` ${O({prefix:y})}`]).option("--direction",`Direction to travel: ${B.join(", ")}`).option("--distance","Travel as a fraction of the screen (0-1)"),{prefix:w}),{prefix:y}).option("--duration","Milliseconds the gesture travels for").option("--timeout",`Milliseconds to wait for any --${w}/--${y} elements`).example("swipe --direction up").example("swipe --direction up --distance 0.25").example("swipe --direction left --from-test-id card --from-index 1").example("swipe --from-position 0.5,0.75 --to-position 0.5,0.3").example("swipe --from-text 'Drag me' --from-y 0.9 --to-test-id drop-zone"),Oo),m(t,"gesture <syntax>",n=>n.describe(["Play a single-pointer gesture",""," > press the pointer down"," / lift it"," {wait} pause 400 ms"," {wait=ms} pause ms"," {...} move the pointer:"," byText=Photo to the element with exactly that text"," byText=/photo/i to the element matching the regex",' byText="My photos" quote values with spaces'," byTestId=card to the element with that test id"," index=1 to the second match, from 0"," x=0 y=0 to a point in it; 0-1 spans it"," 0.5,0.6 to a screen position, each 0-1"," x=0.5 y=0.6 the same screen position"," duration=ms glide time while down; default 400","","Single-quote the gesture. A pointer still down at the end lifts.","Double taps need {wait=100} between taps; Android drops faster ones."]).option("--timeout","Milliseconds to wait for any elements").example("gesture '{byText=Photo}>/' # tap").example("gesture '{byText=Photo}>{wait=800}/' # long-press").example("gesture '{0.5,0.5}>/{wait=100}>/' # double tap").example("gesture '{byTestId=card}>{byTestId=drop-zone duration=600}/' # drag").example(`gesture '{byText="My photos" x=0 y=0}>{wait}/' # top-left corner`).example("gesture '{byText=/photo/i index=1}>{wait=800}/' # 2nd match").example("gesture '{byTestId=slider x=0}>{byTestId=slider x=1 duration=1000}/' # slide").example("gesture '{0.5,0.8}>{0.5,0.6}{0.8,0.6}{0.8,0.2}/' # path").example("gesture '{0.2,0.4}>{0.5,0.6 duration=300}/{0.2,0.7}>{0.8,0.7}/' # 2 strokes").example("gesture '{byTestId=card}>{wait=800}/' --timeout 5000 # wait for card"),nn),m(t,"inspect [output]",n=>Ee(n.describe("Capture the view hierarchy of the screen, or of every element a selector matches")).option("--timeout","Milliseconds to wait for a match").option("--pretty","Pretty-print the JSON",!1).example("inspect").example("inspect --select-text 'Log in'").example("inspect hierarchy.json --pretty"),mn),m(t,"type <text>",n=>n.describe(`Type text; {...} presses a named key: ${vt.join(", ")}`).option("--delay","Milliseconds to wait between steps").example("type 'hello{Enter}'").example("type '{Backspace>16/}'").example("type 'user@example.com{Tab}hunter2{Enter}' --delay 50"),No),He(t,"recording start <output>",n=>n.describe("Start recording the device video to an mp4 file").option("--force","Overwrite the file if it already exists",!1).example("recording start login-flow").example("recording start ./captures/checkout.mp4").example("recording start login-flow --force"),En),He(t,"recording stop",n=>n.describe("Stop recording the device video and close the file").example("recording stop"),On),b(t,"skill install",n=>n.describe("Install the Appetize agent skill for coding agents").option("--agent","Agent to install for, repeatable; defaults to the agents detected").option("--scope","Install for the project (default) or the user").example("skill install").example("skill install --scope user").example("skill install --agent claude --agent cursor"),vo),t}function b(e,t,n,o,{fields:i}={}){const s=t.split(" ").filter(r=>!/^[<[]/.test(r)).join(" ");return n(e.command(t)).action(oi({action:o,fields:i,name:s}))}function ne(e,t,n,o){return b(e,t,i=>n(i).option("--session-id","Target session id; defaults to the sole active session"),Xo(o))}function m(e,t,n,o){return ne(e,t,n,Ho(o))}function He(e,t,n,o){return ne(e,t,n,Jo(o))}function Je(e){return`${String(Date.now()-e)}ms`}function ti(e,t,n){if(e==="json")return JSON.stringify(t===void 0?{}:t,null,2);const o=t===void 0?"":Bo(t,n,process.stdout.columns);return o===""?void 0:o}async function ni({action:e,fields:t=[],name:n},o){const i=Date.now();Q(`invoked: ${process.argv.slice(2).join(" ")}`);const s=wt(o),{format:r,progress:p}=an(s.options,process.stdout,process.stderr),c=zo(p,process.stderr,s.signal);try{const l=ti(r,await e({...s,progress:c}),t);c.succeed(),l!==void 0&&process.stdout.write(`${l}
11
+ `),Q(`ok in ${Je(i)}`)}catch(l){c.fail(),process.stderr.write(`${yt(r,l,{command:n})}
12
+ `),Q(`failed after ${Je(i)}:`,l),process.exitCode=1}}function oi(e){return(...t)=>{ni(e,t)}}ei("0.25.1").parse(process.argv,{boolean:Qo,string:Yo});
package/daemon.js CHANGED
@@ -1,2 +1,2 @@
1
- import{T as _,L as A,M as F,N as E,O as z,F as V,P as N,t as v,Q as j,v as H,R as Q,V as J,W as $,X as G,Y as K,A as Z,Z as X,_ as Y,$ as B,a0 as ee}from"./stream-BowDfEJS.js";import T from"debug";import{createServer as R}from"node:net";import{pipeline as P}from"node:stream";import{rm as te}from"node:fs/promises";import{readFileSync as ne,createWriteStream as oe,existsSync as re,rmSync as se}from"node:fs";import{createServer as ie}from"node:http";import{WebSocketServer as ae}from"ws";import{pipeline as ce}from"node:stream/promises";import{EncodedVideoPacketSource as de,Output as ue,FilePathTarget as le,Mp4OutputFormat as fe,EncodedPacket as pe}from"mediabunny";import"json-rpc-2.0";import"zod/mini";import"node:path";import"node:os";import"stream";import"module";const he=T("appetize.io:transport:ws-ping"),we=3e4;function ge(e){let t=!0;const n=()=>{t=!0};e.on("pong",n);const o=setInterval(()=>{if(!t){clearInterval(o),he("liveness ping went unanswered, terminating"),e.terminate();return}e.readyState===e.OPEN&&(t=!1,e.ping())},we);return{destroy(){clearInterval(o),e.off("pong",n)},pong:n}}const w=T("appetize.io:trace:transport:websocket");class L extends _{constructor(t,{signal:n}={}){super(async r=>{this.#e.send(A(r))},{signal:n}),this.wsOrUrl=t,typeof t=="string"?(this.#e=new WebSocket(t),this.#e.binaryType="arraybuffer"):this.#e=t;const o=this.#e;if(o instanceof WebSocket?(o.addEventListener("open",this.#s),o.addEventListener("message",this.#r),o.addEventListener("error",this.#o),o.addEventListener("close",this.#n),this.#t.push(()=>{o.removeEventListener("open",this.#s),o.removeEventListener("message",this.#r),o.removeEventListener("error",this.#o),o.removeEventListener("close",this.#n)})):(o.addEventListener("open",this.#s),o.addEventListener("message",this.#r),o.addEventListener("error",this.#o),o.addEventListener("close",this.#n),this.#t.push(()=>{o.removeEventListener("open",this.#s),o.removeEventListener("message",this.#r),o.removeEventListener("error",this.#o),o.removeEventListener("close",this.#n)})),this.send=o.send.bind(o),"ping"in o){const{destroy:r,pong:s}=ge(o);this.#c=s,this.#t.push(r)}}wsOrUrl;onclose;onerror;onmessage;onopen;send;get bufferedAmount(){return this.#e.bufferedAmount}get readyState(){return this.#e.readyState}#t=[];#i=!1;#a=!1;#c;#e;close({destroyWs:t=!1,...n}={}){this.closed||(this.#i=t,super.close(n))}handleClose(t){w("close()");for(const n of this.#t.splice(0))n();if((typeof this.wsOrUrl=="string"||this.#i)&&(this.#e.close(t.code,t.reason),"terminate"in this.#e)){const n=this.#e;setTimeout(()=>{n.terminate()},100)}this.#d(),super.handleClose(t)}#d(t){this.#a||(this.#a=!0,this.onclose?.(t))}#n=t=>{w("handleWebSocketClose()",t);try{this.#d(t)}finally{this.close()}};#o=t=>{w("handleWebSocketError()",t),this.onerror?.(t)};#r=async t=>{w("handleWebSocketMessage()",t),this.#c?.();const n=this.#u(t);if(!n){w("handleWebSocketMessage() -> legacy"),this.onmessage?.(t);return}w("handleWebSocketMessage() -> jsonrpc",n),this[F].dispatchMessage(n)};#s=t=>{w("handleWebSocketOpen()",t),this.onopen?.(t)};#u(t){try{const n=E(new Uint8Array(t.data));return z(n)?n:null}catch{return null}}}function b(e){return typeof e=="object"&&e!==null}function I(e){try{const t=E(new Uint8Array(e.data));if(b(t)&&typeof t.name=="string")return{name:t.name,payload:"payload"in t?t.payload:void 0}}catch{}}async function ve(e,t={}){const n=t.baseUrl??(typeof e=="string"?new URL(e).origin:void 0),o=typeof e=="string"?new L(e,{signal:t.signal}):e,r=new V(o,{...t,baseUrl:n});return typeof e=="string"&&await me(o,r,t),r}function me(e,t,n){const o=N(n)?.onLegacyMessage;return new Promise((r,s)=>{e.onopen=()=>{r()},e.onclose=()=>{t.close(),n.signal?.aborted?s(n.signal.reason):s(new Error("The websocket was closed before the device connection was established"))},e.onerror=s,e.onmessage=i=>{const c=I(i);c&&o?.(c)}})}async function ye(e,{onStateChange:t,signal:n}){n?.throwIfAborted(),t?.({phase:"starting"}),await new Promise((o,r)=>{const s=()=>{i(),r(n?.reason)},i=()=>{e.onmessage=void 0,e.onclose=void 0,n?.removeEventListener("abort",s)};e.onmessage=c=>{const a=be(I(c));a&&(t?.(a),a.phase==="ready"&&(i(),o()))},e.onclose=()=>{i(),r(new Error("The device closed before it was ready"))},n?.addEventListener("abort",s,{once:!0})})}function be(e){if(!e)return;if(e.name==="ready")return{phase:"ready"};if(e.name!=="launchStatus")return;switch(b(e.payload)&&typeof e.payload.status=="string"?e.payload.status:void 0){case"downloadingApp":return{phase:"downloadingApp"};case"installingApp":return{phase:"installingApp"};case"launchingApp":return{phase:"launchingApp"};default:return}}function Se(){return typeof process>"u"?void 0:process}function Ee(e){return e==="intercept"?"interceptOnDemand":e}function Te(e,{onClose:t,onEvent:n,signal:o}={}){return new Promise((r,s)=>{const i=new WebSocket(e);i.binaryType="arraybuffer",i.onopen=()=>{W(i,{capabilities:{},t:"handshake"})},i.onmessage=c=>{Le(i,c,{onEvent:n,onHandshake:a=>{r({close:()=>{i.close()},id:a})}})},i.onclose=()=>{s(new v("disconnected",`The connection to ${e} closed`)),t?.()},o?.addEventListener("abort",()=>{s(o.reason),i.close()},{once:!0})})}function Le(e,t,n){const o=E(new Uint8Array(t.data));b(o)&&(o.t==="handshake"&&typeof o.id=="string"?n.onHandshake(o.id):o.name==="ping"?W(e,{name:"pong"}):typeof o.name=="string"&&n.onEvent?.(o.name,o.payload))}function W(e,t){e.send(A(t))}async function ke(e,t,{apiToken:n,onQueue:o,signal:r}={}){const s=j();Pe(s.reject,r);const i=await Te(Ie(e),{onClose:()=>{s.reject(Ae())},onEvent:(c,a)=>{$e(c,a,s,o)},signal:r});return Re(e,{apiToken:n,data:t,socketid:i.id},r).catch(s.reject),await s.promise.finally(()=>{i.close()})}function Ae(){return new v("disconnected","The webserver connection closed before a session was granted")}function U(e,t){return b(e)?e[t]:void 0}function $e(e,t,n,o){if(e==="queue"||e==="concurrentQueue"){const r=e==="queue"?Ue(t):Ce(t);r&&o?.(r)}else e==="newSession"?We(n,t):e==="userError"&&n.reject(new v("denied",De(t)))}function C(e,t){const n=U(e,t);return typeof n=="number"?n:void 0}function m(e,t){const n=U(e,t);return typeof n=="string"?n:void 0}async function Re(e,t,n){const o=await fetch(new URL("/api/session/request",e),{body:JSON.stringify(t),headers:{"content-type":"application/json"},method:"POST",signal:n});if(!o.ok)throw new v("denied",await Me(o))}function Pe(e,t){t?.addEventListener("abort",()=>{e(t.reason)},{once:!0})}function Ie(e){const t=new URL("/client",e);return t.protocol=t.protocol==="http:"?"ws:":"wss:",t.href}function We(e,t){const n=m(t,"path"),o=m(t,"sessionToken");n!==void 0&&o!==void 0?e.resolve({path:n,sessionToken:o}):e.reject(new v("denied","The granted session is missing its address"))}function Ue(e){const t=C(e,"position");return t===void 0?void 0:{position:t,reason:"capacity"}}function Ce(e){const t=C(e,"position");if(t!==void 0)return{limit:m(e,"name")??"Queue",position:t,reason:"concurrency"}}function De(e){return m(e,"message")??"The session request was denied"}async function Me(e){const t=`The webserver rejected the session request (${String(e.status)})`,n=await e.json().catch(()=>{}),o=m(n,"message");return o?`${t}: ${o}`:t}async function qe({apiToken:e=Oe(),codec:t="h264",device:n,endpoint:o="https://appetize.io",launch:r,onStateChange:s,proxy:i,signal:c,target:a}){c?.throwIfAborted(),H({apiToken:e,codec:t,device:n,endpoint:o,launch:r,proxy:i,target:a}),s?.({phase:"requesting"});const d=await ke(o,{codec:t,noVideo:!0,proxy:Ee(i),publicKey:a,...J(n),...Q(r)},{apiToken:e,onQueue:h=>{s?.({phase:"queued",queue:h})},signal:c});return{baseUrl:new URL(d.path).origin,url:xe(d)}}function Oe(){return Se()?.env.APPETIZE_API_TOKEN}function xe(e){const t=new URL("/client",e.path);return t.protocol=t.protocol==="http:"?"ws:":"wss:",t.searchParams.set("sessionToken",e.sessionToken),t.href}async function _e(e,{host:t="127.0.0.1",onError:n,port:o=0,signal:r}={}){r?.throwIfAborted();let s;const i=()=>{const u=s;s=void 0,u&&(u.tunnel?.close(),u.socket.destroy())},c=async u=>{const{socket:l}=u;try{const p=await e.debug.createAdbTunnel();if(l.destroyed){p.close();return}u.tunnel=p,p.closed.catch(S=>{n?.(S)}),Fe(l,p)}catch(p){l.destroyed||n?.(p),l.destroy()}},a=R(u=>{i();const l={socket:u};s=l,u.once("close",()=>{s===l&&(s=void 0)}),c(l)}),d=()=>{r?.removeEventListener("abort",d),i(),a.close()};r?.addEventListener("abort",d,{once:!0});const h=await ze(a,t,o);return{close:d,url:new URL(`adb://${h.address}:${String(h.port)}`)}}function Fe(e,t){P(t.readable,e,D),P(e,async n=>{const o=t.writable.getWriter();try{for await(const r of n)await o.write(r);await o.close()}catch(r){throw await o.abort(r),r}},D)}function D(){}function ze(e,t,n){return new Promise((o,r)=>{e.once("error",r),e.listen({host:t,port:n},()=>{e.off("error",r);const s=e.address();if(s===null||typeof s=="string"){r(new Error("The listener has no tcp address"));return}o(s)})})}async function Ve(e,{methods:t={},path:n,signal:o}){o?.throwIfAborted(),await te(n,{force:!0});const r=new Set,s=R(c=>{r.add(c),c.once("close",()=>{r.delete(c)}),$(new G(c),e,{leftEffects:()=>t})}),i=()=>{o?.removeEventListener("abort",i);for(const c of r)c.destroy();s.close()};return await Ne(s,n),o?.aborted&&(i(),o.throwIfAborted()),o?.addEventListener("abort",i,{once:!0}),{close:i,path:n}}function Ne(e,t){return new Promise((n,o)=>{e.once("error",o),e.listen(t,()=>{e.off("error",o),n()})})}const je=T("appetize:daemon");function f(e){je(e)}function He(e,{message:t="The operation timed out"}={}){const n=new AbortController,o=setTimeout(()=>{n.abort(new Error(t))},e),r=()=>{clearTimeout(o)};return{cancel:r,signal:n.signal,[Symbol.dispose]:r}}var Qe=(e,t)=>(t=Symbol[e])?t:Symbol.for("Symbol."+e),M=e=>{throw TypeError(e)},Je=(e,t,n)=>{if(t!=null){typeof t!="object"&&typeof t!="function"&&M("Object expected");var o,r;o===void 0&&(o=t[Qe("dispose")]),typeof o!="function"&&M("Object not disposable"),r&&(o=function(){try{r.call(this)}catch(s){return Promise.reject(s)}}),e.push([n,o,t])}return t},Ge=(e,t,n)=>{var o=typeof SuppressedError=="function"?SuppressedError:function(i,c,a,d){return d=Error(a),d.name="SuppressedError",d.error=i,d.suppressed=c,d},r=i=>t=n?new o(i,t,"An error was suppressed during disposal"):(n=!0,i),s=i=>{for(;i=e.pop();)try{var c=i[1]&&i[1].call(i[2]);if(i[0])return Promise.resolve(c).then(s,a=>(r(a),s()))}catch(a){r(a)}if(n)throw t};return s()};const Ke=1e4;async function Ze(e,t,{onClose:n,signal:o}={}){var r=[];try{const c=Je(r,He(Ke,{message:"Timed out waiting for session request state"})),a=AbortSignal.any([o,c.signal].filter(g=>!!g)),d=g=>{t.save({state:g}),f(g.phase),g.phase!=="requesting"&&c.cancel()},{featureFlags:h,sessionId:u,...l}=e,{baseUrl:p,url:S}=await qe({...l,onStateChange:d,signal:a});t.save({baseUrl:p});const y=new L(S,{signal:a});return await ye(y,{onStateChange:d,signal:a}),y.onclose=()=>{n?.("The device connection closed")},{device:await ve(y,{baseUrl:p,signal:a}),transport:y}}catch(c){var s=c,i=!0}finally{Ge(r,s,i)}}function Xe(){const e=K(),t=Z(e.sessionId,e.proxy),n=X({device:e.device,endpoint:e.endpoint,open:e.launch?.url,pid:process.pid,proxy:e.proxy,sessionId:e.sessionId,startedAt:new Date().toISOString(),target:e.target});return n.save({logs:t}),{config:e,logs:t,store:n}}async function Ye(e,t,n,{signal:o}={}){try{if(!await Be(t))return;const r=await _e(e,{onError:s=>{f(`adb endpoint error: ${q(s)}`)},signal:o});n.save({adbSerial:r.url.host}),f(`adb endpoint listening at ${r.url.host}`)}catch(r){f(`adb endpoint unavailable: ${q(r)}`)}}async function Be(e){return await Y(e.device.id,{endpoint:e.endpoint})==="android"}function q(e){return e instanceof Error?e.message:String(e)}async function et(e,t,n,{recorder:o,signal:r}){const{path:s}=await Ve(e,{methods:{"appetizeio.cli.record.start":async i=>await o.start(i),"appetizeio.cli.record.stop":async()=>await o.stop()},path:B(n),signal:r});return t.save({controlSocket:s}),s}const O="127.0.0.1";async function tt(e,t,n={}){try{const o=await nt(e,n);return t.save({viewerUrl:o.url.href}),f(`web endpoint listening at ${o.url.href}`),o}catch(o){f(`web endpoint unavailable: ${at(o)}`);return}}async function nt(e,{port:t=0,signal:n,viewerHtml:o=ne(new URL("./viewer.html",import.meta.url),"utf8")}){n?.throwIfAborted();const r=ie((u,l)=>{rt(u,l,o)}),s=new Set,i=new ae({noServer:!0,perMessageDeflate:!1});let c;i.on("connection",u=>{if(s.size>0){u.close(1013,"Viewer already connected");return}s.add(u);const l=new L(u);$(l,e),u.once("close",()=>{s.delete(u)})}),r.on("upgrade",(u,l,p)=>{st(i,u,l,p)});const a=()=>(c??=new Promise((u,l)=>{n?.removeEventListener("abort",d);for(const p of s)ot(p);i.close(),r.close(p=>{p?l(p):u()})}),c),d=()=>{a()};await it(r,t),n?.addEventListener("abort",d,{once:!0});const h=r.address();if(!h||typeof h=="string")throw await a(),new Error("Web address unavailable");return{close:a,url:new URL(`http://${O}:${String(h.port)}/`)}}function ot(e){e.close(1001)}function rt(e,t,n){if(e.method==="GET"&&e.url==="/"){t.writeHead(200,{"Cache-Control":"no-store","Content-Type":"text/html; charset=utf-8"}),t.end(n);return}t.writeHead(404).end()}function st(e,t,n,o){if(t.url!=="/ws"){n.destroy();return}e.handleUpgrade(t,n,o,r=>{e.emit("connection",r,t)})}function it(e,t){return new Promise((n,o)=>{const r=s=>{o(s)};e.once("error",r),e.listen(t,O,()=>{e.removeListener("error",r),n()})})}function at(e){return e instanceof Error?e.message:String(e)}function ct(e){const t=new AbortController,n=dt(e,t),o=ee();return o.addEventListener("abort",()=>{const{reason:r}=o;n(r instanceof Error?r.message:String(r))},{once:!0}),{shutdown:n,signal:t.signal}}function dt(e,t){let n=!1;return o=>{n||(n=!0,e.save({endedAt:new Date().toISOString(),endedReason:o,state:{phase:"ended"}}),f(o),t.abort())}}async function x(e,t,{label:n,signal:o}){try{const r=await e();await ce(r.readable.pipeThrough(ut()),oe(t,{flags:"a"}))}catch(r){if(o?.aborted)return;const s=r instanceof Error?r.message:String(r);f(`${n} ended with an error: ${s}`)}}function ut(){return new TransformStream({transform:(e,t)=>{t.enqueue(`${JSON.stringify(e)}
2
- `)}})}async function lt(e,t,{signal:n}={}){await x(async()=>await e.debug.createLogStream({signal:n}),t,{label:"log capture",signal:n})}async function ft(e,t,{signal:n}={}){await x(async()=>await e.debug.createProxyInterceptStream({signal:n}),t,{label:"network capture",signal:n})}const k=30;async function pt(e,t){await e.pipeTo(wt(t))}function ht(e){return{decoderConfig:{codec:"avc1.640028",codedHeight:e.height,codedWidth:e.width}}}function wt(e){let t;const n=async()=>{await t?.output.finalize()};return new WritableStream({abort:n,close:n,write:async o=>{o.data.byteLength!==0&&(t??=await gt(mt(o),e),vt(t,o),await yt(t,o))}})}async function gt(e,t){const n=new de("avc"),o=new ue({format:new fe({fastStart:"fragmented"}),target:new le(t,{chunked:!1})});return o.addVideoTrack(n,{frameRate:k}),await o.start(),{frame:0,output:o,seen:{height:e.height,width:e.width},size:{height:e.height,width:e.width},source:n}}function vt(e,t){if(t.type!=="key")return;const{seen:n,size:o}=e;t.width===n.width&&t.height===n.height||(e.seen={height:t.height,width:t.width},f(`video resized to ${String(t.width)}x${String(t.height)}; keeping ${String(o.width)}x${String(o.height)}`))}function mt(e){if(e.type!=="key")throw new Error("Video stream started without a key chunk");return e}async function yt(e,t){const n=new pe(t.data,t.type,e.frame/k,1/k);e.frame+=1,await e.source.add(n,ht(e.size))}function bt(e,t,{signal:n}={}){let o,r;const s=async(a,{force:d=!1}={})=>{if(re(a)){if(!d)throw new Error(`A recording already exists at ${a}; pass --force to overwrite`);se(a)}const h=await e.video.createStream({signal:n});return o={done:St(h,a),path:a,stream:h},t.save({video:{path:a,recording:!0}}),f(`recording video to ${a}`),{path:a}},i=async a=>{a.stream.close();try{await a.done,t.save({video:{path:a.path,recording:!1}})}finally{o=void 0,r=void 0}},c=async()=>{if(!o)return;const{path:a}=o;await i(o),f(`closed the video recording: ${a}`)};return n?.addEventListener("abort",()=>{c()},{once:!0}),{start:async({force:a=!1,path:d})=>{const h=o?.path??r;if(h!==void 0)throw new Error(`Already recording to ${h}`);r=d;try{return await s(d,{force:a})}finally{r=void 0}},stop:async()=>{if(!o)throw new Error("No video recording in progress");const{path:a}=o;return await i(o),{path:a}}}}async function St(e,t){try{await pt(e.readable,t)}catch(n){f(`video capture ended with an error: ${String(n)}`)}}async function Et(){const{config:e,logs:t,store:n}=Xe();f(`recording to ${n.path}`);const{shutdown:o,signal:r}=ct(n);try{const{device:s,transport:i}=await Ze(e,n,{onClose:o,signal:r}),c=bt(s,n,{signal:r});await Ye(s,e,n,{signal:r}),await tt(i,n,{signal:r});const a=await et(i,n,e.sessionId,{recorder:c,signal:r});f(`control socket listening at ${a}`),lt(s,t.device,{signal:r}),f(`recording device logs to ${t.device}`),t.network&&(ft(s,t.network,{signal:r}),f(`recording network events to ${t.network}`))}catch(s){if(r.aborted)return;const i=s instanceof Error?s.message:String(s);n.save({endedAt:new Date().toISOString(),endedReason:i,state:{message:i,phase:"error"}}),f(`error: ${i}`),process.exitCode=1}}Et();
1
+ import{T as _,P as A,Q as F,R as T,V as z,J as V,W as j,y as v,X as N,x as H,Y as Q,Z as J,_ as $,$ as G,a0 as K,F as Z,a1 as X,a2 as Y,a3 as B,a4 as ee}from"./stream-C4JjU85l.js";import b from"debug";import{createServer as R}from"node:net";import{pipeline as P}from"node:stream";import{rm as te}from"node:fs/promises";import{readFileSync as ne,createWriteStream as oe,existsSync as re,rmSync as se}from"node:fs";import{createServer as ie}from"node:http";import{WebSocketServer as ae}from"ws";import{pipeline as ce}from"node:stream/promises";import{EncodedVideoPacketSource as de,Output as ue,Mp4OutputFormat as le,EncodedPacket as fe,FilePathTarget as pe}from"mediabunny";import"json-rpc-2.0";import"zod/mini";import"node:path";import"node:os";import"stream";import"module";const he=b("appetize.io:transport:ws-ping"),we=3e4;function ge(e){let t=!0;const n=()=>{t=!0};e.on("pong",n);const o=setInterval(()=>{if(!t){clearInterval(o),he("liveness ping went unanswered, terminating"),e.terminate();return}e.readyState===e.OPEN&&(t=!1,e.ping())},we);return{destroy(){clearInterval(o),e.off("pong",n)},pong:n}}const w=b("appetize.io:trace:transport:websocket");class L extends _{constructor(t,{signal:n}={}){super(async r=>{this.#e.send(A(r))},{signal:n}),this.wsOrUrl=t,typeof t=="string"?(this.#e=new WebSocket(t),this.#e.binaryType="arraybuffer"):this.#e=t;const o=this.#e;if(o instanceof WebSocket?(o.addEventListener("open",this.#s),o.addEventListener("message",this.#r),o.addEventListener("error",this.#o),o.addEventListener("close",this.#n),this.#t.push(()=>{o.removeEventListener("open",this.#s),o.removeEventListener("message",this.#r),o.removeEventListener("error",this.#o),o.removeEventListener("close",this.#n)})):(o.addEventListener("open",this.#s),o.addEventListener("message",this.#r),o.addEventListener("error",this.#o),o.addEventListener("close",this.#n),this.#t.push(()=>{o.removeEventListener("open",this.#s),o.removeEventListener("message",this.#r),o.removeEventListener("error",this.#o),o.removeEventListener("close",this.#n)})),this.send=o.send.bind(o),"ping"in o){const{destroy:r,pong:s}=ge(o);this.#c=s,this.#t.push(r)}}wsOrUrl;onclose;onerror;onmessage;onopen;send;get bufferedAmount(){return this.#e.bufferedAmount}get readyState(){return this.#e.readyState}#t=[];#i=!1;#a=!1;#c;#e;close({destroyWs:t=!1,...n}={}){this.closed||(this.#i=t,super.close(n))}handleClose(t){w("close()");for(const n of this.#t.splice(0))n();if((typeof this.wsOrUrl=="string"||this.#i)&&(this.#e.close(t.code,t.reason),"terminate"in this.#e)){const n=this.#e;setTimeout(()=>{n.terminate()},100)}this.#d(),super.handleClose(t)}#d(t){this.#a||(this.#a=!0,this.onclose?.(t))}#n=t=>{w("handleWebSocketClose()",t);try{this.#d(t)}finally{this.close()}};#o=t=>{w("handleWebSocketError()",t),this.onerror?.(t)};#r=async t=>{w("handleWebSocketMessage()",t),this.#c?.();const n=this.#u(t);if(!n){w("handleWebSocketMessage() -> legacy"),this.onmessage?.(t);return}w("handleWebSocketMessage() -> jsonrpc",n),this[F].dispatchMessage(n)};#s=t=>{w("handleWebSocketOpen()",t),this.onopen?.(t)};#u(t){try{const n=T(new Uint8Array(t.data));return z(n)?n:null}catch{return null}}}function S(e){return typeof e=="object"&&e!==null}function I(e){try{const t=T(new Uint8Array(e.data));if(S(t)&&typeof t.name=="string")return{name:t.name,payload:"payload"in t?t.payload:void 0}}catch{}}async function ve(e,t={}){const n=t.baseUrl??(typeof e=="string"?new URL(e).origin:void 0),o=typeof e=="string"?new L(e,{signal:t.signal}):e,r=new V(o,{...t,baseUrl:n});return typeof e=="string"&&await ye(o,r,t),r}function ye(e,t,n){const o=j(n)?.onLegacyMessage;return new Promise((r,s)=>{e.onopen=()=>{r()},e.onclose=()=>{t.close(),n.signal?.aborted?s(n.signal.reason):s(new Error("The websocket was closed before the device connection was established"))},e.onerror=s,e.onmessage=i=>{const c=I(i);c&&o?.(c)}})}const me=b("appetize:client:render-video-to-mp4"),k=30;async function be(e,t){await e.pipeTo(Ee(t))}function Se(e){return{decoderConfig:{codec:"avc1.640028",codedHeight:e.height,codedWidth:e.width}}}function Ee(e){let t;const n=async()=>{await t?.output.finalize()};return new WritableStream({abort:n,close:n,write:async o=>{if(o.data.byteLength!==0)try{t??=await Te(ke(o),e()),Le(t,o),await Ae(t,o)}catch(r){throw await t?.output.cancel(),r}}})}async function Te(e,t){const n=new de("avc"),o=new ue({format:new le({fastStart:"fragmented"}),target:t});return o.addVideoTrack(n,{frameRate:k}),await o.start(),{frame:0,output:o,seen:{height:e.height,width:e.width},size:{height:e.height,width:e.width},source:n}}function Le(e,t){if(t.type!=="key")return;const{seen:n,size:o}=e;t.width===n.width&&t.height===n.height||(e.seen={height:t.height,width:t.width},me(`video resized to ${String(t.width)}x${String(t.height)}; keeping ${String(o.width)}x${String(o.height)}`))}function ke(e){if(e.type!=="key")throw new Error("Video stream started without a key chunk");return e}async function Ae(e,t){const n=new fe(t.data,t.type,e.frame/k,1/k);e.frame+=1,await e.source.add(n,Se(e.size))}async function $e(e,{onStateChange:t,signal:n}){n?.throwIfAborted(),t?.({phase:"starting"}),await new Promise((o,r)=>{const s=()=>{i(),r(n?.reason)},i=()=>{e.onmessage=void 0,e.onclose=void 0,n?.removeEventListener("abort",s)};e.onmessage=c=>{const a=Re(I(c));a&&(t?.(a),a.phase==="ready"&&(i(),o()))},e.onclose=()=>{i(),r(new Error("The device closed before it was ready"))},n?.addEventListener("abort",s,{once:!0})})}function Re(e){if(!e)return;if(e.name==="ready")return{phase:"ready"};if(e.name!=="launchStatus")return;switch(S(e.payload)&&typeof e.payload.status=="string"?e.payload.status:void 0){case"downloadingApp":return{phase:"downloadingApp"};case"installingApp":return{phase:"installingApp"};case"launchingApp":return{phase:"launchingApp"};default:return}}function Pe(){return typeof process>"u"?void 0:process}function Ie(e){return e==="intercept"?"interceptOnDemand":e}function We(e,{onClose:t,onEvent:n,signal:o}={}){return new Promise((r,s)=>{const i=new WebSocket(e);i.binaryType="arraybuffer",i.onopen=()=>{W(i,{capabilities:{},t:"handshake"})},i.onmessage=c=>{Ue(i,c,{onEvent:n,onHandshake:a=>{r({close:()=>{i.close()},id:a})}})},i.onclose=()=>{s(new v("disconnected",`The connection to ${e} closed`)),t?.()},o?.addEventListener("abort",()=>{s(o.reason),i.close()},{once:!0})})}function Ue(e,t,n){const o=T(new Uint8Array(t.data));S(o)&&(o.t==="handshake"&&typeof o.id=="string"?n.onHandshake(o.id):o.name==="ping"?W(e,{name:"pong"}):typeof o.name=="string"&&n.onEvent?.(o.name,o.payload))}function W(e,t){e.send(A(t))}async function Ce(e,t,{apiToken:n,onQueue:o,signal:r}={}){const s=N();s.promise.catch(()=>{}),Oe(s.reject,r);const i=await We(xe(e),{onClose:()=>{s.reject(De())},onEvent:(c,a)=>{Me(c,a,s,o)},signal:r});return qe(e,{apiToken:n,data:t,socketid:i.id},r).catch(s.reject),await s.promise.finally(()=>{i.close()})}function De(){return new v("disconnected","The webserver connection closed before a session was granted")}function U(e,t){return S(e)?e[t]:void 0}function Me(e,t,n,o){if(e==="queue"||e==="concurrentQueue"){const r=e==="queue"?Fe(t):ze(t);r&&o?.(r)}else e==="newSession"?_e(n,t):e==="userError"&&n.reject(new v("denied",Ve(t)))}function C(e,t){const n=U(e,t);return typeof n=="number"?n:void 0}function y(e,t){const n=U(e,t);return typeof n=="string"?n:void 0}async function qe(e,t,n){const o=await fetch(new URL("/api/session/request",e),{body:JSON.stringify(t),headers:{"content-type":"application/json"},method:"POST",signal:n});if(!o.ok)throw new v("denied",await je(o))}function Oe(e,t){t?.addEventListener("abort",()=>{e(t.reason)},{once:!0})}function xe(e){const t=new URL("/client",e);return t.protocol=t.protocol==="http:"?"ws:":"wss:",t.href}function _e(e,t){const n=y(t,"path"),o=y(t,"sessionToken");n!==void 0&&o!==void 0?e.resolve({path:n,sessionToken:o}):e.reject(new v("denied","The granted session is missing its address"))}function Fe(e){const t=C(e,"position");return t===void 0?void 0:{position:t,reason:"capacity"}}function ze(e){const t=C(e,"position");if(t!==void 0)return{limit:y(e,"name")??"Queue",position:t,reason:"concurrency"}}function Ve(e){return y(e,"message")??"The session request was denied"}async function je(e){const t=`The webserver rejected the session request (${String(e.status)})`,n=await e.json().catch(()=>{}),o=y(n,"message");return o?`${t}: ${o}`:t}async function Ne({apiToken:e=He(),codec:t="h264",device:n,endpoint:o="https://appetize.io",launch:r,onStateChange:s,proxy:i,signal:c,target:a}){c?.throwIfAborted(),H({apiToken:e,codec:t,device:n,endpoint:o,launch:r,proxy:i,target:a}),s?.({phase:"requesting"});const d=await Ce(o,{codec:t,noVideo:!0,proxy:Ie(i),publicKey:a,...J(n),...Q(r)},{apiToken:e,onQueue:h=>{s?.({phase:"queued",queue:h})},signal:c});return{baseUrl:new URL(d.path).origin,sessionToken:d.sessionToken,url:Qe(d)}}function He(){return Pe()?.env.APPETIZE_API_TOKEN}function Qe(e){const t=new URL("/client",e.path);return t.protocol=t.protocol==="http:"?"ws:":"wss:",t.searchParams.set("sessionToken",e.sessionToken),t.href}async function Je(e,t){await be(e,()=>new pe(t,{chunked:!1}))}async function Ge(e,{host:t="127.0.0.1",onError:n,port:o=0,signal:r}={}){r?.throwIfAborted();let s;const i=()=>{const u=s;s=void 0,u&&(u.tunnel?.close(),u.socket.destroy())},c=async u=>{const{socket:l}=u;try{const f=await e.debug.createAdbTunnel();if(l.destroyed){f.close();return}u.tunnel=f,f.closed.catch(E=>{n?.(E)}),Ke(l,f)}catch(f){l.destroyed||n?.(f),l.destroy()}},a=R(u=>{i();const l={socket:u};s=l,u.once("close",()=>{s===l&&(s=void 0)}),c(l)}),d=()=>{r?.removeEventListener("abort",d),i(),a.close()};r?.addEventListener("abort",d,{once:!0});const h=await Ze(a,t,o);return{close:d,url:new URL(`adb://${h.address}:${String(h.port)}`)}}function Ke(e,t){P(t.readable,e,D),P(e,async n=>{const o=t.writable.getWriter();try{for await(const r of n)await o.write(r);await o.close()}catch(r){throw await o.abort(r),r}},D)}function D(){}function Ze(e,t,n){return new Promise((o,r)=>{e.once("error",r),e.listen({host:t,port:n},()=>{e.off("error",r);const s=e.address();if(s===null||typeof s=="string"){r(new Error("The listener has no tcp address"));return}o(s)})})}async function Xe(e,{methods:t={},path:n,signal:o}){o?.throwIfAborted(),await te(n,{force:!0});const r=new Set,s=R(c=>{r.add(c),c.once("close",()=>{r.delete(c)}),$(new G(c),e,{leftEffects:()=>t})}),i=()=>{o?.removeEventListener("abort",i);for(const c of r)c.destroy();s.close()};return await Ye(s,n),o?.aborted&&(i(),o.throwIfAborted()),o?.addEventListener("abort",i,{once:!0}),{close:i,path:n}}function Ye(e,t){return new Promise((n,o)=>{e.once("error",o),e.listen(t,()=>{e.off("error",o),n()})})}const Be=b("appetize:daemon");function p(e){Be(e)}function et(e,{message:t="The operation timed out"}={}){const n=new AbortController,o=setTimeout(()=>{n.abort(new Error(t))},e),r=()=>{clearTimeout(o)};return{cancel:r,signal:n.signal,[Symbol.dispose]:r}}var tt=(e,t)=>(t=Symbol[e])?t:Symbol.for("Symbol."+e),M=e=>{throw TypeError(e)},nt=(e,t,n)=>{if(t!=null){typeof t!="object"&&typeof t!="function"&&M("Object expected");var o,r;o===void 0&&(o=t[tt("dispose")]),typeof o!="function"&&M("Object not disposable"),r&&(o=function(){try{r.call(this)}catch(s){return Promise.reject(s)}}),e.push([n,o,t])}return t},ot=(e,t,n)=>{var o=typeof SuppressedError=="function"?SuppressedError:function(i,c,a,d){return d=Error(a),d.name="SuppressedError",d.error=i,d.suppressed=c,d},r=i=>t=n?new o(i,t,"An error was suppressed during disposal"):(n=!0,i),s=i=>{for(;i=e.pop();)try{var c=i[1]&&i[1].call(i[2]);if(i[0])return Promise.resolve(c).then(s,a=>(r(a),s()))}catch(a){r(a)}if(n)throw t};return s()};const rt=1e4;async function st(e,t,{onClose:n,signal:o}={}){var r=[];try{const c=nt(r,et(rt,{message:"Timed out waiting for session request state"})),a=AbortSignal.any([o,c.signal].filter(g=>!!g)),d=g=>{t.save({state:g}),p(g.phase),g.phase!=="requesting"&&c.cancel()},{featureFlags:h,sessionId:u,...l}=e,{baseUrl:f,url:E}=await Ne({...l,onStateChange:d,signal:a});t.save({baseUrl:f});const m=new L(E,{signal:a});return await $e(m,{onStateChange:d,signal:a}),m.onclose=()=>{n?.("The device connection closed")},{device:await ve(m,{baseUrl:f,signal:a}),transport:m}}catch(c){var s=c,i=!0}finally{ot(r,s,i)}}function it(){const e=K(),t=Z(e.sessionId,e.proxy),n=X({device:e.device,endpoint:e.endpoint,open:e.launch?.url,pid:process.pid,proxy:e.proxy,sessionId:e.sessionId,startedAt:new Date().toISOString(),target:e.target});return n.save({logs:t}),{config:e,logs:t,store:n}}async function at(e,t,n,{signal:o}={}){try{if(!await ct(t))return;const r=await Ge(e,{onError:s=>{p(`adb endpoint error: ${q(s)}`)},signal:o});n.save({adbSerial:r.url.host}),p(`adb endpoint listening at ${r.url.host}`)}catch(r){p(`adb endpoint unavailable: ${q(r)}`)}}async function ct(e){return await Y(e.device.id,{endpoint:e.endpoint})==="android"}function q(e){return e instanceof Error?e.message:String(e)}async function dt(e,t,n,{recorder:o,signal:r}){const{path:s}=await Xe(e,{methods:{"appetizeio.cli.record.start":async i=>await o.start(i),"appetizeio.cli.record.stop":async()=>await o.stop()},path:B(n),signal:r});return t.save({controlSocket:s}),s}const O="127.0.0.1";async function ut(e,t,n={}){try{const o=await lt(e,n);return t.save({viewerUrl:o.url.href}),p(`web endpoint listening at ${o.url.href}`),o}catch(o){p(`web endpoint unavailable: ${gt(o)}`);return}}async function lt(e,{port:t=0,signal:n,viewerHtml:o=ne(new URL("./viewer.html",import.meta.url),"utf8")}){n?.throwIfAborted();const r=ie((u,l)=>{pt(u,l,o)}),s=new Set,i=new ae({noServer:!0,perMessageDeflate:!1});let c;i.on("connection",u=>{if(s.size>0){u.close(1013,"Viewer already connected");return}s.add(u);const l=new L(u);$(l,e),u.once("close",()=>{s.delete(u)})}),r.on("upgrade",(u,l,f)=>{ht(i,u,l,f)});const a=()=>(c??=new Promise((u,l)=>{n?.removeEventListener("abort",d);for(const f of s)ft(f);i.close(),r.close(f=>{f?l(f):u()})}),c),d=()=>{a()};await wt(r,t),n?.addEventListener("abort",d,{once:!0});const h=r.address();if(!h||typeof h=="string")throw await a(),new Error("Web address unavailable");return{close:a,url:new URL(`http://${O}:${String(h.port)}/`)}}function ft(e){e.close(1001)}function pt(e,t,n){if(e.method==="GET"&&e.url==="/"){t.writeHead(200,{"Cache-Control":"no-store","Content-Type":"text/html; charset=utf-8"}),t.end(n);return}t.writeHead(404).end()}function ht(e,t,n,o){if(t.url!=="/ws"){n.destroy();return}e.handleUpgrade(t,n,o,r=>{e.emit("connection",r,t)})}function wt(e,t){return new Promise((n,o)=>{const r=s=>{o(s)};e.once("error",r),e.listen(t,O,()=>{e.removeListener("error",r),n()})})}function gt(e){return e instanceof Error?e.message:String(e)}function vt(e){const t=new AbortController,n=yt(e,t),o=ee();return o.addEventListener("abort",()=>{const{reason:r}=o;n(r instanceof Error?r.message:String(r))},{once:!0}),{shutdown:n,signal:t.signal}}function yt(e,t){let n=!1;return o=>{n||(n=!0,e.save({endedAt:new Date().toISOString(),endedReason:o,state:{phase:"ended"}}),p(o),t.abort())}}async function x(e,t,{label:n,signal:o}){try{const r=await e();await ce(r.readable.pipeThrough(mt()),oe(t,{flags:"a"}))}catch(r){if(o?.aborted)return;const s=r instanceof Error?r.message:String(r);p(`${n} ended with an error: ${s}`)}}function mt(){return new TransformStream({transform:(e,t)=>{t.enqueue(`${JSON.stringify(e)}
2
+ `)}})}async function bt(e,t,{signal:n}={}){await x(async()=>await e.debug.createLogStream({signal:n}),t,{label:"log capture",signal:n})}async function St(e,t,{signal:n}={}){await x(async()=>await e.debug.createProxyInterceptStream({signal:n}),t,{label:"network capture",signal:n})}function Et(e,t,{signal:n}={}){let o,r;const s=async(a,{force:d=!1}={})=>{if(re(a)){if(!d)throw new Error(`A recording already exists at ${a}; pass --force to overwrite`);se(a)}const h=await e.video.createStream({signal:n});return o={done:Tt(h,a),path:a,stream:h},t.save({video:{path:a,recording:!0}}),p(`recording video to ${a}`),{path:a}},i=async a=>{a.stream.close();try{await a.done,t.save({video:{path:a.path,recording:!1}})}finally{o=void 0,r=void 0}},c=async()=>{if(!o)return;const{path:a}=o;await i(o),p(`closed the video recording: ${a}`)};return n?.addEventListener("abort",()=>{c()},{once:!0}),{start:async({force:a=!1,path:d})=>{const h=o?.path??r;if(h!==void 0)throw new Error(`Already recording to ${h}`);r=d;try{return await s(d,{force:a})}finally{r=void 0}},stop:async()=>{if(!o)throw new Error("No video recording in progress");const{path:a}=o;return await i(o),{path:a}}}}async function Tt(e,t){try{await Je(e.readable,t)}catch(n){p(`video capture ended with an error: ${String(n)}`)}}async function Lt(){const{config:e,logs:t,store:n}=it();p(`recording to ${n.path}`);const{shutdown:o,signal:r}=vt(n);try{const{device:s,transport:i}=await st(e,n,{onClose:o,signal:r}),c=Et(s,n,{signal:r});await at(s,e,n,{signal:r}),await ut(i,n,{signal:r});const a=await dt(i,n,e.sessionId,{recorder:c,signal:r});p(`control socket listening at ${a}`),bt(s,t.device,{signal:r}),p(`recording device logs to ${t.device}`),t.network&&(St(s,t.network,{signal:r}),p(`recording network events to ${t.network}`))}catch(s){if(r.aborted)return;const i=s instanceof Error?s.message:String(s);n.save({endedAt:new Date().toISOString(),endedReason:i,state:{message:i,phase:"error"}}),p(`error: ${i}`),process.exitCode=1}}Lt();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@appetize/cli",
3
- "version": "0.24.0",
3
+ "version": "0.25.1",
4
4
  "description": "Run, inspect and control iOS and Android apps on Appetize cloud devices",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "homepage": "https://appetize.io",
@@ -32,10 +32,10 @@
32
32
  "debug": "^4.4.3",
33
33
  "human-id": "^4.2.2",
34
34
  "json-rpc-2.0": "^1.8.1",
35
- "mediabunny": "^1.61.3",
35
+ "mediabunny": "^1.61.4",
36
36
  "sade": "^1.8.1",
37
37
  "ws": "^8.22.0",
38
38
  "yocto-spinner": "^1.2.2",
39
- "zod": "^4.6.5"
39
+ "zod": "^4.6.7"
40
40
  }
41
41
  }
@@ -10,7 +10,7 @@ description: >-
10
10
  or answering what is currently on screen — even if Appetize is not mentioned
11
11
  by name.
12
12
  metadata:
13
- cli-version: '0.24.0'
13
+ cli-version: '0.25.1'
14
14
  ---
15
15
 
16
16
  # Appetize
@@ -200,7 +200,7 @@ appetize open myapp://orders/42 --json
200
200
  appetize inspect --select-test-id order-42 --timeout 5000 --json
201
201
  ```
202
202
 
203
- `open`, like `session start --open`, only delivers the URL, so wait for the
203
+ `open`, like `session start --launch-url`, only delivers the URL, so wait for the
204
204
  destination with `inspect --timeout`. A custom scheme needs its app installed.
205
205
 
206
206
  ## Logged-out state
@@ -36,6 +36,12 @@ Session directories live under `~/.appetize/cli/sessions/`, or
36
36
  `--device-ios-keyboards` (repeatable) and `--no-device-ios-autocorrect`;
37
37
  Android takes `--no-device-android-soft-keyboard` and
38
38
  `--device-android-shell`, which needs a target.
39
+ - `--launch-url` opens a URL once ready. These need a target: `--launch-app`
40
+ (another app id), `--no-launch-app` (skip launching), `--launch-permissions`
41
+ (`grant`), `--launch-params` and, on iOS, `--launch-ios-args`. The last two
42
+ repeat; `--launch-params` takes `key=value`, the value JSON when valid
43
+ (`retries=3` is a number, `'zip="90210"'` a string, `'tags=["qa"]'` an array).
44
+ `=` joins a value starting with `-`.
39
45
 
40
46
  ## session stop
41
47
 
@@ -1,4 +1,4 @@
1
- import We from"debug";import{JSONRPCServerAndClient as Ur,JSONRPCServer as Lr,JSONRPCClient as Pr,JSONRPC as Cr}from"json-rpc-2.0";import*as m from"zod/mini";import{writeFileSync as _r,renameSync as Nr,mkdirSync as Mt,readFileSync as Dr,rmSync as Br,readdirSync as zr}from"node:fs";import{sep as Fr,join as ne}from"node:path";import{homedir as Ut}from"node:os";import{Transform as jr}from"stream";import{createRequire as $r}from"module";import{connect as Vr}from"node:net";class Kr extends Event{code;reason;wasClean;constructor(e,r={}){super(e,r),this.code=r.code??0,this.reason=r.reason??"",this.wasClean=r.wasClean??!1}}function qr(t,e){const r="CloseEvent"in globalThis?globalThis.CloseEvent:Kr;return new r(t,e)}class Wr{#e=new EventTarget;addEventListener(e,r,s){return this.#e.addEventListener(e,r,s),()=>{this.#e.removeEventListener(e,r,s)}}removeEventListener(e,r,s){this.#e.removeEventListener(e,r,s)}dispatchEvent(e){return this.#e.dispatchEvent(e)}}const U=Symbol.for("@appetizeio/rpc:rpcMethods");class Jr extends Wr{send;constructor(e){super(),this.send=e}dispatchClose(e){return this.dispatchEvent(qr("close",e))}dispatchMessage(e){return this.dispatchEvent(new CustomEvent("message",{detail:e}))}}const Gr="@appetizeio/rpc:playwrightAdapter";class ve{closed=!1;[U];#e;constructor(e,{signal:r}={}){this[U]=new Jr(e),this.#e=r,this.#e?.addEventListener("abort",this.#t)}close(e={}){this.closed||(this.closed=!0,this.handleClose(e))}handleClose(e){this.#e?.removeEventListener("abort",this.#t),this[U].dispatchClose(e)}#t=()=>{this.close({code:1e3,reason:String(this.#e?.reason)})}}const Ce=Symbol.for(Gr);function Hr(t){window[Ce]&&console.warn("playwright exposed more than once, overwriting previous adapter");const e={send(r){t[U].send(r)},subscribe(r){return t[U].addEventListener("message",s=>{r(s.detail)})}};return window[Ce]=e,()=>{window[Ce]===e&&delete window[Ce]}}const Lt=We("appetize.io:error:rpc");function Je(t,e){const r=new Ur(new Lr({errorListener:Lt}),Zr(t),{errorListener:Lt}),s=t[U].addEventListener("message",({detail:i})=>{r.receiveAndSend(i)}),n=t[U].addEventListener("close",()=>{s(),r.rejectAllPendingRequests("Transport closed")},{once:!0});for(const i in e){const l=e[i];l&&r.addMethod(i,l.bind(e))}return{rpc:r,unsub:()=>{s(),n()}}}function Pt(t,e){const{rpc:r,unsub:s}=Je(t,e);return{client:r.client,unsub:s}}function _e(t,e){const r=t[U].addEventListener("message",({detail:n})=>{if("method"in n)try{e({method:n.method,param:n.params})}catch{}}),s=t[U].addEventListener("close",r,{once:!0});return()=>{r(),s()}}function Zr(t){return new Pr(t[U].send.bind(t[U]),()=>Math.floor(Math.random()*Number.MAX_SAFE_INTEGER)+1)}function Ge(t,e,{leftEffects:r=()=>({}),notifiesLeft:s,notifiesRight:n,rightEffects:i=()=>({})}={}){const l=Je(t,{}),y=Je(e,{}),p=[()=>{l.unsub(),y.unsub()}],A=()=>{for(const _ of p)try{_()}catch{}},E=y.rpc.client,R=l.rpc.client;p.push(t[U].addEventListener("close",()=>{A()},{once:!0}),e[U].addEventListener("close",()=>{A()},{once:!0}));const M=r(E,R);for(const _ in M){const P=M[_];P&&l.rpc.addMethod(_,P)}const N=i(R,E);for(const _ in N){const P=N[_];P&&y.rpc.addMethod(_,P)}return Ct(l.rpc,y.rpc,{notifies:s}),Ct(y.rpc,l.rpc,{notifies:n}),A}function Ct(t,e,{notifies:r}={}){t.applyServerMiddleware(async(s,n)=>{const i=r?.();if(i){const{id:y,...p}=n;i[U].send(p)}if(t.hasMethod(n.method))return await s(n);if(!n.id)return e.notify(n.method,n.params),null;const l=await e.request(n.method,n.params);return{id:n.id,jsonrpc:Cr,result:l}})}function ee(t,...e){t.notify(e[0],e[1],e[2])}const Yr=(...t)=>Pt(...t),Qr=["h264","jpeg"],He=["ArrowDown","ArrowLeft","ArrowRight","ArrowUp","Backspace","Enter","Tab"],_t=["landscapeLeft","landscapeRight","portrait","upsideDown"];function Ze(){const t=new ve(async r=>{e[U].dispatchMessage(r)}),e=new ve(async r=>{t[U].dispatchMessage(r)});return t[U].addEventListener("close",()=>{e.close()},{once:!0}),e[U].addEventListener("close",()=>{t.close()},{once:!0}),[t,e]}function Nt(t,e){const r=[],s=()=>{for(const n of r)n()};r.push(t[U].addEventListener("message",n=>e[U].send(n.detail))),r.push(t[U].addEventListener("close",s,{once:!0})),r.push(e[U].addEventListener("message",n=>t[U].send(n.detail))),r.push(e[U].addEventListener("close",s,{once:!0}))}function Ye(t){return!!t&&typeof t=="object"&&"jsonrpc"in t}const ie=We("appetize.io:trace:transport:iframe");class Dt extends ve{onmessage;#e;#t;constructor(e,{origin:r="*",signal:s}={}){super(async n=>{e.postMessage(n,this.#e)},{signal:s}),this.#t=e,this.#e=r,window.addEventListener("message",this.#r)}postMessage(e,r,s){ie("postMessage(legacy)",{message:e,targetOrigin:r,transfer:s}),this.#t.postMessage(e,r??this.#e,s)}handleClose(e){ie("close()"),window.removeEventListener("message",this.#r),super.handleClose(e)}#r=async e=>{if(ie("handleMessage()",e),e.source!==this.#t||(ie("handleMessage() -> source ok"),this.#e!=="*"&&e.origin!==this.#e))return;ie("handleMessage() -> origin ok");const r=e.data;if(!Ye(r)){ie("handleMessage() -> legacy"),this.onmessage?.(e);return}ie("handleMessage() -> jsonrpc"),this[U].dispatchMessage(r)}}function Ne(){let t,e;return{promise:new Promise((s,n)=>{e=s,t=n}),reject:t,resolve:e}}const Xr=2*1024*1024,Bt=We("appetize:client:acked-writable-stream");class es{unacked=0;#e;#t;#r;#s;#n=[];#o;constructor(e){this.#r=e,this.#o=e.window??Xr}abort(e){this.#i(e),this.#r.onAbort?.(e)}async close(){await this.#c(()=>this.unacked===0),this.#r.onClose?.()}fail(e){this.#i(e)&&this.#r.onError?.(e)}start(e){this.#e=e}write(e){const r=e.byteLength;return this.unacked+=r,this.#r.send(e).then(()=>{this.unacked-=r,this.#s&&(this.#s.acked+=r),this.#a()},s=>{this.fail(s)}),this.unacked>=this.#o&&!this.#s&&(this.#s={acked:0,at:performance.now()},Bt("window full: %d bytes unacked, writes stalled",this.unacked)),this.#c(()=>this.unacked<this.#o)}#a(){if(this.#s&&this.unacked<=this.#o/2){const e=performance.now()-this.#s.at;Bt("pressure relieved after %dms: %d bytes acked, %s MB/s",Math.round(e),this.#s.acked,(this.#s.acked/Math.max(e,1)/1e3).toFixed(2)),this.#s=void 0}this.#n=this.#n.filter(e=>e.until()?(e.resolve(void 0),!1):!0)}#i(e){if(this.#t)return!1;this.#t={reason:e},this.#e.error(e);const r=this.#n;this.#n=[];for(const s of r)s.reject(e);return!0}#c(e){if(e())return Promise.resolve();const r={...Ne(),until:e};return this.#n.push(r),r.promise}}class ts extends WritableStream{get unacked(){return this.#e.unacked}#e;constructor(e){const r=new es(e);super({abort:s=>{r.abort(s)},close:()=>r.close(),start:s=>{r.start(s)},write:s=>r.write(s)}),this.#e=r}fail(e){this.#e.fail(e)}}const rs=1024*1024;class ss{#e;#t=!1;#r;#s;constructor(e){this.#r=e}cancel(e){this.#n(),this.#r?.(e)}close(){this.#n()&&this.#e.close()}error(e){this.#n()&&this.#e.error(e)}pull(){const e=this.#s;this.#s=void 0,e?.resolve(void 0)}async push(e){if(this.#t)return;this.#s??=Ne();const{promise:r}=this.#s;this.#e.enqueue(e),await r}start(e){this.#e=e}#n(){return this.#t?!1:(this.#t=!0,this.pull(),!0)}}class ns extends ReadableStream{#e;constructor({highWaterMark:e=rs,onCancel:r}={}){const s=new ss(r);super({cancel:n=>{s.cancel(n)},pull:()=>{s.pull()},start:n=>{s.start(n)}},new ByteLengthQueuingStrategy({highWaterMark:e})),this.#e=s}close(){this.#e.close()}error(e){this.#e.error(e)}push(e){return this.#e.push(e)}}class is{closed;readable;writable;#e=[];#t;#r;#s;#n;#o;#a="starting";constructor(e,{onClose:r,receiveBuffer:s,sendWindow:n,signal:i}){if(this.#o=e,this.#t=Ne(),this.closed=this.#t.promise,this.closed.catch(os),this.#s=new ns({highWaterMark:s,onCancel:()=>{this.#i(void 0)}}),this.readable=this.#s,this.#n=new ts({onAbort:()=>{this.#i(void 0)},onClose:()=>{this.#i(void 0)},onError:l=>{this.#i(l)},send:l=>e.request("appetizeio.device.server.debug.adbTunnel.data",{data:l}),window:n}),this.writable=this.#n,i){const l=()=>{this.#i(i.reason)};i.addEventListener("abort",l,{once:!0}),this.#e.push(()=>{i.removeEventListener("abort",l)})}this.#e.push(()=>{r(this)})}close=()=>{this.#i(void 0)};detach(){this.#i(void 0,{notifyServer:!1})}async handleData(e){this.#a==="open"&&await this.#s.push(e)}handleStopped({error:e}){this.#a==="open"&&this.#i(e?new Error(e):void 0)}async start(){try{await this.#o.request("appetizeio.device.server.debug.adbTunnel.start",void 0)}catch(e){throw this.#i(e),e}if(this.#a==="closed")throw this.#r?this.#r:new Error("The adb tunnel closed before it started");this.#a="open"}async[Symbol.asyncDispose](){this.close();try{await this.closed}catch{}}#i(e,{notifyServer:r=!0}={}){if(this.#a!=="closed"){this.#a="closed",this.#r=e,r&&ee(this.#o,"appetizeio.device.server.debug.adbTunnel.stop",void 0),e?(this.#s.error(e),this.#n.fail(e)):(this.#s.close(),this.#n.fail(new Error("The adb tunnel has stopped")));for(const s of this.#e)s();e?this.#t.reject(e):this.#t.resolve(void 0)}}}function os(){}class as{readable;ready;#e=[];#t=!1;#r;#s;#n;constructor({label:e,onClose:r,signal:s}){this.#s=e,this.ready=new Promise((i,l)=>{this.#n={reject:l,resolve:i}});let n;if(this.readable=new ReadableStream({cancel:()=>{this.#a()},start:i=>{n=i}}),!n)throw new Error("ReadableStream controller was not initialized");if(this.#r=n,s){const i=()=>{this.fail(s.reason)};s.addEventListener("abort",i,{once:!0}),this.#e.push(()=>{s.removeEventListener("abort",i)})}this.#e.push(()=>{r(this)})}close=()=>{this.#o()};fail(e){this.#o(e)}handleItem(e){this.#r.enqueue(e)}markReady(){if(!this.#n)return;const{resolve:e}=this.#n;this.#n=void 0,e(this)}async*[Symbol.asyncIterator](){const e=this.readable.getReader();try{for(let r=await e.read();!r.done;r=await e.read())yield r.value}finally{await e.cancel()}}#o(e){this.#t||(this.#r.close(),this.#a(e))}#a(e){this.#t=!0;for(const r of this.#e)r();this.#n?.reject(e??new Error(`${this.#s} closed before it started`)),this.#n=void 0}}class cs{get subscribers(){return this.#r}#e;#t;#r=new Set;constructor(e){this.#e=e}close(){this.#t=void 0;for(const e of[...this.#r])e.close();this.#r.clear()}add(e){this.#r.add(e)}ensureStarted(){return this.#t||(this.#t=(async()=>{try{return await this.#e.start()}catch(e){throw this.#t=void 0,e}})()),this.#t}release(e){this.#r.delete(e),!(this.#r.size>0||!this.#t)&&(this.#t=void 0,this.#e.stop())}}class zt extends cs{#e;constructor(e){super({start:e.start,stop:e.stop}),this.#e=e.label}async createStream({signal:e}={}){e?.throwIfAborted();const r=new as({label:this.#e,onClose:s=>{this.release(s)},signal:e});this.add(r);try{await this.ensureStarted(),r.markReady()}catch(s){r.fail(s)}return await r.ready}handleNotification(e){for(const r of this.subscribers)r.handleItem(e)}}class ls{#e;#t;#r;#s;constructor(e){this.#s=e,this.#t=new zt({label:"Log stream",start:()=>e.request("appetizeio.device.server.debug.log.start"),stop:()=>{ee(e,"appetizeio.device.server.debug.log.stop",void 0)}}),this.#r=new zt({label:"Proxy intercept stream",start:()=>e.request("appetizeio.device.server.debug.proxyIntercept.start"),stop:()=>{ee(e,"appetizeio.device.server.debug.proxyIntercept.stop",void 0)}})}close(){this.#e?.detach(),this.#t.close(),this.#r.close()}async createAdbTunnel({signal:e}={}){e?.throwIfAborted(),this.#e?.close();const r=new is(this.#s,{onClose:()=>{this.#e=void 0},signal:e});return this.#e=r,await r.start(),r}async createLogStream(e){return await this.#t.createStream(e)}async createProxyInterceptStream(e){return await this.#r.createStream(e)}async handleAdbTunnelData({data:e}){await this.#e?.handleData(e)}handleAdbTunnelStopped(e){this.#e?.handleStopped(e)}handleLogEntry(e){this.#t.handleNotification(e)}handleProxyInterceptEvent(e){this.#r.handleNotification(e)}}function Qe(t){return{...fs(t),index:t.index,within:t.within?Qe(t.within):void 0}}function fs(t){switch(t.by){case"testId":return{by:"testId",testId:t.testId};case"text":return{by:"text",text:us(t.text)}}}function us(t){return typeof t=="string"?{kind:"exact",value:t}:{flags:t.flags,kind:"regex",source:t.source}}const ds=400,Ft=["byTestId","byText","duration","index","x","y"],hs=new Set(Ft),ps=/^-?(?:\d+(?:\.\d*)?|\.\d+)$/u,ys=/^[a-z]$/u,Xe=/^\s$/u;class D extends SyntaxError{constructor(e,r,s){super(`${e} at position ${String(r)}`,{cause:s})}}class ws{#e=0;#t;constructor(e){this.#t=e}parse(){const e=[];for(;this.#e<this.#t.length;){const r=this.#i();if(Xe.test(r))this.#e++;else if(r===">"){if(this.#t.charAt(this.#e+1)===">")throw new D('Force press ">>" is not supported',this.#e);this.#e++,e.push({kind:"down"})}else if(r==="/")this.#e++,e.push({kind:"up"});else if(r==="{")e.push(this.#o());else{const[s]=this.#t.slice(this.#e,this.#e+2);throw new D(`Unexpected ${JSON.stringify(s)}; write selectors as {...}`,this.#e)}}return e}#r(){const e=this.#e,r=this.#c(s=>s!=="="&&!et(s));if(this.#i()!=="=")return{kind:"bare",name:r,offset:e};if(r.length===0)throw new D('Expected an attribute name before "="',e);return this.#e++,{kind:"attribute",name:r,offset:e,value:this.#a()}}#s(){const e=this.#e;this.#e++;let r="";for(;;){const s=this.#i();if(this.#e++,s==='"')return r;if(s==="\\"){const n=this.#i();if(n!=='"'&&n!=="\\"&&n!=="")throw new D('Only \\" and \\\\ escapes are supported',this.#e-1);this.#e++,r+=n}else{if(s==="")throw new D("Unclosed string",e);r+=s}}}#n(){const e=this.#e;this.#e++;let r="",s=!1;for(;;){const i=this.#i();if(i==="")throw new D("Unclosed regex",e);if(this.#e++,i==="/"&&!s)break;r+=i,i==="\\"?(r+=this.#i(),this.#e++):i==="["?s=!0:i==="]"&&(s=!1)}const n=this.#c(i=>ys.test(i));try{return new RegExp(r,n)}catch(i){throw new D(`Invalid regex /${r}/${n}`,e,i)}}#o(){const e=this.#e;this.#e++;let r;const s={offsets:{}};for(let n=0;;n++){this.#l();const i=this.#i();if(i==="")throw new D('Unclosed "{"',e);if(i==="}"){if(this.#e++,n===0)throw new D('Expected a selector or wait in "{}"',e);return r===void 0?bs(s,e):{duration:r,kind:"wait"}}const l=this.#r();if(n===0&&l.name==="wait")r=l.kind==="attribute"?$t(l.value,"wait"):ds;else{if(r!==void 0)throw new D('"wait" takes no other attributes',l.offset);gs(s,l,n)}}}#a(){const e=this.#e,r=this.#i();let s;if(r==='"')s={kind:"quoted",offset:e,text:this.#s()};else if(r==="/")s={kind:"regex",offset:e,regex:this.#n()};else{const n=this.#c(i=>!et(i));if(n.length===0)throw new D('Expected a value after "="',e);return{kind:"raw",offset:e,text:n}}if(!et(this.#i()))throw new D('Expected a space or "}" after the value',this.#e);return s}#i(){return this.#t.charAt(this.#e)}#c(e){const r=this.#e;for(;this.#e<this.#t.length&&e(this.#i());)this.#e++;return this.#t.slice(r,this.#e)}#l(){this.#c(e=>Xe.test(e))}}function jt(t){return new ws(t).parse()}function gs(t,e,r){const{name:s,offset:n}=e;if(e.kind==="attribute"){tt(t,s,n,e.value);return}if(!s.includes(","))throw new D(`Expected key=value, got ${JSON.stringify(s)}`,n);if(r>0)throw new D("Write the x,y position first",n);const[i,l,...y]=s.split(",");if(y.length>0)throw new D("Expected a screen position as x,y",n);const p=n+i.length+1;tt(t,"x",n,{kind:"raw",offset:n,text:i}),tt(t,"y",p,{kind:"raw",offset:p,text:l})}function ms(t){return hs.has(t)}function et(t){return t===""||t==="}"||Xe.test(t)}function tt(t,e,r,s){if(!ms(e))throw new D(`Unknown attribute ${JSON.stringify(e)}; expected one of ${Ft.join(", ")}`,r);if(t.offsets[e]!==void 0)throw new D(`Duplicate attribute ${JSON.stringify(e)}`,r);switch(t.offsets[e]=r,e){case"byTestId":case"byText":if(t.byText!==void 0||t.byTestId!==void 0)throw new D("Only one of byText and byTestId may be given",r);e==="byText"?t.byText=vs(s):t.byTestId=Ss(s);return;default:t[e]=$t(s,e)}}function bs(t,e){return{duration:t.duration,kind:"move",to:Es(t,e)}}function $t(t,e){if(t.kind!=="raw"||!ps.test(t.text))throw new D(`"${e}" takes a number`,t.offset);return Number(t.text)}function Es(t,e){const{byTestId:r,byText:s,index:n,offsets:i,x:l,y}=t;if(s!==void 0)return{by:"text",index:n,text:s,x:l,y};if(r!==void 0)return{by:"testId",index:n,testId:r,x:l,y};if(i.index!==void 0)throw new D('"index" needs byText or byTestId',i.index);if(l===void 0||y===void 0)throw new D("A screen position needs x and y",e);return{by:"position",x:l,y}}function Ss(t){if(t.kind==="regex")throw new D('"byTestId" takes a string',t.offset);return t.text}function vs(t){return t.kind==="regex"?t.regex:t.text}function Ae(t){return t.by==="position"?{by:"position",x:t.x,y:t.y}:{...Qe(t),x:t.x,y:t.y}}function As(t){return t.map(e=>e.kind==="move"?{duration:e.duration,kind:"move",to:Ae(e.to)}:e)}function xs(t){return{press:e=>{ee(t,"appetizeio.device.server.keyboard.press",{key:e})}}}function ks({onRequest:t,parent:e,proxyInlet:r,signal:s}){const n=new Dt(e,{signal:s}),i=[()=>{n.close()}];return Nt(n,r),t&&i.push(_e(n,l=>{t(l,{source:"parent"})})),{cleanup:()=>{for(const l of i)l()},notifies:()=>e===globalThis.window?void 0:n}}function Is({onRequest:t,proxyInlet:e}){const[r,s]=Ze(),i=[Hr(s),()=>{r.close()}];return Nt(r,e),t&&i.push(_e(r,l=>{t(l,{source:"parent"})})),{cleanup:()=>{for(const l of i)l()},notifies:()=>r}}function Os(t){return"to"in t?{from:Ae(t.from),kind:"path",to:Ae(t.to)}:{direction:t.direction,distance:t.distance,from:t.from?Ae(t.from):void 0,kind:"direction"}}function Ts(t){return{down:(e,r)=>{ee(t,"appetizeio.device.server.touch.down",{x:e,y:r})},move:(e,r)=>{ee(t,"appetizeio.device.server.touch.move",{x:e,y:r})},up:(e,r)=>{ee(t,"appetizeio.device.server.touch.up",{x:e,y:r})}}}const Rs=new Set(He),Ms=/^(?<key>[A-Za-z]+)>(?<repeat>\d+)\/$/u,Us=/(\{\{|\{[^{}]*\})/u;function Ls(t){const e=[];let r="";function s(){r.length>0&&(e.push({kind:"text",text:r}),r="")}for(const[n,i]of t.split(Us).entries())if(n%2===0){if(i.includes("{"))throw new Error(`Unclosed "{" in ${JSON.stringify(t)}`);r+=i}else i==="{{"?r+="{":(s(),e.push(Cs(i.slice(1,-1))));return s(),e}function Ps(t,e){if(!Rs.has(t))throw e.endsWith(">")?new Error(`Holding a key is not supported: {${e}}`):e.startsWith("/")?new Error(`Releasing a key is not supported: {${e}}`):new Error(`{${e}} does not name a supported key. Supported: ${He.join(", ")}. Type characters as text, and escape a literal "{" as "{{".`)}function Cs(t){const e=Ms.exec(t)?.groups,r=e?.key??t;if(Ps(r,t),!e)return{key:r,kind:"press"};const s=Number(e.repeat);if(s<1)throw new Error(`Repeat for {${t}} must be at least 1`);return{key:r,kind:"press",repeat:s}}const _s=Symbol("@appetizeio/client:v1Compat");function Vt(t){return t?.[_s]}class Ns{readable;ready;get dimensions(){return this.#s}#e=[];#t=!1;#r;#s;#n;#o;constructor({onClose:e,requestKeyFrame:r,signal:s}){this.#n=r,this.ready=new Promise((i,l)=>{this.#o={reject:l,resolve:i}});let n;if(this.readable=new ReadableStream({cancel:()=>{this.#i()},start:i=>{n=i}}),!n)throw new Error("ReadableStream controller was not initialized");if(this.#r=n,s){const i=()=>{this.fail(s.reason)};s.addEventListener("abort",i,{once:!0}),this.#e.push(()=>{s.removeEventListener("abort",i)})}this.#e.push(()=>{e(this)})}close=()=>{this.#a()};fail(e){this.#a(e)}handleChunk(e){if(this.#o){if(e.type!=="key")return;const{resolve:r}=this.#o;this.#o=void 0,this.#s={height:e.height,width:e.width},r(this)}else e.type==="key"&&(this.#s={height:e.height,width:e.width});this.#r.enqueue(e)}requestKeyFrame=()=>{this.#t||this.#n()};async*[Symbol.asyncIterator](){const e=this.readable.getReader();try{for(let r=await e.read();!r.done;r=await e.read())yield r.value}finally{await e.cancel()}}#a(e){this.#t||(this.#r.close(),this.#i(e))}#i(e){this.#t=!0;for(const r of this.#e)r();this.#o?.reject(e??new Error("Video stream closed before the first key chunk")),this.#o=void 0}}class Ds{#e=!1;#t;#r;#s=new Set;constructor(e){this.#t=e}close(){this.#r=void 0;for(const e of[...this.#s])e.close()}async createStream({signal:e}={}){e?.throwIfAborted();const r=new Ns({onClose:s=>{this.#o(s)},requestKeyFrame:()=>{this.#a()},signal:e});this.#s.add(r);try{await this.#n()}catch(s){r.fail(s)}return await r.ready}handleChunk(e){e.type==="key"&&(this.#e=!1);for(const r of this.#s)r.handleChunk(e)}#n(){return this.#r?(this.#a(),this.#r):(this.#e=!0,this.#r=(async()=>{try{await this.#t.request("appetizeio.device.server.video.start")}catch(e){throw this.#r=void 0,e}})(),this.#r)}#o(e){this.#s.delete(e),!(this.#s.size>0||!this.#r)&&(this.#r=void 0,ee(this.#t,"appetizeio.device.server.video.stop",void 0))}#a(){this.#e||(this.#e=!0,ee(this.#t,"appetizeio.device.server.video.requestKeyFrame",void 0))}}class Bs{debug;keyboard;touch;video;#e;#t=[];#r;constructor(e,r={}){const s=Vt(r)??{},{baseUrl:n,onClose:i,signal:l}=r;this.#e=n?zs(n):void 0;const{onRequest:y,parent:p,proxyRequest:A}=s,E=Fs(y);l?.addEventListener("abort",this.close);const[R,M]=Ze(),[N,_]=Ze();this.#t.push(()=>{R.close(),M.close(),N.close(),_.close()}),this.#t.push(Ge(_,e,{leftEffects:A}));const P=p==="playwright"?Is({onRequest:E,proxyInlet:N}):p?ks({onRequest:E,parent:p,proxyInlet:N,signal:l}):void 0;P&&this.#t.push(P.cleanup),this.#t.push(Ge(M,N,{notifiesLeft:P?.notifies}));const{client:Z,unsub:Ee}=Yr(R,{"appetizeio.device.client.debug.adbTunnel.data":V=>Y.handleAdbTunnelData(V),"appetizeio.device.client.debug.adbTunnel.stopped":async V=>{Y.handleAdbTunnelStopped(V)},"appetizeio.device.client.debug.log.entry":async V=>{Y.handleLogEntry(V)},"appetizeio.device.client.debug.proxyIntercept.event":async V=>{Y.handleProxyInterceptEvent(V)},"appetizeio.device.client.video.chunk":async V=>{k.handleChunk(V)}});this.#r=Z,this.#t.push(Ee);const Y=new ls(this.#r);this.#t.push(()=>{Y.close()});const k=new Ds(this.#r);this.#t.push(()=>{k.close()}),this.debug=Y,this.keyboard=xs(this.#r),this.touch=Ts(this.#r),this.video=k,E&&(this.#t.push(_e(M,V=>{E(V,{source:"self"})})),e instanceof Dt&&this.#t.push(_e(e,V=>{E(V,{source:"iframe"})}))),this.#t.push(()=>i?.())}async clearKeychain(){await this.#r.request("appetizeio.device.server.clearKeychain")}close=()=>{for(const e of this.#t)try{e()}catch(r){console.error("Device cleanup error:",r)}};async fold(e){await this.#r.request("appetizeio.device.server.fold",{hinge:e})}async gesture(e,r){await this.#r.request("appetizeio.device.server.gesture",{options:r,steps:As(typeof e=="string"?jt(e):e)})}async inspect(e,r){return await this.#r.request("appetizeio.device.server.inspect",{options:r,selector:e?Qe(e):void 0})}async open(e){new URL(e),await this.#r.request("appetizeio.device.server.open",{url:e})}async press(e){await this.#r.request("appetizeio.device.server.press",{action:e})}async rotate(e){await this.#r.request("appetizeio.device.server.rotate",{orientation:e})}async screenshot(){const e=await this.#r.request("appetizeio.device.server.screenshot"),r=this.#e?new URL(e.url,this.#e).href:e.url,s=await fetch(r);if(!s.ok)throw new Error(`Screenshot download failed: ${String(s.status)} ${s.statusText}`);const n=s.headers.get("content-type")??"application/octet-stream";return{data:new Uint8Array(await s.arrayBuffer()),mimeType:n}}async swipe(e,r){await this.#r.request("appetizeio.device.server.swipe",{gesture:Os(e),options:r})}async tap(e,r){await this.#r.request("appetizeio.device.server.tap",{options:r,selector:Ae(e)})}async type(e,r){await this.#r.request("appetizeio.device.server.type",{options:r,steps:Ls(e)})}}function zs(t){const e=new URL(t);return e.protocol==="ws:"?e.protocol="http:":e.protocol==="wss:"&&(e.protocol="https:"),e.href}const Fs=t=>{if(t)return(e,r)=>{e.method.startsWith("appetizeio.device.server.")&&t(e,r)}};let rt;try{rt=new TextDecoder}catch{}let w,q,f=0;const st=[],js=105,$s=57342,Vs=57343,Kt=57337,qt=6,pe={};let xe=11281e4,te=1681e4,oe=st,ke=0,I={},B,Ie,Oe=0,ae=0,z,G,F=[],nt=[],W,K,Te,Wt={useRecords:!1,mapsAsObjects:!0},Re=!1,Jt=2;try{new Function("")}catch{Jt=1/0}class be{constructor(e){if(e&&((e.keyMap||e._keyMap)&&!e.useRecords&&(e.useRecords=!1,e.mapsAsObjects=!0),e.useRecords===!1&&e.mapsAsObjects===void 0&&(e.mapsAsObjects=!0),e.getStructures&&(e.getShared=e.getStructures),e.getShared&&!e.structures&&((e.structures=[]).uninitialized=!0),e.keyMap)){this.mapKey=new Map;for(let[r,s]of Object.entries(e.keyMap))this.mapKey.set(s,r)}Object.assign(this,e)}decodeKey(e){return this.keyMap&&this.mapKey.get(e)||e}encodeKey(e){return this.keyMap&&this.keyMap.hasOwnProperty(e)?this.keyMap[e]:e}encodeKeys(e){if(!this._keyMap)return e;let r=new Map;for(let[s,n]of Object.entries(e))r.set(this._keyMap.hasOwnProperty(s)?this._keyMap[s]:s,n);return r}decodeKeys(e){if(!this._keyMap||e.constructor.name!="Map")return e;if(!this._mapKey){this._mapKey=new Map;for(let[s,n]of Object.entries(this._keyMap))this._mapKey.set(n,s)}let r={};return e.forEach((s,n)=>r[H(this._mapKey.has(n)?this._mapKey.get(n):n)]=s),r}mapDecode(e,r){let s=this.decode(e);return this._keyMap&&s.constructor.name==="Array"?s.map(n=>this.decodeKeys(n)):s}decode(e,r){if(w)return er(()=>(ct(),this?this.decode(e,r):be.prototype.decode.call(Wt,e,r)));q=r>-1?r:e.length,f=0,ke=0,ae=0,Ie=null,oe=st,z=null,w=e;try{K=e.dataView||(e.dataView=new DataView(e.buffer,e.byteOffset,e.byteLength))}catch(s){throw w=null,e instanceof Uint8Array?s:new Error("Source must be a Uint8Array or Buffer but was a "+(e&&typeof e=="object"?e.constructor.name:typeof e))}if(this instanceof be){if(I=this,W=this.sharedValues&&(this.pack?new Array(this.maxPrivatePackedValues||16).concat(this.sharedValues):this.sharedValues),this.structures)return B=this.structures,De();(!B||B.length>0)&&(B=[])}else I=Wt,(!B||B.length>0)&&(B=[]),W=null;return De()}decodeMultiple(e,r){let s,n=0;try{let i=e.length;Re=!0;let l=this?this.decode(e,i):ft.decode(e,i);if(r){if(r(l)===!1)return;for(;f<i;)if(n=f,r(De())===!1)return}else{for(s=[l];f<i;)n=f,s.push(De());return s}}catch(i){throw i.lastPosition=n,i.values=s,i}finally{Re=!1,ct()}}}function De(){try{let t=O();if(z){if(f>=z.postBundlePosition){let e=new Error("Unexpected bundle position");throw e.incomplete=!0,e}f=z.postBundlePosition,z=null}if(f==q)B=null,w=null,G&&(G=null);else if(f>q){let e=new Error("Unexpected end of CBOR data");throw e.incomplete=!0,e}else if(!Re)throw new Error("Data read, but end of buffer not reached");return t}catch(t){throw ct(),(t instanceof RangeError||t.message.startsWith("Unexpected end of buffer"))&&(t.incomplete=!0),t}}function ce(){let t=new Error("Unexpected end of CBOR data");return t.incomplete=!0,t}function O(){if(!(f<q))throw ce();let t=w[f++],e=t>>5;if(t=t&31,t>23)switch(t){case 24:if(f>=q)throw ce();t=w[f++];break;case 25:if(e==7)return Js();t=K.getUint16(f),f+=2;break;case 26:if(e==7){let r=K.getFloat32(f);if(I.useFloat32>2){let s=lt[(w[f]&127)<<1|w[f+1]>>7];return f+=4,(s*r+(r>0?.5:-.5)>>0)/s}return f+=4,r}if(t=K.getUint32(f),f+=4,e===1)return-1-t;break;case 27:if(e==7){let r=K.getFloat64(f);return f+=8,r}if(e>1){if(K.getUint32(f)>0)throw new Error("JavaScript does not support arrays, maps, or strings with length over 4294967295");t=K.getUint32(f+4)}else I.int64AsNumber?(t=K.getUint32(f)*4294967296,t+=K.getUint32(f+4)):t=K.getBigUint64(f);f+=8;break;case 31:switch(e){case 2:case 3:throw new Error("Indefinite length not supported for byte or text strings");case 4:let r=[],s,n=0;for(;(s=O())!=pe;){if(n>=xe)throw new Error(`Array length exceeds ${xe}`);r[n++]=s}return e==4?r:e==3?r.join(""):Buffer.concat(r);case 5:let i;if(I.mapsAsObjects){let l={},y=0;if(I.keyMap)for(;(i=O())!=pe;){if(y++>=te)throw new Error(`Property count exceeds ${te}`);l[H(I.decodeKey(i))]=O()}else for(;(i=O())!=pe;){if(y++>=te)throw new Error(`Property count exceeds ${te}`);l[H(i)]=O()}return l}else{Te&&(I.mapsAsObjects=!0,Te=!1);let l=new Map;if(I.keyMap){let y=0;for(;(i=O())!=pe;){if(y++>=te)throw new Error(`Map size exceeds ${te}`);l.set(I.decodeKey(i),O())}}else{let y=0;for(;(i=O())!=pe;){if(y++>=te)throw new Error(`Map size exceeds ${te}`);l.set(i,O())}}return l}case 7:return pe;default:throw new Error("Invalid major type for indefinite length "+e)}default:throw new Error("Unknown token "+t)}switch(e){case 0:return t;case 1:return~t;case 2:return Ws(t);case 3:if(ae>=f)return Ie.slice(f-Oe,(f+=t)-Oe);if(ae==0&&q<140&&t<32){let n=t<16?Zt(t):qs(t);if(n!=null)return n}return Ht(t);case 4:if(t>=xe)throw new Error(`Array length exceeds ${xe}`);if(t>q-f)throw ce();let r=new Array(t);for(let n=0;n<t;n++)r[n]=O();return r;case 5:if(t>=te)throw new Error(`Map size exceeds ${xe}`);if(t>(q-f)/2)throw ce();if(I.mapsAsObjects){let n={};if(I.keyMap)for(let i=0;i<t;i++)n[H(I.decodeKey(O()))]=O();else for(let i=0;i<t;i++)n[H(O())]=O();return n}else{Te&&(I.mapsAsObjects=!0,Te=!1);let n=new Map;if(I.keyMap)for(let i=0;i<t;i++)n.set(I.decodeKey(O()),O());else for(let i=0;i<t;i++)n.set(O(),O());return n}case 6:if(t>=Kt){let n=B[t&8191];if(n)return n.read||(n.read=it(n)),n.read();if(t<65536){if(t==Vs){let i=we(),l=O(),y=O();ot(l,y);let p={};if(I.keyMap)for(let A=2;A<i;A++){let E=I.decodeKey(y[A-2]);p[H(E)]=O()}else for(let A=2;A<i;A++){let E=y[A-2];p[H(E)]=O()}return p}else if(t==$s){let i=we(),l=O();for(let y=2;y<i;y++)ot(l++,O());return O()}else if(t==Kt)return Xs();if(I.getShared&&(at(),n=B[t&8191],n))return n.read||(n.read=it(n)),n.read()}}let s=F[t];if(s)return s.handlesRead?s(O):s(O());{let n=O();for(let i=0;i<nt.length;i++){let l=nt[i](t,n);if(l!==void 0)return l}return new le(n,t)}case 7:switch(t){case 20:return!1;case 21:return!0;case 22:return null;case 23:return;default:let n=(W||fe())[t];if(n!==void 0)return n;throw new Error("Unknown token "+t)}default:throw isNaN(t)?ce():new Error("Unknown CBOR token "+t)}}const Gt=/^[a-zA-Z_$][a-zA-Z\d_$]*$/;function it(t){if(!t)throw new Error("Structure is required in record definition");function e(){let r=w[f++];if(r=r&31,r>23)switch(r){case 24:r=w[f++];break;case 25:r=K.getUint16(f),f+=2;break;case 26:r=K.getUint32(f),f+=4;break;default:throw new Error("Expected array header, but got "+w[f-1])}let s=this.compiledReader;for(;s;){if(s.propertyCount===r)return s(O);s=s.next}if(this.slowReads++>=Jt){let i=this.length==r?this:this.slice(0,r);return s=I.keyMap?new Function("r","return {"+i.map(l=>I.decodeKey(l)).map(l=>Gt.test(l)?H(l)+":r()":"["+JSON.stringify(l)+"]:r()").join(",")+"}"):new Function("r","return {"+i.map(l=>Gt.test(l)?H(l)+":r()":"["+JSON.stringify(l)+"]:r()").join(",")+"}"),this.compiledReader&&(s.next=this.compiledReader),s.propertyCount=r,this.compiledReader=s,s(O)}let n={};if(I.keyMap)for(let i=0;i<r;i++)n[H(I.decodeKey(this[i]))]=O();else for(let i=0;i<r;i++)n[H(this[i])]=O();return n}return t.slowReads=0,e}function H(t){if(typeof t=="string")return t==="__proto__"?"__proto_":t;if(typeof t=="number"||typeof t=="boolean"||typeof t=="bigint")return t.toString();if(t==null)return t+"";throw new Error("Invalid property name type "+typeof t)}let Ht=Be;function Ks(t){Ht=e();function e(r){return function(n){let i=oe[ke++];if(i==null){if(z)return Be(n);let y=t(f,q,n,w);if(typeof y=="string")i=y,oe=st;else if(oe=y,ke=1,ae=1,i=oe[0],i===void 0)throw new Error("Unexpected end of buffer")}let l=i.length;return l<=n?(f+=n,i):(Ie=i,Oe=f,ae=f+l,f+=n,i.slice(0,n))}}}function Be(t){let e;if(t<16&&(e=Zt(t)))return e;if(t>64&&rt)return rt.decode(w.subarray(f,f+=t));const r=f+t,s=[];for(e="";f<r;){const n=w[f++];if((n&128)===0)s.push(n);else if((n&224)===192)if(n<194||f>=r||(w[f]&192)!==128)s.push(65533);else{const i=w[f++]&63;s.push((n&31)<<6|i)}else if((n&240)===224){const i=f<r?w[f]:0;if(f>=r||(i&192)!==128||n===224&&i<160||n===237&&i>=160)s.push(65533);else if(f++,f>=r||(w[f]&192)!==128)s.push(65533);else{const l=w[f++]&63;s.push((n&31)<<12|(i&63)<<6|l)}}else if((n&248)===240){const i=f<r?w[f]:0;if(n>244||f>=r||(i&192)!==128||n===240&&i<144||n===244&&i>=144)s.push(65533);else if(f++,f>=r||(w[f]&192)!==128)s.push(65533);else{const l=w[f++]&63;if(f>=r||(w[f]&192)!==128)s.push(65533);else{const y=w[f++]&63;let p=(n&7)<<18|(i&63)<<12|l<<6|y;p-=65536,s.push(p>>>10&1023|55296),s.push(56320|p&1023)}}}else s.push(65533);s.length>=4096&&(e+=$.apply(String,s),s.length=0)}return s.length>0&&(e+=$.apply(String,s)),e}let $=String.fromCharCode;function qs(t){let e=f,r=new Array(t);for(let s=0;s<t;s++){const n=w[f++];if((n&128)>0){f=e;return}r[s]=n}return $.apply(String,r)}function Zt(t){if(t<4)if(t<2){if(t===0)return"";{let e=w[f++];if((e&128)>1){f-=1;return}return $(e)}}else{let e=w[f++],r=w[f++];if((e&128)>0||(r&128)>0){f-=2;return}if(t<3)return $(e,r);let s=w[f++];if((s&128)>0){f-=3;return}return $(e,r,s)}else{let e=w[f++],r=w[f++],s=w[f++],n=w[f++];if((e&128)>0||(r&128)>0||(s&128)>0||(n&128)>0){f-=4;return}if(t<6){if(t===4)return $(e,r,s,n);{let i=w[f++];if((i&128)>0){f-=5;return}return $(e,r,s,n,i)}}else if(t<8){let i=w[f++],l=w[f++];if((i&128)>0||(l&128)>0){f-=6;return}if(t<7)return $(e,r,s,n,i,l);let y=w[f++];if((y&128)>0){f-=7;return}return $(e,r,s,n,i,l,y)}else{let i=w[f++],l=w[f++],y=w[f++],p=w[f++];if((i&128)>0||(l&128)>0||(y&128)>0||(p&128)>0){f-=8;return}if(t<10){if(t===8)return $(e,r,s,n,i,l,y,p);{let A=w[f++];if((A&128)>0){f-=9;return}return $(e,r,s,n,i,l,y,p,A)}}else if(t<12){let A=w[f++],E=w[f++];if((A&128)>0||(E&128)>0){f-=10;return}if(t<11)return $(e,r,s,n,i,l,y,p,A,E);let R=w[f++];if((R&128)>0){f-=11;return}return $(e,r,s,n,i,l,y,p,A,E,R)}else{let A=w[f++],E=w[f++],R=w[f++],M=w[f++];if((A&128)>0||(E&128)>0||(R&128)>0||(M&128)>0){f-=12;return}if(t<14){if(t===12)return $(e,r,s,n,i,l,y,p,A,E,R,M);{let N=w[f++];if((N&128)>0){f-=13;return}return $(e,r,s,n,i,l,y,p,A,E,R,M,N)}}else{let N=w[f++],_=w[f++];if((N&128)>0||(_&128)>0){f-=14;return}if(t<15)return $(e,r,s,n,i,l,y,p,A,E,R,M,N,_);let P=w[f++];if((P&128)>0){f-=15;return}return $(e,r,s,n,i,l,y,p,A,E,R,M,N,_,P)}}}}}function Ws(t){return I.copyBuffers?Uint8Array.prototype.slice.call(w,f,f+=t):w.subarray(f,f+=t)}let Yt=new Float32Array(1),ze=new Uint8Array(Yt.buffer,0,4);function Js(){let t=w[f++],e=w[f++],r=(t&127)>>2;if(r===31)return e||t&3?NaN:t&128?-1/0:1/0;if(r===0){let s=((t&3)<<8|e)/16777216;return t&128?-s:s}return ze[3]=t&128|(r>>1)+56,ze[2]=(t&7)<<5|e>>3,ze[1]=e<<5,ze[0]=0,Yt[0]}new Array(4096);class le{constructor(e,r){this.value=e,this.tag=r}}F[0]=t=>new Date(t),F[1]=t=>new Date(Math.round(t*1e3)),F[2]=t=>{let e=BigInt(0);for(let r=0,s=t.byteLength;r<s;r++)e=BigInt(t[r])+(e<<BigInt(8));return e},F[3]=t=>BigInt(-1)-F[2](t),F[4]=t=>+(t[1]+"e"+t[0]),F[5]=t=>t[1]*Math.exp(t[0]*Math.log(2));const ot=(t,e)=>{t=t-57344;let r=B[t];r&&r.isShared&&((B.restoreStructures||(B.restoreStructures=[]))[t]=r),B[t]=e,e.read=it(e)};F[js]=t=>{let e=t.length,r=t[1];ot(t[0],r);let s={};for(let n=2;n<e;n++){let i=r[n-2];s[H(i)]=t[n]}return s},F[14]=t=>z?z[0].slice(z.position0,z.position0+=t):new le(t,14),F[15]=t=>z?z[1].slice(z.position1,z.position1+=t):new le(t,15);let Gs={Error,RegExp};F[27]=t=>(Gs[t[0]]||Error)(t[1],t[2]);const Qt=t=>{if(w[f++]!=132){let r=new Error("Packed values structure must be followed by a 4 element array");throw w.length<f&&(r.incomplete=!0),r}let e=t();if(!e||!e.length){let r=new Error("Packed values structure must be followed by a 4 element array");throw r.incomplete=!0,r}return W=W?e.concat(W.slice(e.length)):e,W.prefixes=t(),W.suffixes=t(),t()};Qt.handlesRead=!0,F[51]=Qt,F[qt]=t=>{if(!W)if(I.getShared)at();else return new le(t,qt);if(typeof t=="number")return W[16+(t>=0?2*t:-2*t-1)];let e=new Error("No support for non-integer packed references yet");throw t===void 0&&(e.incomplete=!0),e},F[28]=t=>{G||(G=new Map,G.id=0);let e=G.id++,r=f,s=w[f],n;s>>5==4?n=[]:n={};let i={target:n};G.set(e,i);let l=t();return i.used?(Object.getPrototypeOf(n)!==Object.getPrototypeOf(l)&&(f=r,n=l,G.set(e,{target:n}),l=t()),Object.assign(n,l)):(i.target=l,l)},F[28].handlesRead=!0,F[29]=t=>{let e=G.get(t);return e.used=!0,e.target},F[258]=t=>new Set(t),(F[259]=t=>(I.mapsAsObjects&&(I.mapsAsObjects=!1,Te=!0),t())).handlesRead=!0;function ye(t,e){return typeof t=="string"?t+e:t instanceof Array?t.concat(e):Object.assign({},t,e)}function fe(){if(!W)if(I.getShared)at();else throw new Error("No packed values available");return W}const Hs=1399353956;nt.push((t,e)=>{if(t>=225&&t<=255)return ye(fe().prefixes[t-224],e);if(t>=28704&&t<=32767)return ye(fe().prefixes[t-28672],e);if(t>=1879052288&&t<=2147483647)return ye(fe().prefixes[t-1879048192],e);if(t>=216&&t<=223)return ye(e,fe().suffixes[t-216]);if(t>=27647&&t<=28671)return ye(e,fe().suffixes[t-27639]);if(t>=1811940352&&t<=1879048191)return ye(e,fe().suffixes[t-1811939328]);if(t==Hs)return{packedValues:W,structures:B.slice(0),version:e};if(t==55799)return e});const Zs=new Uint8Array(new Uint16Array([1]).buffer)[0]==1,Xt=[Uint8Array,Uint8ClampedArray,Uint16Array,Uint32Array,typeof BigUint64Array>"u"?{name:"BigUint64Array"}:BigUint64Array,Int8Array,Int16Array,Int32Array,typeof BigInt64Array>"u"?{name:"BigInt64Array"}:BigInt64Array,Float32Array,Float64Array],Ys=[64,68,69,70,71,72,77,78,79,85,86];for(let t=0;t<Xt.length;t++)Qs(Xt[t],Ys[t]);function Qs(t,e){let r="get"+t.name.slice(0,-5),s;typeof t=="function"?s=t.BYTES_PER_ELEMENT:t=null;for(let n=0;n<2;n++){if(!n&&s==1)continue;let i=s==2?1:s==4?2:s==8?3:0;F[n?e:e-4]=s==1||n==Zs?l=>{if(!t)throw new Error("Could not find typed array for code "+e);return!I.copyBuffers&&(s===1||s===2&&!(l.byteOffset&1)||s===4&&!(l.byteOffset&3)||s===8&&!(l.byteOffset&7))?new t(l.buffer,l.byteOffset,l.byteLength>>i):new t(Uint8Array.prototype.slice.call(l,0).buffer)}:l=>{if(!t)throw new Error("Could not find typed array for code "+e);let y=new DataView(l.buffer,l.byteOffset,l.byteLength),p=l.length>>i,A=new t(p),E=y[r];for(let R=0;R<p;R++)A[R]=E.call(y,R<<i,n);return A}}}function Xs(){let t=we(),e=f+O();for(let s=2;s<t;s++){let n=we();f+=n}let r=f;return f=e,z=[Be(we()),Be(we())],z.position0=0,z.position1=0,z.postBundlePosition=f,f=r,O()}function we(){if(!(f<q))throw ce();let t=w[f++]&31;if(t>23)switch(t){case 24:if(f>=q)throw ce();t=w[f++];break;case 25:t=K.getUint16(f),f+=2;break;case 26:t=K.getUint32(f),f+=4;break}return t}function at(){if(I.getShared){let t=er(()=>(w=null,I.getShared()))||{},e=t.structures||[];I.sharedVersion=t.version,W=I.sharedValues=t.packedValues,B===!0?I.structures=B=e:B.splice.apply(B,[0,e.length].concat(e))}}function er(t){let e=q,r=f,s=ke,n=Oe,i=ae,l=Ie,y=oe,p=G,A=z,E=new Uint8Array(w.slice(0,q)),R=B,M=I,N=Re,_=t();return q=e,f=r,ke=s,Oe=n,ae=i,Ie=l,oe=y,G=p,z=A,w=E,Re=N,B=R,I=M,K=new DataView(w.buffer,w.byteOffset,w.byteLength),_}function ct(){w=null,G=null,B=null}const lt=new Array(147);for(let t=0;t<256;t++)lt[t]=+("1e"+Math.floor(45.15-t*.30103));let ft=new be({useRecords:!1});const en=ft.decode;ft.decodeMultiple;let Fe;try{Fe=new TextEncoder}catch{}let ut,tr;const je=typeof globalThis=="object"&&globalThis.Buffer,Me=typeof je<"u",dt=Me?je.allocUnsafeSlow:Uint8Array,rr=Me?je:Uint8Array,sr=256,nr=Me?4294967296:2144337920;let ht,c,L,o=0,re,j=null;const tn=61440,rn=/[\u0080-\uFFFF]/,J=Symbol("record-id");class ir extends be{constructor(e){super(e),this.offset=0;let r,s,n,i,l;e=e||{};let y=rr.prototype.utf8Write?function(a,g){return c.utf8Write(a,g,c.byteLength-g)}:Fe&&Fe.encodeInto?function(a,g){return Fe.encodeInto(a,c.subarray(g)).written}:!1,p=this,A=e.structures||e.saveStructures,E=e.maxSharedStructures;if(E==null&&(E=A?128:0),E>8190)throw new Error("Maximum maxSharedStructure is 8190");let R=e.sequential;R&&(E=0),this.structures||(this.structures=[]),this.saveStructures&&(this.saveShared=this.saveStructures);let M,N,_=e.sharedValues,P;if(_){P=Object.create(null);for(let a=0,g=_.length;a<g;a++)P[_[a]]=a}let Z=[],Ee=0,Y=0;this.mapEncode=function(a,g){return this._keyMap&&!this._mapped&&a.constructor.name==="Array"&&(a=a.map(d=>this.encodeKeys(d))),this.encode(a,g)},this.encode=function(a,g){if(c||(c=new dt(8192),L=new DataView(c.buffer,0,8192),o=0),re=c.length-10,re-o<2048?(c=new dt(c.length),L=new DataView(c.buffer,0,c.length),re=c.length-10,o=0):g===lr&&(o=o+7&2147483640),r=o,p.useSelfDescribedHeader&&(L.setUint32(o,3654940416),o+=3),l=p.structuredClone?new Map:null,p.bundleStrings&&typeof a!="string"?(j=[],j.size=1/0):j=null,s=p.structures,s){if(s.uninitialized){let h=p.getShared()||{};p.structures=s=h.structures||[],p.sharedVersion=h.version;let u=p.sharedValues=h.packedValues;if(u){P={};for(let b=0,S=u.length;b<S;b++)P[u[b]]=b}}let d=s.length;if(d>E&&!R&&(d=E),!s.transitions){s.transitions=Object.create(null);for(let h=0;h<d;h++){let u=s[h];if(!u)continue;let b,S=s.transitions;for(let v=0,x=u.length;v<x;v++){S[J]===void 0&&(S[J]=h);let T=u[v];b=S[T],b||(b=S[T]=Object.create(null)),S=b}S[J]=h|1048576}}R||(s.nextId=d)}if(n&&(n=!1),i=s||[],N=P,e.pack){let d=new Map;if(d.values=[],d.encoder=p,d.maxValues=e.maxPrivatePackedValues||(P?16:1/0),d.objectMap=P||!1,d.samplingPackedValues=M,$e(a,d),d.values.length>0){c[o++]=216,c[o++]=51,Q(4);let h=d.values;k(h),Q(0),Q(0),N=Object.create(P||null);for(let u=0,b=h.length;u<b;u++)N[h[u]]=u}}ht=g&gt;try{if(ht)return;if(k(a),j&&cr(r,k),p.offset=o,l&&l.idsToInsert){o+=l.idsToInsert.length*2,o>re&&de(o),p.offset=o;let d=on(c.subarray(r,o),l.idsToInsert);return l=null,d}return g&lr?(c.start=r,c.end=o,c):c.subarray(r,o)}finally{if(s){if(Y<10&&Y++,s.length>E&&(s.length=E),Ee>1e4)s.transitions=null,Y=0,Ee=0,Z.length>0&&(Z=[]);else if(Z.length>0&&!R){for(let d=0,h=Z.length;d<h;d++)Z[d][J]=void 0;Z=[]}}if(n&&p.saveShared){p.structures.length>E&&(p.structures=p.structures.slice(0,E));let d=c.subarray(r,o);return p.updateSharedData()===!1?p.encode(a):d}g&cn&&(o=r)}},this.findCommonStringsToPack=()=>(M=new Map,P||(P=Object.create(null)),a=>{let g=a&&a.threshold||4,d=this.pack?a.maxPrivatePackedValues||16:0;_||(_=this.sharedValues=[]);for(let[h,u]of M)u.count>g&&(P[h]=d++,_.push(h),n=!0);for(;this.saveShared&&this.updateSharedData()===!1;);M=null});const k=a=>{o>re&&(c=de(o));var g=typeof a,d;if(g==="string"){if(N){let S=N[a];if(S>=0){S<16?c[o++]=S+224:(c[o++]=198,S&1?k(15-S>>1):k(S-16>>1));return}else if(M&&!e.pack){let v=M.get(a);v?v.count++:M.set(a,{count:1})}}let h=a.length;if(j&&h>=4&&h<1024){if((j.size+=h)>tn){let v,x=(j[0]?j[0].length*3+j[1].length:0)+10;o+x>re&&(c=de(o+x)),c[o++]=217,c[o++]=223,c[o++]=249,c[o++]=j.position?132:130,c[o++]=26,v=o-r,o+=4,j.position&&cr(r,k),j=["",""],j.size=0,j.position=v}let S=rn.test(a);j[S?0:1]+=a,c[o++]=S?206:207,k(h);return}let u;h<32?u=1:h<256?u=2:h<65536?u=3:u=5;let b=h*3;if(o+b>re&&(c=de(o+b)),h<64||!y){let S,v,x,T=o+u;for(S=0;S<h;S++)v=a.charCodeAt(S),v<128?c[T++]=v:v<2048?(c[T++]=v>>6|192,c[T++]=v&63|128):(v&64512)===55296&&((x=a.charCodeAt(S+1))&64512)===56320?(v=65536+((v&1023)<<10)+(x&1023),S++,c[T++]=v>>18|240,c[T++]=v>>12&63|128,c[T++]=v>>6&63|128,c[T++]=v&63|128):(c[T++]=v>>12|224,c[T++]=v>>6&63|128,c[T++]=v&63|128);d=T-o-u}else d=y(a,o+u,b);d<24?c[o++]=96|d:d<256?(u<2&&c.copyWithin(o+2,o+1,o+1+d),c[o++]=120,c[o++]=d):d<65536?(u<3&&c.copyWithin(o+3,o+2,o+2+d),c[o++]=121,c[o++]=d>>8,c[o++]=d&255):(u<5&&c.copyWithin(o+5,o+3,o+3+d),c[o++]=122,L.setUint32(o,d),o+=4),o+=d}else if(g==="number")if(!this.alwaysUseFloat&&a>>>0===a)a<24?c[o++]=a:a<256?(c[o++]=24,c[o++]=a):a<65536?(c[o++]=25,c[o++]=a>>8,c[o++]=a&255):(c[o++]=26,L.setUint32(o,a),o+=4);else if(!this.alwaysUseFloat&&a>>0===a)a>=-24?c[o++]=31-a:a>=-256?(c[o++]=56,c[o++]=~a):a>=-65536?(c[o++]=57,L.setUint16(o,~a),o+=2):(c[o++]=58,L.setUint32(o,~a),o+=4);else if(!this.alwaysUseFloat&&a<0&&a>=-4294967296&&Math.floor(a)===a)c[o++]=58,L.setUint32(o,-1-a),o+=4;else{let h;if((h=this.useFloat32)>0&&a<4294967296&&a>=-2147483648){c[o++]=250,L.setFloat32(o,a);let u;if(h<4||(u=a*lt[(c[o]&127)<<1|c[o+1]>>7])>>0===u){o+=4;return}else o--}c[o++]=251,L.setFloat64(o,a),o+=8}else if(g==="object")if(!a)c[o++]=246;else{if(l){let u=l.get(a);if(u){if(c[o++]=216,c[o++]=29,c[o++]=25,!u.references){let b=l.idsToInsert||(l.idsToInsert=[]);u.references=[],b.push(u)}u.references.push(o-r),o+=2;return}else l.set(a,{offset:o-r})}let h=a.constructor;if(h===Object)this.skipFunction===!0&&(a=Object.fromEntries([...Object.keys(a).filter(u=>typeof a[u]!="function").map(u=>[u,a[u]])])),V(a);else if(h===Array){d=a.length,d<24?c[o++]=128|d:Q(d);for(let u=0;u<d;u++)k(a[u])}else if(h===Map)if((this.mapsAsObjects?this.useTag259ForMaps!==!1:this.useTag259ForMaps)&&(c[o++]=217,c[o++]=1,c[o++]=3),d=a.size,d<24?c[o++]=160|d:d<256?(c[o++]=184,c[o++]=d):d<65536?(c[o++]=185,c[o++]=d>>8,c[o++]=d&255):(c[o++]=186,L.setUint32(o,d),o+=4),p.keyMap)for(let[u,b]of a)k(p.encodeKey(u)),k(b);else for(let[u,b]of a)k(u),k(b);else{for(let u=0,b=ut.length;u<b;u++){let S=tr[u];if(a instanceof S){let v=ut[u],x=v.tag;x==null&&(x=v.getTag&&v.getTag.call(this,a)),x<24?c[o++]=192|x:x<256?(c[o++]=216,c[o++]=x):x<65536?(c[o++]=217,c[o++]=x>>8,c[o++]=x&255):x>-1&&(c[o++]=218,L.setUint32(o,x),o+=4),v.encode.call(this,a,k,de);return}}if(a[Symbol.iterator]){if(ht){let u=new Error("Iterable should be serialized as iterator");throw u.iteratorNotHandled=!0,u}c[o++]=159;for(let u of a)k(u);c[o++]=255;return}if(a[Symbol.asyncIterator]||pt(a)){let u=new Error("Iterable/blob should be serialized as iterator");throw u.iteratorNotHandled=!0,u}if(this.useToJSON&&a.toJSON){const u=a.toJSON();if(u!==a)return k(u)}V(a)}}else if(g==="boolean")c[o++]=a?245:244;else if(g==="bigint"){if(a<BigInt(1)<<BigInt(64)&&a>=0)c[o++]=27,L.setBigUint64(o,a);else if(a>-(BigInt(1)<<BigInt(64))&&a<0)c[o++]=59,L.setBigUint64(o,-a-BigInt(1));else if(this.largeBigIntToFloat)c[o++]=251,L.setFloat64(o,Number(a));else{a>=BigInt(0)?c[o++]=194:(c[o++]=195,a=BigInt(-1)-a);let h=[];for(;a;)h.push(Number(a&BigInt(255))),a>>=BigInt(8);yt(new Uint8Array(h.reverse()),de);return}o+=8}else if(g==="undefined")c[o++]=247;else throw new Error("Unknown type: "+g)},V=this.useRecords===!1?this.variableMapSize?a=>{let g=Object.keys(a),d=Object.values(a),h=g.length;if(h<24?c[o++]=160|h:h<256?(c[o++]=184,c[o++]=h):h<65536?(c[o++]=185,c[o++]=h>>8,c[o++]=h&255):(c[o++]=186,L.setUint32(o,h),o+=4),p.keyMap)for(let u=0;u<h;u++)k(p.encodeKey(g[u])),k(d[u]);else for(let u=0;u<h;u++)k(g[u]),k(d[u])}:a=>{c[o++]=185;let g=o-r;o+=2;let d=0;if(p.keyMap)for(let h in a)(typeof a.hasOwnProperty!="function"||a.hasOwnProperty(h))&&(k(p.encodeKey(h)),k(a[h]),d++);else for(let h in a)(typeof a.hasOwnProperty!="function"||a.hasOwnProperty(h))&&(k(h),k(a[h]),d++);c[g+++r]=d>>8,c[g+r]=d&255}:(a,g)=>{let d,h=i.transitions||(i.transitions=Object.create(null)),u=0,b=0,S,v;if(this.keyMap){v=Object.keys(a).map(T=>this.encodeKey(T)),b=v.length;for(let T=0;T<b;T++){let Rt=v[T];d=h[Rt],d||(d=h[Rt]=Object.create(null),u++),h=d}}else for(let T in a)(typeof a.hasOwnProperty!="function"||a.hasOwnProperty(T))&&(d=h[T],d||(h[J]&1048576&&(S=h[J]&65535),d=h[T]=Object.create(null),u++),h=d,b++);let x=h[J];if(x!==void 0)x&=65535,c[o++]=217,c[o++]=x>>8|224,c[o++]=x&255;else if(v||(v=h.__keys__||(h.__keys__=Object.keys(a))),S===void 0?(x=i.nextId++,x||(x=0,i.nextId=1),x>=sr&&(i.nextId=(x=E)+1)):x=S,i[x]=v,x<E){c[o++]=217,c[o++]=x>>8|224,c[o++]=x&255,h=i.transitions;for(let T=0;T<b;T++)(h[J]===void 0||h[J]&1048576)&&(h[J]=x),h=h[v[T]];h[J]=x|1048576,n=!0}else{if(h[J]=x,L.setUint32(o,3655335680),o+=3,u&&(Ee+=Y*u),Z.length>=sr-E&&(Z.shift()[J]=void 0),Z.push(h),Q(b+2),k(57344+x),k(v),g)return;for(let T in a)(typeof a.hasOwnProperty!="function"||a.hasOwnProperty(T))&&k(a[T]);return}if(b<24?c[o++]=128|b:Q(b),!g)for(let T in a)(typeof a.hasOwnProperty!="function"||a.hasOwnProperty(T))&&k(a[T])},de=a=>{let g;if(a>16777216){if(a-r>nr)throw new Error("Encoded buffer would be larger than maximum buffer size");g=Math.min(nr,Math.round(Math.max((a-r)*(a>67108864?1.25:2),4194304)/4096)*4096)}else g=(Math.max(a-r<<2,c.length-1)>>12)+1<<12;let d=new dt(g);return L=new DataView(d.buffer,0,g),c.copy?c.copy(d,0,r,a):d.set(c.slice(r,a)),o-=r,r=0,re=d.length-10,c=d};let se=100,It=1e3;this.encodeAsIterable=function(a,g){return Ot(a,g,he)},this.encodeAsAsyncIterable=function(a,g){return Ot(a,g,Tt)};function*he(a,g,d){let h=a.constructor;if(h===Object){let u=p.useRecords!==!1;u?V(a,!0):or(Object.keys(a).length,160);for(let b in a){let S=a[b];u||k(b),S&&typeof S=="object"?g[b]?yield*he(S,g[b]):yield*qe(S,g,b):k(S)}}else if(h===Array){let u=a.length;Q(u);for(let b=0;b<u;b++){let S=a[b];S&&(typeof S=="object"||o-r>se)?g.element?yield*he(S,g.element):yield*qe(S,g,"element"):k(S)}}else if(a[Symbol.iterator]&&!a.buffer){c[o++]=159;for(let u of a)u&&(typeof u=="object"||o-r>se)?g.element?yield*he(u,g.element):yield*qe(u,g,"element"):k(u);c[o++]=255}else pt(a)?(or(a.size,64),yield c.subarray(r,o),yield a,Se()):a[Symbol.asyncIterator]?(c[o++]=159,yield c.subarray(r,o),yield a,Se(),c[o++]=255):k(a);d&&o>r?yield c.subarray(r,o):o-r>se&&(yield c.subarray(r,o),Se())}function*qe(a,g,d){let h=o-r;try{k(a),o-r>se&&(yield c.subarray(r,o),Se())}catch(u){if(u.iteratorNotHandled)g[d]={},o=r+h,yield*he.call(this,a,g[d]);else throw u}}function Se(){se=It,p.encode(null,gt)}function Ot(a,g,d){return g&&g.chunkThreshold?se=It=g.chunkThreshold:se=100,a&&typeof a=="object"?(p.encode(null,gt),d(a,p.iterateProperties||(p.iterateProperties={}),!0)):[p.encode(a)]}async function*Tt(a,g){for(let d of he(a,g,!0)){let h=d.constructor;if(h===rr||h===Uint8Array)yield d;else if(pt(d)){let u=d.stream().getReader(),b;for(;!(b=await u.read()).done;)yield b.value}else if(d[Symbol.asyncIterator])for await(let u of d)Se(),u?yield*Tt(u,g.async||(g.async={})):yield p.encode(u);else yield d}}}useBuffer(e){c=e,L=new DataView(c.buffer,c.byteOffset,c.byteLength),o=0}clearSharedData(){this.structures&&(this.structures=[]),this.sharedValues&&(this.sharedValues=void 0)}updateSharedData(){let e=this.sharedVersion||0;this.sharedVersion=e+1;let r=this.structures.slice(0),s=new ar(r,this.sharedValues,this.sharedVersion),n=this.saveShared(s,i=>(i&&i.version||0)==e);return n===!1?(s=this.getShared()||{},this.structures=s.structures||[],this.sharedValues=s.packedValues,this.sharedVersion=s.version,this.structures.nextId=this.structures.length):r.forEach((i,l)=>this.structures[l]=i),n}}function or(t,e){t<24?c[o++]=e|t:t<256?(c[o++]=e|24,c[o++]=t):t<65536?(c[o++]=e|25,c[o++]=t>>8,c[o++]=t&255):(c[o++]=e|26,L.setUint32(o,t),o+=4)}class ar{constructor(e,r,s){this.structures=e,this.packedValues=r,this.version=s}}function Q(t){t<24?c[o++]=128|t:t<256?(c[o++]=152,c[o++]=t):t<65536?(c[o++]=153,c[o++]=t>>8,c[o++]=t&255):(c[o++]=154,L.setUint32(o,t),o+=4)}const sn=typeof Blob>"u"?function(){}:Blob;function pt(t){if(t instanceof sn)return!0;let e=t[Symbol.toStringTag];return e==="Blob"||e==="File"}function $e(t,e){switch(typeof t){case"string":if(t.length>3){if(e.objectMap[t]>-1||e.values.length>=e.maxValues)return;let s=e.get(t);if(s)++s.count==2&&e.values.push(t);else if(e.set(t,{count:1}),e.samplingPackedValues){let n=e.samplingPackedValues.get(t);n?n.count++:e.samplingPackedValues.set(t,{count:1})}}break;case"object":if(t)if(t instanceof Array)for(let s=0,n=t.length;s<n;s++)$e(t[s],e);else{let s=!e.encoder.useRecords;for(var r in t)t.hasOwnProperty(r)&&(s&&$e(r,e),$e(t[r],e))}break;case"function":console.log(t)}}const nn=new Uint8Array(new Uint16Array([1]).buffer)[0]==1;tr=[Date,Set,Error,RegExp,le,ArrayBuffer,Uint8Array,Uint8ClampedArray,Uint16Array,Uint32Array,typeof BigUint64Array>"u"?function(){}:BigUint64Array,Int8Array,Int16Array,Int32Array,typeof BigInt64Array>"u"?function(){}:BigInt64Array,Float32Array,Float64Array,ar],ut=[{tag:1,encode(t,e){let r=t.getTime()/1e3;(this.useTimestamp32||t.getMilliseconds()===0)&&r>=0&&r<4294967296?(c[o++]=26,L.setUint32(o,r),o+=4):(c[o++]=251,L.setFloat64(o,r),o+=8)}},{tag:258,encode(t,e){let r=Array.from(t);e(r)}},{tag:27,encode(t,e){e([t.name,t.message])}},{tag:27,encode(t,e){e(["RegExp",t.source,t.flags])}},{getTag(t){return t.tag},encode(t,e){e(t.value)}},{encode(t,e,r){yt(t,r)}},{getTag(t){if(t.constructor===Uint8Array&&(this.tagUint8Array||Me&&this.tagUint8Array!==!1))return 64},encode(t,e,r){yt(t,r)}},X(68,1),X(69,2),X(70,4),X(71,8),X(72,1),X(77,2),X(78,4),X(79,8),X(85,4),X(86,8),{encode(t,e){let r=t.packedValues||[],s=t.structures||[];if(r.values.length>0){c[o++]=216,c[o++]=51,Q(4);let n=r.values;e(n),Q(0),Q(0),packedObjectMap=Object.create(sharedPackedObjectMap||null);for(let i=0,l=n.length;i<l;i++)packedObjectMap[n[i]]=i}if(s){L.setUint32(o,3655335424),o+=3;let n=s.slice(0);n.unshift(57344),n.push(new le(t.version,1399353956)),e(n)}else e(new le(t.version,1399353956))}}];function X(t,e){return!nn&&e>1&&(t-=4),{tag:t,encode:function(s,n){let i=s.byteLength,l=s.byteOffset||0,y=s.buffer||s;n(Me?je.from(y,l,i):new Uint8Array(y,l,i))}}}function yt(t,e){let r=t.byteLength;r<24?c[o++]=64+r:r<256?(c[o++]=88,c[o++]=r):r<65536?(c[o++]=89,c[o++]=r>>8,c[o++]=r&255):(c[o++]=90,L.setUint32(o,r),o+=4),o+r>=c.length&&e(o+r),c.set(t.buffer?t:new Uint8Array(t),o),o+=r}function on(t,e){let r,s=e.length*2,n=t.length-s;e.sort((i,l)=>i.offset>l.offset?1:-1);for(let i=0;i<e.length;i++){let l=e[i];l.id=i;for(let y of l.references)t[y++]=i>>8,t[y]=i&255}for(;r=e.pop();){let i=r.offset;t.copyWithin(i+s,i,n),s-=2;let l=i+s;t[l++]=216,t[l++]=28,n=i}return t}function cr(t,e){L.setUint32(j.position+t,o-j.position-t+1);let r=j;j=null,e(r[0]),e(r[1])}let wt=new ir({useRecords:!1});const an=wt.encode;wt.encodeAsIterable,wt.encodeAsAsyncIterable;const lr=512,cn=1024,gt=2048;class ln extends jr{constructor(e){e||(e={}),e.objectMode=!0,super(e),e.structures=[],this.decoder=e.decoder||new be(e)}_transform(e,r,s){this.incompleteBuffer&&(e=Buffer.concat([this.incompleteBuffer,e]),this.incompleteBuffer=null);let n;try{n=this.decoder.decodeMultiple(e)}catch(i){if(i.incomplete)this.incompleteBuffer=e.slice(i.lastPosition),n=i.values;else return s(i)}finally{for(let i of n||[])i===null&&(i=this.getNullValue()),this.push(i)}s()}getNullValue(){return Symbol.for(null)}}const fn=process.env.CBOR_NATIVE_ACCELERATION_DISABLED!==void 0&&process.env.CBOR_NATIVE_ACCELERATION_DISABLED.toLowerCase()==="true";if(!fn){let t;try{typeof require=="function"?t=require("cbor-extract"):t=$r(import.meta.url)("cbor-extract"),t&&Ks(t.extractStrings)}catch{}}const fr=["light","dark"],ur=["xs","s","m","l","xl","xxl","xxxl"];function un(t){return{adbShellCommand:t.android?.shell,appearance:t.appearance,deviceType:t.id,disableVirtualKeyboard:t.android?.softKeyboard===!1?!0:void 0,fontSize:t.fontSize,iosAutocorrect:t.ios?.autocorrect,iosKeyboard:t.ios?.keyboards,language:t.locale,locale:t.locale,location:t.location&&[t.location.latitude,t.location.longitude],orientation:t.orientation,osVersion:t.osVersion,timezone:t.timezone}}const dn=["grant"];function hn(t){return{grantPermissions:t?.permissions==="grant"?!0:void 0,launchApp:t?.app,launchArgs:t?.ios?.args,launchUrl:t?.url,params:t?.params}}class dr extends Error{code;issues;constructor(e,r,s=[]){super(r),this.name="SessionRequestError",this.code=e,this.issues=s}}const C=t=>`expected ${t}`,ge=t=>m.string(C(t)).check(m.minLength(1,C(t))),Ue=t=>m.literal(t,C(`one of ${t.join(", ")}`)),me=t=>m.object(t,C("an object")),hr=()=>m.boolean(C("true or false")),pr=t=>m.number(C("a number")).check(m.gte(-t,C(`at least -${String(t)}`)),m.lte(t,C(`at most ${String(t)}`))),pn=/^\w{2}(?:_\w{2})?@sw(=[\w-]+)?$/,yn=/^[a-z0-9_.=:/ ()"-]+$/i,wn='letters, digits or _ . = : / ( ) " - and spaces',gn=/^[A-Za-z]{2,3}([-_][A-Za-z0-9]{2,8})*$/;function mn(t){if(!gn.test(t))return!1;try{return new Intl.Locale(t.replaceAll("_","-")),!0}catch{return!1}}function bn(t){try{return new Intl.DateTimeFormat(void 0,{timeZone:t}),!0}catch{return!1}}const mt={code:"needsTarget"},yr={code:"needsLaunchApp"},bt="has no effect without a target",wr="has no effect without a target, or with launch.app: false";function gr({launch:t}){return t?.app!==!1}const En=m.object({apiToken:m.optional(ge("an API token")),codec:m.optional(Ue(Qr)),device:me({android:m.optional(me({shell:m.optional(ge("a shell command")),softKeyboard:m.optional(hr())})),appearance:m.optional(Ue(fr)),fontSize:m.optional(Ue(ur)),id:ge("a device id"),ios:m.optional(me({autocorrect:m.optional(hr()),keyboards:m.optional(m.array(m.string(C("a keyboard layout")).check(m.regex(pn,C("a layout like en_US@sw=QWERTY"))),C("a list of keyboard layouts")))})),locale:m.optional(m.string(C("a BCP 47 tag, e.g. fr-CA")).check(m.refine(mn,{error:C("a BCP 47 tag, e.g. fr-CA")}))),location:m.optional(me({latitude:pr(90),longitude:pr(180)})),orientation:m.optional(Ue(_t)),osVersion:m.optional(ge("an OS version")),timezone:m.optional(m.string(C("an IANA timezone")).check(m.refine(bn,{error:C("an IANA timezone, e.g. America/Toronto")})))}),endpoint:m.optional(m.url(C("a URL"))),launch:m.optional(me({app:m.optional(m.union([ge("an app id"),m.literal(!1)],C("an app id or false"))),ios:m.optional(me({args:m.optional(m.array(m.string(C("an argument")).check(m.regex(yn,C(wn))),C("a list of arguments")).check(m.maxLength(20,C("at most 20 arguments"))))})),params:m.optional(m.custom(t=>typeof t=="object"&&t!==null&&!Array.isArray(t),C("an object"))),permissions:m.optional(Ue(dn)),url:m.optional(m.url(C("a URL")))})),proxy:m.optional(m.union([m.literal("intercept"),m.templateLiteral(["http://",m.string()])],C("intercept or an http:// URL"))),target:m.optional(ge("an app, build or group id"))}).check(m.refine(t=>t.device.android?.shell===void 0||t.target!==void 0,{error:bt,params:mt,path:["device","android","shell"]}),m.refine(t=>t.launch?.app===void 0||t.target!==void 0,{error:bt,params:mt,path:["launch","app"]}),m.refine(t=>t.launch?.permissions===void 0||t.target!==void 0,{error:bt,params:mt,path:["launch","permissions"]}),m.refine(t=>t.launch?.params===void 0||t.target!==void 0&&gr(t),{error:wr,params:yr,path:["launch","params"]}),m.refine(t=>t.launch?.ios?.args===void 0||t.target!==void 0&&gr(t),{error:wr,params:yr,path:["launch","ios","args"]}));function Sn(t){if(t.code==="custom"){const e=t.params?.code;if(e==="needsTarget"||e==="needsLaunchApp")return e}return"invalidValue"}function vn(t){const e=En.safeParse(t);if(e.success)return;const r=e.error.issues.map(s=>({code:Sn(s),message:s.message,path:s.path.join(".")}));throw new dr("invalid",r.map(({message:s,path:n})=>`${n}: ${s}`).join(`
2
- `),r)}const An={dateStyle:"medium",timeStyle:"short"},xn=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(?::\d{2}(?:\.\d+)?)?(?:Z|[+-]\d{2}:\d{2})$/;function Ve(t){return Array.isArray(t)?t.map(Ve).join(", "):typeof t=="boolean"?t?"yes":"no":typeof t=="number"?t.toLocaleString():kn(t)}function kn(t){if(xn.test(t)){const r=new Date(t);if(!Number.isNaN(r.getTime()))return r.toLocaleString(void 0,An)}const e=Ut();return t===e?"~":t.startsWith(`${e}${Fr}`)?`~${t.slice(e.length)}`:t}function mr(){return process.env.APPETIZE_CLI_HOME??ne(Ut(),".appetize","cli","sessions")}function Et(t){return ne(mr(),t)}class Ke extends Error{details;constructor(e,r={},s){super(e,s===void 0?void 0:{cause:s}),this.name="CommandError",this.details=r}hints(e){return[]}}class Pe extends Ke{sessionDir;constructor(e,{cause:r,details:s={},sessionId:n}){const i=Et(n);super(e,Object.assign({sessionDir:i},s),r),this.name="SessionError",this.sessionDir=i}static wrap(e,r){if(e instanceof Pe||e instanceof ue)return e;const s=e instanceof Error?e.message:String(e),n=e instanceof Ke?e.details:{};return new Pe(s,{cause:e,details:n,sessionId:r})}hints(){return[`Check the session logs for details: ${Ve(this.sessionDir)}`]}}class In extends Pe{constructor(e){super(`Session ${e} already exists`,{sessionId:e}),this.name="SessionAlreadyExistsError"}hints(){return[`Pass --force to replace it, deleting ${Ve(this.sessionDir)}`]}}class ue extends Ke{#e;constructor(e,r=[]){super(e),this.name="UsageError",this.#e=r}hints({command:e}){return[...this.#e,`Run 'appetize ${e} --help' for usage`]}}function On(t,e,r){const s=e instanceof Error?e.message:String(e);if(!(e instanceof Ke))return t==="json"?JSON.stringify({error:{message:s}},null,2):`\u2716 ${s}`;const n=e.hints(r);if(t==="json"){const i=n.length>0?{hints:n}:{};return JSON.stringify({error:{message:s,...e.details,...i}},null,2)}return[`\u2716 ${s}`,...n.map(i=>` ${i}`)].join(`
3
- `)}function St(t){try{return process.kill(t,0),!0}catch{return!1}}const Tn=["SIGINT","SIGTERM"],Rn=150;function Mn(t){const e=new AbortController,r=setInterval(()=>{St(t)||(clearInterval(r),e.abort(new Error("The device session exited")))},Rn);return r.unref(),e.signal}function br(){const t=new AbortController;for(const e of Tn)process.once(e,()=>{t.abort(new Error(`Received ${e}`))});return t.signal}function Un(t,e){return new Promise((r,s)=>{if(e.aborted){s(Er(e.reason));return}const n=()=>{clearTimeout(i),s(Er(e.reason))},i=setTimeout(()=>{e.removeEventListener("abort",n),r()},t);e.addEventListener("abort",n,{once:!0})})}function Er(t){return t instanceof Error?t:new Error(String(t))}function Ln(t,{defaultValue:e=!1}={}){return t===!e?!e:void 0}function Pn(t){const e=t.at(-1);return{options:Nn(e)?e:{},positionals:t.slice(0,-1).filter(r=>typeof r=="string"),signal:br()}}function Cn(t,e){const r=Sr(t,e);return r===void 0?void 0:vr(r,e)}function Sr(t,e){if(t===void 0)return;const r=typeof t=="boolean"?Number.NaN:Number(t);if(!Number.isFinite(r))throw new ue(`${e} expects a number, e.g., ${e}=-0.1`);return r}function vt(t,e){if(t!==void 0){if(typeof t!="string"||t==="")throw new ue(`${e} needs a value`);return t}}function vr(t,e){if(!(t>=0&&t<=1))throw new ue(`${e} expects a number between 0 and 1`);return t}function _n(t,e){const r=vt(t,e);if(r===void 0)throw new ue(`${e} needs a value`);return r}function Nn(t){return typeof t=="object"&&t!==null}const Dn="APPETIZEIO_FEATURE_FLAGS";function Bn(){const t={};for(const e of(process.env[Dn]??"").split(",")){const r=e.trim();r!==""&&(t[r]=!0)}return t}function zn(){const t=process.env.APPETIZE_API_TOKEN;if(!t)throw new Error("APPETIZE_API_TOKEN must be set");return t}function Ar(t){return vt(t.endpoint,"--endpoint")??Fn()}function Fn(){const t=process.env.APPETIZE_ENDPOINT?.trim();return t===""?void 0:t}const jn="https://appetize.io";async function xr(t,{authorize:e=!0,commandOptions:r={},query:s={},...n}={}){const i=new URL(t,Ar(r)??jn);for(const[p,A]of Object.entries(s))i.searchParams.set(p,A);const l=new Headers(n.headers);e&&l.set("x-api-key",zn());const y=await fetch(i,{...n,headers:l});if(!y.ok)throw new Error(`The webserver rejected the request (${String(y.status)})`);return await y.json()}const kr=["android","ios"];function Ir(t={},e){return xr("/api/v2/service/devices",{authorize:!1,commandOptions:t,signal:e})}function $n(t){return kr.includes(t)}async function Vn(t,e={}){return(await Ir(e)).find(s=>s.id===t)?.platform}function Kn(t){let e={...t,updatedAt:new Date().toISOString()};return{path:xt(e.sessionId),save:r=>(e={...e,...r,updatedAt:new Date().toISOString()},Qn(e),e)}}function Or(t){const e=t.state?.phase;return e==="ended"||e==="error"?!1:St(t.pid)}function qn(){const t=mr();return Mt(t,{recursive:!0}),zr(t).map(e=>At(e)).filter(e=>e!==void 0)}function Wn(t){if(t!==void 0){const r=At(t);if(!r)throw new Error(`No session found for id ${t}`);return r}const e=qn().filter(Or);if(e.length===0)throw new Error("No active sessions");if(e.length>1)throw new ue("There are multiple active sessions",["Specify --session-id to pick one"]);return e[0]}function At(t){try{return JSON.parse(Dr(xt(t),"utf8"))}catch{return}}function Jn(t){Br(Et(t),{force:!0,recursive:!0})}function Gn(t){return ne(Le(t),"control.sock")}function Tr(t){return ne(Le(t),"daemon.log")}function Hn(t){return ne(Le(t),"device.log.jsonl")}function Zn(t,e){return{daemon:Tr(t),device:Hn(t),...e==="intercept"?{network:Yn(t)}:void 0}}function Yn(t){return ne(Le(t),"network.jsonl")}function Le(t){const e=Et(t);return Mt(e,{recursive:!0}),e}function xt(t){return ne(Le(t),"state.json")}function Qn(t){const e=xt(t.sessionId),r=`${e}.tmp`;_r(r,`${JSON.stringify(t,null,2)}
4
- `),Nr(r,e)}const kt="APPETIZE_DAEMON_CONFIG";function Xn(){const t=process.env[kt];if(!t)throw new Error(`${kt} is not set`);return JSON.parse(t)}function ei(t){return JSON.stringify(t)}function ti(){let t,e;return{promise:new Promise((s,n)=>{e=s,t=n}),reject:t,resolve:e}}const Rr={useRecords:!1},ri=new ir(Rr);class Mr extends ve{#e=[];#t;constructor(e,{signal:r}={}){super(async l=>{this.#t.write(ri.encode(l))},{signal:r}),this.#t=e;const s=new ln(Rr);s.on("data",l=>{Ye(l)&&this[U].dispatchMessage(l)}),s.on("error",()=>{this.close()});const n=l=>{s.write(l)},i=()=>{this.close()};e.on("data",n),e.once("close",i),e.once("error",i),this.#e.push(()=>{e.off("data",n),e.off("close",i),e.off("error",i),s.destroy()})}handleClose(e){for(const r of this.#e.splice(0))r();super.handleClose(e)}}function si(t,e){const{promise:r,reject:s,resolve:n}=ti(),i=Vr(t),l=e?.signal,y=()=>{i.off("connect",E),i.off("error",R),l?.removeEventListener("abort",A)},p=M=>{y(),i.destroy(),s(M)},A=()=>{p(new Error("The connection was aborted"))},E=()=>{y();const M=new Mr(i,e);M[U].addEventListener("close",()=>{i.destroy()},{once:!0}),n(M)},R=M=>{p(M)};return l?.aborted?(p(new Error("The connection was aborted")),r):(i.once("connect",E),i.once("error",R),l?.addEventListener("abort",A,{once:!0}),r)}export{Gn as $,Zn as A,Cn as B,Ve as C,kt as D,si as E,Bs as F,Pt as G,Wn as H,Pn as I,On as J,He as K,an as L,U as M,en as N,Ye as O,Vt as P,Ne as Q,hn as R,Pe as S,ve as T,ue as U,un as V,Ge as W,Mr as X,Xn as Y,Kn as Z,Vn as _,Sr as a,br as a0,Ir as b,kr as c,Un as d,jt as e,xr as f,_n as g,_t as h,$n as i,Tr as j,Or as k,St as l,Mn as m,Ln as n,ur as o,vt as p,fr as q,vr as r,ei as s,dr as t,Bn as u,vn as v,Ar as w,At as x,In as y,Jn as z};
1
+ import Je from"debug";import{JSONRPCServerAndClient as Cr,JSONRPCServer as Pr,JSONRPCClient as _r,JSONRPC as Nr}from"json-rpc-2.0";import*as m from"zod/mini";import{writeFileSync as Dr,renameSync as Br,mkdirSync as Mt,readFileSync as zr,rmSync as Fr,readdirSync as jr}from"node:fs";import{sep as $r,join as ie}from"node:path";import{homedir as Ut}from"node:os";import{Transform as Vr}from"stream";import{createRequire as Kr}from"module";import{connect as qr}from"node:net";class Wr extends Event{code;reason;wasClean;constructor(e,r={}){super(e,r),this.code=r.code??0,this.reason=r.reason??"",this.wasClean=r.wasClean??!1}}function Jr(t,e){const r="CloseEvent"in globalThis?globalThis.CloseEvent:Wr;return new r(t,e)}class Gr{#e=new EventTarget;addEventListener(e,r,s){return this.#e.addEventListener(e,r,s),()=>{this.#e.removeEventListener(e,r,s)}}removeEventListener(e,r,s){this.#e.removeEventListener(e,r,s)}dispatchEvent(e){return this.#e.dispatchEvent(e)}}const U=Symbol.for("@appetizeio/rpc:rpcMethods");class Hr extends Gr{send;constructor(e){super(),this.send=e}dispatchClose(e){return this.dispatchEvent(Jr("close",e))}dispatchMessage(e){return this.dispatchEvent(new CustomEvent("message",{detail:e}))}}const Zr="@appetizeio/rpc:playwrightAdapter";class ve{closed=!1;[U];#e;constructor(e,{signal:r}={}){this[U]=new Hr(e),this.#e=r,this.#e?.addEventListener("abort",this.#t)}close(e={}){this.closed||(this.closed=!0,this.handleClose(e))}handleClose(e){this.#e?.removeEventListener("abort",this.#t),this[U].dispatchClose(e)}#t=()=>{this.close({code:1e3,reason:String(this.#e?.reason)})}}const Pe=Symbol.for(Zr);function Yr(t){window[Pe]&&console.warn("playwright exposed more than once, overwriting previous adapter");const e={send(r){t[U].send(r)},subscribe(r){return t[U].addEventListener("message",s=>{r(s.detail)})}};return window[Pe]=e,()=>{window[Pe]===e&&delete window[Pe]}}const Lt=Je("appetize.io:error:rpc");function Ge(t,e){const r=new Cr(new Pr({errorListener:Lt}),Qr(t),{errorListener:Lt}),s=t[U].addEventListener("message",({detail:i})=>{r.receiveAndSend(i)}),n=t[U].addEventListener("close",()=>{s(),r.rejectAllPendingRequests("Transport closed")},{once:!0});for(const i in e){const l=e[i];l&&r.addMethod(i,l.bind(e))}return{rpc:r,unsub:()=>{s(),n()}}}function Ct(t,e){const{rpc:r,unsub:s}=Ge(t,e);return{client:r.client,unsub:s}}function _e(t,e){const r=t[U].addEventListener("message",({detail:n})=>{if("method"in n)try{e({method:n.method,param:n.params})}catch{}}),s=t[U].addEventListener("close",r,{once:!0});return()=>{r(),s()}}function Qr(t){return new _r(t[U].send.bind(t[U]),()=>Math.floor(Math.random()*Number.MAX_SAFE_INTEGER)+1)}function He(t,e,{leftEffects:r=()=>({}),notifiesLeft:s,notifiesRight:n,rightEffects:i=()=>({})}={}){const l=Ge(t,{}),y=Ge(e,{}),p=[()=>{l.unsub(),y.unsub()}],A=()=>{for(const _ of p)try{_()}catch{}},E=y.rpc.client,R=l.rpc.client;p.push(t[U].addEventListener("close",()=>{A()},{once:!0}),e[U].addEventListener("close",()=>{A()},{once:!0}));const M=r(E,R);for(const _ in M){const C=M[_];C&&l.rpc.addMethod(_,C)}const N=i(R,E);for(const _ in N){const C=N[_];C&&y.rpc.addMethod(_,C)}return Pt(l.rpc,y.rpc,{notifies:s}),Pt(y.rpc,l.rpc,{notifies:n}),A}function Pt(t,e,{notifies:r}={}){t.applyServerMiddleware(async(s,n)=>{const i=r?.();if(i){const{id:y,...p}=n;i[U].send(p)}if(t.hasMethod(n.method))return await s(n);if(!n.id)return e.notify(n.method,n.params),null;const l=await e.request(n.method,n.params);return{id:n.id,jsonrpc:Nr,result:l}})}function ee(t,...e){t.notify(e[0],e[1],e[2])}const Xr=(...t)=>Ct(...t),es=["h264","jpeg"],Ze=["ArrowDown","ArrowLeft","ArrowRight","ArrowUp","Backspace","Enter","Tab"],_t=["landscapeLeft","landscapeRight","portrait","upsideDown"];function Ye(){const t=new ve(async r=>{e[U].dispatchMessage(r)}),e=new ve(async r=>{t[U].dispatchMessage(r)});return t[U].addEventListener("close",()=>{e.close()},{once:!0}),e[U].addEventListener("close",()=>{t.close()},{once:!0}),[t,e]}function Nt(t,e){const r=[],s=()=>{for(const n of r)n()};r.push(t[U].addEventListener("message",n=>e[U].send(n.detail))),r.push(t[U].addEventListener("close",s,{once:!0})),r.push(e[U].addEventListener("message",n=>t[U].send(n.detail))),r.push(e[U].addEventListener("close",s,{once:!0}))}function Qe(t){return!!t&&typeof t=="object"&&"jsonrpc"in t}const oe=Je("appetize.io:trace:transport:iframe");class Dt extends ve{onmessage;#e;#t;constructor(e,{origin:r="*",signal:s}={}){super(async n=>{e.postMessage(n,this.#e)},{signal:s}),this.#t=e,this.#e=r,window.addEventListener("message",this.#r)}postMessage(e,r,s){oe("postMessage(legacy)",{message:e,targetOrigin:r,transfer:s}),this.#t.postMessage(e,r??this.#e,s)}handleClose(e){oe("close()"),window.removeEventListener("message",this.#r),super.handleClose(e)}#r=async e=>{if(oe("handleMessage()",e),e.source!==this.#t||(oe("handleMessage() -> source ok"),this.#e!=="*"&&e.origin!==this.#e))return;oe("handleMessage() -> origin ok");const r=e.data;if(!Qe(r)){oe("handleMessage() -> legacy"),this.onmessage?.(e);return}oe("handleMessage() -> jsonrpc"),this[U].dispatchMessage(r)}}function Ne(){let t,e;return{promise:new Promise((s,n)=>{e=s,t=n}),reject:t,resolve:e}}const ts=2*1024*1024,Bt=Je("appetize:client:acked-writable-stream");class rs{unacked=0;#e;#t;#r;#s;#n=[];#o;constructor(e){this.#r=e,this.#o=e.window??ts}abort(e){this.#i(e),this.#r.onAbort?.(e)}async close(){await this.#c(()=>this.unacked===0),this.#r.onClose?.()}fail(e){this.#i(e)&&this.#r.onError?.(e)}start(e){this.#e=e}write(e){const r=e.byteLength;return this.unacked+=r,this.#r.send(e).then(()=>{this.unacked-=r,this.#s&&(this.#s.acked+=r),this.#a()},s=>{this.fail(s)}),this.unacked>=this.#o&&!this.#s&&(this.#s={acked:0,at:performance.now()},Bt("window full: %d bytes unacked, writes stalled",this.unacked)),this.#c(()=>this.unacked<this.#o)}#a(){if(this.#s&&this.unacked<=this.#o/2){const e=performance.now()-this.#s.at;Bt("pressure relieved after %dms: %d bytes acked, %s MB/s",Math.round(e),this.#s.acked,(this.#s.acked/Math.max(e,1)/1e3).toFixed(2)),this.#s=void 0}this.#n=this.#n.filter(e=>e.until()?(e.resolve(void 0),!1):!0)}#i(e){if(this.#t)return!1;this.#t={reason:e},this.#e.error(e);const r=this.#n;this.#n=[];for(const s of r)s.reject(e);return!0}#c(e){if(e())return Promise.resolve();const r={...Ne(),until:e};return this.#n.push(r),r.promise}}class ss extends WritableStream{get unacked(){return this.#e.unacked}#e;constructor(e){const r=new rs(e);super({abort:s=>{r.abort(s)},close:()=>r.close(),start:s=>{r.start(s)},write:s=>r.write(s)}),this.#e=r}fail(e){this.#e.fail(e)}}const ns=1024*1024;class is{#e;#t=!1;#r;#s;constructor(e){this.#r=e}cancel(e){this.#n(),this.#r?.(e)}close(){this.#n()&&this.#e.close()}error(e){this.#n()&&this.#e.error(e)}pull(){const e=this.#s;this.#s=void 0,e?.resolve(void 0)}async push(e){if(this.#t)return;this.#s??=Ne();const{promise:r}=this.#s;this.#e.enqueue(e),await r}start(e){this.#e=e}#n(){return this.#t?!1:(this.#t=!0,this.pull(),!0)}}class os extends ReadableStream{#e;constructor({highWaterMark:e=ns,onCancel:r}={}){const s=new is(r);super({cancel:n=>{s.cancel(n)},pull:()=>{s.pull()},start:n=>{s.start(n)}},new ByteLengthQueuingStrategy({highWaterMark:e})),this.#e=s}close(){this.#e.close()}error(e){this.#e.error(e)}push(e){return this.#e.push(e)}}class as{closed;readable;writable;#e=[];#t;#r;#s;#n;#o;#a="starting";constructor(e,{onClose:r,receiveBuffer:s,sendWindow:n,signal:i}){if(this.#o=e,this.#t=Ne(),this.closed=this.#t.promise,this.closed.catch(cs),this.#s=new os({highWaterMark:s,onCancel:()=>{this.#i(void 0)}}),this.readable=this.#s,this.#n=new ss({onAbort:()=>{this.#i(void 0)},onClose:()=>{this.#i(void 0)},onError:l=>{this.#i(l)},send:l=>e.request("appetizeio.device.server.debug.adbTunnel.data",{data:l}),window:n}),this.writable=this.#n,i){const l=()=>{this.#i(i.reason)};i.addEventListener("abort",l,{once:!0}),this.#e.push(()=>{i.removeEventListener("abort",l)})}this.#e.push(()=>{r(this)})}close=()=>{this.#i(void 0)};detach(){this.#i(void 0,{notifyServer:!1})}async handleData(e){this.#a==="open"&&await this.#s.push(e)}handleStopped({error:e}){this.#a==="open"&&this.#i(e?new Error(e):void 0)}async start(){try{await this.#o.request("appetizeio.device.server.debug.adbTunnel.start",void 0)}catch(e){throw this.#i(e),e}if(this.#a==="closed")throw this.#r?this.#r:new Error("The adb tunnel closed before it started");this.#a="open"}async[Symbol.asyncDispose](){this.close();try{await this.closed}catch{}}#i(e,{notifyServer:r=!0}={}){if(this.#a!=="closed"){this.#a="closed",this.#r=e,r&&ee(this.#o,"appetizeio.device.server.debug.adbTunnel.stop",void 0),e?(this.#s.error(e),this.#n.fail(e)):(this.#s.close(),this.#n.fail(new Error("The adb tunnel has stopped")));for(const s of this.#e)s();e?this.#t.reject(e):this.#t.resolve(void 0)}}}function cs(){}class ls{readable;ready;#e=[];#t=!1;#r;#s;#n;constructor({label:e,onClose:r,signal:s}){this.#s=e,this.ready=new Promise((i,l)=>{this.#n={reject:l,resolve:i}});let n;if(this.readable=new ReadableStream({cancel:()=>{this.#a()},start:i=>{n=i}}),!n)throw new Error("ReadableStream controller was not initialized");if(this.#r=n,s){const i=()=>{this.fail(s.reason)};s.addEventListener("abort",i,{once:!0}),this.#e.push(()=>{s.removeEventListener("abort",i)})}this.#e.push(()=>{r(this)})}close=()=>{this.#o()};fail(e){this.#o(e)}handleItem(e){this.#r.enqueue(e)}markReady(){if(!this.#n)return;const{resolve:e}=this.#n;this.#n=void 0,e(this)}async*[Symbol.asyncIterator](){const e=this.readable.getReader();try{for(let r=await e.read();!r.done;r=await e.read())yield r.value}finally{await e.cancel()}}#o(e){this.#t||(this.#r.close(),this.#a(e))}#a(e){this.#t=!0;for(const r of this.#e)r();this.#n?.reject(e??new Error(`${this.#s} closed before it started`)),this.#n=void 0}}class fs{get subscribers(){return this.#r}#e;#t;#r=new Set;constructor(e){this.#e=e}close(){this.#t=void 0;for(const e of[...this.#r])e.close();this.#r.clear()}add(e){this.#r.add(e)}ensureStarted(){return this.#t||(this.#t=(async()=>{try{return await this.#e.start()}catch(e){throw this.#t=void 0,e}})()),this.#t}release(e){this.#r.delete(e),!(this.#r.size>0||!this.#t)&&(this.#t=void 0,this.#e.stop())}}class zt extends fs{#e;constructor(e){super({start:e.start,stop:e.stop}),this.#e=e.label}async createStream({signal:e}={}){e?.throwIfAborted();const r=new ls({label:this.#e,onClose:s=>{this.release(s)},signal:e});this.add(r);try{await this.ensureStarted(),r.markReady()}catch(s){r.fail(s)}return await r.ready}handleNotification(e){for(const r of this.subscribers)r.handleItem(e)}}class us{#e;#t;#r;#s;constructor(e){this.#s=e,this.#t=new zt({label:"Log stream",start:()=>e.request("appetizeio.device.server.debug.log.start"),stop:()=>{ee(e,"appetizeio.device.server.debug.log.stop",void 0)}}),this.#r=new zt({label:"Proxy intercept stream",start:()=>e.request("appetizeio.device.server.debug.proxyIntercept.start"),stop:()=>{ee(e,"appetizeio.device.server.debug.proxyIntercept.stop",void 0)}})}close(){this.#e?.detach(),this.#t.close(),this.#r.close()}async createAdbTunnel({signal:e}={}){e?.throwIfAborted(),this.#e?.close();const r=new as(this.#s,{onClose:()=>{this.#e=void 0},signal:e});return this.#e=r,await r.start(),r}async createLogStream(e){return await this.#t.createStream(e)}async createProxyInterceptStream(e){return await this.#r.createStream(e)}async handleAdbTunnelData({data:e}){await this.#e?.handleData(e)}handleAdbTunnelStopped(e){this.#e?.handleStopped(e)}handleLogEntry(e){this.#t.handleNotification(e)}handleProxyInterceptEvent(e){this.#r.handleNotification(e)}}function Xe(t){return{...ds(t),index:t.index,within:t.within?Xe(t.within):void 0}}function ds(t){switch(t.by){case"testId":return{by:"testId",testId:t.testId};case"text":return{by:"text",text:hs(t.text)}}}function hs(t){return typeof t=="string"?{kind:"exact",value:t}:{flags:t.flags,kind:"regex",source:t.source}}const ps=400,Ft=["byTestId","byText","duration","index","x","y"],ys=new Set(Ft),ws=/^-?(?:\d+(?:\.\d*)?|\.\d+)$/u,gs=/^[a-z]$/u,et=/^\s$/u;class D extends SyntaxError{constructor(e,r,s){super(`${e} at position ${String(r)}`,{cause:s})}}class ms{#e=0;#t;constructor(e){this.#t=e}parse(){const e=[];for(;this.#e<this.#t.length;){const r=this.#i();if(et.test(r))this.#e++;else if(r===">"){if(this.#t.charAt(this.#e+1)===">")throw new D('Force press ">>" is not supported',this.#e);this.#e++,e.push({kind:"down"})}else if(r==="/")this.#e++,e.push({kind:"up"});else if(r==="{")e.push(this.#o());else{const[s]=this.#t.slice(this.#e,this.#e+2);throw new D(`Unexpected ${JSON.stringify(s)}; write selectors as {...}`,this.#e)}}return e}#r(){const e=this.#e,r=this.#c(s=>s!=="="&&!tt(s));if(this.#i()!=="=")return{kind:"bare",name:r,offset:e};if(r.length===0)throw new D('Expected an attribute name before "="',e);return this.#e++,{kind:"attribute",name:r,offset:e,value:this.#a()}}#s(){const e=this.#e;this.#e++;let r="";for(;;){const s=this.#i();if(this.#e++,s==='"')return r;if(s==="\\"){const n=this.#i();if(n!=='"'&&n!=="\\"&&n!=="")throw new D('Only \\" and \\\\ escapes are supported',this.#e-1);this.#e++,r+=n}else{if(s==="")throw new D("Unclosed string",e);r+=s}}}#n(){const e=this.#e;this.#e++;let r="",s=!1;for(;;){const i=this.#i();if(i==="")throw new D("Unclosed regex",e);if(this.#e++,i==="/"&&!s)break;r+=i,i==="\\"?(r+=this.#i(),this.#e++):i==="["?s=!0:i==="]"&&(s=!1)}const n=this.#c(i=>gs.test(i));try{return new RegExp(r,n)}catch(i){throw new D(`Invalid regex /${r}/${n}`,e,i)}}#o(){const e=this.#e;this.#e++;let r;const s={offsets:{}};for(let n=0;;n++){this.#l();const i=this.#i();if(i==="")throw new D('Unclosed "{"',e);if(i==="}"){if(this.#e++,n===0)throw new D('Expected a selector or wait in "{}"',e);return r===void 0?Ss(s,e):{duration:r,kind:"wait"}}const l=this.#r();if(n===0&&l.name==="wait")r=l.kind==="attribute"?$t(l.value,"wait"):ps;else{if(r!==void 0)throw new D('"wait" takes no other attributes',l.offset);bs(s,l,n)}}}#a(){const e=this.#e,r=this.#i();let s;if(r==='"')s={kind:"quoted",offset:e,text:this.#s()};else if(r==="/")s={kind:"regex",offset:e,regex:this.#n()};else{const n=this.#c(i=>!tt(i));if(n.length===0)throw new D('Expected a value after "="',e);return{kind:"raw",offset:e,text:n}}if(!tt(this.#i()))throw new D('Expected a space or "}" after the value',this.#e);return s}#i(){return this.#t.charAt(this.#e)}#c(e){const r=this.#e;for(;this.#e<this.#t.length&&e(this.#i());)this.#e++;return this.#t.slice(r,this.#e)}#l(){this.#c(e=>et.test(e))}}function jt(t){return new ms(t).parse()}function bs(t,e,r){const{name:s,offset:n}=e;if(e.kind==="attribute"){rt(t,s,n,e.value);return}if(!s.includes(","))throw new D(`Expected key=value, got ${JSON.stringify(s)}`,n);if(r>0)throw new D("Write the x,y position first",n);const[i,l,...y]=s.split(",");if(y.length>0)throw new D("Expected a screen position as x,y",n);const p=n+i.length+1;rt(t,"x",n,{kind:"raw",offset:n,text:i}),rt(t,"y",p,{kind:"raw",offset:p,text:l})}function Es(t){return ys.has(t)}function tt(t){return t===""||t==="}"||et.test(t)}function rt(t,e,r,s){if(!Es(e))throw new D(`Unknown attribute ${JSON.stringify(e)}; expected one of ${Ft.join(", ")}`,r);if(t.offsets[e]!==void 0)throw new D(`Duplicate attribute ${JSON.stringify(e)}`,r);switch(t.offsets[e]=r,e){case"byTestId":case"byText":if(t.byText!==void 0||t.byTestId!==void 0)throw new D("Only one of byText and byTestId may be given",r);e==="byText"?t.byText=xs(s):t.byTestId=As(s);return;default:t[e]=$t(s,e)}}function Ss(t,e){return{duration:t.duration,kind:"move",to:vs(t,e)}}function $t(t,e){if(t.kind!=="raw"||!ws.test(t.text))throw new D(`"${e}" takes a number`,t.offset);return Number(t.text)}function vs(t,e){const{byTestId:r,byText:s,index:n,offsets:i,x:l,y}=t;if(s!==void 0)return{by:"text",index:n,text:s,x:l,y};if(r!==void 0)return{by:"testId",index:n,testId:r,x:l,y};if(i.index!==void 0)throw new D('"index" needs byText or byTestId',i.index);if(l===void 0||y===void 0)throw new D("A screen position needs x and y",e);return{by:"position",x:l,y}}function As(t){if(t.kind==="regex")throw new D('"byTestId" takes a string',t.offset);return t.text}function xs(t){return t.kind==="regex"?t.regex:t.text}function Ae(t){return t.by==="position"?{by:"position",x:t.x,y:t.y}:{...Xe(t),x:t.x,y:t.y}}function ks(t){return t.map(e=>e.kind==="move"?{duration:e.duration,kind:"move",to:Ae(e.to)}:e)}function Is(t){return{press:e=>{ee(t,"appetizeio.device.server.keyboard.press",{key:e})}}}function Os({onRequest:t,parent:e,proxyInlet:r,signal:s}){const n=new Dt(e,{signal:s}),i=[()=>{n.close()}];return Nt(n,r),t&&i.push(_e(n,l=>{t(l,{source:"parent"})})),{cleanup:()=>{for(const l of i)l()},notifies:()=>e===globalThis.window?void 0:n}}function Ts({onRequest:t,proxyInlet:e}){const[r,s]=Ye(),i=[Yr(s),()=>{r.close()}];return Nt(r,e),t&&i.push(_e(r,l=>{t(l,{source:"parent"})})),{cleanup:()=>{for(const l of i)l()},notifies:()=>r}}function Rs(t){return"to"in t?{from:Ae(t.from),kind:"path",to:Ae(t.to)}:{direction:t.direction,distance:t.distance,from:t.from?Ae(t.from):void 0,kind:"direction"}}function Ms(t){return{down:(e,r)=>{ee(t,"appetizeio.device.server.touch.down",{x:e,y:r})},move:(e,r)=>{ee(t,"appetizeio.device.server.touch.move",{x:e,y:r})},up:(e,r)=>{ee(t,"appetizeio.device.server.touch.up",{x:e,y:r})}}}const Us=new Set(Ze),Ls=/^(?<key>[A-Za-z]+)>(?<repeat>\d+)\/$/u,Cs=/(\{\{|\{[^{}]*\})/u;function Ps(t){const e=[];let r="";function s(){r.length>0&&(e.push({kind:"text",text:r}),r="")}for(const[n,i]of t.split(Cs).entries())if(n%2===0){if(i.includes("{"))throw new Error(`Unclosed "{" in ${JSON.stringify(t)}`);r+=i}else i==="{{"?r+="{":(s(),e.push(Ns(i.slice(1,-1))));return s(),e}function _s(t,e){if(!Us.has(t))throw e.endsWith(">")?new Error(`Holding a key is not supported: {${e}}`):e.startsWith("/")?new Error(`Releasing a key is not supported: {${e}}`):new Error(`{${e}} does not name a supported key. Supported: ${Ze.join(", ")}. Type characters as text, and escape a literal "{" as "{{".`)}function Ns(t){const e=Ls.exec(t)?.groups,r=e?.key??t;if(_s(r,t),!e)return{key:r,kind:"press"};const s=Number(e.repeat);if(s<1)throw new Error(`Repeat for {${t}} must be at least 1`);return{key:r,kind:"press",repeat:s}}const Ds=Symbol("@appetizeio/client:v1Compat");function Vt(t){return t?.[Ds]}class Bs{readable;ready;get dimensions(){return this.#s}#e=[];#t=!1;#r;#s;#n;#o;constructor({onClose:e,requestKeyFrame:r,signal:s}){this.#n=r,this.ready=new Promise((i,l)=>{this.#o={reject:l,resolve:i}});let n;if(this.readable=new ReadableStream({cancel:()=>{this.#i()},start:i=>{n=i}}),!n)throw new Error("ReadableStream controller was not initialized");if(this.#r=n,s){const i=()=>{this.fail(s.reason)};s.addEventListener("abort",i,{once:!0}),this.#e.push(()=>{s.removeEventListener("abort",i)})}this.#e.push(()=>{e(this)})}close=()=>{this.#a()};fail(e){this.#a(e)}handleChunk(e){if(this.#o){if(e.type!=="key")return;const{resolve:r}=this.#o;this.#o=void 0,this.#s={height:e.height,width:e.width},r(this)}else e.type==="key"&&(this.#s={height:e.height,width:e.width});this.#r.enqueue(e)}requestKeyFrame=()=>{this.#t||this.#n()};async*[Symbol.asyncIterator](){const e=this.readable.getReader();try{for(let r=await e.read();!r.done;r=await e.read())yield r.value}finally{await e.cancel()}}#a(e){this.#t||(this.#r.close(),this.#i(e))}#i(e){this.#t=!0;for(const r of this.#e)r();this.#o?.reject(e??new Error("Video stream closed before the first key chunk")),this.#o=void 0}}class zs{#e=!1;#t;#r;#s=new Set;constructor(e){this.#t=e}close(){this.#r=void 0;for(const e of[...this.#s])e.close()}async createStream({signal:e}={}){e?.throwIfAborted();const r=new Bs({onClose:s=>{this.#o(s)},requestKeyFrame:()=>{this.#a()},signal:e});this.#s.add(r);try{await this.#n()}catch(s){r.fail(s)}return await r.ready}handleChunk(e){e.type==="key"&&(this.#e=!1);for(const r of this.#s)r.handleChunk(e)}#n(){return this.#r?(this.#a(),this.#r):(this.#e=!0,this.#r=(async()=>{try{await this.#t.request("appetizeio.device.server.video.start")}catch(e){throw this.#r=void 0,e}})(),this.#r)}#o(e){this.#s.delete(e),!(this.#s.size>0||!this.#r)&&(this.#r=void 0,ee(this.#t,"appetizeio.device.server.video.stop",void 0))}#a(){this.#e||(this.#e=!0,ee(this.#t,"appetizeio.device.server.video.requestKeyFrame",void 0))}}class Fs{debug;keyboard;touch;video;#e;#t=[];#r;constructor(e,r={}){const s=Vt(r)??{},{baseUrl:n,onClose:i,signal:l}=r;this.#e=n?js(n):void 0;const{onRequest:y,parent:p,proxyRequest:A}=s,E=$s(y);l?.addEventListener("abort",this.close);const[R,M]=Ye(),[N,_]=Ye();this.#t.push(()=>{R.close(),M.close(),N.close(),_.close()}),this.#t.push(He(_,e,{leftEffects:A}));const C=p==="playwright"?Ts({onRequest:E,proxyInlet:N}):p?Os({onRequest:E,parent:p,proxyInlet:N,signal:l}):void 0;C&&this.#t.push(C.cleanup),this.#t.push(He(M,N,{notifiesLeft:C?.notifies}));const{client:Z,unsub:Ee}=Xr(R,{"appetizeio.device.client.debug.adbTunnel.data":V=>Y.handleAdbTunnelData(V),"appetizeio.device.client.debug.adbTunnel.stopped":async V=>{Y.handleAdbTunnelStopped(V)},"appetizeio.device.client.debug.log.entry":async V=>{Y.handleLogEntry(V)},"appetizeio.device.client.debug.proxyIntercept.event":async V=>{Y.handleProxyInterceptEvent(V)},"appetizeio.device.client.video.chunk":async V=>{k.handleChunk(V)}});this.#r=Z,this.#t.push(Ee);const Y=new us(this.#r);this.#t.push(()=>{Y.close()});const k=new zs(this.#r);this.#t.push(()=>{k.close()}),this.debug=Y,this.keyboard=Is(this.#r),this.touch=Ms(this.#r),this.video=k,E&&(this.#t.push(_e(M,V=>{E(V,{source:"self"})})),e instanceof Dt&&this.#t.push(_e(e,V=>{E(V,{source:"iframe"})}))),this.#t.push(()=>i?.())}async clearKeychain(){await this.#r.request("appetizeio.device.server.clearKeychain")}close=()=>{for(const e of this.#t)try{e()}catch(r){console.error("Device cleanup error:",r)}};async fold(e){await this.#r.request("appetizeio.device.server.fold",{hinge:e})}async gesture(e,r){await this.#r.request("appetizeio.device.server.gesture",{options:r,steps:ks(typeof e=="string"?jt(e):e)})}async inspect(e,r){return await this.#r.request("appetizeio.device.server.inspect",{options:r,selector:e?Xe(e):void 0})}async open(e){new URL(e),await this.#r.request("appetizeio.device.server.open",{url:e})}async press(e){await this.#r.request("appetizeio.device.server.press",{action:e})}async rotate(e){await this.#r.request("appetizeio.device.server.rotate",{orientation:e})}async screenshot(){const e=await this.#r.request("appetizeio.device.server.screenshot"),r=this.#e?new URL(e.url,this.#e).href:e.url,s=await fetch(r);if(!s.ok)throw new Error(`Screenshot download failed: ${String(s.status)} ${s.statusText}`);const n=s.headers.get("content-type")??"application/octet-stream";return{data:new Uint8Array(await s.arrayBuffer()),mimeType:n}}async swipe(e,r){await this.#r.request("appetizeio.device.server.swipe",{gesture:Rs(e),options:r})}async tap(e,r){await this.#r.request("appetizeio.device.server.tap",{options:r,selector:Ae(e)})}async type(e,r){await this.#r.request("appetizeio.device.server.type",{options:r,steps:Ps(e)})}}function js(t){const e=new URL(t);return e.protocol==="ws:"?e.protocol="http:":e.protocol==="wss:"&&(e.protocol="https:"),e.href}const $s=t=>{if(t)return(e,r)=>{e.method.startsWith("appetizeio.device.server.")&&t(e,r)}};let st;try{st=new TextDecoder}catch{}let w,q,f=0;const nt=[],Vs=105,Ks=57342,qs=57343,Kt=57337,qt=6,pe={};let xe=11281e4,te=1681e4,ae=nt,ke=0,I={},B,Ie,Oe=0,ce=0,z,G,F=[],it=[],W,K,Te,Wt={useRecords:!1,mapsAsObjects:!0},Re=!1,Jt=2;try{new Function("")}catch{Jt=1/0}class be{constructor(e){if(e&&((e.keyMap||e._keyMap)&&!e.useRecords&&(e.useRecords=!1,e.mapsAsObjects=!0),e.useRecords===!1&&e.mapsAsObjects===void 0&&(e.mapsAsObjects=!0),e.getStructures&&(e.getShared=e.getStructures),e.getShared&&!e.structures&&((e.structures=[]).uninitialized=!0),e.keyMap)){this.mapKey=new Map;for(let[r,s]of Object.entries(e.keyMap))this.mapKey.set(s,r)}Object.assign(this,e)}decodeKey(e){return this.keyMap&&this.mapKey.get(e)||e}encodeKey(e){return this.keyMap&&this.keyMap.hasOwnProperty(e)?this.keyMap[e]:e}encodeKeys(e){if(!this._keyMap)return e;let r=new Map;for(let[s,n]of Object.entries(e))r.set(this._keyMap.hasOwnProperty(s)?this._keyMap[s]:s,n);return r}decodeKeys(e){if(!this._keyMap||e.constructor.name!="Map")return e;if(!this._mapKey){this._mapKey=new Map;for(let[s,n]of Object.entries(this._keyMap))this._mapKey.set(n,s)}let r={};return e.forEach((s,n)=>r[H(this._mapKey.has(n)?this._mapKey.get(n):n)]=s),r}mapDecode(e,r){let s=this.decode(e);return this._keyMap&&s.constructor.name==="Array"?s.map(n=>this.decodeKeys(n)):s}decode(e,r){if(w)return er(()=>(lt(),this?this.decode(e,r):be.prototype.decode.call(Wt,e,r)));q=r>-1?r:e.length,f=0,ke=0,ce=0,Ie=null,ae=nt,z=null,w=e;try{K=e.dataView||(e.dataView=new DataView(e.buffer,e.byteOffset,e.byteLength))}catch(s){throw w=null,e instanceof Uint8Array?s:new Error("Source must be a Uint8Array or Buffer but was a "+(e&&typeof e=="object"?e.constructor.name:typeof e))}if(this instanceof be){if(I=this,W=this.sharedValues&&(this.pack?new Array(this.maxPrivatePackedValues||16).concat(this.sharedValues):this.sharedValues),this.structures)return B=this.structures,De();(!B||B.length>0)&&(B=[])}else I=Wt,(!B||B.length>0)&&(B=[]),W=null;return De()}decodeMultiple(e,r){let s,n=0;try{let i=e.length;Re=!0;let l=this?this.decode(e,i):ut.decode(e,i);if(r){if(r(l)===!1)return;for(;f<i;)if(n=f,r(De())===!1)return}else{for(s=[l];f<i;)n=f,s.push(De());return s}}catch(i){throw i.lastPosition=n,i.values=s,i}finally{Re=!1,lt()}}}function De(){try{let t=O();if(z){if(f>=z.postBundlePosition){let e=new Error("Unexpected bundle position");throw e.incomplete=!0,e}f=z.postBundlePosition,z=null}if(f==q)B=null,w=null,G&&(G=null);else if(f>q){let e=new Error("Unexpected end of CBOR data");throw e.incomplete=!0,e}else if(!Re)throw new Error("Data read, but end of buffer not reached");return t}catch(t){throw lt(),(t instanceof RangeError||t.message.startsWith("Unexpected end of buffer"))&&(t.incomplete=!0),t}}function le(){let t=new Error("Unexpected end of CBOR data");return t.incomplete=!0,t}function O(){if(!(f<q))throw le();let t=w[f++],e=t>>5;if(t=t&31,t>23)switch(t){case 24:if(f>=q)throw le();t=w[f++];break;case 25:if(e==7)return Hs();t=K.getUint16(f),f+=2;break;case 26:if(e==7){let r=K.getFloat32(f);if(I.useFloat32>2){let s=ft[(w[f]&127)<<1|w[f+1]>>7];return f+=4,(s*r+(r>0?.5:-.5)>>0)/s}return f+=4,r}if(t=K.getUint32(f),f+=4,e===1)return-1-t;break;case 27:if(e==7){let r=K.getFloat64(f);return f+=8,r}if(e>1){if(K.getUint32(f)>0)throw new Error("JavaScript does not support arrays, maps, or strings with length over 4294967295");t=K.getUint32(f+4)}else I.int64AsNumber?(t=K.getUint32(f)*4294967296,t+=K.getUint32(f+4)):t=K.getBigUint64(f);f+=8;break;case 31:switch(e){case 2:case 3:throw new Error("Indefinite length not supported for byte or text strings");case 4:let r=[],s,n=0;for(;(s=O())!=pe;){if(n>=xe)throw new Error(`Array length exceeds ${xe}`);r[n++]=s}return e==4?r:e==3?r.join(""):Buffer.concat(r);case 5:let i;if(I.mapsAsObjects){let l={},y=0;if(I.keyMap)for(;(i=O())!=pe;){if(y++>=te)throw new Error(`Property count exceeds ${te}`);l[H(I.decodeKey(i))]=O()}else for(;(i=O())!=pe;){if(y++>=te)throw new Error(`Property count exceeds ${te}`);l[H(i)]=O()}return l}else{Te&&(I.mapsAsObjects=!0,Te=!1);let l=new Map;if(I.keyMap){let y=0;for(;(i=O())!=pe;){if(y++>=te)throw new Error(`Map size exceeds ${te}`);l.set(I.decodeKey(i),O())}}else{let y=0;for(;(i=O())!=pe;){if(y++>=te)throw new Error(`Map size exceeds ${te}`);l.set(i,O())}}return l}case 7:return pe;default:throw new Error("Invalid major type for indefinite length "+e)}default:throw new Error("Unknown token "+t)}switch(e){case 0:return t;case 1:return~t;case 2:return Gs(t);case 3:if(ce>=f)return Ie.slice(f-Oe,(f+=t)-Oe);if(ce==0&&q<140&&t<32){let n=t<16?Zt(t):Js(t);if(n!=null)return n}return Ht(t);case 4:if(t>=xe)throw new Error(`Array length exceeds ${xe}`);if(t>q-f)throw le();let r=new Array(t);for(let n=0;n<t;n++)r[n]=O();return r;case 5:if(t>=te)throw new Error(`Map size exceeds ${xe}`);if(t>(q-f)/2)throw le();if(I.mapsAsObjects){let n={};if(I.keyMap)for(let i=0;i<t;i++)n[H(I.decodeKey(O()))]=O();else for(let i=0;i<t;i++)n[H(O())]=O();return n}else{Te&&(I.mapsAsObjects=!0,Te=!1);let n=new Map;if(I.keyMap)for(let i=0;i<t;i++)n.set(I.decodeKey(O()),O());else for(let i=0;i<t;i++)n.set(O(),O());return n}case 6:if(t>=Kt){let n=B[t&8191];if(n)return n.read||(n.read=ot(n)),n.read();if(t<65536){if(t==qs){let i=we(),l=O(),y=O();at(l,y);let p={};if(I.keyMap)for(let A=2;A<i;A++){let E=I.decodeKey(y[A-2]);p[H(E)]=O()}else for(let A=2;A<i;A++){let E=y[A-2];p[H(E)]=O()}return p}else if(t==Ks){let i=we(),l=O();for(let y=2;y<i;y++)at(l++,O());return O()}else if(t==Kt)return tn();if(I.getShared&&(ct(),n=B[t&8191],n))return n.read||(n.read=ot(n)),n.read()}}let s=F[t];if(s)return s.handlesRead?s(O):s(O());{let n=O();for(let i=0;i<it.length;i++){let l=it[i](t,n);if(l!==void 0)return l}return new fe(n,t)}case 7:switch(t){case 20:return!1;case 21:return!0;case 22:return null;case 23:return;default:let n=(W||ue())[t];if(n!==void 0)return n;throw new Error("Unknown token "+t)}default:throw isNaN(t)?le():new Error("Unknown CBOR token "+t)}}const Gt=/^[a-zA-Z_$][a-zA-Z\d_$]*$/;function ot(t){if(!t)throw new Error("Structure is required in record definition");function e(){let r=w[f++];if(r=r&31,r>23)switch(r){case 24:r=w[f++];break;case 25:r=K.getUint16(f),f+=2;break;case 26:r=K.getUint32(f),f+=4;break;default:throw new Error("Expected array header, but got "+w[f-1])}let s=this.compiledReader;for(;s;){if(s.propertyCount===r)return s(O);s=s.next}if(this.slowReads++>=Jt){let i=this.length==r?this:this.slice(0,r);return s=I.keyMap?new Function("r","return {"+i.map(l=>I.decodeKey(l)).map(l=>Gt.test(l)?H(l)+":r()":"["+JSON.stringify(l)+"]:r()").join(",")+"}"):new Function("r","return {"+i.map(l=>Gt.test(l)?H(l)+":r()":"["+JSON.stringify(l)+"]:r()").join(",")+"}"),this.compiledReader&&(s.next=this.compiledReader),s.propertyCount=r,this.compiledReader=s,s(O)}let n={};if(I.keyMap)for(let i=0;i<r;i++)n[H(I.decodeKey(this[i]))]=O();else for(let i=0;i<r;i++)n[H(this[i])]=O();return n}return t.slowReads=0,e}function H(t){if(typeof t=="string")return t==="__proto__"?"__proto_":t;if(typeof t=="number"||typeof t=="boolean"||typeof t=="bigint")return t.toString();if(t==null)return t+"";throw new Error("Invalid property name type "+typeof t)}let Ht=Be;function Ws(t){Ht=e();function e(r){return function(n){let i=ae[ke++];if(i==null){if(z)return Be(n);let y=t(f,q,n,w);if(typeof y=="string")i=y,ae=nt;else if(ae=y,ke=1,ce=1,i=ae[0],i===void 0)throw new Error("Unexpected end of buffer")}let l=i.length;return l<=n?(f+=n,i):(Ie=i,Oe=f,ce=f+l,f+=n,i.slice(0,n))}}}function Be(t){let e;if(t<16&&(e=Zt(t)))return e;if(t>64&&st)return st.decode(w.subarray(f,f+=t));const r=f+t,s=[];for(e="";f<r;){const n=w[f++];if((n&128)===0)s.push(n);else if((n&224)===192)if(n<194||f>=r||(w[f]&192)!==128)s.push(65533);else{const i=w[f++]&63;s.push((n&31)<<6|i)}else if((n&240)===224){const i=f<r?w[f]:0;if(f>=r||(i&192)!==128||n===224&&i<160||n===237&&i>=160)s.push(65533);else if(f++,f>=r||(w[f]&192)!==128)s.push(65533);else{const l=w[f++]&63;s.push((n&31)<<12|(i&63)<<6|l)}}else if((n&248)===240){const i=f<r?w[f]:0;if(n>244||f>=r||(i&192)!==128||n===240&&i<144||n===244&&i>=144)s.push(65533);else if(f++,f>=r||(w[f]&192)!==128)s.push(65533);else{const l=w[f++]&63;if(f>=r||(w[f]&192)!==128)s.push(65533);else{const y=w[f++]&63;let p=(n&7)<<18|(i&63)<<12|l<<6|y;p-=65536,s.push(p>>>10&1023|55296),s.push(56320|p&1023)}}}else s.push(65533);s.length>=4096&&(e+=$.apply(String,s),s.length=0)}return s.length>0&&(e+=$.apply(String,s)),e}let $=String.fromCharCode;function Js(t){let e=f,r=new Array(t);for(let s=0;s<t;s++){const n=w[f++];if((n&128)>0){f=e;return}r[s]=n}return $.apply(String,r)}function Zt(t){if(t<4)if(t<2){if(t===0)return"";{let e=w[f++];if((e&128)>1){f-=1;return}return $(e)}}else{let e=w[f++],r=w[f++];if((e&128)>0||(r&128)>0){f-=2;return}if(t<3)return $(e,r);let s=w[f++];if((s&128)>0){f-=3;return}return $(e,r,s)}else{let e=w[f++],r=w[f++],s=w[f++],n=w[f++];if((e&128)>0||(r&128)>0||(s&128)>0||(n&128)>0){f-=4;return}if(t<6){if(t===4)return $(e,r,s,n);{let i=w[f++];if((i&128)>0){f-=5;return}return $(e,r,s,n,i)}}else if(t<8){let i=w[f++],l=w[f++];if((i&128)>0||(l&128)>0){f-=6;return}if(t<7)return $(e,r,s,n,i,l);let y=w[f++];if((y&128)>0){f-=7;return}return $(e,r,s,n,i,l,y)}else{let i=w[f++],l=w[f++],y=w[f++],p=w[f++];if((i&128)>0||(l&128)>0||(y&128)>0||(p&128)>0){f-=8;return}if(t<10){if(t===8)return $(e,r,s,n,i,l,y,p);{let A=w[f++];if((A&128)>0){f-=9;return}return $(e,r,s,n,i,l,y,p,A)}}else if(t<12){let A=w[f++],E=w[f++];if((A&128)>0||(E&128)>0){f-=10;return}if(t<11)return $(e,r,s,n,i,l,y,p,A,E);let R=w[f++];if((R&128)>0){f-=11;return}return $(e,r,s,n,i,l,y,p,A,E,R)}else{let A=w[f++],E=w[f++],R=w[f++],M=w[f++];if((A&128)>0||(E&128)>0||(R&128)>0||(M&128)>0){f-=12;return}if(t<14){if(t===12)return $(e,r,s,n,i,l,y,p,A,E,R,M);{let N=w[f++];if((N&128)>0){f-=13;return}return $(e,r,s,n,i,l,y,p,A,E,R,M,N)}}else{let N=w[f++],_=w[f++];if((N&128)>0||(_&128)>0){f-=14;return}if(t<15)return $(e,r,s,n,i,l,y,p,A,E,R,M,N,_);let C=w[f++];if((C&128)>0){f-=15;return}return $(e,r,s,n,i,l,y,p,A,E,R,M,N,_,C)}}}}}function Gs(t){return I.copyBuffers?Uint8Array.prototype.slice.call(w,f,f+=t):w.subarray(f,f+=t)}let Yt=new Float32Array(1),ze=new Uint8Array(Yt.buffer,0,4);function Hs(){let t=w[f++],e=w[f++],r=(t&127)>>2;if(r===31)return e||t&3?NaN:t&128?-1/0:1/0;if(r===0){let s=((t&3)<<8|e)/16777216;return t&128?-s:s}return ze[3]=t&128|(r>>1)+56,ze[2]=(t&7)<<5|e>>3,ze[1]=e<<5,ze[0]=0,Yt[0]}new Array(4096);class fe{constructor(e,r){this.value=e,this.tag=r}}F[0]=t=>new Date(t),F[1]=t=>new Date(Math.round(t*1e3)),F[2]=t=>{let e=BigInt(0);for(let r=0,s=t.byteLength;r<s;r++)e=BigInt(t[r])+(e<<BigInt(8));return e},F[3]=t=>BigInt(-1)-F[2](t),F[4]=t=>+(t[1]+"e"+t[0]),F[5]=t=>t[1]*Math.exp(t[0]*Math.log(2));const at=(t,e)=>{t=t-57344;let r=B[t];r&&r.isShared&&((B.restoreStructures||(B.restoreStructures=[]))[t]=r),B[t]=e,e.read=ot(e)};F[Vs]=t=>{let e=t.length,r=t[1];at(t[0],r);let s={};for(let n=2;n<e;n++){let i=r[n-2];s[H(i)]=t[n]}return s},F[14]=t=>z?z[0].slice(z.position0,z.position0+=t):new fe(t,14),F[15]=t=>z?z[1].slice(z.position1,z.position1+=t):new fe(t,15);let Zs={Error,RegExp};F[27]=t=>(Zs[t[0]]||Error)(t[1],t[2]);const Qt=t=>{if(w[f++]!=132){let r=new Error("Packed values structure must be followed by a 4 element array");throw w.length<f&&(r.incomplete=!0),r}let e=t();if(!e||!e.length){let r=new Error("Packed values structure must be followed by a 4 element array");throw r.incomplete=!0,r}return W=W?e.concat(W.slice(e.length)):e,W.prefixes=t(),W.suffixes=t(),t()};Qt.handlesRead=!0,F[51]=Qt,F[qt]=t=>{if(!W)if(I.getShared)ct();else return new fe(t,qt);if(typeof t=="number")return W[16+(t>=0?2*t:-2*t-1)];let e=new Error("No support for non-integer packed references yet");throw t===void 0&&(e.incomplete=!0),e},F[28]=t=>{G||(G=new Map,G.id=0);let e=G.id++,r=f,s=w[f],n;s>>5==4?n=[]:n={};let i={target:n};G.set(e,i);let l=t();return i.used?(Object.getPrototypeOf(n)!==Object.getPrototypeOf(l)&&(f=r,n=l,G.set(e,{target:n}),l=t()),Object.assign(n,l)):(i.target=l,l)},F[28].handlesRead=!0,F[29]=t=>{let e=G.get(t);return e.used=!0,e.target},F[258]=t=>new Set(t),(F[259]=t=>(I.mapsAsObjects&&(I.mapsAsObjects=!1,Te=!0),t())).handlesRead=!0;function ye(t,e){return typeof t=="string"?t+e:t instanceof Array?t.concat(e):Object.assign({},t,e)}function ue(){if(!W)if(I.getShared)ct();else throw new Error("No packed values available");return W}const Ys=1399353956;it.push((t,e)=>{if(t>=225&&t<=255)return ye(ue().prefixes[t-224],e);if(t>=28704&&t<=32767)return ye(ue().prefixes[t-28672],e);if(t>=1879052288&&t<=2147483647)return ye(ue().prefixes[t-1879048192],e);if(t>=216&&t<=223)return ye(e,ue().suffixes[t-216]);if(t>=27647&&t<=28671)return ye(e,ue().suffixes[t-27639]);if(t>=1811940352&&t<=1879048191)return ye(e,ue().suffixes[t-1811939328]);if(t==Ys)return{packedValues:W,structures:B.slice(0),version:e};if(t==55799)return e});const Qs=new Uint8Array(new Uint16Array([1]).buffer)[0]==1,Xt=[Uint8Array,Uint8ClampedArray,Uint16Array,Uint32Array,typeof BigUint64Array>"u"?{name:"BigUint64Array"}:BigUint64Array,Int8Array,Int16Array,Int32Array,typeof BigInt64Array>"u"?{name:"BigInt64Array"}:BigInt64Array,Float32Array,Float64Array],Xs=[64,68,69,70,71,72,77,78,79,85,86];for(let t=0;t<Xt.length;t++)en(Xt[t],Xs[t]);function en(t,e){let r="get"+t.name.slice(0,-5),s;typeof t=="function"?s=t.BYTES_PER_ELEMENT:t=null;for(let n=0;n<2;n++){if(!n&&s==1)continue;let i=s==2?1:s==4?2:s==8?3:0;F[n?e:e-4]=s==1||n==Qs?l=>{if(!t)throw new Error("Could not find typed array for code "+e);return!I.copyBuffers&&(s===1||s===2&&!(l.byteOffset&1)||s===4&&!(l.byteOffset&3)||s===8&&!(l.byteOffset&7))?new t(l.buffer,l.byteOffset,l.byteLength>>i):new t(Uint8Array.prototype.slice.call(l,0).buffer)}:l=>{if(!t)throw new Error("Could not find typed array for code "+e);let y=new DataView(l.buffer,l.byteOffset,l.byteLength),p=l.length>>i,A=new t(p),E=y[r];for(let R=0;R<p;R++)A[R]=E.call(y,R<<i,n);return A}}}function tn(){let t=we(),e=f+O();for(let s=2;s<t;s++){let n=we();f+=n}let r=f;return f=e,z=[Be(we()),Be(we())],z.position0=0,z.position1=0,z.postBundlePosition=f,f=r,O()}function we(){if(!(f<q))throw le();let t=w[f++]&31;if(t>23)switch(t){case 24:if(f>=q)throw le();t=w[f++];break;case 25:t=K.getUint16(f),f+=2;break;case 26:t=K.getUint32(f),f+=4;break}return t}function ct(){if(I.getShared){let t=er(()=>(w=null,I.getShared()))||{},e=t.structures||[];I.sharedVersion=t.version,W=I.sharedValues=t.packedValues,B===!0?I.structures=B=e:B.splice.apply(B,[0,e.length].concat(e))}}function er(t){let e=q,r=f,s=ke,n=Oe,i=ce,l=Ie,y=ae,p=G,A=z,E=new Uint8Array(w.slice(0,q)),R=B,M=I,N=Re,_=t();return q=e,f=r,ke=s,Oe=n,ce=i,Ie=l,ae=y,G=p,z=A,w=E,Re=N,B=R,I=M,K=new DataView(w.buffer,w.byteOffset,w.byteLength),_}function lt(){w=null,G=null,B=null}const ft=new Array(147);for(let t=0;t<256;t++)ft[t]=+("1e"+Math.floor(45.15-t*.30103));let ut=new be({useRecords:!1});const rn=ut.decode;ut.decodeMultiple;let Fe;try{Fe=new TextEncoder}catch{}let dt,tr;const je=typeof globalThis=="object"&&globalThis.Buffer,Me=typeof je<"u",ht=Me?je.allocUnsafeSlow:Uint8Array,rr=Me?je:Uint8Array,sr=256,nr=Me?4294967296:2144337920;let pt,c,L,o=0,re,j=null;const sn=61440,nn=/[\u0080-\uFFFF]/,J=Symbol("record-id");class ir extends be{constructor(e){super(e),this.offset=0;let r,s,n,i,l;e=e||{};let y=rr.prototype.utf8Write?function(a,g){return c.utf8Write(a,g,c.byteLength-g)}:Fe&&Fe.encodeInto?function(a,g){return Fe.encodeInto(a,c.subarray(g)).written}:!1,p=this,A=e.structures||e.saveStructures,E=e.maxSharedStructures;if(E==null&&(E=A?128:0),E>8190)throw new Error("Maximum maxSharedStructure is 8190");let R=e.sequential;R&&(E=0),this.structures||(this.structures=[]),this.saveStructures&&(this.saveShared=this.saveStructures);let M,N,_=e.sharedValues,C;if(_){C=Object.create(null);for(let a=0,g=_.length;a<g;a++)C[_[a]]=a}let Z=[],Ee=0,Y=0;this.mapEncode=function(a,g){return this._keyMap&&!this._mapped&&a.constructor.name==="Array"&&(a=a.map(d=>this.encodeKeys(d))),this.encode(a,g)},this.encode=function(a,g){if(c||(c=new ht(8192),L=new DataView(c.buffer,0,8192),o=0),re=c.length-10,re-o<2048?(c=new ht(c.length),L=new DataView(c.buffer,0,c.length),re=c.length-10,o=0):g===lr&&(o=o+7&2147483640),r=o,p.useSelfDescribedHeader&&(L.setUint32(o,3654940416),o+=3),l=p.structuredClone?new Map:null,p.bundleStrings&&typeof a!="string"?(j=[],j.size=1/0):j=null,s=p.structures,s){if(s.uninitialized){let h=p.getShared()||{};p.structures=s=h.structures||[],p.sharedVersion=h.version;let u=p.sharedValues=h.packedValues;if(u){C={};for(let b=0,S=u.length;b<S;b++)C[u[b]]=b}}let d=s.length;if(d>E&&!R&&(d=E),!s.transitions){s.transitions=Object.create(null);for(let h=0;h<d;h++){let u=s[h];if(!u)continue;let b,S=s.transitions;for(let v=0,x=u.length;v<x;v++){S[J]===void 0&&(S[J]=h);let T=u[v];b=S[T],b||(b=S[T]=Object.create(null)),S=b}S[J]=h|1048576}}R||(s.nextId=d)}if(n&&(n=!1),i=s||[],N=C,e.pack){let d=new Map;if(d.values=[],d.encoder=p,d.maxValues=e.maxPrivatePackedValues||(C?16:1/0),d.objectMap=C||!1,d.samplingPackedValues=M,$e(a,d),d.values.length>0){c[o++]=216,c[o++]=51,Q(4);let h=d.values;k(h),Q(0),Q(0),N=Object.create(C||null);for(let u=0,b=h.length;u<b;u++)N[h[u]]=u}}pt=g&mt;try{if(pt)return;if(k(a),j&&cr(r,k),p.offset=o,l&&l.idsToInsert){o+=l.idsToInsert.length*2,o>re&&de(o),p.offset=o;let d=cn(c.subarray(r,o),l.idsToInsert);return l=null,d}return g&lr?(c.start=r,c.end=o,c):c.subarray(r,o)}finally{if(s){if(Y<10&&Y++,s.length>E&&(s.length=E),Ee>1e4)s.transitions=null,Y=0,Ee=0,Z.length>0&&(Z=[]);else if(Z.length>0&&!R){for(let d=0,h=Z.length;d<h;d++)Z[d][J]=void 0;Z=[]}}if(n&&p.saveShared){p.structures.length>E&&(p.structures=p.structures.slice(0,E));let d=c.subarray(r,o);return p.updateSharedData()===!1?p.encode(a):d}g&fn&&(o=r)}},this.findCommonStringsToPack=()=>(M=new Map,C||(C=Object.create(null)),a=>{let g=a&&a.threshold||4,d=this.pack?a.maxPrivatePackedValues||16:0;_||(_=this.sharedValues=[]);for(let[h,u]of M)u.count>g&&(C[h]=d++,_.push(h),n=!0);for(;this.saveShared&&this.updateSharedData()===!1;);M=null});const k=a=>{o>re&&(c=de(o));var g=typeof a,d;if(g==="string"){if(N){let S=N[a];if(S>=0){S<16?c[o++]=S+224:(c[o++]=198,S&1?k(15-S>>1):k(S-16>>1));return}else if(M&&!e.pack){let v=M.get(a);v?v.count++:M.set(a,{count:1})}}let h=a.length;if(j&&h>=4&&h<1024){if((j.size+=h)>sn){let v,x=(j[0]?j[0].length*3+j[1].length:0)+10;o+x>re&&(c=de(o+x)),c[o++]=217,c[o++]=223,c[o++]=249,c[o++]=j.position?132:130,c[o++]=26,v=o-r,o+=4,j.position&&cr(r,k),j=["",""],j.size=0,j.position=v}let S=nn.test(a);j[S?0:1]+=a,c[o++]=S?206:207,k(h);return}let u;h<32?u=1:h<256?u=2:h<65536?u=3:u=5;let b=h*3;if(o+b>re&&(c=de(o+b)),h<64||!y){let S,v,x,T=o+u;for(S=0;S<h;S++)v=a.charCodeAt(S),v<128?c[T++]=v:v<2048?(c[T++]=v>>6|192,c[T++]=v&63|128):(v&64512)===55296&&((x=a.charCodeAt(S+1))&64512)===56320?(v=65536+((v&1023)<<10)+(x&1023),S++,c[T++]=v>>18|240,c[T++]=v>>12&63|128,c[T++]=v>>6&63|128,c[T++]=v&63|128):(c[T++]=v>>12|224,c[T++]=v>>6&63|128,c[T++]=v&63|128);d=T-o-u}else d=y(a,o+u,b);d<24?c[o++]=96|d:d<256?(u<2&&c.copyWithin(o+2,o+1,o+1+d),c[o++]=120,c[o++]=d):d<65536?(u<3&&c.copyWithin(o+3,o+2,o+2+d),c[o++]=121,c[o++]=d>>8,c[o++]=d&255):(u<5&&c.copyWithin(o+5,o+3,o+3+d),c[o++]=122,L.setUint32(o,d),o+=4),o+=d}else if(g==="number")if(!this.alwaysUseFloat&&a>>>0===a)a<24?c[o++]=a:a<256?(c[o++]=24,c[o++]=a):a<65536?(c[o++]=25,c[o++]=a>>8,c[o++]=a&255):(c[o++]=26,L.setUint32(o,a),o+=4);else if(!this.alwaysUseFloat&&a>>0===a)a>=-24?c[o++]=31-a:a>=-256?(c[o++]=56,c[o++]=~a):a>=-65536?(c[o++]=57,L.setUint16(o,~a),o+=2):(c[o++]=58,L.setUint32(o,~a),o+=4);else if(!this.alwaysUseFloat&&a<0&&a>=-4294967296&&Math.floor(a)===a)c[o++]=58,L.setUint32(o,-1-a),o+=4;else{let h;if((h=this.useFloat32)>0&&a<4294967296&&a>=-2147483648){c[o++]=250,L.setFloat32(o,a);let u;if(h<4||(u=a*ft[(c[o]&127)<<1|c[o+1]>>7])>>0===u){o+=4;return}else o--}c[o++]=251,L.setFloat64(o,a),o+=8}else if(g==="object")if(!a)c[o++]=246;else{if(l){let u=l.get(a);if(u){if(c[o++]=216,c[o++]=29,c[o++]=25,!u.references){let b=l.idsToInsert||(l.idsToInsert=[]);u.references=[],b.push(u)}u.references.push(o-r),o+=2;return}else l.set(a,{offset:o-r})}let h=a.constructor;if(h===Object)this.skipFunction===!0&&(a=Object.fromEntries([...Object.keys(a).filter(u=>typeof a[u]!="function").map(u=>[u,a[u]])])),V(a);else if(h===Array){d=a.length,d<24?c[o++]=128|d:Q(d);for(let u=0;u<d;u++)k(a[u])}else if(h===Map)if((this.mapsAsObjects?this.useTag259ForMaps!==!1:this.useTag259ForMaps)&&(c[o++]=217,c[o++]=1,c[o++]=3),d=a.size,d<24?c[o++]=160|d:d<256?(c[o++]=184,c[o++]=d):d<65536?(c[o++]=185,c[o++]=d>>8,c[o++]=d&255):(c[o++]=186,L.setUint32(o,d),o+=4),p.keyMap)for(let[u,b]of a)k(p.encodeKey(u)),k(b);else for(let[u,b]of a)k(u),k(b);else{for(let u=0,b=dt.length;u<b;u++){let S=tr[u];if(a instanceof S){let v=dt[u],x=v.tag;x==null&&(x=v.getTag&&v.getTag.call(this,a)),x<24?c[o++]=192|x:x<256?(c[o++]=216,c[o++]=x):x<65536?(c[o++]=217,c[o++]=x>>8,c[o++]=x&255):x>-1&&(c[o++]=218,L.setUint32(o,x),o+=4),v.encode.call(this,a,k,de);return}}if(a[Symbol.iterator]){if(pt){let u=new Error("Iterable should be serialized as iterator");throw u.iteratorNotHandled=!0,u}c[o++]=159;for(let u of a)k(u);c[o++]=255;return}if(a[Symbol.asyncIterator]||yt(a)){let u=new Error("Iterable/blob should be serialized as iterator");throw u.iteratorNotHandled=!0,u}if(this.useToJSON&&a.toJSON){const u=a.toJSON();if(u!==a)return k(u)}V(a)}}else if(g==="boolean")c[o++]=a?245:244;else if(g==="bigint"){if(a<BigInt(1)<<BigInt(64)&&a>=0)c[o++]=27,L.setBigUint64(o,a);else if(a>-(BigInt(1)<<BigInt(64))&&a<0)c[o++]=59,L.setBigUint64(o,-a-BigInt(1));else if(this.largeBigIntToFloat)c[o++]=251,L.setFloat64(o,Number(a));else{a>=BigInt(0)?c[o++]=194:(c[o++]=195,a=BigInt(-1)-a);let h=[];for(;a;)h.push(Number(a&BigInt(255))),a>>=BigInt(8);wt(new Uint8Array(h.reverse()),de);return}o+=8}else if(g==="undefined")c[o++]=247;else throw new Error("Unknown type: "+g)},V=this.useRecords===!1?this.variableMapSize?a=>{let g=Object.keys(a),d=Object.values(a),h=g.length;if(h<24?c[o++]=160|h:h<256?(c[o++]=184,c[o++]=h):h<65536?(c[o++]=185,c[o++]=h>>8,c[o++]=h&255):(c[o++]=186,L.setUint32(o,h),o+=4),p.keyMap)for(let u=0;u<h;u++)k(p.encodeKey(g[u])),k(d[u]);else for(let u=0;u<h;u++)k(g[u]),k(d[u])}:a=>{c[o++]=185;let g=o-r;o+=2;let d=0;if(p.keyMap)for(let h in a)(typeof a.hasOwnProperty!="function"||a.hasOwnProperty(h))&&(k(p.encodeKey(h)),k(a[h]),d++);else for(let h in a)(typeof a.hasOwnProperty!="function"||a.hasOwnProperty(h))&&(k(h),k(a[h]),d++);c[g+++r]=d>>8,c[g+r]=d&255}:(a,g)=>{let d,h=i.transitions||(i.transitions=Object.create(null)),u=0,b=0,S,v;if(this.keyMap){v=Object.keys(a).map(T=>this.encodeKey(T)),b=v.length;for(let T=0;T<b;T++){let Rt=v[T];d=h[Rt],d||(d=h[Rt]=Object.create(null),u++),h=d}}else for(let T in a)(typeof a.hasOwnProperty!="function"||a.hasOwnProperty(T))&&(d=h[T],d||(h[J]&1048576&&(S=h[J]&65535),d=h[T]=Object.create(null),u++),h=d,b++);let x=h[J];if(x!==void 0)x&=65535,c[o++]=217,c[o++]=x>>8|224,c[o++]=x&255;else if(v||(v=h.__keys__||(h.__keys__=Object.keys(a))),S===void 0?(x=i.nextId++,x||(x=0,i.nextId=1),x>=sr&&(i.nextId=(x=E)+1)):x=S,i[x]=v,x<E){c[o++]=217,c[o++]=x>>8|224,c[o++]=x&255,h=i.transitions;for(let T=0;T<b;T++)(h[J]===void 0||h[J]&1048576)&&(h[J]=x),h=h[v[T]];h[J]=x|1048576,n=!0}else{if(h[J]=x,L.setUint32(o,3655335680),o+=3,u&&(Ee+=Y*u),Z.length>=sr-E&&(Z.shift()[J]=void 0),Z.push(h),Q(b+2),k(57344+x),k(v),g)return;for(let T in a)(typeof a.hasOwnProperty!="function"||a.hasOwnProperty(T))&&k(a[T]);return}if(b<24?c[o++]=128|b:Q(b),!g)for(let T in a)(typeof a.hasOwnProperty!="function"||a.hasOwnProperty(T))&&k(a[T])},de=a=>{let g;if(a>16777216){if(a-r>nr)throw new Error("Encoded buffer would be larger than maximum buffer size");g=Math.min(nr,Math.round(Math.max((a-r)*(a>67108864?1.25:2),4194304)/4096)*4096)}else g=(Math.max(a-r<<2,c.length-1)>>12)+1<<12;let d=new ht(g);return L=new DataView(d.buffer,0,g),c.copy?c.copy(d,0,r,a):d.set(c.slice(r,a)),o-=r,r=0,re=d.length-10,c=d};let ne=100,It=1e3;this.encodeAsIterable=function(a,g){return Ot(a,g,he)},this.encodeAsAsyncIterable=function(a,g){return Ot(a,g,Tt)};function*he(a,g,d){let h=a.constructor;if(h===Object){let u=p.useRecords!==!1;u?V(a,!0):or(Object.keys(a).length,160);for(let b in a){let S=a[b];u||k(b),S&&typeof S=="object"?g[b]?yield*he(S,g[b]):yield*We(S,g,b):k(S)}}else if(h===Array){let u=a.length;Q(u);for(let b=0;b<u;b++){let S=a[b];S&&(typeof S=="object"||o-r>ne)?g.element?yield*he(S,g.element):yield*We(S,g,"element"):k(S)}}else if(a[Symbol.iterator]&&!a.buffer){c[o++]=159;for(let u of a)u&&(typeof u=="object"||o-r>ne)?g.element?yield*he(u,g.element):yield*We(u,g,"element"):k(u);c[o++]=255}else yt(a)?(or(a.size,64),yield c.subarray(r,o),yield a,Se()):a[Symbol.asyncIterator]?(c[o++]=159,yield c.subarray(r,o),yield a,Se(),c[o++]=255):k(a);d&&o>r?yield c.subarray(r,o):o-r>ne&&(yield c.subarray(r,o),Se())}function*We(a,g,d){let h=o-r;try{k(a),o-r>ne&&(yield c.subarray(r,o),Se())}catch(u){if(u.iteratorNotHandled)g[d]={},o=r+h,yield*he.call(this,a,g[d]);else throw u}}function Se(){ne=It,p.encode(null,mt)}function Ot(a,g,d){return g&&g.chunkThreshold?ne=It=g.chunkThreshold:ne=100,a&&typeof a=="object"?(p.encode(null,mt),d(a,p.iterateProperties||(p.iterateProperties={}),!0)):[p.encode(a)]}async function*Tt(a,g){for(let d of he(a,g,!0)){let h=d.constructor;if(h===rr||h===Uint8Array)yield d;else if(yt(d)){let u=d.stream().getReader(),b;for(;!(b=await u.read()).done;)yield b.value}else if(d[Symbol.asyncIterator])for await(let u of d)Se(),u?yield*Tt(u,g.async||(g.async={})):yield p.encode(u);else yield d}}}useBuffer(e){c=e,L=new DataView(c.buffer,c.byteOffset,c.byteLength),o=0}clearSharedData(){this.structures&&(this.structures=[]),this.sharedValues&&(this.sharedValues=void 0)}updateSharedData(){let e=this.sharedVersion||0;this.sharedVersion=e+1;let r=this.structures.slice(0),s=new ar(r,this.sharedValues,this.sharedVersion),n=this.saveShared(s,i=>(i&&i.version||0)==e);return n===!1?(s=this.getShared()||{},this.structures=s.structures||[],this.sharedValues=s.packedValues,this.sharedVersion=s.version,this.structures.nextId=this.structures.length):r.forEach((i,l)=>this.structures[l]=i),n}}function or(t,e){t<24?c[o++]=e|t:t<256?(c[o++]=e|24,c[o++]=t):t<65536?(c[o++]=e|25,c[o++]=t>>8,c[o++]=t&255):(c[o++]=e|26,L.setUint32(o,t),o+=4)}class ar{constructor(e,r,s){this.structures=e,this.packedValues=r,this.version=s}}function Q(t){t<24?c[o++]=128|t:t<256?(c[o++]=152,c[o++]=t):t<65536?(c[o++]=153,c[o++]=t>>8,c[o++]=t&255):(c[o++]=154,L.setUint32(o,t),o+=4)}const on=typeof Blob>"u"?function(){}:Blob;function yt(t){if(t instanceof on)return!0;let e=t[Symbol.toStringTag];return e==="Blob"||e==="File"}function $e(t,e){switch(typeof t){case"string":if(t.length>3){if(e.objectMap[t]>-1||e.values.length>=e.maxValues)return;let s=e.get(t);if(s)++s.count==2&&e.values.push(t);else if(e.set(t,{count:1}),e.samplingPackedValues){let n=e.samplingPackedValues.get(t);n?n.count++:e.samplingPackedValues.set(t,{count:1})}}break;case"object":if(t)if(t instanceof Array)for(let s=0,n=t.length;s<n;s++)$e(t[s],e);else{let s=!e.encoder.useRecords;for(var r in t)t.hasOwnProperty(r)&&(s&&$e(r,e),$e(t[r],e))}break;case"function":console.log(t)}}const an=new Uint8Array(new Uint16Array([1]).buffer)[0]==1;tr=[Date,Set,Error,RegExp,fe,ArrayBuffer,Uint8Array,Uint8ClampedArray,Uint16Array,Uint32Array,typeof BigUint64Array>"u"?function(){}:BigUint64Array,Int8Array,Int16Array,Int32Array,typeof BigInt64Array>"u"?function(){}:BigInt64Array,Float32Array,Float64Array,ar],dt=[{tag:1,encode(t,e){let r=t.getTime()/1e3;(this.useTimestamp32||t.getMilliseconds()===0)&&r>=0&&r<4294967296?(c[o++]=26,L.setUint32(o,r),o+=4):(c[o++]=251,L.setFloat64(o,r),o+=8)}},{tag:258,encode(t,e){let r=Array.from(t);e(r)}},{tag:27,encode(t,e){e([t.name,t.message])}},{tag:27,encode(t,e){e(["RegExp",t.source,t.flags])}},{getTag(t){return t.tag},encode(t,e){e(t.value)}},{encode(t,e,r){wt(t,r)}},{getTag(t){if(t.constructor===Uint8Array&&(this.tagUint8Array||Me&&this.tagUint8Array!==!1))return 64},encode(t,e,r){wt(t,r)}},X(68,1),X(69,2),X(70,4),X(71,8),X(72,1),X(77,2),X(78,4),X(79,8),X(85,4),X(86,8),{encode(t,e){let r=t.packedValues||[],s=t.structures||[];if(r.values.length>0){c[o++]=216,c[o++]=51,Q(4);let n=r.values;e(n),Q(0),Q(0),packedObjectMap=Object.create(sharedPackedObjectMap||null);for(let i=0,l=n.length;i<l;i++)packedObjectMap[n[i]]=i}if(s){L.setUint32(o,3655335424),o+=3;let n=s.slice(0);n.unshift(57344),n.push(new fe(t.version,1399353956)),e(n)}else e(new fe(t.version,1399353956))}}];function X(t,e){return!an&&e>1&&(t-=4),{tag:t,encode:function(s,n){let i=s.byteLength,l=s.byteOffset||0,y=s.buffer||s;n(Me?je.from(y,l,i):new Uint8Array(y,l,i))}}}function wt(t,e){let r=t.byteLength;r<24?c[o++]=64+r:r<256?(c[o++]=88,c[o++]=r):r<65536?(c[o++]=89,c[o++]=r>>8,c[o++]=r&255):(c[o++]=90,L.setUint32(o,r),o+=4),o+r>=c.length&&e(o+r),c.set(t.buffer?t:new Uint8Array(t),o),o+=r}function cn(t,e){let r,s=e.length*2,n=t.length-s;e.sort((i,l)=>i.offset>l.offset?1:-1);for(let i=0;i<e.length;i++){let l=e[i];l.id=i;for(let y of l.references)t[y++]=i>>8,t[y]=i&255}for(;r=e.pop();){let i=r.offset;t.copyWithin(i+s,i,n),s-=2;let l=i+s;t[l++]=216,t[l++]=28,n=i}return t}function cr(t,e){L.setUint32(j.position+t,o-j.position-t+1);let r=j;j=null,e(r[0]),e(r[1])}let gt=new ir({useRecords:!1});const ln=gt.encode;gt.encodeAsIterable,gt.encodeAsAsyncIterable;const lr=512,fn=1024,mt=2048;class un extends Vr{constructor(e){e||(e={}),e.objectMode=!0,super(e),e.structures=[],this.decoder=e.decoder||new be(e)}_transform(e,r,s){this.incompleteBuffer&&(e=Buffer.concat([this.incompleteBuffer,e]),this.incompleteBuffer=null);let n;try{n=this.decoder.decodeMultiple(e)}catch(i){if(i.incomplete)this.incompleteBuffer=e.slice(i.lastPosition),n=i.values;else return s(i)}finally{for(let i of n||[])i===null&&(i=this.getNullValue()),this.push(i)}s()}getNullValue(){return Symbol.for(null)}}const dn=process.env.CBOR_NATIVE_ACCELERATION_DISABLED!==void 0&&process.env.CBOR_NATIVE_ACCELERATION_DISABLED.toLowerCase()==="true";if(!dn){let t;try{typeof require=="function"?t=require("cbor-extract"):t=Kr(import.meta.url)("cbor-extract"),t&&Ws(t.extractStrings)}catch{}}const fr=["light","dark"],ur=["xs","s","m","l","xl","xxl","xxxl"];function hn(t){return{adbShellCommand:t.android?.shell,appearance:t.appearance,deviceType:t.id,disableVirtualKeyboard:t.android?.softKeyboard===!1?!0:void 0,fontSize:t.fontSize,iosAutocorrect:t.ios?.autocorrect,iosKeyboard:t.ios?.keyboards,language:t.locale,locale:t.locale,location:t.location&&[t.location.latitude,t.location.longitude],orientation:t.orientation,osVersion:t.osVersion,timezone:t.timezone}}const dr=["grant"];function pn(t){return{grantPermissions:t?.permissions==="grant"?!0:void 0,launchApp:t?.app,launchArgs:t?.ios?.args,launchUrl:t?.url,params:t?.params}}class hr extends Error{code;issues;constructor(e,r,s=[]){super(r),this.name="SessionRequestError",this.code=e,this.issues=s}}const P=t=>`expected ${t}`,ge=t=>m.string(P(t)).check(m.minLength(1,P(t))),Ue=t=>m.literal(t,P(`one of ${t.join(", ")}`)),me=t=>m.object(t,P("an object")),pr=()=>m.boolean(P("true or false")),yr=t=>m.number(P("a number")).check(m.gte(-t,P(`at least -${String(t)}`)),m.lte(t,P(`at most ${String(t)}`))),yn=/^\w{2}(?:_\w{2})?@sw(=[\w-]+)?$/,wn=/^[a-z0-9_.=:/ ()"-]+$/i,gn='letters, digits or _ . = : / ( ) " - and spaces',mn=/^[A-Za-z]{2,3}([-_][A-Za-z0-9]{2,8})*$/;function bn(t){if(!mn.test(t))return!1;try{return new Intl.Locale(t.replaceAll("_","-")),!0}catch{return!1}}function En(t){try{return new Intl.DateTimeFormat(void 0,{timeZone:t}),!0}catch{return!1}}const bt={code:"needsTarget"},wr={code:"needsLaunchApp"},Et="has no effect without a target",gr="has no effect without a target, or with launch.app: false";function mr({launch:t}){return t?.app!==!1}const Sn=m.object({apiToken:m.optional(ge("an API token")),codec:m.optional(Ue(es)),device:me({android:m.optional(me({shell:m.optional(ge("a shell command")),softKeyboard:m.optional(pr())})),appearance:m.optional(Ue(fr)),fontSize:m.optional(Ue(ur)),id:ge("a device id"),ios:m.optional(me({autocorrect:m.optional(pr()),keyboards:m.optional(m.array(m.string(P("a keyboard layout")).check(m.regex(yn,P("a layout like en_US@sw=QWERTY"))),P("a list of keyboard layouts")))})),locale:m.optional(m.string(P("a BCP 47 tag, e.g. fr-CA")).check(m.refine(bn,{error:P("a BCP 47 tag, e.g. fr-CA")}))),location:m.optional(me({latitude:yr(90),longitude:yr(180)})),orientation:m.optional(Ue(_t)),osVersion:m.optional(ge("an OS version")),timezone:m.optional(m.string(P("an IANA timezone")).check(m.refine(En,{error:P("an IANA timezone, e.g. America/Toronto")})))}),endpoint:m.optional(m.url(P("a URL"))),launch:m.optional(me({app:m.optional(m.union([ge("an app id"),m.literal(!1)],P("an app id or false"))),ios:m.optional(me({args:m.optional(m.array(m.string(P("an argument")).check(m.regex(wn,P(gn))),P("a list of arguments")).check(m.maxLength(20,P("at most 20 arguments"))))})),params:m.optional(m.custom(t=>typeof t=="object"&&t!==null&&!Array.isArray(t),P("an object"))),permissions:m.optional(Ue(dr)),url:m.optional(m.url(P("a URL")))})),proxy:m.optional(m.union([m.literal("intercept"),m.templateLiteral(["http://",m.string()])],P("intercept or an http:// URL"))),target:m.optional(ge("an app, build or group id"))}).check(m.refine(t=>t.device.android?.shell===void 0||t.target!==void 0,{error:Et,params:bt,path:["device","android","shell"]}),m.refine(t=>t.launch?.app===void 0||t.target!==void 0,{error:Et,params:bt,path:["launch","app"]}),m.refine(t=>t.launch?.permissions===void 0||t.target!==void 0,{error:Et,params:bt,path:["launch","permissions"]}),m.refine(t=>t.launch?.params===void 0||t.target!==void 0&&mr(t),{error:gr,params:wr,path:["launch","params"]}),m.refine(t=>t.launch?.ios?.args===void 0||t.target!==void 0&&mr(t),{error:gr,params:wr,path:["launch","ios","args"]}));function vn(t){if(t.code==="custom"){const e=t.params?.code;if(e==="needsTarget"||e==="needsLaunchApp")return e}return"invalidValue"}function An(t){const e=Sn.safeParse(t);if(e.success)return;const r=e.error.issues.map(s=>({code:vn(s),message:s.message,path:s.path.join(".")}));throw new hr("invalid",r.map(({message:s,path:n})=>`${n}: ${s}`).join(`
2
+ `),r)}const xn={dateStyle:"medium",timeStyle:"short"},kn=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(?::\d{2}(?:\.\d+)?)?(?:Z|[+-]\d{2}:\d{2})$/;function Ve(t){return Array.isArray(t)?t.map(Ve).join(", "):typeof t=="boolean"?t?"yes":"no":typeof t=="number"?t.toLocaleString():In(t)}function In(t){if(kn.test(t)){const r=new Date(t);if(!Number.isNaN(r.getTime()))return r.toLocaleString(void 0,xn)}const e=Ut();return t===e?"~":t.startsWith(`${e}${$r}`)?`~${t.slice(e.length)}`:t}function br(){return process.env.APPETIZE_CLI_HOME??ie(Ut(),".appetize","cli","sessions")}function St(t){return ie(br(),t)}class Ke extends Error{details;constructor(e,r={},s){super(e,s===void 0?void 0:{cause:s}),this.name="CommandError",this.details=r}hints(e){return[]}}class Ce extends Ke{sessionDir;constructor(e,{cause:r,details:s={},sessionId:n}){const i=St(n);super(e,Object.assign({sessionDir:i},s),r),this.name="SessionError",this.sessionDir=i}static wrap(e,r){if(e instanceof Ce||e instanceof se)return e;const s=e instanceof Error?e.message:String(e),n=e instanceof Ke?e.details:{};return new Ce(s,{cause:e,details:n,sessionId:r})}hints(){return[`Check the session logs for details: ${Ve(this.sessionDir)}`]}}class On extends Ce{constructor(e){super(`Session ${e} already exists`,{sessionId:e}),this.name="SessionAlreadyExistsError"}hints(){return[`Pass --force to replace it, deleting ${Ve(this.sessionDir)}`]}}class se extends Ke{#e;constructor(e,r=[]){super(e),this.name="UsageError",this.#e=r}hints({command:e}){return[...this.#e,`Run 'appetize ${e} --help' for usage`]}}function Tn(t,e,r){const s=e instanceof Error?e.message:String(e);if(!(e instanceof Ke))return t==="json"?JSON.stringify({error:{message:s}},null,2):`\u2716 ${s}`;const n=e.hints(r);if(t==="json"){const i=n.length>0?{hints:n}:{};return JSON.stringify({error:{message:s,...e.details,...i}},null,2)}return[`\u2716 ${s}`,...n.map(i=>` ${i}`)].join(`
3
+ `)}function vt(t){try{return process.kill(t,0),!0}catch{return!1}}const Rn=["SIGINT","SIGTERM"],Mn=150;function Un(t){const e=new AbortController,r=setInterval(()=>{vt(t)||(clearInterval(r),e.abort(new Error("The device session exited")))},Mn);return r.unref(),e.signal}function Er(){const t=new AbortController;for(const e of Rn)process.once(e,()=>{t.abort(new Error(`Received ${e}`))});return t.signal}function Ln(t,e){return new Promise((r,s)=>{if(e.aborted){s(Sr(e.reason));return}const n=()=>{clearTimeout(i),s(Sr(e.reason))},i=setTimeout(()=>{e.removeEventListener("abort",n),r()},t);e.addEventListener("abort",n,{once:!0})})}function Sr(t){return t instanceof Error?t:new Error(String(t))}function Cn(t){return Object.values(t).some(e=>e!==void 0)?t:void 0}function Pn(t,{defaultValue:e=!1}={}){return t===!e?!e:void 0}function _n(t,e,r){const s=qe(t,r);if(s===void 0)return;const n=e.find(i=>i===s);if(n===void 0)throw new se(`${r} expects one of ${e.join(", ")}`);return n}function Nn(t){const e=t.at(-1);return{options:zn(e)?e:{},positionals:t.slice(0,-1).filter(r=>typeof r=="string"),signal:Er()}}function Dn(t,e){const r=vr(t,e);return r===void 0?void 0:Ar(r,e)}function vr(t,e){if(t===void 0)return;const r=typeof t=="boolean"?Number.NaN:Number(t);if(!Number.isFinite(r))throw new se(`${e} expects a number, e.g., ${e}=-0.1`);return r}function Bn(t,e){return t===void 0?void 0:(Array.isArray(t)?t:[t]).map(s=>xr(s,e))}function qe(t,e){if(t!==void 0){if(typeof t!="string"||t==="")throw new se(`${e} needs a value`);return t}}function Ar(t,e){if(!(t>=0&&t<=1))throw new se(`${e} expects a number between 0 and 1`);return t}function xr(t,e){const r=qe(t,e);if(r===void 0)throw new se(`${e} needs a value`);return r}function zn(t){return typeof t=="object"&&t!==null}const Fn="APPETIZEIO_FEATURE_FLAGS";function jn(){const t={};for(const e of(process.env[Fn]??"").split(",")){const r=e.trim();r!==""&&(t[r]=!0)}return t}function $n(){const t=process.env.APPETIZE_API_TOKEN;if(!t)throw new Error("APPETIZE_API_TOKEN must be set");return t}function kr(t){return qe(t.endpoint,"--endpoint")??Vn()}function Vn(){const t=process.env.APPETIZE_ENDPOINT?.trim();return t===""?void 0:t}const Kn="https://appetize.io";async function Ir(t,{authorize:e=!0,commandOptions:r={},query:s={},...n}={}){const i=new URL(t,kr(r)??Kn);for(const[p,A]of Object.entries(s))i.searchParams.set(p,A);const l=new Headers(n.headers);e&&l.set("x-api-key",$n());const y=await fetch(i,{...n,headers:l});if(!y.ok)throw new Error(await Wn(y));return await y.json()}function qn(t){if(!(typeof t!="object"||t===null||!("message"in t)))return typeof t.message=="string"?t.message:void 0}async function Wn(t){const e=`The webserver rejected the request (${String(t.status)})`,r=await t.json().catch(()=>{}),s=qn(r);return s?`${e}: ${s}`:e}const Or=["android","ios"];function Tr(t={},e){return Ir("/api/v2/service/devices",{authorize:!1,commandOptions:t,signal:e})}function Jn(t){return Or.includes(t)}async function Gn(t,e={}){return(await Tr(e)).find(s=>s.id===t)?.platform}function Hn(t){let e={...t,updatedAt:new Date().toISOString()};return{path:xt(e.sessionId),save:r=>(e={...e,...r,updatedAt:new Date().toISOString()},si(e),e)}}function Rr(t){const e=t.state?.phase;return e==="ended"||e==="error"?!1:vt(t.pid)}function Zn(){const t=br();return Mt(t,{recursive:!0}),jr(t).map(e=>At(e)).filter(e=>e!==void 0)}function Yn(t){if(t!==void 0){const r=At(t);if(!r)throw new Error(`No session found for id ${t}`);return r}const e=Zn().filter(Rr);if(e.length===0)throw new Error("No active sessions");if(e.length>1)throw new se("There are multiple active sessions",["Specify --session-id to pick one"]);return e[0]}function At(t){try{return JSON.parse(zr(xt(t),"utf8"))}catch{return}}function Qn(t){Fr(St(t),{force:!0,recursive:!0})}function Xn(t){return ie(Le(t),"control.sock")}function Mr(t){return ie(Le(t),"daemon.log")}function ei(t){return ie(Le(t),"device.log.jsonl")}function ti(t,e){return{daemon:Mr(t),device:ei(t),...e==="intercept"?{network:ri(t)}:void 0}}function ri(t){return ie(Le(t),"network.jsonl")}function Le(t){const e=St(t);return Mt(e,{recursive:!0}),e}function xt(t){return ie(Le(t),"state.json")}function si(t){const e=xt(t.sessionId),r=`${e}.tmp`;Dr(r,`${JSON.stringify(t,null,2)}
4
+ `),Br(r,e)}const kt="APPETIZE_DAEMON_CONFIG";function ni(){const t=process.env[kt];if(!t)throw new Error(`${kt} is not set`);return JSON.parse(t)}function ii(t){return JSON.stringify(t)}function oi(){let t,e;return{promise:new Promise((s,n)=>{e=s,t=n}),reject:t,resolve:e}}const Ur={useRecords:!1},ai=new ir(Ur);class Lr extends ve{#e=[];#t;constructor(e,{signal:r}={}){super(async l=>{this.#t.write(ai.encode(l))},{signal:r}),this.#t=e;const s=new un(Ur);s.on("data",l=>{Qe(l)&&this[U].dispatchMessage(l)}),s.on("error",()=>{this.close()});const n=l=>{s.write(l)},i=()=>{this.close()};e.on("data",n),e.once("close",i),e.once("error",i),this.#e.push(()=>{e.off("data",n),e.off("close",i),e.off("error",i),s.destroy()})}handleClose(e){for(const r of this.#e.splice(0))r();super.handleClose(e)}}function ci(t,e){const{promise:r,reject:s,resolve:n}=oi(),i=qr(t),l=e?.signal,y=()=>{i.off("connect",E),i.off("error",R),l?.removeEventListener("abort",A)},p=M=>{y(),i.destroy(),s(M)},A=()=>{p(new Error("The connection was aborted"))},E=()=>{y();const M=new Lr(i,e);M[U].addEventListener("close",()=>{i.destroy()},{once:!0}),n(M)},R=M=>{p(M)};return l?.aborted?(p(new Error("The connection was aborted")),r):(i.once("connect",E),i.once("error",R),l?.addEventListener("abort",A,{once:!0}),r)}export{Lr as $,kr as A,At as B,On as C,kt as D,Qn as E,ti as F,Dn as G,Ve as H,ci as I,Fs as J,Ct as K,Yn as L,Nn as M,Tn as N,Ze as O,ln as P,U as Q,rn as R,Ce as S,ve as T,se as U,Qe as V,Vt as W,Ne as X,pn as Y,hn as Z,He as _,vr as a,ni as a0,Hn as a1,Gn as a2,Xn as a3,Er as a4,Tr as b,Or as c,Ln as d,jt as e,Ir as f,xr as g,_t as h,Jn as i,Mr as j,Rr as k,vt as l,Un as m,Cn as n,Pn as o,qe as p,Bn as q,Ar as r,ii as s,_n as t,ur as u,fr as v,dr as w,An as x,hr as y,jn as z};