@ycodium-ai/plugin-devices 0.2.3799 → 0.2.3817

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -36,14 +36,19 @@ path on the client computer.
36
36
 
37
37
  For Android, the plugin detects and validates an existing SDK with runnable `adb`
38
38
  and `emulator`. Existing virtual devices can be reused without installing
39
- `avdmanager` or changing the SDK. Running an existing virtual device still writes
39
+ `avdmanager`, Java or ffmpeg, and without changing the SDK: the device helper answers
40
+ the device hub's `avdmanager list avd` from the AVD folder, and screens stream through
41
+ the bundled scrcpy server. Running an existing virtual device still writes
40
42
  to that device's data. An incompatible running ADB server is reported without
41
43
  stopping or restarting it.
42
44
 
43
45
  If a private environment is needed, accept the Android SDK license and choose
44
46
  **Download and prepare**. The plugin downloads fixed official Google archives for
45
47
  Platform-Tools, Emulator and an Android 15 AOSP system image, checks their recorded
46
- sizes and official checksums, and creates a private virtual device. SDK files,
48
+ sizes and official checksums, and creates a private virtual device. The panel shows
49
+ the current component, amount, speed and time left; cancelling keeps components that
50
+ finished downloading. **Download proxy** in the Devices settings chooses the proxy
51
+ for these downloads when the machine default is slow. SDK files,
47
52
  Android preferences, emulator configuration, AVD data and controlled temporary files
48
53
  use the selected private storage. Global environment variables and shell files are
49
54
  not changed. The plugin does not install an application build toolchain or Java.
package/assets/ui.js CHANGED
@@ -1,4 +1,4 @@
1
- var ta=`/*! tailwindcss v4.3.0 | MIT License | https://tailwindcss.com */
1
+ var ra=`/*! tailwindcss v4.3.0 | MIT License | https://tailwindcss.com */
2
2
  @layer properties, theme, base, components, utilities;
3
3
  @layer properties;
4
4
  @layer utilities {
@@ -90,6 +90,9 @@ var ta=`/*! tailwindcss v4.3.0 | MIT License | https://tailwindcss.com */
90
90
  width: 100%;
91
91
  height: 100%;
92
92
  }
93
+ .h-1\\.5:where(:scope, *) {
94
+ height: calc(var(--spacing, 0.25rem) * 1.5);
95
+ }
93
96
  .h-9:where(:scope, *) {
94
97
  height: calc(var(--spacing, 0.25rem) * 9);
95
98
  }
@@ -358,6 +361,12 @@ var ta=`/*! tailwindcss v4.3.0 | MIT License | https://tailwindcss.com */
358
361
  background-color: color-mix(in oklab, var(--info) 10%, transparent);
359
362
  }
360
363
  }
364
+ .bg-muted:where(:scope, *) {
365
+ background-color: var(--muted);
366
+ }
367
+ .bg-primary:where(:scope, *) {
368
+ background-color: var(--primary);
369
+ }
361
370
  .bg-warning:where(:scope, *) {
362
371
  background-color: var(--warning);
363
372
  }
@@ -548,7 +557,7 @@ var ta=`/*! tailwindcss v4.3.0 | MIT License | https://tailwindcss.com */
548
557
  }
549
558
  }
550
559
  }
551
- `;var so=window.__ycodiumPluginHost.react;var{Activity:Dr,Children:Pr,Component:Ar,Fragment:Tr,Profiler:Br,PureComponent:Mr,StrictMode:Rr,Suspense:Fr,__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE:Ur,__COMPILER_RUNTIME:Or,act:Er,cache:qr,cacheSignal:Hr,captureOwnerStack:Nr,cloneElement:Gr,createContext:ka,createElement:le,createRef:Vr,forwardRef:Re,isValidElement:zr,lazy:_r,memo:Wr,startTransition:Kr,unstable_useCacheRefresh:Xr,use:$r,useActionState:jr,useCallback:se,useContext:Da,useDebugValue:Zr,useDeferredValue:Jr,useEffect:T,useEffectEvent:Qr,useId:Yr,useImperativeHandle:el,useInsertionEffect:al,useLayoutEffect:Pa,useMemo:de,useOptimistic:tl,useReducer:ol,useRef:q,useState:h,useSyncExternalStore:Aa,useTransition:rl,version:ll}=so;var Ta=ka(null),Fe=Ta.Provider;function E(){let e=Da(Ta);if(e===null)throw new Error("The devices panel has not been registered.");return e}var Ba=window.__ycodiumPluginHost.modules?.["@ycodium-ai/plugin-api/ui"];if(!Ba)throw new Error("This plugin needs a newer Ycodium app. Update the app.");var{HOST_TEAM_VIEW_PREFIX:nl,PLUGIN_UI_BRIDGE_VERSION:il,PLUGIN_UI_FLOATING_VIEW_PROP:Ma,PLUGIN_UI_GLOBAL_KEY:fl,PLUGIN_UI_HOST_CAPABILITIES:cl,PLUGIN_UI_HOST_COMMAND_PALETTE_UNAVAILABLE_MESSAGE:pl,PLUGIN_UI_HOST_UPGRADE_MESSAGE:ml,TEAM_VIEW_KEY_PATTERN:gl,communicationRecordStage:Ll,defineTeamView:hl,isTeamViewKey:xl,pluginUiHostHasCapability:ne}=Ba;var uo="deviceFloat",Ue="device",_=e=>`${e.hostId}\0${e.id}`;function he(e){let a={hostId:e.hostId,deviceId:e.id,platform:e.platform};return{viewId:uo,key:_(e),title:e.name,props:{...a},sourceSize:e.platform==="ios"?{width:9,height:19.5}:{width:9,height:20},...e.platform==="android"?{cornerRatio:.14}:{}}}function Ra(e){let a=e.orientation==="landscape_left"||e.orientation==="landscape_right",t=Math.max(e.width,e.height),o=Math.min(e.width,e.height);return a?{width:t,height:o}:{width:o,height:t}}var oa=new Map,ra=new Set,Oe=(e,a)=>`${e}\0${a}`;function Fa(e,a){return Aa(t=>(ra.add(t),()=>{ra.delete(t)}),()=>oa.get(Oe(e,a))??null)}function Ee(e,a,t){let o=Oe(e,a);if((oa.get(o)??null)!==t){oa.set(o,t);for(let l of ra)l()}}var la=new Set;function sa(e,a,t,o=!0){let l=`${Oe(e,a)}\0${t}`;o?la.add(l):la.delete(l)}function Ua(e){let a=new Set,t=[];for(let o of e.sessions){if(o.threadId!==e.threadId)continue;let l=e.devices.find(u=>u.hostId===o.hostId&&u.id===o.deviceId);if(l===void 0)continue;let d=_(l);if(a.add(d),e.previous===null||e.previous.has(d))continue;let s=`${Oe(e.environmentId,e.threadId)}\0${d}`;la.delete(s)||t.push(l)}return{seen:a,opened:t}}var qe="ycodium-devices-ui";function k(e){return(a=>le(E().ui[e],{...a,className:`${qe} ${typeof a.className=="string"?a.className:""}`}))}var I=k("Button"),H=k("Spinner"),ie=k("Switch"),Oa=k("Tooltip"),Ea=k("TooltipPopup"),qa=k("TooltipTrigger"),He=k("Menu"),Ne=k("MenuPopup"),xe=k("MenuItem"),Ha=k("MenuSeparator"),Ge=k("MenuTrigger"),Na=k("MenuRadioGroup"),Ga=k("MenuRadioItem"),Q=k("Input"),Va=k("Textarea"),da=k("Select"),ua=k("SelectTrigger"),na=k("SelectValue"),ia=k("SelectPopup"),fa=k("SelectItem"),Ve=k("Collapsible"),ze=k("CollapsibleTrigger"),_e=k("CollapsiblePanel"),za=k("ToggleGroup"),_a=k("Toggle"),Wa=k("Popover"),Ka=k("PopoverTrigger"),Xa=k("PopoverPopup");var{jsx:r,jsxs:f,Fragment:Z}=window.__ycodiumPluginHost.jsxRuntime;function J(e){return f("div",{className:"flex size-full flex-col items-center justify-center gap-3 p-6 text-center",children:[e.stage==="error"?null:r(H,{size:"sm"}),f("div",{className:"space-y-1",children:[r("p",{className:"text-sm font-medium text-foreground",children:e.name}),e.description?r("p",{className:"text-xs text-muted-foreground",children:e.description}):null]}),r("p",{role:e.stage==="error"?"alert":"status",className:e.stage==="error"?"max-w-sm whitespace-pre-wrap break-words text-xs text-destructive-foreground":"max-w-sm text-xs text-muted-foreground",children:e.message}),e.children]})}var We=class{decoder=new TextDecoder;rawDecoder=new TextDecoder("utf-8",{ignoreBOM:!0});pending="";raw="";data=[];eventName="";lastId=null;push(a){let t=[];return this.scan(a,!1,(o,l)=>{l!==void 0&&t.push(l)}),t}pushBlocks(a){let t=[];return this.scan(a,!0,(o,l)=>t.push({raw:o,event:l})),t}scan(a,t,o){let l=this.decoder.decode(a,{stream:!0}),d=this.pending+l;if(this.rawDecoder!==void 0){let u=this.rawDecoder.decode(a,{stream:!0});t&&(this.raw+=u.slice(0,u.length-l.length)),d.length>0&&(this.rawDecoder=void 0,d.charCodeAt(0)===65279&&(t&&(this.raw+=d[0]),d=d.slice(1)))}let s=0;for(let u=0;u<d.length;u++){let n=d[u];if(n!==`
560
+ `;var mo=window.__ycodiumPluginHost.react;var{Activity:Fr,Children:Er,Component:Or,Fragment:Ur,Profiler:qr,PureComponent:Hr,StrictMode:Nr,Suspense:Gr,__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE:Vr,__COMPILER_RUNTIME:zr,act:_r,cache:Wr,cacheSignal:Kr,captureOwnerStack:Xr,cloneElement:$r,createContext:Da,createElement:se,createRef:jr,forwardRef:Ee,isValidElement:Zr,lazy:Jr,memo:Qr,startTransition:Yr,unstable_useCacheRefresh:el,use:al,useActionState:tl,useCallback:de,useContext:Pa,useDebugValue:ol,useDeferredValue:rl,useEffect:T,useEffectEvent:ll,useId:sl,useImperativeHandle:dl,useInsertionEffect:ul,useLayoutEffect:Aa,useMemo:ue,useOptimistic:nl,useReducer:il,useRef:V,useState:h,useSyncExternalStore:Ta,useTransition:fl,version:cl}=mo;var Ba=Da(null),Oe=Ba.Provider;function q(){let e=Pa(Ba);if(e===null)throw new Error("The devices panel has not been registered.");return e}var Ma=window.__ycodiumPluginHost.modules?.["@ycodium-ai/plugin-api/ui"];if(!Ma)throw new Error("This plugin needs a newer Ycodium app. Update the app.");var{HOST_TEAM_VIEW_PREFIX:Ll,PLUGIN_UI_BRIDGE_VERSION:hl,PLUGIN_UI_FLOATING_VIEW_PROP:Ra,PLUGIN_UI_GLOBAL_KEY:xl,PLUGIN_UI_HOST_CAPABILITIES:Il,PLUGIN_UI_HOST_COMMAND_PALETTE_UNAVAILABLE_MESSAGE:Cl,PLUGIN_UI_HOST_UPGRADE_MESSAGE:Sl,TEAM_VIEW_KEY_PATTERN:vl,communicationRecordStage:yl,defineTeamView:wl,isTeamViewKey:bl,pluginUiHostHasCapability:ie}=Ma;var go="deviceFloat",Ue="device",X=e=>`${e.hostId}\0${e.id}`;function xe(e){let a={hostId:e.hostId,deviceId:e.id,platform:e.platform};return{viewId:go,key:X(e),title:e.name,props:{...a},sourceSize:e.platform==="ios"?{width:9,height:19.5}:{width:9,height:20},...e.platform==="android"?{cornerRatio:.14}:{}}}function Fa(e){let a=e.orientation==="landscape_left"||e.orientation==="landscape_right",t=Math.max(e.width,e.height),o=Math.min(e.width,e.height);return a?{width:t,height:o}:{width:o,height:t}}var la=new Map,sa=new Set,qe=(e,a)=>`${e}\0${a}`;function Ea(e,a){return Ta(t=>(sa.add(t),()=>{sa.delete(t)}),()=>la.get(qe(e,a))??null)}function He(e,a,t){let o=qe(e,a);if((la.get(o)??null)!==t){la.set(o,t);for(let l of sa)l()}}var da=new Set;function ua(e,a,t,o=!0){let l=`${qe(e,a)}\0${t}`;o?da.add(l):da.delete(l)}function Oa(e){let a=new Set,t=[];for(let o of e.sessions){if(o.threadId!==e.threadId)continue;let l=e.devices.find(u=>u.hostId===o.hostId&&u.id===o.deviceId);if(l===void 0)continue;let d=X(l);if(a.add(d),e.previous===null||e.previous.has(d))continue;let s=`${qe(e.environmentId,e.threadId)}\0${d}`;da.delete(s)||t.push(l)}return{seen:a,opened:t}}var Ne="ycodium-devices-ui";function b(e){return(a=>se(q().ui[e],{...a,className:`${Ne} ${typeof a.className=="string"?a.className:""}`}))}var I=b("Button"),H=b("Spinner"),fe=b("Switch"),Ua=b("Tooltip"),qa=b("TooltipPopup"),Ha=b("TooltipTrigger"),Ge=b("Menu"),Ve=b("MenuPopup"),Ie=b("MenuItem"),Na=b("MenuSeparator"),ze=b("MenuTrigger"),Ga=b("MenuRadioGroup"),Va=b("MenuRadioItem"),ee=b("Input"),za=b("Textarea"),na=b("Select"),ia=b("SelectTrigger"),fa=b("SelectValue"),ca=b("SelectPopup"),pa=b("SelectItem"),_e=b("Collapsible"),We=b("CollapsibleTrigger"),Ke=b("CollapsiblePanel"),_a=b("ToggleGroup"),Wa=b("Toggle"),Ka=b("Popover"),Xa=b("PopoverTrigger"),$a=b("PopoverPopup");var{jsx:r,jsxs:f,Fragment:$}=window.__ycodiumPluginHost.jsxRuntime;function Y(e){return f("div",{className:"flex size-full flex-col items-center justify-center gap-3 p-6 text-center",children:[e.stage==="error"?null:r(H,{size:"sm"}),f("div",{className:"space-y-1",children:[r("p",{className:"text-sm font-medium text-foreground",children:e.name}),e.description?r("p",{className:"text-xs text-muted-foreground",children:e.description}):null]}),r("p",{role:e.stage==="error"?"alert":"status",className:e.stage==="error"?"max-w-sm whitespace-pre-wrap break-words text-xs text-destructive-foreground":"max-w-sm text-xs text-muted-foreground",children:e.message}),e.children]})}var Xe=class{decoder=new TextDecoder;rawDecoder=new TextDecoder("utf-8",{ignoreBOM:!0});pending="";raw="";data=[];eventName="";lastId=null;push(a){let t=[];return this.scan(a,!1,(o,l)=>{l!==void 0&&t.push(l)}),t}pushBlocks(a){let t=[];return this.scan(a,!0,(o,l)=>t.push({raw:o,event:l})),t}scan(a,t,o){let l=this.decoder.decode(a,{stream:!0}),d=this.pending+l;if(this.rawDecoder!==void 0){let u=this.rawDecoder.decode(a,{stream:!0});t&&(this.raw+=u.slice(0,u.length-l.length)),d.length>0&&(this.rawDecoder=void 0,d.charCodeAt(0)===65279&&(t&&(this.raw+=d[0]),d=d.slice(1)))}let s=0;for(let u=0;u<d.length;u++){let n=d[u];if(n!==`
552
561
  `&&n!=="\r")continue;if(n==="\r"&&u===d.length-1)break;let i=d.slice(s,u);n==="\r"&&d[u+1]===`
553
562
  `&&u++,t&&(this.raw+=d.slice(s,u+1));let c=this.line(i);i===""&&(o(this.raw,c),this.raw=""),s=u+1}this.pending=d.slice(s)}flush(){let a=this.raw+this.pending+this.decoder.decode();return this.raw="",this.pending="",this.data=[],this.eventName="",a}line(a){if(a===""){let d=this.data.length>0?{event:this.eventName||"message",data:this.data.join(`
554
- `),id:this.lastId}:void 0;return this.data=[],this.eventName="",d}if(a.startsWith(":"))return;let t=a.indexOf(":"),o=t===-1?a:a.slice(0,t),l=t===-1?"":a.slice(t+1);l.startsWith(" ")&&(l=l.slice(1)),o==="data"?this.data.push(l):o==="event"?this.eventName=l:o==="id"&&!l.includes("\0")&&(this.lastId=l)}};async function Ke(e,a,t){let o=e.body;if(!o)throw new Error("The response has no body to stream.");let l=o.getReader(),d=()=>{l.cancel().catch(()=>{})};if(t?.aborted)return d();t?.addEventListener("abort",d,{once:!0});try{for(;;){let{done:s,value:u}=await l.read();if(s||t?.aborted)return;a(u)}}catch(s){if(t?.aborted)return;throw s}finally{t?.removeEventListener("abort",d)}}async function $a(e,a,t){if(!e.ok)throw await e.body?.cancel().catch(()=>{}),new Error(`Event stream failed (${e.status}).`);let o=new We;await Ke(e,l=>{for(let d of o.push(l))a(d)},t)}var fe=e=>e==="ios"?"/vendor/serve-sim":"/vendor/serve-emu";var no=1e3,io=500,Xe=(e,a,t)=>`${fe(e.platform)}${a}${t?`?${new URLSearchParams(t).toString()}`:""}`,ja=async(e,a,t)=>{let o=await e.transport.fetch(a,t?{signal:t}:void 0);if(!o.ok)throw new Error(`${o.status} ${o.statusText}`);return await o.json()},W=e=>typeof e=="object"&&e!==null,z=(e,a)=>typeof e=="number"&&Number.isFinite(e)?e:a,fo=e=>{let a=e[0],t=W(a)&&W(a.frame)?a.frame:null,o=Math.max(1,z(t?.width,1)),l=Math.max(1,z(t?.height,1)),d=[],s=(u,n)=>{if(d.length>=io||!W(u)||!W(u.frame))return;let i=u.frame,c=z(i.width,0),m=z(i.height,0);!(Math.abs(c-o)<.5&&Math.abs(m-l)<.5)&&c>0&&m>0&&d.push({id:typeof u.AXUniqueId=="string"?u.AXUniqueId:n,label:typeof u.AXLabel=="string"?u.AXLabel:"",role:typeof u.type=="string"?u.type:"",x:z(i.x,0)/o,y:z(i.y,0)/l,width:c/o,height:m/l}),(Array.isArray(u.children)?u.children:[]).forEach((w,y)=>s(w,`${n}.${y}`))};return e.forEach((u,n)=>s(u,String(n))),d},Za=e=>W(e)&&typeof e.error=="string"?e.error:"Unexpected accessibility payload.";async function Qa(e,a){if(e.platform==="ios"){let n=await ja(e,Xe(e,`/helper/${encodeURIComponent(e.deviceId)}/ax`),a);return Array.isArray(n)?{elements:fo(n),errors:[]}:{elements:[],errors:[Za(n)]}}let t=await ja(e,Xe(e,"/api/accessibility",{device:e.deviceId}),a);if(!W(t)||!Array.isArray(t.nodes))return{elements:[],errors:[Za(t)]};let o=t.nodes.filter(n=>W(n)&&W(n.bounds)),l=o[0]?.bounds,d=Math.max(1,z(l?.right,1)),s=Math.max(1,z(l?.bottom,1));return{elements:o.slice(1).flatMap(n=>{let i=n.bounds,c=z(i.left,0),m=z(i.top,0),x=(z(i.right,c)-c)/d,L=(z(i.bottom,m)-m)/s,w=typeof n.text=="string"?n.text:"",y=typeof n.contentDescription=="string"?n.contentDescription:"",b=w||y;if(x>=.95&&L>=.9)return[];if(!b&&n.clickable!==!0)return[];let g=typeof n.className=="string"?n.className:"";return[{id:String(n.id??""),label:b,role:g.split(".").at(-1)??"",x:c/d,y:m/s,width:x,height:L}]}),errors:[]}}var Ya=(e,a,t)=>{let o=new AbortController,l=null,d=()=>{e.transport.fetch(a,{signal:o.signal}).then(s=>$a(s,u=>{try{t(JSON.parse(u.data))}catch{}},o.signal)).catch(()=>{}).finally(()=>{o.signal.aborted||(l=setTimeout(d,no))})};return d(),()=>{o.abort(),l!==null&&clearTimeout(l)}};function et(e,a){return e.platform!=="ios"?()=>{}:Ya(e,Xe(e,"/appstate",{device:e.deviceId}),t=>{if(W(t)){if(t.bundleId===null||t.bundleId===""){a(null);return}typeof t.bundleId=="string"&&a({id:t.bundleId,...typeof t.pid=="number"?{pid:t.pid}:{},...typeof t.isReactNative=="boolean"?{isReactNative:t.isReactNative}:{}})}})}var Ja=e=>!W(e)||typeof e.id!="number"?null:{id:e.id,timestamp:typeof e.timestamp=="string"?e.timestamp:"",kind:typeof e.kind=="string"?e.kind:"",summary:typeof e.summary=="string"?e.summary:typeof e.msg=="string"?e.msg:""};function at(e,a){return e.platform!=="ios"?()=>{}:Ya(e,Xe(e,"/api/event-log/events",{device:e.deviceId,limit:"100"}),t=>{if(!W(t))return;if(Array.isArray(t.events)){a(t.events.flatMap(l=>Ja(l)??[]),!0);return}let o=Ja(t.event);o&&a([o],!1)})}function B(){return{t:E().i18n.usePluginTranslation()}}function je(e){if(e.length<4)return"avc1.42E01E";let a=t=>t.toString(16).padStart(2,"0");return`avc1.${a(e[1])}${a(e[2])}${a(e[3])}`}function tt(e){let a=new Uint8Array(e);if(a.byteLength>16){let t=new DataView(e,0,16);if(t.getUint32(0,!1)===1397050709&&t.getUint8(4)===1){let o=t.getBigUint64(8,!1);return{data:a.subarray(16),isKey:(t.getUint8(5)&1)!==0,timestamp:o<=BigInt(Number.MAX_SAFE_INTEGER)?Number(o):null}}}return{data:a,isKey:null,timestamp:null}}var ot=e=>{try{return JSON.parse(e)?.type==="video-session"}catch{return!1}};function rt(e){let a=!1,t=null,o=e.length,l=0;for(;l+2<o;){if(e[l]===0&&e[l+1]===0){let d=0;if(e[l+2]===1?d=3:l+3<o&&e[l+2]===0&&e[l+3]===1&&(d=4),d){let s=e[l+d]&31;s===7&&!t&&(t=e.subarray(l+d)),s===5&&(a=!0),l+=d+1;continue}}l++}return{isKey:a,sps:t}}var co={1:"description",2:"keyframe",3:"delta",4:"seed"},$e=class{buffer=new Uint8Array(64*1024);length=0;push(a){if(this.length+a.length>this.buffer.length){let l=this.buffer.length;for(;l<this.length+a.length;)l*=2;let d=new Uint8Array(l);d.set(this.buffer.subarray(0,this.length)),this.buffer=d}this.buffer.set(a,this.length),this.length+=a.length;let t=[],o=0;for(;this.length-o>=4;){let d=new DataView(this.buffer.buffer,this.buffer.byteOffset+o,4).getUint32(0,!1);if(this.length-o-4<d)break;if(d>=1){let s=co[this.buffer[o+4]];s&&t.push({type:s,payload:this.buffer.slice(o+5,o+4+d)})}o+=4+d}return o>0&&(this.buffer.copyWithin(0,o,this.length),this.length-=o),t}reset(){this.length=0}};var po={Enter:40,Escape:41,Backspace:42,Tab:43,Space:44,Minus:45,Equal:46,BracketLeft:47,BracketRight:48,Backslash:49,Semicolon:51,Quote:52,Backquote:53,Comma:54,Period:55,Slash:56,Delete:76,ArrowRight:79,ArrowLeft:80,ArrowDown:81,ArrowUp:82,ControlLeft:224,ShiftLeft:225,AltLeft:226,MetaLeft:227,ControlRight:228,ShiftRight:229,AltRight:230,MetaRight:231};function lt(e){return/^Key[A-Z]$/.test(e)?4+(e.charCodeAt(3)-65):/^Digit[1-9]$/.test(e)?30+(e.charCodeAt(5)-49):e==="Digit0"?39:po[e]??null}var st={ArrowUp:19,ArrowDown:20,ArrowLeft:21,ArrowRight:22,Tab:61,Enter:66,Backspace:67,Delete:112,Home:122,End:123,PageUp:92,PageDown:93};function ca(e){if(e.stopped)return;let a=o=>{e.configuring=!1,e.connecting(o),e.scheduleRetry("input",()=>ca(e))},t;try{t=e.transport.connect(`${e.vendor}/ws?device=${e.device}&frame-meta=1`)}catch(o){e.events.onInputConnected(!1,o.message),a(o.message);return}e.socket=t,t.onopen=()=>{e.stopped||e.socket!==t||(e.connecting(),e.events.onInputConnected(!0))},t.onmessage=o=>{if(e.stopped||e.socket!==t)return;if(typeof o.data=="string"){ot(o.data)&&(e.closeDecoder(),e.configuring=!1,e.connecting(),e.requestKeyframe());return}let l=tt(o.data),d=!e.videoDecoder||e.videoDecoder.state!=="configured",u=l.isKey===null||l.isKey&&d?rt(l.data):null,n=l.isKey??u?.isKey??!1;if(u?.sps&&d){if(e.configuring)return;e.configuring=!0;let i=e.decoderEpoch,c=()=>!e.stopped&&e.socket===t;e.configureDecoder({codec:je(u.sps)},c).then(m=>{!c()||i!==e.decoderEpoch||(e.configuring=!1,e.awaitingKeyframe=!0,m&&e.requestKeyframe())});return}if(d){n||e.requestKeyframe();return}e.decode(n,l.data,l.timestamp)},t.onclose=o=>{e.socket===t&&(e.socket=null,e.closeDecoder(),!e.stopped&&(e.events.onInputConnected(!1,o.reason||`closed ${o.code}`),a(o.reason||void 0)))},t.onerror=()=>t.close()}function dt(e){return{sendTouch(a,t,o){let l=a==="begin"?"down":a==="move"?"move":"up";e.send(JSON.stringify({type:"touch",action:l,x:t,y:o}))},sendKey(a,t){if(t!=="down")return;if(a.key==="Escape")return e.send(JSON.stringify({type:"back"}));let o=st[a.key];if(o!==void 0)return e.send(JSON.stringify({type:"key",keycode:o}));a.key.length===1&&!a.metaKey&&!a.ctrlKey&&e.send(JSON.stringify({type:"text",text:a.key}))},pressButton(a){let t=a==="appSwitcher"?"recents":a;(t==="home"||t==="back"||t==="recents"||t==="power")&&e.send(JSON.stringify({type:t}))},rotate(){},setOrientation(){}}}function ut(e){return{present(a,t,o){let l=e.getContext("2d");return l?((e.width!==t||e.height!==o)&&(e.width=t,e.height=o),l.drawImage(a,0,0,t,o),!0):!1}}}var nt=new TextEncoder,it=new TextDecoder;function ct(e){if(!e)return null;let a=/boundary=(?:"([^"]+)"|([^;\s]+))/i.exec(e),t=a?.[1]??a?.[2];return t?t.startsWith("--")?t:`--${t}`:null}function ft(e,a,t,o){let l=o-a.length;for(let d=t;d<=l;d++){if(e[d]!==a[0])continue;let s=1;for(;s<a.length&&e[d+s]===a[s];)s++;if(s===a.length)return d}return-1}var Ze=class{delimiter;buffer=new Uint8Array(64*1024);length=0;pos=0;state="boundary";contentLength=null;scanFrom=0;constructor(a){this.delimiter=a?nt.encode(a):null}push(a){this.append(a);let t=[];for(;;){if(this.state==="done"){this.pos=this.length=0;break}if(this.state==="boundary"){if(!this.readBoundary())break}else if(this.state==="headers"){if(!this.readHeaders())break}else{let o=this.readBody();if(!o)break;o.length>0&&t.push(o)}}if(this.length-this.pos>16777216)throw new Error("MJPEG part is too large.");return this.pos>0&&(this.buffer.copyWithin(0,this.pos,this.length),this.length-=this.pos,this.scanFrom=Math.max(0,this.scanFrom-this.pos),this.pos=0),t}append(a){if(this.length+a.length>this.buffer.length){let t=this.buffer.length;for(;t<this.length+a.length;)t*=2;let o=new Uint8Array(t);o.set(this.buffer.subarray(0,this.length)),this.buffer=o}this.buffer.set(a,this.length),this.length+=a.length}lineEnd(a){return this.buffer.subarray(0,this.length).indexOf(10,a)}readBoundary(){let a=this.buffer;if(!this.delimiter)for(;;){let s=this.lineEnd(this.pos);if(s===-1)return!1;let u=it.decode(a.subarray(this.pos,s)).trim();if(this.pos=s+1,u.startsWith("--"))return this.delimiter=nt.encode(u),this.state="headers",!0}let t=this.delimiter,o=ft(a,t,this.pos,this.length);if(o===-1)return this.pos=Math.max(this.pos,this.length-t.length+1),!1;let l=o+t.length;if(l+2>this.length)return this.pos=o,!1;if(a[l]===45&&a[l+1]===45)return this.state="done",!0;let d=this.lineEnd(l);return d===-1?(this.pos=o,!1):(this.pos=d+1,this.state="headers",!0)}readHeaders(){let a=this.pos,t=null;for(;;){let o=this.lineEnd(a);if(o===-1)return!1;let l=it.decode(this.buffer.subarray(a,o)).replace(/\r$/,"");if(a=o+1,l==="")break;let d=l.indexOf(":");if(d>0&&l.slice(0,d).trim().toLowerCase()==="content-length"){let s=Number.parseInt(l.slice(d+1).trim(),10);Number.isFinite(s)&&s>=0&&(t=s)}}return this.pos=a,this.contentLength=t,this.scanFrom=a,this.state="body",!0}readBody(){if(this.contentLength!==null){if(this.length-this.pos<this.contentLength)return null;let o=this.buffer.slice(this.pos,this.pos+this.contentLength);return this.pos+=this.contentLength,this.state="boundary",o}let a=this.delimiter,t=Math.max(this.scanFrom,this.pos+1);for(;;){let o=ft(this.buffer,a,t,this.length);if(o===-1)return this.scanFrom=Math.max(this.pos,this.length-a.length),null;if(this.buffer[o-1]!==10){t=o+1;continue}let l=o-1;l>this.pos&&this.buffer[l-1]===13&&l--;let d=this.buffer.slice(this.pos,Math.max(l,this.pos));return this.pos=o,this.state="boundary",d}}};async function mo(e,a,t){let o=new Ze(ct(e.headers.get("content-type")));await Ke(e,l=>{for(let d of o.push(l))a(d)},t)}function Ie(e){e.stopped||e.mjpeg||(e.mjpeg=!0,e.controller?.abort(),e.controller=null,e.closeDecoder(),e.connecting(),e.events.onMjpegFallback?.(),pt(e))}var pa=e=>`${e.vendor}/helper/${e.device}/stream.mjpeg`;async function pt(e){let a=e.generation,t=++e.videoGeneration,o=new AbortController;e.controller=o;let l=()=>!e.stopped&&e.generation===a&&e.videoGeneration===t&&e.controller===o,d=null,s=!1,u=async()=>{s=!0;try{for(;d;){let i=d;d=null;try{let c=await e.createBitmap(new Blob([i],{type:"image/jpeg"}));try{l()&&e.paint(c,c.width,c.height)}finally{c.close()}}catch{}}}finally{s=!1}},n;try{let i=await e.transport.fetch(pa(e),{signal:o.signal});if(!l()){await i.body?.cancel();return}if(!i.ok||!i.body)throw new Error(`stream ${i.status}`);if(await mo(i,c=>{l()&&(d=c,s||u())},o.signal),!l())return;n="Device stream ended."}catch(i){if(!l())return;n=i.message}l()&&(e.controller=null,o.abort(),e.connecting(n),e.scheduleRetry("video",()=>{pt(e)}))}var go=1e3,ma=15e3,Lo=16667,ho=8,xo=e=>typeof e=="object"&&e!==null&&"present"in e;function gt(e){let{transport:a,platform:t,events:o}=e,l=xo(e.output)?e.output:ut(e.output),d=u=>e.globals?.[u]??globalThis[u],s={platform:t,transport:a,events:o,preferMjpeg:e.preferMjpeg===!0,vendor:fe(t),device:encodeURIComponent(e.deviceId),stopped:!0,generation:0,videoGeneration:0,decoderEpoch:0,socket:null,controller:null,primeController:null,videoDecoder:null,timestamp:0,awaitingKeyframe:!0,screen:null,firstFrame:!1,configuring:!1,mjpeg:!1,frameTimer:null,videoReadTimer:null,retryTimers:new Map,webCodecs(){let u=d("VideoDecoder"),n=d("EncodedVideoChunk");return u&&n?{VideoDecoder:u,EncodedVideoChunk:n}:null},createBitmap(u){let n=d("createImageBitmap");return n?n(u):Promise.reject(new Error("createImageBitmap is unavailable."))},setStatus(u,n){s.stopped||o.onStatus(u,n)},fail(u){s.stopped||(s.stop(),o.onInputConnected(!1,u),o.onStatus("error",u))},connecting(u){s.firstFrame=!1,s.frameTimer===null&&(s.frameTimer=setTimeout(()=>s.fail("No video received from the device. Reconnect to try again."),ma)),s.setStatus("connecting",u)},paint(u,n,i){if(!s.stopped){if(t==="android"&&(s.screen?.width!==n||s.screen.height!==i)&&(s.screen={width:n,height:i,orientation:n>i?"landscape_left":"portrait"},o.onScreen(s.screen)),!l.present(u,n,i)){s.fail("Could not display the device stream. Reconnect to try again.");return}s.firstFrame||(s.firstFrame=!0,s.frameTimer!==null&&clearTimeout(s.frameTimer),s.frameTimer=null,s.setStatus("streaming"))}},closeDecoder(){s.decoderEpoch++,s.configuring=!1;try{s.videoDecoder?.close()}catch{}s.videoDecoder=null,s.awaitingKeyframe=!0},recoverDecoder(){t==="ios"?Ie(s):(s.closeDecoder(),s.connecting("Video decoder restarted."),s.requestKeyframe())},async configureDecoder(u,n=()=>!s.stopped){let i=s.webCodecs();if(!i)return!1;let c=s.decoderEpoch,m={...u,optimizeForLatency:!0},x=await i.VideoDecoder.isConfigSupported(m).catch(()=>({supported:!1}));if(!n()||c!==s.decoderEpoch)return!1;if(!x.supported)return t==="android"&&s.fail(`This browser cannot decode ${u.codec}.`),!1;try{return(!s.videoDecoder||s.videoDecoder.state==="closed")&&(s.videoDecoder=Io(s,i)),s.videoDecoder.configure(m),!0}catch(L){return t==="android"&&s.fail(`Video decoder: ${L.message}`),!1}},decode(u,n,i){let c=s.videoDecoder,m=s.webCodecs();if(!(!c||c.state!=="configured"||!m)){if(s.awaitingKeyframe){if(!u)return;s.awaitingKeyframe=!1}if(c.decodeQueueSize>ho){s.recoverDecoder();return}try{c.decode(new m.EncodedVideoChunk({type:u?"key":"delta",timestamp:i??s.timestamp,data:n})),s.timestamp+=Lo}catch{s.recoverDecoder()}}},requestKeyframe(){t==="android"&&s.socket?.readyState===1&&s.socket.send(JSON.stringify({type:"reset-video",ack:!1}))},scheduleRetry(u,n){s.stopped||s.retryTimers.has(u)||s.retryTimers.set(u,setTimeout(()=>{s.retryTimers.delete(u),n()},go))},send(u){!s.stopped&&s.socket?.readyState===1&&s.socket.send(u)},stop(){if(s.stopped)return;s.stopped=!0,s.generation++,s.videoGeneration++,s.mjpeg=!1,s.frameTimer!==null&&clearTimeout(s.frameTimer),s.frameTimer=null,s.videoReadTimer!==null&&clearTimeout(s.videoReadTimer),s.videoReadTimer=null;for(let n of s.retryTimers.values())clearTimeout(n);s.retryTimers.clear(),s.primeController?.abort(),s.primeController=null,s.controller?.abort(),s.controller=null;let u=s.socket;s.socket=null,u?.close(),s.closeDecoder()}};return s}function Io(e,a){let t=e.videoGeneration,o=()=>e.platform!=="ios"||t===e.videoGeneration,l=new a.VideoDecoder({output:d=>{try{e.videoDecoder===l&&o()&&e.paint(d,d.displayWidth,d.displayHeight)}finally{d.close()}},error:()=>{e.stopped||e.videoDecoder!==l||!o()||e.recoverDecoder()}});return l}var Co=3,So=4,vo=6,Lt=7,yo=13,wo=130,bo=2e3,ko=new TextEncoder,Do=new TextDecoder,Je=["portrait","landscape_left","portrait_upside_down","landscape_right"],Po=new Set(Je);function ce(e,a){let t=ko.encode(JSON.stringify(a)),o=new Uint8Array(1+t.length);return o[0]=e,o.set(t,1),o}function Ao(e){if(typeof e!="object"||e===null)return null;let{width:a,height:t,orientation:o,screenId:l}=e;if(typeof a!="number"||!Number.isFinite(a)||a<=0||typeof t!="number"||!Number.isFinite(t)||t<=0||typeof o!="string"||!Po.has(o))return null;let d={width:a,height:t,orientation:o};return typeof l=="number"?{...d,screenId:l}:d}function ht(e,a){It(e),a?xt(e):Ie(e)}async function xt(e){let a=e.generation,t=++e.videoGeneration,o=new $e,l=new AbortController;e.controller=l;let d=()=>!e.stopped&&e.generation===a&&e.videoGeneration===t&&e.controller===l,s;try{let u=await e.transport.fetch(`${e.vendor}/helper/${e.device}/stream.avcc`,{signal:l.signal});if(!d()){await u.body?.cancel();return}if(!u.ok||!u.body)throw new Error(`stream ${u.status}`);let n=u.body.getReader();for(;;){let i=setTimeout(()=>{d()&&e.fail("Device stream stopped receiving video. Reconnect to try again.")},ma);e.videoReadTimer=i;let c;try{c=await n.read()}finally{clearTimeout(i),e.videoReadTimer===i&&(e.videoReadTimer=null)}let{done:m,value:x}=c;if(!d())return;if(m)break;for(let L of o.push(x))switch(L.type){case"seed":e.createBitmap(new Blob([L.payload],{type:"image/jpeg"})).then(w=>{try{d()&&e.paint(w,w.width,w.height)}finally{w.close()}}).catch(()=>{});break;case"description":{e.awaitingKeyframe=!0;let w=await e.configureDecoder({codec:je(L.payload),description:L.payload},d);if(!d())return;if(!w){if(await n.cancel().catch(()=>{}),!d())return;Ie(e);return}break}case"keyframe":case"delta":e.decode(L.type==="keyframe",L.payload);break}}}catch(u){if(!d())return;s=u.message}d()&&(e.controller=null,l.abort(),e.closeDecoder(),e.connecting(s),e.scheduleRetry("video",()=>{xt(e)}))}async function To(e,a){let t=new AbortController;e.primeController=t;let o=setTimeout(()=>t.abort(),bo);try{let l=await e.transport.fetch(pa(e),{signal:t.signal});if(e.stopped||e.generation!==a)return;await l.body?.getReader().read()}catch{}finally{clearTimeout(o),t.abort(),e.primeController===t&&(e.primeController=null)}}async function It(e){if(e.stopped)return;let a=e.generation;if(await To(e,a),e.stopped||e.generation!==a)return;let t=()=>e.scheduleRetry("input",()=>{It(e)}),o;try{o=e.transport.connect(`${e.vendor}/helper/ws?device=${e.device}`)}catch(l){e.events.onInputConnected(!1,l.message),t();return}e.socket=o,o.onopen=()=>{e.stopped||e.socket!==o||(o.send(ce(yo,{enabled:!1})),e.events.onInputConnected(!0))},o.onmessage=l=>{if(e.stopped||e.socket!==o||typeof l.data=="string")return;let d=new Uint8Array(l.data);if(!(d.length<1||d[0]!==wo))try{let s=Ao(JSON.parse(Do.decode(d.subarray(1))));s&&(e.screen=s,e.events.onScreen(s))}catch{}},o.onclose=l=>{e.socket===o&&(e.socket=null,!e.stopped&&(e.events.onInputConnected(!1,l.reason||(l.code===1006?"input socket refused":`closed ${l.code}`)),t()))},o.onerror=()=>o.close()}function Bo(e,a,t){let o=e.screen;if(!o||o.width>o.height)return{x:a,y:t};switch(o.orientation){case"landscape_left":return{x:t,y:1-a};case"landscape_right":return{x:1-t,y:a};case"portrait_upside_down":return{x:1-a,y:1-t};default:return{x:a,y:t}}}function Ct(e){return{sendTouch(a,t,o){e.send(ce(Co,{type:a,...Bo(e,t,o)}))},sendKey(a,t){let o=lt(a.code);o!==null&&e.send(ce(vo,{type:t,usage:o}))},pressButton(a){let t=a==="home"?"home":a==="appSwitcher"?"app_switcher":a==="power"?"lock":null;t&&e.send(ce(So,{button:t}))},rotate(){let a=e.screen?.orientation??"portrait",t=Je[(Je.indexOf(a)+1)%Je.length];e.send(ce(Lt,{orientation:t}))},setOrientation(a){e.send(ce(Lt,{orientation:a}))}}}function St(e){let a=gt(e),t=e.platform==="ios"?Ct(a):dt(a);return{start:()=>{if(!a.stopped)return;a.stopped=!1,a.generation++,a.configuring=!1,a.connecting();let l=a.webCodecs()!==null&&!(e.platform==="ios"&&a.preferMjpeg);e.platform==="ios"?ht(a,l):l?ca(a):a.fail("This browser cannot decode the Android stream (WebCodecs unavailable).")},stop:a.stop,isMjpeg:()=>a.mjpeg,...t}}var Mo=56,Ro=2e3;function Fo(e,a,t,o=0){let l=Math.max(0,a-o);if(l===0||t===0)return{width:0,height:0};let d={width:t*e,height:t};return d.width<=l?d:{width:l,height:l/e}}function Uo(e,a){if(!a)return e==="ios"?9/19.5:9/20;let t=a.orientation==="landscape_left"||a.orientation==="landscape_right",o=Math.max(a.width,a.height),l=Math.min(a.width,a.height);return t?o/l:l/o}function Oo(e,a){if(e!=="ios"||!a||a.width>a.height)return 0;switch(a.orientation){case"landscape_left":return 90;case"landscape_right":return-90;case"portrait_upside_down":return 180;default:return 0}}var Eo=()=>typeof navigator<"u"&&/iPhone|iPad|iPod/.test(navigator.userAgent);function Qe(e){let{t:a}=B(),t=q(null),o=q(null),[l,d]=h("connecting"),[s,u]=h(),[n,i]=h(null),[c,m]=h({connected:!1}),{onHandle:x,onStreaming:L,onScreen:w,transport:y,platform:b,deviceId:g}=e;T(()=>w?.(n),[w,n]),T(()=>{let p=t.current;if(!p)return;let S=St({transport:y,platform:b,deviceId:g,output:p,preferMjpeg:Eo(),events:{onStatus:(D,C)=>{d(D),u(C),L(D==="streaming")},onScreen:i,onInputConnected:(D,C)=>{m({connected:D,...C?{detail:C}:{}}),x({pressButton:S.pressButton,rotate:S.rotate,inputConnected:D})}}});return o.current=S,m({connected:!1}),S.start(),x({pressButton:S.pressButton,rotate:S.rotate,inputConnected:!1}),()=>{S.stop(),o.current=null,x(null),L(!1),i(null)}},[g,x,L,b,y]);let P=q(null),[A,U]=h({width:0,height:0});T(()=>{let p=P.current;if(!p)return;let S=()=>{let C=p.getBoundingClientRect();U(re=>re.width===C.width&&re.height===C.height?re:{width:C.width,height:C.height})};S();let D=new ResizeObserver(S);return D.observe(p),()=>D.disconnect()},[]);let N=e.withControls?Mo:0,F=de(()=>Fo(Uo(b,n),A.width,A.height,N),[A,N,b,n]),O=Oo(b,n),$=O===90||O===-90?{width:F.height,height:F.width,left:(F.width-F.height)/2,top:(F.height-F.width)/2,transform:`rotate(${O}deg)`}:{width:F.width,height:F.height,...O?{transform:`rotate(${O}deg)`}:{}},[R,G]=h([]);T(()=>{if(!e.axOverlay)return;let p=null,S=null,D=!1,C=async()=>{p=new AbortController;try{let re=await Qa({transport:y,platform:b,deviceId:g},p.signal);D||G(re.elements)}catch{}D||(S=setTimeout(()=>{C()},Ro))};return C(),()=>{D=!0,p?.abort(),S&&clearTimeout(S),G([])}},[g,b,e.axOverlay,y]);let V=q(!1),M=p=>{let S=p.currentTarget.getBoundingClientRect(),D=(p.clientX-S.left)/S.width,C=(p.clientY-S.top)/S.height;return{x:Math.min(1,Math.max(0,D)),y:Math.min(1,Math.max(0,C))}},j=p=>{if(!V.current)return;V.current=!1;let{x:S,y:D}=M(p);o.current?.sendTouch("end",S,D)};return f("div",{ref:P,className:"relative flex size-full min-h-0 min-w-0 items-center justify-center overflow-hidden",style:N?{paddingRight:N}:void 0,tabIndex:0,role:"application","aria-label":a(b==="ios"?"stream.iosScreen":"stream.androidScreen"),onKeyDown:p=>{p.target===p.currentTarget&&(p.metaKey&&!["r","R"].includes(p.key)||(p.preventDefault(),o.current?.sendKey(p.nativeEvent,"down")))},onKeyUp:p=>{p.target===p.currentTarget&&o.current?.sendKey(p.nativeEvent,"up")},children:[f("div",{className:"relative touch-none select-none",style:{width:F.width,height:F.height},onPointerDown:p=>{p.currentTarget.setPointerCapture(p.pointerId),p.currentTarget.parentElement?.focus(),V.current=!0;let{x:S,y:D}=M(p);o.current?.sendTouch("begin",S,D)},onPointerMove:p=>{if(!V.current)return;let{x:S,y:D}=M(p);o.current?.sendTouch("move",S,D)},onPointerUp:j,onPointerCancel:j,children:[r("canvas",{ref:t,className:"absolute top-0 left-0",style:$}),R.length>0?r("div",{className:"pointer-events-none absolute inset-0","aria-hidden":!0,children:R.map(p=>r("div",{className:"absolute border border-info/80 bg-info/10",style:{left:`${p.x*100}%`,top:`${p.y*100}%`,width:`${p.width*100}%`,height:`${p.height*100}%`},children:p.label?r("span",{className:"absolute -top-3.5 left-0 max-w-full truncate rounded-sm bg-info px-1 text-ui-2xs leading-3.5 text-white",children:p.label}):null},p.id))}):null]}),l==="streaming"&&!c.connected?r("div",{className:"pointer-events-none absolute inset-x-0 bottom-0 flex justify-center p-2",children:r("span",{className:"rounded-md bg-background/85 px-2 py-1 text-xs text-muted-foreground",children:c.detail?a("stream.inputLostDetail",{detail:c.detail}):a("stream.inputLost")})}):null,l!=="streaming"?r("div",{className:"absolute inset-0 bg-background",children:r(J,{name:e.deviceName,description:e.deviceDescription,stage:l==="error"?"error":"connecting",message:l==="error"?s??a("stream.failed"):a("stream.connecting"),children:l==="error"?r(I,{size:"sm",variant:"outline",onClick:()=>{o.current?.stop(),o.current?.start()},children:a("stream.reconnect")}):null})}):null]})}var qo={hosts:[],hostStatuses:{},devices:[],sessions:[],bootingDevices:[],revision:0};function pe(e){let t=E().commands.useSubscription("state",{},{environmentId:e});return{state:t.data??qo,loaded:t.data!==null,error:t.error,unavailable:t.isUnavailable}}function Y(){let e=E();return se((a,t,o={})=>e.commands.invoke(a,o,{environmentId:t}),[e])}var me="local",Ye=class extends Error{code;constructor(a,t,o){super(t,o),this.name="DeviceError",this.code=a}};var vt="hub";function ea(e){let a=E(),[t,o]=h({status:"connecting"});return T(()=>{let l=a.network;if(!ne(a,"network")||l===void 0){o({status:"failed",message:null});return}let d=!1;return o({status:"connecting"}),l.client(e).then(s=>{d||o({status:"ready",transport:{fetch:(u,n)=>s.fetch(vt,u,{...n,instance:me}),connect:u=>s.connect(vt,u,{instance:me})}})},s=>{d||o({status:"failed",message:s instanceof Error?s.message:String(s)})}),()=>{d=!0}},[a,e]),t}var yt=()=>{};function wt(e){let{environmentId:a,threadId:t,hostId:o,deviceId:l,platform:d}=e,s=e[Ma],u=E(),{t:n}=B(),{state:i,loaded:c}=pe(a),m=ea(a),x=de(()=>({environmentId:a,threadId:t}),[a,t]),L=i.devices.find(P=>P.hostId===o&&P.id===l),w=i.sessions.some(P=>P.threadId===t&&P.hostId===o&&P.deviceId===l);T(()=>{c&&!w&&u.floating?.close(x,s.key)},[u,s.key,c,w,x]),T(()=>(s.setOpenInPanel(()=>{Ee(a,t,s.key),u.floating?.openPanel(x,Ue),u.floating?.close(x,s.key)}),()=>s.setOpenInPanel(null)),[u,a,s,x,t]);let y=se(P=>s.reportSourceSize(P===null?null:Ra(P)),[s]),b=L?.name??l,g=L?.version??d;return m.status!=="ready"?r(J,{name:b,description:g,stage:m.status==="failed"?"error":"connecting",message:m.status==="failed"?m.message??n("workspace.needsNewerApp"):n("stream.connecting")}):r(Qe,{transport:m.transport,platform:d,deviceId:l,deviceName:b,deviceDescription:g,axOverlay:!1,withControls:!1,onHandle:yt,onStreaming:yt,onScreen:y})}var aa=(...e)=>e.filter((a,t,o)=>!!a&&a.trim()!==""&&o.indexOf(a)===t).join(" ").trim();var bt=e=>e.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase();var kt=e=>e.replace(/^([A-Z])|[\s-_]+(\w)/g,(a,t,o)=>o?o.toUpperCase():t.toLowerCase());var ga=e=>{let a=kt(e);return a.charAt(0).toUpperCase()+a.slice(1)};var Dt={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"};var Pt=e=>{for(let a in e)if(a.startsWith("aria-")||a==="role"||a==="title")return!0;return!1};var At=Re(({color:e="currentColor",size:a=24,strokeWidth:t=2,absoluteStrokeWidth:o,className:l="",children:d,iconNode:s,...u},n)=>le("svg",{ref:n,...Dt,width:a,height:a,stroke:e,strokeWidth:o?Number(t)*24/Number(a):t,className:aa("lucide",l),...!d&&!Pt(u)&&{"aria-hidden":"true"},...u},[...s.map(([i,c])=>le(i,c)),...Array.isArray(d)?d:[d]]));var v=(e,a)=>{let t=Re(({className:o,...l},d)=>le(At,{ref:d,iconNode:a,className:aa(`lucide-${bt(ga(e))}`,`lucide-${e}`,o),...l}));return t.displayName=ga(e),t};var Ho=[["path",{d:"M13.997 4a2 2 0 0 1 1.76 1.05l.486.9A2 2 0 0 0 18.003 7H20a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V9a2 2 0 0 1 2-2h1.997a2 2 0 0 0 1.759-1.048l.489-.904A2 2 0 0 1 10.004 4z",key:"18u6gg"}],["circle",{cx:"12",cy:"13",r:"3",key:"1vg3eu"}]],Ce=v("camera",Ho);var No=[["path",{d:"m6 9 6 6 6-6",key:"qrunsl"}]],Se=v("chevron-down",No);var Go=[["path",{d:"m15 18-6-6 6-6",key:"1wnfg3"}]],ve=v("chevron-left",Go);var Vo=[["circle",{cx:"12",cy:"12",r:"1",key:"41hilf"}],["circle",{cx:"19",cy:"12",r:"1",key:"1wjl8i"}],["circle",{cx:"5",cy:"12",r:"1",key:"1pcz8c"}]],ee=v("ellipsis",Vo);var zo=[["path",{d:"M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8",key:"5wwlr5"}],["path",{d:"M3 10a2 2 0 0 1 .709-1.528l7-6a2 2 0 0 1 2.582 0l7 6A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z",key:"r6nss1"}]],ae=v("house",zo);var _o=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M12 16v-4",key:"1dtifu"}],["path",{d:"M12 8h.01",key:"e9boi3"}]],ye=v("info",_o);var Wo=[["path",{d:"M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401",key:"kfwtm"}]],we=v("moon",Wo);var Ko=[["path",{d:"M21 9V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v10c0 1.1.9 2 2 2h4",key:"daa4of"}],["rect",{width:"10",height:"7",x:"12",y:"13",rx:"2",key:"1nb8gs"}]],be=v("picture-in-picture-2",Ko);var Xo=[["path",{d:"M12 2v10",key:"mnfbl"}],["path",{d:"M18.4 6.6a9 9 0 1 1-12.77.04",key:"obofu9"}]],ke=v("power",Xo);var $o=[["path",{d:"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8",key:"1357e3"}],["path",{d:"M3 3v5h5",key:"1xhq8a"}]],ge=v("rotate-ccw",$o);var jo=[["path",{d:"M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8",key:"1p45f6"}],["path",{d:"M21 3v5h-5",key:"1q7to0"}]],De=v("rotate-cw",jo);var Zo=[["path",{d:"M10 5H3",key:"1qgfaw"}],["path",{d:"M12 19H3",key:"yhmn1j"}],["path",{d:"M14 3v4",key:"1sua03"}],["path",{d:"M16 17v4",key:"1q0r14"}],["path",{d:"M21 12h-9",key:"1o4lsq"}],["path",{d:"M21 19h-5",key:"1rlt1p"}],["path",{d:"M21 5h-7",key:"1oszz2"}],["path",{d:"M8 10v4",key:"tgpxqk"}],["path",{d:"M8 12H3",key:"a7s4jb"}]],Pe=v("sliders-horizontal",Zo);var Jo=[["rect",{width:"14",height:"20",x:"5",y:"2",rx:"2",ry:"2",key:"1yt0o3"}],["path",{d:"M12 18h.01",key:"mhygvu"}]],Le=v("smartphone",Jo);var Qo=[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}]],Ae=v("square",Qo);var Yo=[["circle",{cx:"12",cy:"12",r:"4",key:"4exip2"}],["path",{d:"M12 2v2",key:"tus03m"}],["path",{d:"M12 20v2",key:"1lh1kg"}],["path",{d:"m4.93 4.93 1.41 1.41",key:"149t6j"}],["path",{d:"m17.66 17.66 1.41 1.41",key:"ptbguv"}],["path",{d:"M2 12h2",key:"1t8f8n"}],["path",{d:"M20 12h2",key:"1q8mjw"}],["path",{d:"m6.34 17.66-1.41 1.41",key:"1m8zz5"}],["path",{d:"m19.07 4.93-1.41 1.41",key:"1shlcs"}]],Te=v("sun",Yo);var er=[["path",{d:"M12 4v16",key:"1654pz"}],["path",{d:"M4 7V5a1 1 0 0 1 1-1h14a1 1 0 0 1 1 1v2",key:"e0r10z"}],["path",{d:"M9 20h6",key:"s66wpe"}]],Be=v("type",er);var ar=[["path",{d:"M18 6 6 18",key:"1bl5f8"}],["path",{d:"m6 6 12 12",key:"d8bk6v"}]],K=v("x",ar);function tr(e,a){let t=o=>a(o==="hub"?"versions.hubName":"versions.agentName");return e.status==="starting"?a("panel.startingHost"):e.status!=="installing"?e.message??"":e.tool&&e.toVersion?e.fromVersion?a("panel.updatingTool",{tool:t(e.tool),from:e.fromVersion,to:e.toVersion}):a("panel.installingTool",{tool:t(e.tool),to:e.toVersion}):a("panel.installing")}function La(){let{t:e}=B();return a=>tr(a,e)}function Tt(e){let{t:a}=B(),t=La(),[o,l]=h(!1),d=e.detail;return!d||d.status==="ready"||d.status==="idle"?null:d.status==="failed"?f("div",{role:"alert",className:"flex items-start gap-2 border-b bg-destructive/5 px-3 py-2 text-xs",children:[f("div",{className:"min-w-0 flex-1 space-y-0.5",children:[r("p",{className:"font-medium text-destructive-foreground",children:a("panel.hostFailed")}),d.message?r("p",{className:"whitespace-pre-wrap break-words text-muted-foreground",children:d.message}):null]}),f(I,{size:"xs",variant:"outline",disabled:o,onClick:()=>{l(!0),e.onRetry().finally(()=>l(!1))},children:[o?r(H,{size:"xs"}):r(De,{}),a(o?"panel.retrying":"panel.retry")]})]}):f("div",{role:"status",className:"flex items-center gap-2 border-b px-3 py-2 text-xs text-muted-foreground",children:[r(H,{size:"xs"}),r("span",{className:"min-w-0 flex-1",children:t(d)})]})}var ha=["hub","agent"],xa=e=>e!==void 0&&!e.installedVersions.includes(e.requiredVersion);function Bt(e){let{t:a}=B(),t=Y(),[o,l]=h(null),[d,s]=h(null),u=e.host?.tools,n=e.busy||o!==null,i=m=>{l(m),s(null),(m==="check"?t("inspect",e.environmentId):t("updateTool",e.environmentId,{tool:m})).catch(()=>s(a(m==="check"?"versions.checkFailed":"versions.updateFailed"))).finally(()=>l(null))},c=m=>m??a("versions.none");return f(Wa,{children:[f(Ka,{render:r(I,{size:"xs",variant:"ghost","aria-label":a("versions.title")}),children:[r(ye,{}),a("versions.title"),ha.some(m=>xa(u?.[m]))?r("span",{className:"size-1.5 rounded-full bg-warning","aria-hidden":!0}):null]}),r(Xa,{side:"bottom",align:"start",className:"w-80",children:f("div",{className:"space-y-3 text-xs",children:[ha.map(m=>{let x=u?.[m];return f("section",{className:"space-y-1",children:[r("h4",{className:"font-medium text-foreground",children:a(m==="hub"?"versions.hubName":"versions.agentName")}),f("dl",{className:"grid grid-cols-[auto_1fr] gap-x-3 gap-y-0.5 text-muted-foreground",children:[r("dt",{children:a("versions.required")}),r("dd",{className:"font-mono",children:c(x?.requiredVersion)}),r("dt",{children:a("versions.installed")}),r("dd",{className:"font-mono",children:x&&x.installedVersions.length>0?x.installedVersions.join(", "):a("versions.none")}),r("dt",{children:a("versions.running")}),r("dd",{className:"font-mono",children:c(x?.runningVersion)})]}),xa(x)?f(I,{size:"xs",variant:"outline",disabled:n,onClick:()=>i(m),children:[o===m?r(H,{size:"xs"}):null,a("versions.updateTo",{version:x?.requiredVersion??""})]}):null]},m)}),u===void 0?r("p",{className:"text-muted-foreground",children:a("versions.unknown")}):null,ha.some(m=>xa(u?.[m]))?r("p",{className:"text-muted-foreground",children:a("versions.pendingPolicy")}):null,d?r("p",{role:"alert",className:"text-destructive-foreground",children:d}):null,f("div",{className:"flex items-center justify-between gap-2 border-t pt-2",children:[r("p",{className:"text-muted-foreground",children:a("versions.checkHint")}),f(I,{size:"xs",variant:"ghost",disabled:n,onClick:()=>i("check"),children:[o==="check"?r(H,{size:"xs"}):null,a("versions.check")]})]})]})})]})}function Mt(e){return e.supported?e.freeBytes!==null&&e.freeBytes<e.requiredFreeBytes?"environment.notEnoughSpace":null:e.reasonCode?`environment.reasons.${e.reasonCode}`:"environment.unsupported"}function Rt(e,a){return e.cacheBytes>0||a==="android"&&e.deviceDataBytes>0}function Ft(e){let{t:a}=B(),t=Y(),l=E().commands.useSubscription("environmentProgress",{},{environmentId:e.environmentId}).data,[d,s]=h(!1),[u,n]=h("android"),[i,c]=h(""),[m,x]=h(""),[L,w]=h(null),[y,b]=h(!1),[g,P]=h(!1),[A,U]=h(!1),[N,F]=h(null),[O,X]=h(!1),[$,R]=h(!1),[G,V]=h(null),M=N!==null||l?.status==="working";T(()=>{l?.status==="done"&&l.plan?.platform===u&&l.id===G&&(w(l.plan),R(!0)),l?.status==="failed"&&l.id===G&&X(!0)},[u,l,G]);let j=()=>{w(null),b(!1),P(!1),U(!1),R(!1),V(null)},p=async(C,re={})=>{F(C),X(!1),R(!1);try{let ba=await t(C,e.environmentId,{platform:u,directory:i,version:m,...re});C==="cleanupEnvironment"?w(await t("environmentPlan",e.environmentId,{platform:u,directory:i,version:m})):C==="prepareEnvironment"?V(ba.id??null):w(ba),R(C==="cleanupEnvironment")}catch{X(!0)}finally{F(null)}},S=L?Mt(L):null,D=C=>C===null?a("environment.unknownSize"):`${(C/1024**3).toFixed(2)} GiB`;return f(Ve,{open:d,onOpenChange:s,className:"w-full text-left",children:[r(ze,{render:r(I,{variant:"outline",size:"sm",className:"w-full"}),children:a("environment.title")}),r(_e,{children:f("div",{className:"space-y-3 rounded-md border p-3 text-xs",children:[r("p",{children:a("environment.description")}),r("div",{className:"flex gap-2",children:["android","ios"].map(C=>r(I,{size:"sm",variant:u===C?"default":"outline",disabled:M,onClick:()=>{n(C),j()},children:a(C==="ios"?"panel.platformIos":"panel.platformAndroid")},C))}),f("label",{className:"block space-y-1",children:[r("span",{children:a("environment.directory")}),r(Q,{value:i,disabled:M,onChange:C=>{c(C.target.value),j()},placeholder:a("environment.defaultDirectory")})]}),r("p",{children:a("environment.directoryHint")}),u==="ios"?f("label",{className:"block space-y-1",children:[r("span",{children:a("environment.iosVersion")}),r(Q,{value:m,disabled:M,onChange:C=>{x(C.target.value),j()},placeholder:a("environment.iosVersionPlaceholder")})]}):null,r(I,{size:"sm",variant:"outline",disabled:M,onClick:()=>{p("environmentPlan")},children:a("environment.inspect")}),L?f("div",{className:"space-y-2",children:[f("dl",{className:"grid grid-cols-[auto_1fr] gap-x-3 gap-y-1 break-all",children:[r("dt",{children:a("environment.source")}),r("dd",{children:a(`environment.sources.${L.source}`)}),r("dt",{children:a("environment.version")}),r("dd",{children:L.version||a("environment.versionRequired")}),r("dt",{children:a("environment.location")}),r("dd",{children:L.root}),L.existingSdkRoot?f(Z,{children:[r("dt",{children:a("environment.existingSdk")}),r("dd",{children:L.existingSdkRoot})]}):null,r("dt",{children:a("environment.download")}),r("dd",{children:D(L.downloadBytes)}),r("dt",{children:a("environment.free")}),r("dd",{children:D(L.freeBytes)}),r("dt",{children:a("environment.required")}),r("dd",{children:D(L.requiredFreeBytes)})]}),L.source==="external"?r("p",{children:a("environment.external")}):null,L.reasonCode&&L.supported?r("p",{role:"status",children:a(`environment.reasons.${L.reasonCode}`)}):null,r("a",{className:"underline",href:L.guidanceUrl,target:"_blank",rel:"noreferrer",children:a("environment.guide")}),u==="ios"?r("p",{children:a("environment.appleOwnership")}):r("p",{children:a("environment.privateOwnership")}),r("ul",{children:L.licenses.map(C=>r("li",{children:r("a",{className:"underline",href:C.url,target:"_blank",rel:"noreferrer",children:a(u==="ios"?"environment.appleLicense":"environment.androidLicense")})},C.url))}),f("label",{className:"flex items-center gap-2",children:[r(ie,{checked:y,disabled:M,onCheckedChange:b}),r("span",{children:a("environment.acceptLicense")})]}),u==="ios"?f("label",{className:"flex items-center gap-2",children:[r(ie,{checked:g,disabled:M,onCheckedChange:P}),r("span",{children:a("environment.confirmApple")})]}):null,S?r("p",{role:"alert",className:"font-medium text-warning-foreground",children:a(S)}):null,r(I,{size:"sm",disabled:M||!L.supported||!y||u==="ios"&&(!g||!m)||L.freeBytes===null||L.freeBytes<L.requiredFreeBytes,onClick:()=>{p("prepareEnvironment",{acceptLicenses:y,confirmAppleInstall:g})},children:a("environment.prepare")}),Rt(L,u)?f("div",{className:"space-y-2 border-t pt-2",children:[r("p",{children:a("environment.retention")}),r(I,{size:"sm",variant:"outline",disabled:M||L.cacheBytes===0,onClick:()=>{p("cleanupEnvironment",{category:"cache",confirm:!0})},children:a("environment.cleanCache",{size:D(L.cacheBytes)})}),u==="android"?f(Z,{children:[r("p",{children:a("environment.deviceData",{size:D(L.deviceDataBytes)})}),f("label",{className:"flex items-center gap-2",children:[r(ie,{checked:A,disabled:M,onCheckedChange:U}),r("span",{children:a("environment.confirmData")})]}),r(I,{size:"sm",variant:"destructive",disabled:M||!A||L.deviceDataBytes===0,onClick:()=>{p("cleanupEnvironment",{category:"devices",confirm:A})},children:a("environment.cleanDevices")})]}):null]}):null]}):null,M?f("p",{role:"status",className:"flex items-center gap-2",children:[r(H,{size:"xs"}),a(l?.status==="working"?"environment.preparing":"environment.working")]}):null,O?r("p",{role:"alert",className:"text-destructive-foreground",children:a("environment.failed")}):null,$?r("p",{role:"status",children:a("environment.done")}):null]})})]})}var Ut=["small","default","large","extra-large"],or=e=>Ut.includes(e);function Ot(e){let{t:a}=B(),{handle:t,controls:o}=e,l=o.detail?.settings,d=!t?.inputConnected,s=l?.appearance==="dark"?"light":"dark",u=n=>a(n==="small"?"rail.textSmall":n==="default"?"rail.textDefault":n==="large"?"rail.textLarge":"rail.textExtraLarge");return r("aside",{"aria-label":a("rail.label"),className:"pointer-events-none absolute inset-y-0 right-0 z-10 flex w-14 flex-col items-center justify-center gap-2 overflow-y-auto py-3 pr-2",children:f("div",{className:"pointer-events-auto flex shrink-0 flex-col items-center gap-1 rounded-full border border-border/50 bg-background/80 p-2 shadow-sm",children:[r(te,{label:a("rail.home"),disabled:d,onClick:()=>t?.pressButton("home"),children:r(ae,{})}),e.platform==="android"?f(Z,{children:[r(te,{label:a("rail.back"),disabled:d,onClick:()=>t?.pressButton("back"),children:r(ve,{})}),r(te,{label:a("rail.recents"),disabled:d,onClick:()=>t?.pressButton("recents"),children:r(Ae,{})}),f(He,{children:[r(Ge,{render:r(I,{size:"icon-sm",variant:"ghost","aria-label":a("rail.rotate"),disabled:o.disabled}),children:r(ge,{})}),f(Ne,{side:"left",children:[r(xe,{onClick:()=>{o.act({type:"setOrientation",value:"portrait"})},children:a("rail.portrait")}),r(xe,{onClick:()=>{o.act({type:"setOrientation",value:"landscape_left"})},children:a("rail.landscape")})]})]})]}):r(te,{label:a("rail.rotate"),disabled:d,onClick:()=>t?.rotate(),children:r(ge,{})}),r(rr,{}),r(te,{label:a(s==="dark"?"rail.toDark":"rail.toLight"),disabled:o.disabled||!l?.appearance,onClick:()=>{o.act({type:"setAppearance",value:s})},children:l?.appearance==="dark"?r(Te,{}):r(we,{})}),f(He,{children:[r(Ge,{render:r(I,{size:"icon-sm",variant:"ghost","aria-label":a("rail.textSize"),title:a("rail.textSize"),disabled:o.disabled||!l?.textSize}),children:r(Be,{})}),r(Ne,{side:"left",children:r(Na,{value:l?.textSize??"",onValueChange:n=>{or(n)&&o.act({type:"setTextSize",value:n})},children:Ut.map(n=>r(Ga,{value:n,children:u(n)},n))})})]}),r(te,{label:a("rail.tools"),pressed:e.toolsOpen,onClick:e.onTools,children:r(Pe,{})}),r(te,{label:e.screenshotPending?a("rail.capturing"):a("rail.screenshot"),disabled:!e.streaming||e.screenshotPending,onClick:e.onScreenshot,children:r(Ce,{})}),e.onFloat?r(te,{label:a("rail.float"),onClick:e.onFloat,children:r(be,{})}):null,f(He,{children:[r(Ge,{render:r(I,{size:"icon-sm",variant:"ghost","aria-label":a("rail.more"),title:a("rail.more")}),children:r(ee,{})}),f(Ne,{side:"left",align:"end",children:[f(xe,{onClick:e.onClose,children:[r(K,{}),a("rail.closePanel")]}),r(Ha,{}),f(xe,{variant:"destructive",onClick:e.onPowerOff,children:[r(ke,{}),a("rail.powerOff")]})]})]})]})})}function rr(){return r("div",{"aria-hidden":!0,className:"my-1 h-px w-5 shrink-0 bg-border/70"})}function te(e){return f(Oa,{children:[r(qa,{render:r(I,{size:"icon-sm",variant:e.pressed?"secondary":"ghost","aria-label":e.label,"aria-pressed":e.pressed,disabled:e.disabled,onClick:e.onClick}),children:e.children}),r(Ea,{side:"left",children:e.label})]})}var Ia=(e,a)=>new Ye("invalid-input",`Invalid ${e}: ${a}.`);var Et=4096,qt=["light","dark"],Ht=["small","default","large","extra-large"];var Nt=["clear","tinted"],Gt=["none","grayscale","red-green","green-red","blue-yellow"],Vt=["portrait","landscape_left","portrait_upside_down","landscape_right"],zt=["camera","microphone","photos","contacts","calendar","reminders","location","notifications","motion","media-library","faceid"];var lr=e=>typeof e=="object"&&e!==null&&!Array.isArray(e);var _t=e=>{let a=typeof e=="string"?{aps:{alert:e}}:e;if(!lr(a))throw Ia("push payload","expected a string or an object");let t;try{t=JSON.stringify(a)}catch{t=void 0}if(t===void 0)throw Ia("push payload","could not be encoded as JSON");if(new TextEncoder().encode(t).length>Et)throw Ia("push payload",`larger than ${String(Et)} bytes`);return t};var sr=new Set(["setAppearance","setTextSize","setToggle","setLiquidGlass","setColorFilter","setLocation","clearLocation","setPermission","openUrl","launchApp","terminateApp","sendPush"]),dr=new Set(["setAppearance","setTextSize","setToggle","setOrientation","setLocation","clearLocation","setPermission","openUrl","launchApp","terminateApp"]),ur=new Set(["reduceMotion","increaseContrast","reduceTransparency","showBorders","voiceOver"]),nr=new Set(["reduceMotion","networkEnabled"]),Wt=(e,a)=>(e==="ios"?sr:dr).has(a.type)?a.type==="setToggle"?(e==="ios"?ur:nr).has(a.setting):!0:!1;function ue(e){return f("section",{className:"flex flex-col gap-2 border-b px-3 py-2.5",children:[r("h3",{className:"text-xs font-medium text-muted-foreground",children:e.title}),e.children]})}function oe(e){return f("div",{className:"flex min-h-7 items-center justify-between gap-3",children:[r("span",{className:"shrink-0 text-xs text-muted-foreground",children:e.label}),r("div",{className:"flex min-w-0 items-center justify-end",children:e.children})]})}function Ca(e){return r(oe,{label:e.label,children:r(ie,{"aria-label":e.label,checked:e.checked??!1,disabled:e.disabled||e.checked===void 0,onCheckedChange:a=>{e.onChange(a)}})})}function Sa(e){return r(za,{"aria-label":e.label,variant:"outline",value:e.value===void 0?[]:[e.value],disabled:e.disabled||e.value===void 0,onValueChange:a=>{let t=e.options.find(o=>o.value===a[0]);t&&e.onChange(t.value)},children:e.options.map(a=>r(_a,{size:"xs",value:a.value,children:a.label},a.value))})}function Me(e){let a=e.options.find(t=>t.value===e.value);return f(da,{value:e.value,disabled:e.disabled,onValueChange:t=>{let o=e.options.find(l=>l.value===t);o&&o.value!==e.value&&e.onChange(o.value)},children:[r(ua,{size:"xs",className:e.width??"w-40","aria-label":e.ariaLabel,children:r(na,{children:a?a.label:r("span",{className:"text-muted-foreground",children:e.placeholder})})}),r(ia,{align:"end",alignItemWithTrigger:!1,children:e.options.map(t=>r(fa,{value:t.value,children:t.label},t.value))})]})}function va(e){let[a,t]=h(""),o=a.trim()||e.fallback||"",l=()=>{o&&e.onSubmit(o).then(()=>t(""))};return f("form",{className:"flex gap-1.5",onSubmit:d=>{d.preventDefault(),l()},children:[r(Q,{size:"compact",className:"min-w-0 flex-1 font-mono",placeholder:e.placeholder,"aria-label":e.placeholder,value:a,disabled:e.disabled,onChange:d=>t(d.target.value)}),r(I,{type:"submit",size:"xs",variant:"outline",disabled:e.disabled||!o,children:e.action})]})}var Kt=[{key:"tools.location.sanFrancisco",latitude:37.7749,longitude:-122.4194},{key:"tools.location.newYork",latitude:40.7128,longitude:-74.006},{key:"tools.location.london",latitude:51.5074,longitude:-.1278},{key:"tools.location.stockholm",latitude:59.3293,longitude:18.0686},{key:"tools.location.tokyo",latitude:35.6762,longitude:139.6503}];function $t(e){let{t:a}=B(),[t,o]=h(""),[l,d]=h(""),s={latitude:Number(t),longitude:Number(l)},u=t.trim()!==""&&l.trim()!==""&&Math.abs(s.latitude)<=90&&Math.abs(s.longitude)<=180,n=(i,c)=>e.act({type:"setLocation",latitude:i,longitude:c});return f(ue,{title:a("tools.location.title"),children:[f("div",{className:"flex gap-1.5",children:[r(Q,{size:"compact",className:"min-w-0 flex-1 font-mono",placeholder:a("tools.location.latitude"),"aria-label":a("tools.location.latitude"),inputMode:"decimal",value:t,disabled:e.disabled,onChange:i=>o(i.target.value)}),r(Q,{size:"compact",className:"min-w-0 flex-1 font-mono",placeholder:a("tools.location.longitude"),"aria-label":a("tools.location.longitude"),inputMode:"decimal",value:l,disabled:e.disabled,onChange:i=>d(i.target.value)})]}),f("div",{className:"flex flex-wrap items-center gap-1.5",children:[f(da,{value:null,disabled:e.disabled,onValueChange:i=>{let c=Kt.find(m=>m.key===i);c&&(o(String(c.latitude)),d(String(c.longitude)),n(c.latitude,c.longitude))},children:[r(ua,{size:"xs",className:"w-32","aria-label":a("tools.location.preset"),children:r(na,{children:r("span",{className:"text-muted-foreground",children:a("tools.location.presetPlaceholder")})})}),r(ia,{align:"start",alignItemWithTrigger:!1,children:Kt.map(i=>r(fa,{value:i.key,children:a(i.key)},i.key))})]}),r(I,{size:"xs",variant:"outline",disabled:e.disabled||!u,onClick:()=>{n(s.latitude,s.longitude)},children:a("tools.location.set")}),r(I,{size:"xs",variant:"ghost",disabled:e.disabled,onClick:()=>{o(""),d(""),e.act({type:"clearLocation"})},children:a("tools.location.clear")})]})]})}var ir={camera:"tools.permissions.camera",microphone:"tools.permissions.microphone",photos:"tools.permissions.photos",contacts:"tools.permissions.contacts",calendar:"tools.permissions.calendar",reminders:"tools.permissions.reminders",location:"tools.permissions.location",notifications:"tools.permissions.notifications",motion:"tools.permissions.motion","media-library":"tools.permissions.mediaLibrary",faceid:"tools.permissions.faceId"},fr=new Set(["camera","microphone","photos","contacts","calendar","location","notifications","motion"]);function jt(e){let{t:a}=B(),t=e.platform==="ios",[o,l]=h(""),[d,s]=h("camera"),u=o.trim()||e.defaultAppId,n=zt.filter(c=>t||fr.has(c)).map(c=>({value:c,label:a(!t&&c==="motion"?"tools.permissions.activity":ir[c])})),i=c=>{e.act({type:"setPermission",appId:u,permission:d,decision:c})};return f(ue,{title:a("tools.permissions.title"),children:[r(Q,{size:"compact",className:"font-mono",placeholder:e.defaultAppId||a("tools.permissions.appId"),"aria-label":a("tools.permissions.appId"),value:o,disabled:e.disabled,onChange:c=>l(c.target.value)}),f("div",{className:"flex flex-wrap items-center gap-1.5",children:[r(Me,{ariaLabel:a("tools.permissions.permission"),value:d,options:n,placeholder:a("tools.unknown"),disabled:e.disabled,onChange:c=>(s(c),Promise.resolve())}),r(I,{size:"xs",variant:"outline",disabled:e.disabled||!u,onClick:()=>i("grant"),children:a("tools.permissions.grant")}),r(I,{size:"xs",variant:"outline",disabled:e.disabled||!u,onClick:()=>i("revoke"),children:a("tools.permissions.revoke")}),t?r(I,{size:"xs",variant:"ghost",disabled:e.disabled||!u,onClick:()=>i("reset"),children:a("tools.permissions.reset")}):null]})]})}var cr=e=>{let a=e;try{let t=JSON.parse(e);typeof t=="object"&&t!==null&&!Array.isArray(t)&&(a=t)}catch{}try{return _t(a),a}catch{return null}};function Zt(e){let{t:a}=B(),[t,o]=h(""),l=t.trim(),d=l?cr(l):null,s=e.appId;return f(ue,{title:a("tools.push.title"),children:[r(Va,{size:"sm",rows:4,className:"font-mono",placeholder:a("tools.push.placeholder"),"aria-label":a("tools.push.placeholder"),value:t,disabled:e.disabled||!s,onChange:u=>o(u.target.value)}),f("div",{className:"flex items-center gap-2",children:[r(I,{size:"xs",variant:"outline",disabled:e.disabled||!s||d===null,onClick:()=>{s&&d!==null&&e.act({type:"sendPush",appId:s,payload:d})},children:a("tools.push.send")}),s?l&&d===null?r("p",{className:"text-xs text-destructive-foreground",children:a("tools.push.invalid")}):null:r("p",{className:"text-xs text-muted-foreground",children:a("tools.push.needsApp")})]})]})}var Xt=100;function Jt(e){let{t:a}=B(),[t,o]=h(!1),[l,d]=h([]),{transport:s,platform:u,deviceId:n}=e;return T(()=>{if(!t)return;let i=at({transport:s,platform:u,deviceId:n},(c,m)=>{d(x=>{let L=m?[...c]:[...x,...c];return L.length>Xt?L.slice(-Xt):L})});return()=>{i(),d([])}},[t,s,u,n]),f(Ve,{open:t,onOpenChange:o,children:[f(ze,{className:"flex w-full items-center gap-1.5 border-b px-3 py-2.5 text-left text-xs font-medium text-muted-foreground",children:[a("tools.eventLog.title"),r(Se,{className:`ml-auto size-3.5 transition-transform ${t?"rotate-180":""}`})]}),r(_e,{children:r("ol",{className:"max-h-64 overflow-y-auto px-3 py-2 font-mono text-ui-2xs leading-relaxed",children:l.length===0?r("li",{className:"text-muted-foreground",children:a("tools.eventLog.empty")}):l.map(i=>f("li",{className:"flex gap-2",children:[r("span",{className:"shrink-0 text-muted-foreground",children:i.timestamp.slice(11,19)}),r("span",{className:"truncate",children:i.summary})]},i.id))})})]})}var pr=640,mr={light:"tools.settings.light",dark:"tools.settings.dark"},gr={small:"tools.settings.textSmall",default:"tools.settings.textDefault",large:"tools.settings.textLarge","extra-large":"tools.settings.textExtraLarge"},Lr={clear:"tools.settings.glassClear",tinted:"tools.settings.glassTinted"},hr={none:"tools.settings.filterNone",grayscale:"tools.settings.filterGrayscale","red-green":"tools.settings.filterRedGreen","green-red":"tools.settings.filterGreenRed","blue-yellow":"tools.settings.filterBlueYellow"},xr={portrait:"tools.settings.orientationPortrait",landscape_left:"tools.settings.orientationLandscapeLeft",portrait_upside_down:"tools.settings.orientationUpsideDown",landscape_right:"tools.settings.orientationLandscapeRight"},Ir=[{setting:"reduceMotion",labelKey:"tools.settings.reduceMotion"},{setting:"increaseContrast",labelKey:"tools.settings.increaseContrast"},{setting:"reduceTransparency",labelKey:"tools.settings.reduceTransparency"},{setting:"showBorders",labelKey:"tools.settings.showBorders"},{setting:"voiceOver",labelKey:"tools.settings.voiceOver"},{setting:"networkEnabled",labelKey:"tools.settings.network"}];function Qt(e){let{t:a}=B(),{device:t,controls:o}=e,{detail:l,pending:d,error:s,foregroundApp:u,disabled:n,act:i}=o,c=l?.settings,m=t.platform==="ios",x=q(null),[L,w]=h(!0);Pa(()=>{let g=x.current?.parentElement;if(!g)return;let P=()=>w(g.clientWidth<pr);P();let A=new ResizeObserver(P);return A.observe(g),()=>A.disconnect()},[]);let y=Ht.map(g=>({value:g,label:a(gr[g])})),b=Ir.filter(g=>Wt(t.platform,{type:"setToggle",setting:g.setting,value:!0}));return f("aside",{ref:x,"aria-label":a("tools.title"),className:`flex min-h-0 flex-col border-l bg-background text-sm ${L?"absolute inset-y-0 right-0 z-10 w-full max-w-72 shadow-lg":"w-72 shrink-0"}`,children:[f("div",{className:"flex h-9 shrink-0 items-center gap-2 border-b px-3",children:[r("span",{className:"font-medium",children:a("tools.title")}),d?r(H,{size:"sm"}):null,r(I,{size:"icon-xs",variant:"ghost-muted","aria-label":a("tools.close"),className:"ml-auto",onClick:e.onClose,children:r(K,{})})]}),f("div",{className:"min-h-0 flex-1 overflow-y-auto",children:[s?r("p",{role:"alert",className:"border-b bg-destructive/10 px-3 py-2 text-xs text-destructive-foreground",children:s}):null,l===null&&!s?f("div",{className:"flex items-center gap-2 px-3 py-3 text-xs text-muted-foreground",children:[r(H,{size:"sm"}),a("tools.reading")]}):null,f(ue,{title:a("tools.app.title"),children:[r(oe,{label:a("tools.app.foreground"),children:r("span",{className:"truncate font-mono text-xs",children:u?.id??a("tools.app.none")})}),u?f("div",{className:"flex gap-1.5",children:[r(I,{size:"xs",variant:"outline",disabled:n,onClick:()=>{i({type:"terminateApp",appId:u.id})},children:a("tools.app.terminate")}),r(I,{size:"xs",variant:"outline",disabled:n,onClick:()=>{i({type:"launchApp",appId:u.id})},children:a("tools.app.relaunch")})]}):null,r(va,{placeholder:a("tools.app.urlPlaceholder"),action:a("tools.app.open"),disabled:n,onSubmit:g=>i({type:"openUrl",url:g})}),r(va,{placeholder:a(m?"tools.app.bundleIdPlaceholder":"tools.app.packagePlaceholder"),action:a("tools.app.launch"),disabled:n,fallback:u?.id,onSubmit:g=>i({type:"launchApp",appId:g})})]}),f(ue,{title:a(m?"tools.settings.titleIos":"tools.settings.titleAndroid"),children:[r(oe,{label:a("tools.settings.appearance"),children:r(Sa,{label:a("tools.settings.appearance"),value:c?.appearance,options:qt.map(g=>({value:g,label:a(mr[g])})),disabled:n,onChange:g=>i({type:"setAppearance",value:g})})}),r(oe,{label:a("tools.settings.textSize"),children:r(Me,{ariaLabel:a("tools.settings.textSize"),value:c?.textSize??null,options:y,placeholder:a("tools.unknown"),disabled:n,onChange:g=>i({type:"setTextSize",value:g})})}),m?f(Z,{children:[r(oe,{label:a("tools.settings.liquidGlass"),children:r(Sa,{label:a("tools.settings.liquidGlass"),value:c?.liquidGlass,options:Nt.map(g=>({value:g,label:a(Lr[g])})),disabled:n,onChange:g=>i({type:"setLiquidGlass",value:g})})}),r(oe,{label:a("tools.settings.colorFilter"),children:r(Me,{ariaLabel:a("tools.settings.colorFilter"),value:c?.colorFilter??null,options:Gt.map(g=>({value:g,label:a(hr[g])})),placeholder:a("tools.unknown"),disabled:n,onChange:g=>i({type:"setColorFilter",value:g})})})]}):r(oe,{label:a("tools.settings.orientation"),children:r(Me,{ariaLabel:a("tools.settings.orientation"),value:null,options:Vt.map(g=>({value:g,label:a(xr[g])})),placeholder:a("tools.settings.rotateTo"),disabled:n,onChange:g=>i({type:"setOrientation",value:g})})}),b.map(g=>r(Ca,{label:a(g.labelKey),checked:c?.[g.setting],disabled:n,onChange:P=>i({type:"setToggle",setting:g.setting,value:P})},g.setting))]}),r(ue,{title:a("tools.accessibility.title"),children:r(Ca,{label:a("tools.accessibility.overlay"),checked:e.axOverlay,disabled:!1,onChange:g=>(e.onAxOverlayChange(g),Promise.resolve())})}),r($t,{disabled:n,act:i}),r(jt,{platform:t.platform,defaultAppId:u?.id??"",disabled:n,act:i}),m?r(Zt,{appId:u?.id,disabled:n,act:i}):null,m?r(Jt,{transport:e.transport,platform:t.platform,deviceId:t.id}):null]})]})}var Cr=2e4,ya=class extends Error{status;constructor(a){super(`Screenshot capture failed (${a}). Try again.`),this.status=a}};async function Yt(e,a,t,o){let l=AbortSignal.timeout(Cr),d=await e.fetch(`${fe(a)}/api/screenshot?device=${encodeURIComponent(t)}`,{method:"POST",signal:o?AbortSignal.any([o,l]):l});if(!d.ok)throw new ya(d.status);let s=await d.blob();if(!s.size)throw new Error("The device returned an empty screenshot. Try again.");return s.type?s:new Blob([s],{type:"image/png"})}var eo=e=>e instanceof Error?e.message:String(e);function ao(e){let{environmentId:a,device:t}=e,o=Y(),[l,d]=h(null),[s,u]=h(!1),[n,i]=h(null),c=q(!1),m=q(0),x={hostId:t.hostId,deviceId:t.id},L=y=>o("detail",a,x).then(b=>{m.current===y&&(d(b),i(null))},b=>{m.current===y&&(d(null),i(eo(b)))});return T(()=>{let y=++m.current;return L(y),()=>{m.current++}},[a,t.hostId,t.id]),{detail:l,pending:s,error:n,act:async y=>{if(c.current||l===null)return;c.current=!0;let b=++m.current;u(!0),i(null);try{let g=await o("action",a,{...x,...y});m.current===b?d(g):await L(++m.current)}catch(g){m.current===b&&i(eo(g))}finally{c.current=!1,u(!1)}},disabled:s||l===null,foregroundApp:e.foreground===void 0?l?.foregroundApp??null:e.foreground}}var Sr=()=>typeof window<"u"&&"ReactNativeWebView"in window;function to(e){let{t:a}=B(),t=ea(e.environmentId),[o,l]=h(null),[d,s]=h(!1),[u,n]=h(!1),[i,c]=h(!1),[m,x]=h(),[L,w]=h(!1),[y,b]=h(null),[g,P]=h(null),A=q(null),U=q(null),N=t.status==="ready"?t.transport:null,F=ao({environmentId:e.environmentId,device:e.device,foreground:m}),O=se(R=>l(R),[]),X=se(R=>s(R),[]);T(()=>{if(!N)return;let R=et({transport:N,platform:e.device.platform,deviceId:e.device.id},x);return()=>{R(),x(void 0)}},[e.device.id,e.device.platform,N]),T(()=>()=>{A.current?.abort(),U.current&&URL.revokeObjectURL(U.current)},[]);let $=()=>{if(!N||A.current)return;let R=new AbortController;A.current=R,w(!0),b(null),Yt(N,e.device.platform,e.device.id,R.signal).then(G=>{if(R.signal.aborted)return;U.current&&URL.revokeObjectURL(U.current);let V=URL.createObjectURL(G);if(U.current=V,Sr()){P(V);return}let M=document.createElement("a");M.href=V,M.download=`${e.device.name.replace(/[^a-z0-9-]/gi,"-")}-${Date.now()}.png`,document.body.append(M),M.click(),M.remove()}).catch(G=>{R.signal.aborted||b(G instanceof Error?G.message:a("workspace.screenshotFailed"))}).finally(()=>{A.current===R&&(A.current=null,w(!1))})};return t.status!=="ready"?r(J,{name:e.device.name,description:e.device.version,stage:t.status==="failed"?"error":"connecting",message:t.status==="failed"?t.message??a("workspace.needsNewerApp"):a("stream.connecting"),children:r(I,{size:"sm",variant:"outline",onClick:e.onBack,children:a("workspace.allDevices")})}):f("div",{className:"relative flex min-h-0 min-w-0 flex-1",children:[f("div",{className:"relative flex min-h-0 min-w-0 flex-1 flex-col",children:[y||F.error&&!u?r("p",{role:"alert",className:"px-3 py-2 text-xs text-destructive-foreground",children:y??F.error}):null,f("div",{className:"relative min-h-0 flex-1",children:[r(Qe,{transport:t.transport,platform:e.device.platform,deviceId:e.device.id,deviceName:e.device.name,deviceDescription:e.device.version,axOverlay:i,withControls:!0,onHandle:O,onStreaming:X}),r(Ot,{platform:e.device.platform,handle:o,streaming:d,controls:F,screenshotPending:L,onScreenshot:$,toolsOpen:u,onTools:()=>n(!u),onClose:e.onClose,onPowerOff:e.onPowerOff,onFloat:e.onFloat})]})]}),u?r(Qt,{device:e.device,controls:F,transport:t.transport,axOverlay:i,onAxOverlayChange:c,onClose:()=>n(!1)}):null,g?f("div",{className:"absolute inset-0 z-20 flex flex-col items-center justify-center gap-3 bg-background/95 p-4",children:[r("img",{src:g,alt:a("workspace.screenshotAlt"),className:"max-h-[80%] max-w-full object-contain"}),r("p",{className:"text-xs text-muted-foreground",children:a("workspace.screenshotSaveHint")}),f(I,{size:"sm",variant:"outline",onClick:()=>P(null),children:[r(K,{}),a("workspace.closeBrowser")]})]}):null]})}var wa=e=>e instanceof Error?e.message:String(e);function oo(e){let{environmentId:a,threadId:t}=e,{t:o}=B(),{state:l,loaded:d,error:s,unavailable:u}=pe(a),n=Y(),[i,c]=h(null),[m,x]=h(null),L=Fa(a,t),w=p=>Ee(a,t,p),y=E(),b=ne(y,"floating"),g=()=>{c(null),n("refresh",a).catch(p=>c(wa(p)))};T(()=>{!d||u||n("refresh",a).catch(()=>{})},[a,d,n,u]);let P=de(()=>l.sessions.filter(p=>p.threadId===t),[l.sessions,t]),A=yr(P,L),U=A?l.devices.find(p=>p.hostId===A.hostId&&p.id===A.deviceId):void 0,N=U&&A?he(U):null;T(()=>{y.floating?.present({environmentId:a,threadId:t},N)}),T(()=>()=>y.floating?.present({environmentId:a,threadId:t},null),[y,a,t]);let F=de(()=>wr(l),[l]),O=l.hostStatuses[me],X=O?.status==="ready",$=O?.status==="installing"||O?.status==="starting",R=La(),G=l.bootingDevices.filter(p=>p.threadId===t),V=l.hosts.flatMap(p=>p.platforms.filter(S=>!S.available)),M=async p=>{c(null),x(p),sa(a,t,_(p));try{await n("open",a,{threadId:t,hostId:p.hostId,deviceId:p.id,platform:p.platform}),w(_(p))}catch(S){sa(a,t,_(p),!1),c(wa(S))}finally{x(null)}},j=p=>{A&&(c(null),n("close",a,{threadId:t,hostId:A.hostId,deviceId:A.deviceId,shutdown:p}).then(()=>w(null)).catch(S=>c(wa(S))))};return u?r(J,{name:o("panel.title"),stage:"error",message:o("panel.unavailable")}):f("div",{className:"flex size-full min-h-0 flex-col",children:[G.length>0?r("div",{role:"status",className:"border-b px-3 py-2 text-xs text-muted-foreground",children:o("panel.booting",{names:G.map(p=>p.name).join(", ")})}):null,$&&!U?null:r(Tt,{detail:O,onRetry:()=>n("refresh",a).catch(()=>{})}),i||s?f("div",{role:"alert",className:"flex items-start gap-2 border-b bg-destructive/5 px-3 py-2 text-xs text-destructive-foreground",children:[r("p",{className:"min-w-0 flex-1 whitespace-pre-wrap break-words",children:i??s}),i?r(I,{size:"icon-xs",variant:"ghost","aria-label":o("panel.dismissError"),onClick:()=>c(null),children:r(K,{className:"size-3"})}):null]}):null,r("div",{className:"relative flex min-h-0 flex-1",children:U&&A?r(to,{environmentId:a,device:U,onBack:()=>w(""),onFloat:b?()=>y.floating?.open({environmentId:a,threadId:t},{...he(U),reason:"user"}):void 0,onPowerOff:()=>j(!0),onClose:()=>j(!1)},`${a}\0${_(U)}`):m||$||!d?r(J,{name:m?.name??o("panel.title"),...m?{description:m.version}:{},stage:"opening",message:m?m.booted?o("panel.opening"):o("panel.starting"):$&&O?R(O):o("panel.finding")}):r(vr,{environmentId:a,host:l.hosts.find(p=>p.id===me),grouped:F,hostReady:X,hostFailed:O?.status==="failed",unavailableReasons:V,showNoAvdHint:X&&!l.devices.some(p=>p.platform==="android")&&!V.some(p=>p.platform==="android"),pendingKey:m?_(m):null,onOpen:p=>{M(p)},onRefresh:g})})]})}function vr(e){let{t:a}=B(),t=e.grouped.length===0;return r("div",{className:"flex size-full flex-col overflow-y-auto px-4 py-6 text-sm text-muted-foreground",children:f("div",{className:`mx-auto flex w-full max-w-xl flex-col gap-5 ${t?"items-center text-center":""}`,children:[r(Ft,{environmentId:e.environmentId},e.environmentId),t?f(Z,{children:[r(Le,{className:"size-6 opacity-60"}),r("p",{className:"max-w-sm",children:e.hostFailed?a("panel.hubFailed"):a("panel.empty")})]}):null,e.hostReady?e.grouped.map(o=>f("section",{className:"w-full space-y-2 text-left",children:[f("h3",{className:"flex items-center gap-2 font-medium",children:[r(Le,{className:"size-4 shrink-0"}),o.platform==="ios"?a("panel.platformIos"):a("panel.platformAndroid")]}),r("ul",{className:"divide-y rounded-md border",children:o.devices.map(l=>r("li",{children:f(I,{variant:"ghost",className:"h-auto min-h-11 w-full justify-between gap-3 rounded-none px-3 py-2 text-left font-normal",disabled:e.pendingKey!==null,onClick:()=>e.onOpen(l),children:[f("span",{className:"min-w-0 flex-1",children:[r("span",{className:"block truncate text-foreground",children:l.name}),f("span",{className:"block text-xs",children:[l.version,","," ",l.booted?a("panel.running"):a("panel.stopped")]})]}),e.pendingKey===_(l)?r(H,{size:"xs"}):r("span",{className:"text-xs",children:l.booted?a("panel.open"):a("panel.start")})]})},_(l)))})]},o.platform)):null,e.unavailableReasons.map(o=>r("p",{className:"max-w-sm text-xs",children:o.reasonCode?a(`unavailable.${o.reasonCode}`,{root:o.sdkRoot??""}):o.reason},`${o.platform}:${o.reasonCode}`)),e.showNoAvdHint?r("p",{className:"max-w-sm text-xs",children:a("panel.noAvd")}):null,f("div",{className:`flex flex-wrap items-center gap-2 ${t?"self-center":"self-start"}`,children:[r(I,{variant:t?"outline":"ghost",size:"sm",onClick:e.onRefresh,children:a("panel.refresh")}),r(Bt,{environmentId:e.environmentId,host:e.host,busy:!1})]})]})})}function yr(e,a){if(a!==""){if(a!==null){let t=e.find(o=>_({hostId:o.hostId,id:o.deviceId})===a);if(t)return t}return e.toSorted((t,o)=>o.openedAt.localeCompare(t.openedAt))[0]}}function wr(e){let a=[];for(let t of["ios","android"]){let o=e.devices.filter(l=>l.platform===t).toSorted((l,d)=>Number(d.booted)-Number(l.booted)||l.name.localeCompare(d.name));o.length>0&&a.push({platform:t,devices:o})}return a}function ro({environmentId:e,threadId:a}){let t=E(),{state:o,loaded:l}=pe(e),d=q(null);return T(()=>{if(!l||!ne(t,"floating"))return;let s=`${e}\0${a}`,u=d.current?.key===s?d.current.seen:null,{seen:n,opened:i}=Ua({environmentId:e,threadId:a,previous:u,sessions:o.sessions,devices:o.devices});d.current={key:s,seen:n};for(let c of i)t.floating?.open({environmentId:e,threadId:a},{...he(c),reason:"agent",panelId:Ue})},[t,e,l,o.devices,o.sessions,a]),null}function br(e){return{panels:{device:function(t){return f(Fe,{value:e,children:[r("style",{children:ta}),r("div",{className:`${qe} flex h-full min-h-0 flex-1 flex-col`,children:r(oo,{environmentId:t.environmentId,threadId:t.threadId})})]})}},views:{deviceFloat:function(t){return f(Fe,{value:e,children:[r("style",{children:ta}),r("div",{className:`${qe} relative size-full`,children:r(wt,{...t})})]})},deviceSessions:function(t){return r(Fe,{value:e,children:r(ro,{environmentId:t.environmentId,threadId:t.threadId})})}}}}export{br as default};
563
+ `),id:this.lastId}:void 0;return this.data=[],this.eventName="",d}if(a.startsWith(":"))return;let t=a.indexOf(":"),o=t===-1?a:a.slice(0,t),l=t===-1?"":a.slice(t+1);l.startsWith(" ")&&(l=l.slice(1)),o==="data"?this.data.push(l):o==="event"?this.eventName=l:o==="id"&&!l.includes("\0")&&(this.lastId=l)}};async function $e(e,a,t){let o=e.body;if(!o)throw new Error("The response has no body to stream.");let l=o.getReader(),d=()=>{l.cancel().catch(()=>{})};if(t?.aborted)return d();t?.addEventListener("abort",d,{once:!0});try{for(;;){let{done:s,value:u}=await l.read();if(s||t?.aborted)return;a(u)}}catch(s){if(t?.aborted)return;throw s}finally{t?.removeEventListener("abort",d)}}async function ja(e,a,t){if(!e.ok)throw await e.body?.cancel().catch(()=>{}),new Error(`Event stream failed (${e.status}).`);let o=new Xe;await $e(e,l=>{for(let d of o.push(l))a(d)},t)}var ce=e=>e==="ios"?"/vendor/serve-sim":"/vendor/serve-emu";var Lo=1e3,ho=500,je=(e,a,t)=>`${ce(e.platform)}${a}${t?`?${new URLSearchParams(t).toString()}`:""}`,Za=async(e,a,t)=>{let o=await e.transport.fetch(a,t?{signal:t}:void 0);if(!o.ok)throw new Error(`${o.status} ${o.statusText}`);return await o.json()},j=e=>typeof e=="object"&&e!==null,W=(e,a)=>typeof e=="number"&&Number.isFinite(e)?e:a,xo=e=>{let a=e[0],t=j(a)&&j(a.frame)?a.frame:null,o=Math.max(1,W(t?.width,1)),l=Math.max(1,W(t?.height,1)),d=[],s=(u,n)=>{if(d.length>=ho||!j(u)||!j(u.frame))return;let i=u.frame,c=W(i.width,0),m=W(i.height,0);!(Math.abs(c-o)<.5&&Math.abs(m-l)<.5)&&c>0&&m>0&&d.push({id:typeof u.AXUniqueId=="string"?u.AXUniqueId:n,label:typeof u.AXLabel=="string"?u.AXLabel:"",role:typeof u.type=="string"?u.type:"",x:W(i.x,0)/o,y:W(i.y,0)/l,width:c/o,height:m/l}),(Array.isArray(u.children)?u.children:[]).forEach((w,v)=>s(w,`${n}.${v}`))};return e.forEach((u,n)=>s(u,String(n))),d},Ja=e=>j(e)&&typeof e.error=="string"?e.error:"Unexpected accessibility payload.";async function Ya(e,a){if(e.platform==="ios"){let n=await Za(e,je(e,`/helper/${encodeURIComponent(e.deviceId)}/ax`),a);return Array.isArray(n)?{elements:xo(n),errors:[]}:{elements:[],errors:[Ja(n)]}}let t=await Za(e,je(e,"/api/accessibility",{device:e.deviceId}),a);if(!j(t)||!Array.isArray(t.nodes))return{elements:[],errors:[Ja(t)]};let o=t.nodes.filter(n=>j(n)&&j(n.bounds)),l=o[0]?.bounds,d=Math.max(1,W(l?.right,1)),s=Math.max(1,W(l?.bottom,1));return{elements:o.slice(1).flatMap(n=>{let i=n.bounds,c=W(i.left,0),m=W(i.top,0),x=(W(i.right,c)-c)/d,g=(W(i.bottom,m)-m)/s,w=typeof n.text=="string"?n.text:"",v=typeof n.contentDescription=="string"?n.contentDescription:"",C=w||v;if(x>=.95&&g>=.9)return[];if(!C&&n.clickable!==!0)return[];let L=typeof n.className=="string"?n.className:"";return[{id:String(n.id??""),label:C,role:L.split(".").at(-1)??"",x:c/d,y:m/s,width:x,height:g}]}),errors:[]}}var et=(e,a,t)=>{let o=new AbortController,l=null,d=()=>{e.transport.fetch(a,{signal:o.signal}).then(s=>ja(s,u=>{try{t(JSON.parse(u.data))}catch{}},o.signal)).catch(()=>{}).finally(()=>{o.signal.aborted||(l=setTimeout(d,Lo))})};return d(),()=>{o.abort(),l!==null&&clearTimeout(l)}};function at(e,a){return e.platform!=="ios"?()=>{}:et(e,je(e,"/appstate",{device:e.deviceId}),t=>{if(j(t)){if(t.bundleId===null||t.bundleId===""){a(null);return}typeof t.bundleId=="string"&&a({id:t.bundleId,...typeof t.pid=="number"?{pid:t.pid}:{},...typeof t.isReactNative=="boolean"?{isReactNative:t.isReactNative}:{}})}})}var Qa=e=>!j(e)||typeof e.id!="number"?null:{id:e.id,timestamp:typeof e.timestamp=="string"?e.timestamp:"",kind:typeof e.kind=="string"?e.kind:"",summary:typeof e.summary=="string"?e.summary:typeof e.msg=="string"?e.msg:""};function tt(e,a){return e.platform!=="ios"?()=>{}:et(e,je(e,"/api/event-log/events",{device:e.deviceId,limit:"100"}),t=>{if(!j(t))return;if(Array.isArray(t.events)){a(t.events.flatMap(l=>Qa(l)??[]),!0);return}let o=Qa(t.event);o&&a([o],!1)})}function k(){return{t:q().i18n.usePluginTranslation()}}function Je(e){if(e.length<4)return"avc1.42E01E";let a=t=>t.toString(16).padStart(2,"0");return`avc1.${a(e[1])}${a(e[2])}${a(e[3])}`}function ot(e){let a=new Uint8Array(e);if(a.byteLength>16){let t=new DataView(e,0,16);if(t.getUint32(0,!1)===1397050709&&t.getUint8(4)===1){let o=t.getBigUint64(8,!1);return{data:a.subarray(16),isKey:(t.getUint8(5)&1)!==0,timestamp:o<=BigInt(Number.MAX_SAFE_INTEGER)?Number(o):null}}}return{data:a,isKey:null,timestamp:null}}var rt=e=>{try{return JSON.parse(e)?.type==="video-session"}catch{return!1}};function lt(e){let a=!1,t=null,o=e.length,l=0;for(;l+2<o;){if(e[l]===0&&e[l+1]===0){let d=0;if(e[l+2]===1?d=3:l+3<o&&e[l+2]===0&&e[l+3]===1&&(d=4),d){let s=e[l+d]&31;s===7&&!t&&(t=e.subarray(l+d)),s===5&&(a=!0),l+=d+1;continue}}l++}return{isKey:a,sps:t}}var Io={1:"description",2:"keyframe",3:"delta",4:"seed"},Ze=class{buffer=new Uint8Array(64*1024);length=0;push(a){if(this.length+a.length>this.buffer.length){let l=this.buffer.length;for(;l<this.length+a.length;)l*=2;let d=new Uint8Array(l);d.set(this.buffer.subarray(0,this.length)),this.buffer=d}this.buffer.set(a,this.length),this.length+=a.length;let t=[],o=0;for(;this.length-o>=4;){let d=new DataView(this.buffer.buffer,this.buffer.byteOffset+o,4).getUint32(0,!1);if(this.length-o-4<d)break;if(d>=1){let s=Io[this.buffer[o+4]];s&&t.push({type:s,payload:this.buffer.slice(o+5,o+4+d)})}o+=4+d}return o>0&&(this.buffer.copyWithin(0,o,this.length),this.length-=o),t}reset(){this.length=0}};var Co={Enter:40,Escape:41,Backspace:42,Tab:43,Space:44,Minus:45,Equal:46,BracketLeft:47,BracketRight:48,Backslash:49,Semicolon:51,Quote:52,Backquote:53,Comma:54,Period:55,Slash:56,Delete:76,ArrowRight:79,ArrowLeft:80,ArrowDown:81,ArrowUp:82,ControlLeft:224,ShiftLeft:225,AltLeft:226,MetaLeft:227,ControlRight:228,ShiftRight:229,AltRight:230,MetaRight:231};function st(e){return/^Key[A-Z]$/.test(e)?4+(e.charCodeAt(3)-65):/^Digit[1-9]$/.test(e)?30+(e.charCodeAt(5)-49):e==="Digit0"?39:Co[e]??null}var dt={ArrowUp:19,ArrowDown:20,ArrowLeft:21,ArrowRight:22,Tab:61,Enter:66,Backspace:67,Delete:112,Home:122,End:123,PageUp:92,PageDown:93};function ma(e){if(e.stopped)return;let a=d=>{e.configuring=!1,e.connecting(d),e.scheduleRetry("input",()=>ma(e))},t;try{t=e.transport.connect(`${e.vendor}/ws?device=${e.device}&frame-meta=1`)}catch(d){e.events.onInputConnected(!1,d.message),a(d.message);return}e.socket=t;let o=[],l=!1;t.onopen=()=>{e.stopped||e.socket!==t||(e.connecting(),e.events.onInputConnected(!0))},t.onmessage=d=>{if(e.stopped||e.socket!==t)return;if(typeof d.data=="string"){rt(d.data)&&(e.closeDecoder(),e.configuring=!1,o=[],l=!1,e.connecting());return}let s=ot(d.data),u=!e.videoDecoder||e.videoDecoder.state!=="configured",i=s.isKey===null||s.isKey&&u?lt(s.data):null,c=s.isKey??i?.isKey??!1,m={isKey:c,data:s.data,timestamp:s.timestamp};if(e.configuring){o.push(m);return}if(i?.sps&&u){e.configuring=!0,o=[m];let x=e.decoderEpoch,g=()=>!e.stopped&&e.socket===t;e.configureDecoder({codec:Je(i.sps)},g).then(w=>{if(!g()||x!==e.decoderEpoch)return;e.configuring=!1,e.awaitingKeyframe=!0;let v=o;if(o=[],!!w){for(let C of v)e.decode(C.isKey,C.data,C.timestamp);e.awaitingKeyframe&&e.requestKeyframe()}});return}if(u){!c&&!l&&(l=!0,e.requestKeyframe());return}e.decode(c,s.data,s.timestamp)},t.onclose=d=>{e.socket===t&&(e.socket=null,e.closeDecoder(),!e.stopped&&(e.events.onInputConnected(!1,d.reason||`closed ${d.code}`),a(d.reason||void 0)))},t.onerror=()=>t.close()}function ut(e){return{sendTouch(a,t,o){let l=a==="begin"?"down":a==="move"?"move":"up";e.send(JSON.stringify({type:"touch",action:l,x:t,y:o}))},sendKey(a,t){if(t!=="down")return;if(a.key==="Escape")return e.send(JSON.stringify({type:"back"}));let o=dt[a.key];if(o!==void 0)return e.send(JSON.stringify({type:"key",keycode:o}));a.key.length===1&&!a.metaKey&&!a.ctrlKey&&e.send(JSON.stringify({type:"text",text:a.key}))},pressButton(a){let t=a==="appSwitcher"?"recents":a;(t==="home"||t==="back"||t==="recents"||t==="power")&&e.send(JSON.stringify({type:t}))},rotate(){},setOrientation(){}}}function nt(e){return{present(a,t,o){let l=e.getContext("2d");return l?((e.width!==t||e.height!==o)&&(e.width=t,e.height=o),l.drawImage(a,0,0,t,o),!0):!1}}}var it=new TextEncoder,ft=new TextDecoder;function pt(e){if(!e)return null;let a=/boundary=(?:"([^"]+)"|([^;\s]+))/i.exec(e),t=a?.[1]??a?.[2];return t?t.startsWith("--")?t:`--${t}`:null}function ct(e,a,t,o){let l=o-a.length;for(let d=t;d<=l;d++){if(e[d]!==a[0])continue;let s=1;for(;s<a.length&&e[d+s]===a[s];)s++;if(s===a.length)return d}return-1}var Qe=class{delimiter;buffer=new Uint8Array(64*1024);length=0;pos=0;state="boundary";contentLength=null;scanFrom=0;constructor(a){this.delimiter=a?it.encode(a):null}push(a){this.append(a);let t=[];for(;;){if(this.state==="done"){this.pos=this.length=0;break}if(this.state==="boundary"){if(!this.readBoundary())break}else if(this.state==="headers"){if(!this.readHeaders())break}else{let o=this.readBody();if(!o)break;o.length>0&&t.push(o)}}if(this.length-this.pos>16777216)throw new Error("MJPEG part is too large.");return this.pos>0&&(this.buffer.copyWithin(0,this.pos,this.length),this.length-=this.pos,this.scanFrom=Math.max(0,this.scanFrom-this.pos),this.pos=0),t}append(a){if(this.length+a.length>this.buffer.length){let t=this.buffer.length;for(;t<this.length+a.length;)t*=2;let o=new Uint8Array(t);o.set(this.buffer.subarray(0,this.length)),this.buffer=o}this.buffer.set(a,this.length),this.length+=a.length}lineEnd(a){return this.buffer.subarray(0,this.length).indexOf(10,a)}readBoundary(){let a=this.buffer;if(!this.delimiter)for(;;){let s=this.lineEnd(this.pos);if(s===-1)return!1;let u=ft.decode(a.subarray(this.pos,s)).trim();if(this.pos=s+1,u.startsWith("--"))return this.delimiter=it.encode(u),this.state="headers",!0}let t=this.delimiter,o=ct(a,t,this.pos,this.length);if(o===-1)return this.pos=Math.max(this.pos,this.length-t.length+1),!1;let l=o+t.length;if(l+2>this.length)return this.pos=o,!1;if(a[l]===45&&a[l+1]===45)return this.state="done",!0;let d=this.lineEnd(l);return d===-1?(this.pos=o,!1):(this.pos=d+1,this.state="headers",!0)}readHeaders(){let a=this.pos,t=null;for(;;){let o=this.lineEnd(a);if(o===-1)return!1;let l=ft.decode(this.buffer.subarray(a,o)).replace(/\r$/,"");if(a=o+1,l==="")break;let d=l.indexOf(":");if(d>0&&l.slice(0,d).trim().toLowerCase()==="content-length"){let s=Number.parseInt(l.slice(d+1).trim(),10);Number.isFinite(s)&&s>=0&&(t=s)}}return this.pos=a,this.contentLength=t,this.scanFrom=a,this.state="body",!0}readBody(){if(this.contentLength!==null){if(this.length-this.pos<this.contentLength)return null;let o=this.buffer.slice(this.pos,this.pos+this.contentLength);return this.pos+=this.contentLength,this.state="boundary",o}let a=this.delimiter,t=Math.max(this.scanFrom,this.pos+1);for(;;){let o=ct(this.buffer,a,t,this.length);if(o===-1)return this.scanFrom=Math.max(this.pos,this.length-a.length),null;if(this.buffer[o-1]!==10){t=o+1;continue}let l=o-1;l>this.pos&&this.buffer[l-1]===13&&l--;let d=this.buffer.slice(this.pos,Math.max(l,this.pos));return this.pos=o,this.state="boundary",d}}};async function So(e,a,t){let o=new Qe(pt(e.headers.get("content-type")));await $e(e,l=>{for(let d of o.push(l))a(d)},t)}function Ce(e){e.stopped||e.mjpeg||(e.mjpeg=!0,e.controller?.abort(),e.controller=null,e.closeDecoder(),e.connecting(),e.events.onMjpegFallback?.(),mt(e))}var ga=e=>`${e.vendor}/helper/${e.device}/stream.mjpeg`;async function mt(e){let a=e.generation,t=++e.videoGeneration,o=new AbortController;e.controller=o;let l=()=>!e.stopped&&e.generation===a&&e.videoGeneration===t&&e.controller===o,d=null,s=!1,u=async()=>{s=!0;try{for(;d;){let i=d;d=null;try{let c=await e.createBitmap(new Blob([i],{type:"image/jpeg"}));try{l()&&e.paint(c,c.width,c.height)}finally{c.close()}}catch{}}}finally{s=!1}},n;try{let i=await e.transport.fetch(ga(e),{signal:o.signal});if(!l()){await i.body?.cancel();return}if(!i.ok||!i.body)throw new Error(`stream ${i.status}`);if(await So(i,c=>{l()&&(d=c,s||u())},o.signal),!l())return;n="Device stream ended."}catch(i){if(!l())return;n=i.message}l()&&(e.controller=null,o.abort(),e.connecting(n),e.scheduleRetry("video",()=>{mt(e)}))}var vo=1e3,La=15e3,yo=16667,wo=8,bo=e=>typeof e=="object"&&e!==null&&"present"in e;function Lt(e){let{transport:a,platform:t,events:o}=e,l=bo(e.output)?e.output:nt(e.output),d=u=>e.globals?.[u]??globalThis[u],s={platform:t,transport:a,events:o,preferMjpeg:e.preferMjpeg===!0,vendor:ce(t),device:encodeURIComponent(e.deviceId),stopped:!0,generation:0,videoGeneration:0,decoderEpoch:0,socket:null,controller:null,primeController:null,videoDecoder:null,timestamp:0,awaitingKeyframe:!0,screen:null,firstFrame:!1,configuring:!1,mjpeg:!1,frameTimer:null,videoReadTimer:null,retryTimers:new Map,webCodecs(){let u=d("VideoDecoder"),n=d("EncodedVideoChunk");return u&&n?{VideoDecoder:u,EncodedVideoChunk:n}:null},createBitmap(u){let n=d("createImageBitmap");return n?n(u):Promise.reject(new Error("createImageBitmap is unavailable."))},setStatus(u,n){s.stopped||o.onStatus(u,n)},fail(u){s.stopped||(s.stop(),o.onInputConnected(!1,u),o.onStatus("error",u))},connecting(u){s.firstFrame=!1,s.frameTimer===null&&(s.frameTimer=setTimeout(()=>s.fail("No video received from the device. Reconnect to try again."),La)),s.setStatus("connecting",u)},paint(u,n,i){if(!s.stopped){if(t==="android"&&(s.screen?.width!==n||s.screen.height!==i)&&(s.screen={width:n,height:i,orientation:n>i?"landscape_left":"portrait"},o.onScreen(s.screen)),!l.present(u,n,i)){s.fail("Could not display the device stream. Reconnect to try again.");return}s.firstFrame||(s.firstFrame=!0,s.frameTimer!==null&&clearTimeout(s.frameTimer),s.frameTimer=null,s.setStatus("streaming"))}},closeDecoder(){s.decoderEpoch++,s.configuring=!1;try{s.videoDecoder?.close()}catch{}s.videoDecoder=null,s.awaitingKeyframe=!0},recoverDecoder(){t==="ios"?Ce(s):(s.closeDecoder(),s.connecting("Video decoder restarted."),s.requestKeyframe())},async configureDecoder(u,n=()=>!s.stopped){let i=s.webCodecs();if(!i)return!1;let c=s.decoderEpoch,m={...u,optimizeForLatency:!0},x=await i.VideoDecoder.isConfigSupported(m).catch(()=>({supported:!1}));if(!n()||c!==s.decoderEpoch)return!1;if(!x.supported)return t==="android"&&s.fail(`This browser cannot decode ${u.codec}.`),!1;try{return(!s.videoDecoder||s.videoDecoder.state==="closed")&&(s.videoDecoder=ko(s,i)),s.videoDecoder.configure(m),!0}catch(g){return t==="android"&&s.fail(`Video decoder: ${g.message}`),!1}},decode(u,n,i){let c=s.videoDecoder,m=s.webCodecs();if(!(!c||c.state!=="configured"||!m)){if(s.awaitingKeyframe){if(!u)return;s.awaitingKeyframe=!1}if(c.decodeQueueSize>wo){s.recoverDecoder();return}try{c.decode(new m.EncodedVideoChunk({type:u?"key":"delta",timestamp:i??s.timestamp,data:n})),s.timestamp+=yo}catch{s.recoverDecoder()}}},requestKeyframe(){t==="android"&&s.socket?.readyState===1&&s.socket.send(JSON.stringify({type:"reset-video",ack:!1}))},scheduleRetry(u,n){s.stopped||s.retryTimers.has(u)||s.retryTimers.set(u,setTimeout(()=>{s.retryTimers.delete(u),n()},vo))},send(u){!s.stopped&&s.socket?.readyState===1&&s.socket.send(u)},stop(){if(s.stopped)return;s.stopped=!0,s.generation++,s.videoGeneration++,s.mjpeg=!1,s.frameTimer!==null&&clearTimeout(s.frameTimer),s.frameTimer=null,s.videoReadTimer!==null&&clearTimeout(s.videoReadTimer),s.videoReadTimer=null;for(let n of s.retryTimers.values())clearTimeout(n);s.retryTimers.clear(),s.primeController?.abort(),s.primeController=null,s.controller?.abort(),s.controller=null;let u=s.socket;s.socket=null,u?.close(),s.closeDecoder()}};return s}function ko(e,a){let t=e.videoGeneration,o=()=>e.platform!=="ios"||t===e.videoGeneration,l=new a.VideoDecoder({output:d=>{try{e.videoDecoder===l&&o()&&e.paint(d,d.displayWidth,d.displayHeight)}finally{d.close()}},error:()=>{e.stopped||e.videoDecoder!==l||!o()||e.recoverDecoder()}});return l}var Do=3,Po=4,Ao=6,ht=7,To=13,Bo=130,Mo=2e3,Ro=new TextEncoder,Fo=new TextDecoder,Ye=["portrait","landscape_left","portrait_upside_down","landscape_right"],Eo=new Set(Ye);function pe(e,a){let t=Ro.encode(JSON.stringify(a)),o=new Uint8Array(1+t.length);return o[0]=e,o.set(t,1),o}function Oo(e){if(typeof e!="object"||e===null)return null;let{width:a,height:t,orientation:o,screenId:l}=e;if(typeof a!="number"||!Number.isFinite(a)||a<=0||typeof t!="number"||!Number.isFinite(t)||t<=0||typeof o!="string"||!Eo.has(o))return null;let d={width:a,height:t,orientation:o};return typeof l=="number"?{...d,screenId:l}:d}function xt(e,a){Ct(e),a?It(e):Ce(e)}async function It(e){let a=e.generation,t=++e.videoGeneration,o=new Ze,l=new AbortController;e.controller=l;let d=()=>!e.stopped&&e.generation===a&&e.videoGeneration===t&&e.controller===l,s;try{let u=await e.transport.fetch(`${e.vendor}/helper/${e.device}/stream.avcc`,{signal:l.signal});if(!d()){await u.body?.cancel();return}if(!u.ok||!u.body)throw new Error(`stream ${u.status}`);let n=u.body.getReader();for(;;){let i=setTimeout(()=>{d()&&e.fail("Device stream stopped receiving video. Reconnect to try again.")},La);e.videoReadTimer=i;let c;try{c=await n.read()}finally{clearTimeout(i),e.videoReadTimer===i&&(e.videoReadTimer=null)}let{done:m,value:x}=c;if(!d())return;if(m)break;for(let g of o.push(x))switch(g.type){case"seed":e.createBitmap(new Blob([g.payload],{type:"image/jpeg"})).then(w=>{try{d()&&e.paint(w,w.width,w.height)}finally{w.close()}}).catch(()=>{});break;case"description":{e.awaitingKeyframe=!0;let w=await e.configureDecoder({codec:Je(g.payload),description:g.payload},d);if(!d())return;if(!w){if(await n.cancel().catch(()=>{}),!d())return;Ce(e);return}break}case"keyframe":case"delta":e.decode(g.type==="keyframe",g.payload);break}}}catch(u){if(!d())return;s=u.message}d()&&(e.controller=null,l.abort(),e.closeDecoder(),e.connecting(s),e.scheduleRetry("video",()=>{It(e)}))}async function Uo(e,a){let t=new AbortController;e.primeController=t;let o=setTimeout(()=>t.abort(),Mo);try{let l=await e.transport.fetch(ga(e),{signal:t.signal});if(e.stopped||e.generation!==a)return;await l.body?.getReader().read()}catch{}finally{clearTimeout(o),t.abort(),e.primeController===t&&(e.primeController=null)}}async function Ct(e){if(e.stopped)return;let a=e.generation;if(await Uo(e,a),e.stopped||e.generation!==a)return;let t=()=>e.scheduleRetry("input",()=>{Ct(e)}),o;try{o=e.transport.connect(`${e.vendor}/helper/ws?device=${e.device}`)}catch(l){e.events.onInputConnected(!1,l.message),t();return}e.socket=o,o.onopen=()=>{e.stopped||e.socket!==o||(o.send(pe(To,{enabled:!1})),e.events.onInputConnected(!0))},o.onmessage=l=>{if(e.stopped||e.socket!==o||typeof l.data=="string")return;let d=new Uint8Array(l.data);if(!(d.length<1||d[0]!==Bo))try{let s=Oo(JSON.parse(Fo.decode(d.subarray(1))));s&&(e.screen=s,e.events.onScreen(s))}catch{}},o.onclose=l=>{e.socket===o&&(e.socket=null,!e.stopped&&(e.events.onInputConnected(!1,l.reason||(l.code===1006?"input socket refused":`closed ${l.code}`)),t()))},o.onerror=()=>o.close()}function qo(e,a,t){let o=e.screen;if(!o||o.width>o.height)return{x:a,y:t};switch(o.orientation){case"landscape_left":return{x:t,y:1-a};case"landscape_right":return{x:1-t,y:a};case"portrait_upside_down":return{x:1-a,y:1-t};default:return{x:a,y:t}}}function St(e){return{sendTouch(a,t,o){e.send(pe(Do,{type:a,...qo(e,t,o)}))},sendKey(a,t){let o=st(a.code);o!==null&&e.send(pe(Ao,{type:t,usage:o}))},pressButton(a){let t=a==="home"?"home":a==="appSwitcher"?"app_switcher":a==="power"?"lock":null;t&&e.send(pe(Po,{button:t}))},rotate(){let a=e.screen?.orientation??"portrait",t=Ye[(Ye.indexOf(a)+1)%Ye.length];e.send(pe(ht,{orientation:t}))},setOrientation(a){e.send(pe(ht,{orientation:a}))}}}function vt(e){let a=Lt(e),t=e.platform==="ios"?St(a):ut(a);return{start:()=>{if(!a.stopped)return;a.stopped=!1,a.generation++,a.configuring=!1,a.connecting();let l=a.webCodecs()!==null&&!(e.platform==="ios"&&a.preferMjpeg);e.platform==="ios"?xt(a,l):l?ma(a):a.fail("This browser cannot decode the Android stream (WebCodecs unavailable).")},stop:a.stop,isMjpeg:()=>a.mjpeg,...t}}var Ho=56,No=2e3;function Go(e,a,t,o=0){let l=Math.max(0,a-o);if(l===0||t===0)return{width:0,height:0};let d={width:t*e,height:t};return d.width<=l?d:{width:l,height:l/e}}function Vo(e,a){if(!a)return e==="ios"?9/19.5:9/20;let t=a.orientation==="landscape_left"||a.orientation==="landscape_right",o=Math.max(a.width,a.height),l=Math.min(a.width,a.height);return t?o/l:l/o}function zo(e,a){if(e!=="ios"||!a||a.width>a.height)return 0;switch(a.orientation){case"landscape_left":return 90;case"landscape_right":return-90;case"portrait_upside_down":return 180;default:return 0}}var _o=()=>typeof navigator<"u"&&/iPhone|iPad|iPod/.test(navigator.userAgent);function ea(e){let{t:a}=k(),t=V(null),o=V(null),[l,d]=h("connecting"),[s,u]=h(),[n,i]=h(null),[c,m]=h({connected:!1}),{onHandle:x,onStreaming:g,onScreen:w,transport:v,platform:C,deviceId:L}=e;T(()=>w?.(n),[w,n]),T(()=>{let p=t.current;if(!p)return;let S=vt({transport:v,platform:C,deviceId:L,output:p,preferMjpeg:_o(),events:{onStatus:(A,U)=>{d(A),u(U),g(A==="streaming")},onScreen:i,onInputConnected:(A,U)=>{m({connected:A,...U?{detail:U}:{}}),x({pressButton:S.pressButton,rotate:S.rotate,inputConnected:A})}}});return o.current=S,m({connected:!1}),S.start(),x({pressButton:S.pressButton,rotate:S.rotate,inputConnected:!1}),()=>{S.stop(),o.current=null,x(null),g(!1),i(null)}},[L,x,g,C,v]);let D=V(null),[P,F]=h({width:0,height:0});T(()=>{let p=D.current;if(!p)return;let S=()=>{let U=p.getBoundingClientRect();F(K=>K.width===U.width&&K.height===U.height?K:{width:U.width,height:U.height})};S();let A=new ResizeObserver(S);return A.observe(p),()=>A.disconnect()},[]);let N=e.withControls?Ho:0,B=ue(()=>Go(Vo(C,n),P.width,P.height,N),[P,N,C,n]),E=zo(C,n),Q=E===90||E===-90?{width:B.height,height:B.width,left:(B.width-B.height)/2,top:(B.height-B.width)/2,transform:`rotate(${E}deg)`}:{width:B.width,height:B.height,...E?{transform:`rotate(${E}deg)`}:{}},[M,_]=h([]);T(()=>{if(!e.axOverlay)return;let p=null,S=null,A=!1,U=async()=>{p=new AbortController;try{let K=await Ya({transport:v,platform:C,deviceId:L},p.signal);A||_(K.elements)}catch{}A||(S=setTimeout(()=>{U()},No))};return U(),()=>{A=!0,p?.abort(),S&&clearTimeout(S),_([])}},[L,C,e.axOverlay,v]);let z=V(!1),O=p=>{let S=p.currentTarget.getBoundingClientRect(),A=(p.clientX-S.left)/S.width,U=(p.clientY-S.top)/S.height;return{x:Math.min(1,Math.max(0,A)),y:Math.min(1,Math.max(0,U))}},G=p=>{if(!z.current)return;z.current=!1;let{x:S,y:A}=O(p);o.current?.sendTouch("end",S,A)};return f("div",{ref:D,className:"relative flex size-full min-h-0 min-w-0 items-center justify-center overflow-hidden",style:N?{paddingRight:N}:void 0,tabIndex:0,role:"application","aria-label":a(C==="ios"?"stream.iosScreen":"stream.androidScreen"),onKeyDown:p=>{p.target===p.currentTarget&&(p.metaKey&&!["r","R"].includes(p.key)||(p.preventDefault(),o.current?.sendKey(p.nativeEvent,"down")))},onKeyUp:p=>{p.target===p.currentTarget&&o.current?.sendKey(p.nativeEvent,"up")},children:[f("div",{className:"relative touch-none select-none",style:{width:B.width,height:B.height},onPointerDown:p=>{p.currentTarget.setPointerCapture(p.pointerId),p.currentTarget.parentElement?.focus(),z.current=!0;let{x:S,y:A}=O(p);o.current?.sendTouch("begin",S,A)},onPointerMove:p=>{if(!z.current)return;let{x:S,y:A}=O(p);o.current?.sendTouch("move",S,A)},onPointerUp:G,onPointerCancel:G,children:[r("canvas",{ref:t,className:"absolute top-0 left-0",style:Q}),M.length>0?r("div",{className:"pointer-events-none absolute inset-0","aria-hidden":!0,children:M.map(p=>r("div",{className:"absolute border border-info/80 bg-info/10",style:{left:`${p.x*100}%`,top:`${p.y*100}%`,width:`${p.width*100}%`,height:`${p.height*100}%`},children:p.label?r("span",{className:"absolute -top-3.5 left-0 max-w-full truncate rounded-sm bg-info px-1 text-ui-2xs leading-3.5 text-white",children:p.label}):null},p.id))}):null]}),l==="streaming"&&!c.connected?r("div",{className:"pointer-events-none absolute inset-x-0 bottom-0 flex justify-center p-2",children:r("span",{className:"rounded-md bg-background/85 px-2 py-1 text-xs text-muted-foreground",children:c.detail?a("stream.inputLostDetail",{detail:c.detail}):a("stream.inputLost")})}):null,l!=="streaming"?r("div",{className:"absolute inset-0 bg-background",children:r(Y,{name:e.deviceName,description:e.deviceDescription,stage:l==="error"?"error":"connecting",message:l==="error"?s??a("stream.failed"):a("stream.connecting"),children:l==="error"?r(I,{size:"sm",variant:"outline",onClick:()=>{o.current?.stop(),o.current?.start()},children:a("stream.reconnect")}):null})}):null]})}var Wo={hosts:[],hostStatuses:{},devices:[],sessions:[],bootingDevices:[],revision:0};function me(e){let t=q().commands.useSubscription("state",{},{environmentId:e});return{state:t.data??Wo,loaded:t.data!==null,error:t.error,unavailable:t.isUnavailable}}function ae(){let e=q();return de((a,t,o={})=>e.commands.invoke(a,o,{environmentId:t}),[e])}var ge="local",aa=class extends Error{code;constructor(a,t,o){super(t,o),this.name="DeviceError",this.code=a}};var yt="hub";function ta(e){let a=q(),[t,o]=h({status:"connecting"});return T(()=>{let l=a.network;if(!ie(a,"network")||l===void 0){o({status:"failed",message:null});return}let d=!1;return o({status:"connecting"}),l.client(e).then(s=>{d||o({status:"ready",transport:{fetch:(u,n)=>s.fetch(yt,u,{...n,instance:ge}),connect:u=>s.connect(yt,u,{instance:ge})}})},s=>{d||o({status:"failed",message:s instanceof Error?s.message:String(s)})}),()=>{d=!0}},[a,e]),t}var wt=()=>{};function bt(e){let{environmentId:a,threadId:t,hostId:o,deviceId:l,platform:d}=e,s=e[Ra],u=q(),{t:n}=k(),{state:i,loaded:c}=me(a),m=ta(a),x=ue(()=>({environmentId:a,threadId:t}),[a,t]),g=i.devices.find(D=>D.hostId===o&&D.id===l),w=i.sessions.some(D=>D.threadId===t&&D.hostId===o&&D.deviceId===l);T(()=>{c&&!w&&u.floating?.close(x,s.key)},[u,s.key,c,w,x]),T(()=>(s.setOpenInPanel(()=>{He(a,t,s.key),u.floating?.openPanel(x,Ue),u.floating?.close(x,s.key)}),()=>s.setOpenInPanel(null)),[u,a,s,x,t]);let v=de(D=>s.reportSourceSize(D===null?null:Fa(D)),[s]),C=g?.name??l,L=g?.version??d;return m.status!=="ready"?r(Y,{name:C,description:L,stage:m.status==="failed"?"error":"connecting",message:m.status==="failed"?m.message??n("workspace.needsNewerApp"):n("stream.connecting")}):r(ea,{transport:m.transport,platform:d,deviceId:l,deviceName:C,deviceDescription:L,axOverlay:!1,withControls:!1,onHandle:wt,onStreaming:wt,onScreen:v})}var oa=(...e)=>e.filter((a,t,o)=>!!a&&a.trim()!==""&&o.indexOf(a)===t).join(" ").trim();var kt=e=>e.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase();var Dt=e=>e.replace(/^([A-Z])|[\s-_]+(\w)/g,(a,t,o)=>o?o.toUpperCase():t.toLowerCase());var ha=e=>{let a=Dt(e);return a.charAt(0).toUpperCase()+a.slice(1)};var Pt={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"};var At=e=>{for(let a in e)if(a.startsWith("aria-")||a==="role"||a==="title")return!0;return!1};var Tt=Ee(({color:e="currentColor",size:a=24,strokeWidth:t=2,absoluteStrokeWidth:o,className:l="",children:d,iconNode:s,...u},n)=>se("svg",{ref:n,...Pt,width:a,height:a,stroke:e,strokeWidth:o?Number(t)*24/Number(a):t,className:oa("lucide",l),...!d&&!At(u)&&{"aria-hidden":"true"},...u},[...s.map(([i,c])=>se(i,c)),...Array.isArray(d)?d:[d]]));var y=(e,a)=>{let t=Ee(({className:o,...l},d)=>se(Tt,{ref:d,iconNode:a,className:oa(`lucide-${kt(ha(e))}`,`lucide-${e}`,o),...l}));return t.displayName=ha(e),t};var Ko=[["path",{d:"M13.997 4a2 2 0 0 1 1.76 1.05l.486.9A2 2 0 0 0 18.003 7H20a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V9a2 2 0 0 1 2-2h1.997a2 2 0 0 0 1.759-1.048l.489-.904A2 2 0 0 1 10.004 4z",key:"18u6gg"}],["circle",{cx:"12",cy:"13",r:"3",key:"1vg3eu"}]],Se=y("camera",Ko);var Xo=[["path",{d:"m6 9 6 6 6-6",key:"qrunsl"}]],ve=y("chevron-down",Xo);var $o=[["path",{d:"m15 18-6-6 6-6",key:"1wnfg3"}]],ye=y("chevron-left",$o);var jo=[["circle",{cx:"12",cy:"12",r:"1",key:"41hilf"}],["circle",{cx:"19",cy:"12",r:"1",key:"1wjl8i"}],["circle",{cx:"5",cy:"12",r:"1",key:"1pcz8c"}]],te=y("ellipsis",jo);var Zo=[["path",{d:"M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8",key:"5wwlr5"}],["path",{d:"M3 10a2 2 0 0 1 .709-1.528l7-6a2 2 0 0 1 2.582 0l7 6A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z",key:"r6nss1"}]],oe=y("house",Zo);var Jo=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M12 16v-4",key:"1dtifu"}],["path",{d:"M12 8h.01",key:"e9boi3"}]],we=y("info",Jo);var Qo=[["path",{d:"M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401",key:"kfwtm"}]],be=y("moon",Qo);var Yo=[["path",{d:"M21 9V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v10c0 1.1.9 2 2 2h4",key:"daa4of"}],["rect",{width:"10",height:"7",x:"12",y:"13",rx:"2",key:"1nb8gs"}]],ke=y("picture-in-picture-2",Yo);var er=[["path",{d:"M12 2v10",key:"mnfbl"}],["path",{d:"M18.4 6.6a9 9 0 1 1-12.77.04",key:"obofu9"}]],De=y("power",er);var ar=[["path",{d:"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8",key:"1357e3"}],["path",{d:"M3 3v5h5",key:"1xhq8a"}]],Le=y("rotate-ccw",ar);var tr=[["path",{d:"M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8",key:"1p45f6"}],["path",{d:"M21 3v5h-5",key:"1q7to0"}]],Pe=y("rotate-cw",tr);var or=[["path",{d:"M10 5H3",key:"1qgfaw"}],["path",{d:"M12 19H3",key:"yhmn1j"}],["path",{d:"M14 3v4",key:"1sua03"}],["path",{d:"M16 17v4",key:"1q0r14"}],["path",{d:"M21 12h-9",key:"1o4lsq"}],["path",{d:"M21 19h-5",key:"1rlt1p"}],["path",{d:"M21 5h-7",key:"1oszz2"}],["path",{d:"M8 10v4",key:"tgpxqk"}],["path",{d:"M8 12H3",key:"a7s4jb"}]],Ae=y("sliders-horizontal",or);var rr=[["rect",{width:"14",height:"20",x:"5",y:"2",rx:"2",ry:"2",key:"1yt0o3"}],["path",{d:"M12 18h.01",key:"mhygvu"}]],he=y("smartphone",rr);var lr=[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}]],Te=y("square",lr);var sr=[["circle",{cx:"12",cy:"12",r:"4",key:"4exip2"}],["path",{d:"M12 2v2",key:"tus03m"}],["path",{d:"M12 20v2",key:"1lh1kg"}],["path",{d:"m4.93 4.93 1.41 1.41",key:"149t6j"}],["path",{d:"m17.66 17.66 1.41 1.41",key:"ptbguv"}],["path",{d:"M2 12h2",key:"1t8f8n"}],["path",{d:"M20 12h2",key:"1q8mjw"}],["path",{d:"m6.34 17.66-1.41 1.41",key:"1m8zz5"}],["path",{d:"m19.07 4.93-1.41 1.41",key:"1shlcs"}]],Be=y("sun",sr);var dr=[["path",{d:"M12 4v16",key:"1654pz"}],["path",{d:"M4 7V5a1 1 0 0 1 1-1h14a1 1 0 0 1 1 1v2",key:"e0r10z"}],["path",{d:"M9 20h6",key:"s66wpe"}]],Me=y("type",dr);var ur=[["path",{d:"M18 6 6 18",key:"1bl5f8"}],["path",{d:"m6 6 12 12",key:"d8bk6v"}]],Z=y("x",ur);function nr(e,a){let t=o=>a(o==="hub"?"versions.hubName":"versions.agentName");return e.status==="starting"?a("panel.startingHost"):e.status!=="installing"?e.message??"":e.tool&&e.toVersion?e.fromVersion?a("panel.updatingTool",{tool:t(e.tool),from:e.fromVersion,to:e.toVersion}):a("panel.installingTool",{tool:t(e.tool),to:e.toVersion}):a("panel.installing")}function xa(){let{t:e}=k();return a=>nr(a,e)}function Bt(e){let{t:a}=k(),t=xa(),[o,l]=h(!1),d=e.detail;return!d||d.status==="ready"||d.status==="idle"?null:d.status==="failed"?f("div",{role:"alert",className:"flex items-start gap-2 border-b bg-destructive/5 px-3 py-2 text-xs",children:[f("div",{className:"min-w-0 flex-1 space-y-0.5",children:[r("p",{className:"font-medium text-destructive-foreground",children:a("panel.hostFailed")}),d.message?r("p",{className:"whitespace-pre-wrap break-words text-muted-foreground",children:d.message}):null]}),f(I,{size:"xs",variant:"outline",disabled:o,onClick:()=>{l(!0),e.onRetry().finally(()=>l(!1))},children:[o?r(H,{size:"xs"}):r(Pe,{}),a(o?"panel.retrying":"panel.retry")]})]}):f("div",{role:"status",className:"flex items-center gap-2 border-b px-3 py-2 text-xs text-muted-foreground",children:[r(H,{size:"xs"}),r("span",{className:"min-w-0 flex-1",children:t(d)})]})}var Ia=["hub","agent"],Ca=e=>e!==void 0&&!e.installedVersions.includes(e.requiredVersion);function Mt(e){let{t:a}=k(),t=ae(),[o,l]=h(null),[d,s]=h(null),u=e.host?.tools,n=e.busy||o!==null,i=m=>{l(m),s(null),(m==="check"?t("inspect",e.environmentId):t("updateTool",e.environmentId,{tool:m})).catch(()=>s(a(m==="check"?"versions.checkFailed":"versions.updateFailed"))).finally(()=>l(null))},c=m=>m??a("versions.none");return f(Ka,{children:[f(Xa,{render:r(I,{size:"xs",variant:"ghost","aria-label":a("versions.title")}),children:[r(we,{}),a("versions.title"),Ia.some(m=>Ca(u?.[m]))?r("span",{className:"size-1.5 rounded-full bg-warning","aria-hidden":!0}):null]}),r($a,{side:"bottom",align:"start",className:"w-80",children:f("div",{className:"space-y-3 text-xs",children:[Ia.map(m=>{let x=u?.[m];return f("section",{className:"space-y-1",children:[r("h4",{className:"font-medium text-foreground",children:a(m==="hub"?"versions.hubName":"versions.agentName")}),f("dl",{className:"grid grid-cols-[auto_1fr] gap-x-3 gap-y-0.5 text-muted-foreground",children:[r("dt",{children:a("versions.required")}),r("dd",{className:"font-mono",children:c(x?.requiredVersion)}),r("dt",{children:a("versions.installed")}),r("dd",{className:"font-mono",children:x&&x.installedVersions.length>0?x.installedVersions.join(", "):a("versions.none")}),r("dt",{children:a("versions.running")}),r("dd",{className:"font-mono",children:c(x?.runningVersion)})]}),Ca(x)?f(I,{size:"xs",variant:"outline",disabled:n,onClick:()=>i(m),children:[o===m?r(H,{size:"xs"}):null,a("versions.updateTo",{version:x?.requiredVersion??""})]}):null]},m)}),u===void 0?r("p",{className:"text-muted-foreground",children:a("versions.unknown")}):null,Ia.some(m=>Ca(u?.[m]))?r("p",{className:"text-muted-foreground",children:a("versions.pendingPolicy")}):null,d?r("p",{role:"alert",className:"text-destructive-foreground",children:d}):null,f("div",{className:"flex items-center justify-between gap-2 border-t pt-2",children:[r("p",{className:"text-muted-foreground",children:a("versions.checkHint")}),f(I,{size:"xs",variant:"ghost",disabled:n,onClick:()=>i("check"),children:[o==="check"?r(H,{size:"xs"}):null,a("versions.check")]})]})]})})]})}var Re=e=>e>=1073741824?`${(e/1073741824).toFixed(2)} GB`:`${(e/1048576).toFixed(1)} MB`;function Rt(e){let{phase:a,receivedBytes:t,totalBytes:o,bytesPerSecond:l}=e,d=a==="download"&&t!==void 0&&o?{received:t,total:o}:null,s=d&&l?(d.total-d.received)/l:null;return{titleKey:`environment.stages.${a??"starting"}`,component:e.component??"",percent:d?Math.floor(d.received/d.total*100):null,transferred:d?{done:Re(d.received),total:Re(d.total)}:null,speed:d&&l?Re(l):null,minutesLeft:s===null?null:Math.ceil(s/60),slow:s!==null&&s>1200}}var Ft=e=>e.source==="private"&&e.ready;function Et(e){return e.supported?e.freeBytes!==null&&e.freeBytes<e.requiredFreeBytes?"environment.notEnoughSpace":null:e.reasonCode?`environment.reasons.${e.reasonCode}`:"environment.unsupported"}function Ot(e,a){return e.cacheBytes>0||a==="android"&&e.deviceDataBytes>0}function Ut(e){let{t:a}=k(),t=Rt(e.progress),o=[t.transferred?a("environment.transferred",t.transferred):null,t.speed?a("environment.speed",{speed:t.speed}):null,t.minutesLeft===null?null:a("environment.timeLeft",{minutes:String(t.minutesLeft)})].filter(l=>l!==null);return f("div",{role:"status",className:"space-y-2",children:[f("p",{className:"flex items-center gap-2 font-medium text-foreground",children:[r(H,{size:"xs"}),a(t.titleKey,{component:t.component})]}),t.percent===null?null:r("div",{role:"progressbar","aria-valuemin":0,"aria-valuemax":100,"aria-valuenow":t.percent,className:"h-1.5 overflow-hidden rounded-full bg-muted",children:r("div",{className:"h-full rounded-full bg-primary",style:{width:`${t.percent}%`}})}),o.length>0?r("p",{children:o.join(" \xB7 ")}):null,t.slow?r("p",{className:"text-warning-foreground",children:a("environment.slowDownload")}):null,r("p",{children:a("environment.continues")}),r(I,{size:"sm",variant:"outline",disabled:e.cancelling,onClick:e.onCancel,children:a("environment.cancel")})]})}function qt(e){let{t:a}=k(),t=ae(),l=q().commands.useSubscription("environmentProgress",{},{environmentId:e.environmentId}).data,[d,s]=h(!1),[u,n]=h("android"),[i,c]=h(""),[m,x]=h(""),[g,w]=h(null),[v,C]=h(!1),[L,D]=h(!1),[P,F]=h(!1),[N,B]=h(null),[E,J]=h(!1),[Q,M]=h(!1),[_,z]=h(void 0),O=l?.status==="working",G=N!==null||O,p=l&&l.id!==_?l:null;T(()=>{(O||p?.status==="failed")&&s(!0),p?.status==="done"&&p.plan?.platform===u&&w(p.plan)},[p,u,O]);let S=()=>{w(null),C(!1),D(!1),F(!1),M(!1),z(l?.id)},A=async(R,fo={})=>{B(R),J(!1),M(!1),z(l?.id);try{let co=await t(R,e.environmentId,{platform:u,directory:i,version:m,...fo});R==="cleanupEnvironment"?w(await t("environmentPlan",e.environmentId,{platform:u,directory:i,version:m})):R!=="prepareEnvironment"&&w(co),M(R==="cleanupEnvironment")}catch{J(!0)}finally{B(null)}},U=g?Et(g):null,K=R=>R===null?a("environment.unknownSize"):Re(R),io=g!==null&&Ft(g);return f(_e,{open:d,onOpenChange:s,className:"w-full text-left",children:[r(We,{render:r(I,{variant:"outline",size:"sm",className:"w-full"}),children:a("environment.title")}),r(Ke,{children:f("div",{className:"space-y-3 rounded-md border p-3 text-xs",children:[O?r(Ut,{progress:l,cancelling:N==="cancelEnvironment",onCancel:()=>{B("cancelEnvironment"),t("cancelEnvironment",e.environmentId,{}).catch(()=>J(!0)).finally(()=>B(null))}}):f($,{children:[r("p",{children:a("environment.description")}),e.iosSupported?r("div",{className:"flex gap-2",children:["android","ios"].map(R=>r(I,{size:"sm",variant:u===R?"default":"outline",disabled:G,onClick:()=>{n(R),S()},children:a(R==="ios"?"panel.platformIos":"panel.platformAndroid")},R))}):null,f("label",{className:"block space-y-1",children:[r("span",{children:a("environment.directory")}),r(ee,{value:i,disabled:G,onChange:R=>{c(R.target.value),S()},placeholder:a("environment.defaultDirectory")})]}),r("p",{children:a("environment.directoryHint")}),u==="ios"?f("label",{className:"block space-y-1",children:[r("span",{children:a("environment.iosVersion")}),r(ee,{value:m,disabled:G,onChange:R=>{x(R.target.value),S()},placeholder:a("environment.iosVersionPlaceholder")})]}):null,r(I,{size:"sm",variant:"outline",disabled:G,onClick:()=>{A("environmentPlan")},children:a("environment.inspect")}),g?f("div",{className:"space-y-2",children:[f("dl",{className:"grid grid-cols-[auto_1fr] gap-x-3 gap-y-1 break-all",children:[r("dt",{children:a("environment.source")}),r("dd",{children:a(`environment.sources.${g.source}`)}),r("dt",{children:a("environment.version")}),r("dd",{children:g.version||a("environment.versionRequired")}),r("dt",{children:a("environment.location")}),r("dd",{children:g.root}),g.existingSdkRoot?f($,{children:[r("dt",{children:a("environment.existingSdk")}),r("dd",{children:g.existingSdkRoot})]}):null,r("dt",{children:a("environment.download")}),r("dd",{children:g.downloadBytes===0?a("environment.nothingToDownload"):K(g.downloadBytes)}),r("dt",{children:a("environment.free")}),r("dd",{children:K(g.freeBytes)}),r("dt",{children:a("environment.required")}),r("dd",{children:K(g.requiredFreeBytes)})]}),g.source==="external"?r("p",{children:a("environment.external")}):null,g.reasonCode&&g.supported?r("p",{role:"status",children:a(`environment.reasons.${g.reasonCode}`)}):null,r("a",{className:"underline",href:g.guidanceUrl,target:"_blank",rel:"noreferrer",children:a("environment.guide")}),u==="ios"?r("p",{children:a("environment.appleOwnership")}):r("p",{children:a("environment.privateOwnership")}),io?r("p",{role:"status",className:"font-medium text-foreground",children:a("environment.ready")}):f($,{children:[r("ul",{children:g.licenses.map(R=>r("li",{children:r("a",{className:"underline",href:R.url,target:"_blank",rel:"noreferrer",children:a(u==="ios"?"environment.appleLicense":"environment.androidLicense")})},R.url))}),f("label",{className:"flex items-center gap-2",children:[r(fe,{checked:v,disabled:G,onCheckedChange:C}),r("span",{children:a("environment.acceptLicense")})]}),u==="ios"?f("label",{className:"flex items-center gap-2",children:[r(fe,{checked:L,disabled:G,onCheckedChange:D}),r("span",{children:a("environment.confirmApple")})]}):null,U?r("p",{role:"alert",className:"font-medium text-warning-foreground",children:a(U)}):null,r(I,{size:"sm",disabled:G||!g.supported||!v||u==="ios"&&(!L||!m)||g.freeBytes===null||g.freeBytes<g.requiredFreeBytes,onClick:()=>{A("prepareEnvironment",{acceptLicenses:v,confirmAppleInstall:L})},children:a("environment.prepare")})]}),Ot(g,u)?f("div",{className:"space-y-2 border-t pt-2",children:[r("p",{children:a("environment.retention")}),r(I,{size:"sm",variant:"outline",disabled:G||g.cacheBytes===0,onClick:()=>{A("cleanupEnvironment",{category:"cache",confirm:!0})},children:a("environment.cleanCache",{size:K(g.cacheBytes)})}),u==="android"?f($,{children:[r("p",{children:a("environment.deviceData",{size:K(g.deviceDataBytes)})}),f("label",{className:"flex items-center gap-2",children:[r(fe,{checked:P,disabled:G,onCheckedChange:F}),r("span",{children:a("environment.confirmData")})]}),r(I,{size:"sm",variant:"destructive",disabled:G||!P||g.deviceDataBytes===0,onClick:()=>{A("cleanupEnvironment",{category:"devices",confirm:P})},children:a("environment.cleanDevices")})]}):null]}):null]}):null]}),N!==null&&!O?f("p",{role:"status",className:"flex items-center gap-2",children:[r(H,{size:"xs"}),a("environment.working")]}):null,E?r("p",{role:"alert",className:"text-destructive-foreground",children:a("environment.failed")}):null,p?.status==="failed"?f("div",{role:"alert",className:"space-y-1 text-destructive-foreground",children:[r("p",{children:a("environment.prepareFailed")}),p.message?r("p",{className:"whitespace-pre-wrap break-words text-muted-foreground",children:p.message}):null]}):null,p?.status==="cancelled"?r("p",{role:"status",children:a("environment.cancelled")}):null,Q?r("p",{role:"status",children:a("environment.cleaned")}):null]})})]})}var Ht=["small","default","large","extra-large"],ir=e=>Ht.includes(e);function Nt(e){let{t:a}=k(),{handle:t,controls:o}=e,l=o.detail?.settings,d=!t?.inputConnected,s=l?.appearance==="dark"?"light":"dark",u=n=>a(n==="small"?"rail.textSmall":n==="default"?"rail.textDefault":n==="large"?"rail.textLarge":"rail.textExtraLarge");return r("aside",{"aria-label":a("rail.label"),className:"pointer-events-none absolute inset-y-0 right-0 z-10 flex w-14 flex-col items-center justify-center gap-2 overflow-y-auto py-3 pr-2",children:f("div",{className:"pointer-events-auto flex shrink-0 flex-col items-center gap-1 rounded-full border border-border/50 bg-background/80 p-2 shadow-sm",children:[r(re,{label:a("rail.home"),disabled:d,onClick:()=>t?.pressButton("home"),children:r(oe,{})}),e.platform==="android"?f($,{children:[r(re,{label:a("rail.back"),disabled:d,onClick:()=>t?.pressButton("back"),children:r(ye,{})}),r(re,{label:a("rail.recents"),disabled:d,onClick:()=>t?.pressButton("recents"),children:r(Te,{})}),f(Ge,{children:[r(ze,{render:r(I,{size:"icon-sm",variant:"ghost","aria-label":a("rail.rotate"),disabled:o.disabled}),children:r(Le,{})}),f(Ve,{side:"left",children:[r(Ie,{onClick:()=>{o.act({type:"setOrientation",value:"portrait"})},children:a("rail.portrait")}),r(Ie,{onClick:()=>{o.act({type:"setOrientation",value:"landscape_left"})},children:a("rail.landscape")})]})]})]}):r(re,{label:a("rail.rotate"),disabled:d,onClick:()=>t?.rotate(),children:r(Le,{})}),r(fr,{}),r(re,{label:a(s==="dark"?"rail.toDark":"rail.toLight"),disabled:o.disabled||!l?.appearance,onClick:()=>{o.act({type:"setAppearance",value:s})},children:l?.appearance==="dark"?r(Be,{}):r(be,{})}),f(Ge,{children:[r(ze,{render:r(I,{size:"icon-sm",variant:"ghost","aria-label":a("rail.textSize"),title:a("rail.textSize"),disabled:o.disabled||!l?.textSize}),children:r(Me,{})}),r(Ve,{side:"left",children:r(Ga,{value:l?.textSize??"",onValueChange:n=>{ir(n)&&o.act({type:"setTextSize",value:n})},children:Ht.map(n=>r(Va,{value:n,children:u(n)},n))})})]}),r(re,{label:a("rail.tools"),pressed:e.toolsOpen,onClick:e.onTools,children:r(Ae,{})}),r(re,{label:e.screenshotPending?a("rail.capturing"):a("rail.screenshot"),disabled:!e.streaming||e.screenshotPending,onClick:e.onScreenshot,children:r(Se,{})}),e.onFloat?r(re,{label:a("rail.float"),onClick:e.onFloat,children:r(ke,{})}):null,f(Ge,{children:[r(ze,{render:r(I,{size:"icon-sm",variant:"ghost","aria-label":a("rail.more"),title:a("rail.more")}),children:r(te,{})}),f(Ve,{side:"left",align:"end",children:[f(Ie,{onClick:e.onClose,children:[r(Z,{}),a("rail.closePanel")]}),r(Na,{}),f(Ie,{variant:"destructive",onClick:e.onPowerOff,children:[r(De,{}),a("rail.powerOff")]})]})]})]})})}function fr(){return r("div",{"aria-hidden":!0,className:"my-1 h-px w-5 shrink-0 bg-border/70"})}function re(e){return f(Ua,{children:[r(Ha,{render:r(I,{size:"icon-sm",variant:e.pressed?"secondary":"ghost","aria-label":e.label,"aria-pressed":e.pressed,disabled:e.disabled,onClick:e.onClick}),children:e.children}),r(qa,{side:"left",children:e.label})]})}var Sa=(e,a)=>new aa("invalid-input",`Invalid ${e}: ${a}.`);var Gt=4096,Vt=["light","dark"],zt=["small","default","large","extra-large"];var _t=["clear","tinted"],Wt=["none","grayscale","red-green","green-red","blue-yellow"],Kt=["portrait","landscape_left","portrait_upside_down","landscape_right"],Xt=["camera","microphone","photos","contacts","calendar","reminders","location","notifications","motion","media-library","faceid"];var cr=e=>typeof e=="object"&&e!==null&&!Array.isArray(e);var $t=e=>{let a=typeof e=="string"?{aps:{alert:e}}:e;if(!cr(a))throw Sa("push payload","expected a string or an object");let t;try{t=JSON.stringify(a)}catch{t=void 0}if(t===void 0)throw Sa("push payload","could not be encoded as JSON");if(new TextEncoder().encode(t).length>Gt)throw Sa("push payload",`larger than ${String(Gt)} bytes`);return t};var pr=new Set(["setAppearance","setTextSize","setToggle","setLiquidGlass","setColorFilter","setLocation","clearLocation","setPermission","openUrl","launchApp","terminateApp","sendPush"]),mr=new Set(["setAppearance","setTextSize","setToggle","setOrientation","setLocation","clearLocation","setPermission","openUrl","launchApp","terminateApp"]),gr=new Set(["reduceMotion","increaseContrast","reduceTransparency","showBorders","voiceOver"]),Lr=new Set(["reduceMotion","networkEnabled"]),jt=(e,a)=>(e==="ios"?pr:mr).has(a.type)?a.type==="setToggle"?(e==="ios"?gr:Lr).has(a.setting):!0:!1;function ne(e){return f("section",{className:"flex flex-col gap-2 border-b px-3 py-2.5",children:[r("h3",{className:"text-xs font-medium text-muted-foreground",children:e.title}),e.children]})}function le(e){return f("div",{className:"flex min-h-7 items-center justify-between gap-3",children:[r("span",{className:"shrink-0 text-xs text-muted-foreground",children:e.label}),r("div",{className:"flex min-w-0 items-center justify-end",children:e.children})]})}function va(e){return r(le,{label:e.label,children:r(fe,{"aria-label":e.label,checked:e.checked??!1,disabled:e.disabled||e.checked===void 0,onCheckedChange:a=>{e.onChange(a)}})})}function ya(e){return r(_a,{"aria-label":e.label,variant:"outline",value:e.value===void 0?[]:[e.value],disabled:e.disabled||e.value===void 0,onValueChange:a=>{let t=e.options.find(o=>o.value===a[0]);t&&e.onChange(t.value)},children:e.options.map(a=>r(Wa,{size:"xs",value:a.value,children:a.label},a.value))})}function Fe(e){let a=e.options.find(t=>t.value===e.value);return f(na,{value:e.value,disabled:e.disabled,onValueChange:t=>{let o=e.options.find(l=>l.value===t);o&&o.value!==e.value&&e.onChange(o.value)},children:[r(ia,{size:"xs",className:e.width??"w-40","aria-label":e.ariaLabel,children:r(fa,{children:a?a.label:r("span",{className:"text-muted-foreground",children:e.placeholder})})}),r(ca,{align:"end",alignItemWithTrigger:!1,children:e.options.map(t=>r(pa,{value:t.value,children:t.label},t.value))})]})}function wa(e){let[a,t]=h(""),o=a.trim()||e.fallback||"",l=()=>{o&&e.onSubmit(o).then(()=>t(""))};return f("form",{className:"flex gap-1.5",onSubmit:d=>{d.preventDefault(),l()},children:[r(ee,{size:"compact",className:"min-w-0 flex-1 font-mono",placeholder:e.placeholder,"aria-label":e.placeholder,value:a,disabled:e.disabled,onChange:d=>t(d.target.value)}),r(I,{type:"submit",size:"xs",variant:"outline",disabled:e.disabled||!o,children:e.action})]})}var Zt=[{key:"tools.location.sanFrancisco",latitude:37.7749,longitude:-122.4194},{key:"tools.location.newYork",latitude:40.7128,longitude:-74.006},{key:"tools.location.london",latitude:51.5074,longitude:-.1278},{key:"tools.location.stockholm",latitude:59.3293,longitude:18.0686},{key:"tools.location.tokyo",latitude:35.6762,longitude:139.6503}];function Qt(e){let{t:a}=k(),[t,o]=h(""),[l,d]=h(""),s={latitude:Number(t),longitude:Number(l)},u=t.trim()!==""&&l.trim()!==""&&Math.abs(s.latitude)<=90&&Math.abs(s.longitude)<=180,n=(i,c)=>e.act({type:"setLocation",latitude:i,longitude:c});return f(ne,{title:a("tools.location.title"),children:[f("div",{className:"flex gap-1.5",children:[r(ee,{size:"compact",className:"min-w-0 flex-1 font-mono",placeholder:a("tools.location.latitude"),"aria-label":a("tools.location.latitude"),inputMode:"decimal",value:t,disabled:e.disabled,onChange:i=>o(i.target.value)}),r(ee,{size:"compact",className:"min-w-0 flex-1 font-mono",placeholder:a("tools.location.longitude"),"aria-label":a("tools.location.longitude"),inputMode:"decimal",value:l,disabled:e.disabled,onChange:i=>d(i.target.value)})]}),f("div",{className:"flex flex-wrap items-center gap-1.5",children:[f(na,{value:null,disabled:e.disabled,onValueChange:i=>{let c=Zt.find(m=>m.key===i);c&&(o(String(c.latitude)),d(String(c.longitude)),n(c.latitude,c.longitude))},children:[r(ia,{size:"xs",className:"w-32","aria-label":a("tools.location.preset"),children:r(fa,{children:r("span",{className:"text-muted-foreground",children:a("tools.location.presetPlaceholder")})})}),r(ca,{align:"start",alignItemWithTrigger:!1,children:Zt.map(i=>r(pa,{value:i.key,children:a(i.key)},i.key))})]}),r(I,{size:"xs",variant:"outline",disabled:e.disabled||!u,onClick:()=>{n(s.latitude,s.longitude)},children:a("tools.location.set")}),r(I,{size:"xs",variant:"ghost",disabled:e.disabled,onClick:()=>{o(""),d(""),e.act({type:"clearLocation"})},children:a("tools.location.clear")})]})]})}var hr={camera:"tools.permissions.camera",microphone:"tools.permissions.microphone",photos:"tools.permissions.photos",contacts:"tools.permissions.contacts",calendar:"tools.permissions.calendar",reminders:"tools.permissions.reminders",location:"tools.permissions.location",notifications:"tools.permissions.notifications",motion:"tools.permissions.motion","media-library":"tools.permissions.mediaLibrary",faceid:"tools.permissions.faceId"},xr=new Set(["camera","microphone","photos","contacts","calendar","location","notifications","motion"]);function Yt(e){let{t:a}=k(),t=e.platform==="ios",[o,l]=h(""),[d,s]=h("camera"),u=o.trim()||e.defaultAppId,n=Xt.filter(c=>t||xr.has(c)).map(c=>({value:c,label:a(!t&&c==="motion"?"tools.permissions.activity":hr[c])})),i=c=>{e.act({type:"setPermission",appId:u,permission:d,decision:c})};return f(ne,{title:a("tools.permissions.title"),children:[r(ee,{size:"compact",className:"font-mono",placeholder:e.defaultAppId||a("tools.permissions.appId"),"aria-label":a("tools.permissions.appId"),value:o,disabled:e.disabled,onChange:c=>l(c.target.value)}),f("div",{className:"flex flex-wrap items-center gap-1.5",children:[r(Fe,{ariaLabel:a("tools.permissions.permission"),value:d,options:n,placeholder:a("tools.unknown"),disabled:e.disabled,onChange:c=>(s(c),Promise.resolve())}),r(I,{size:"xs",variant:"outline",disabled:e.disabled||!u,onClick:()=>i("grant"),children:a("tools.permissions.grant")}),r(I,{size:"xs",variant:"outline",disabled:e.disabled||!u,onClick:()=>i("revoke"),children:a("tools.permissions.revoke")}),t?r(I,{size:"xs",variant:"ghost",disabled:e.disabled||!u,onClick:()=>i("reset"),children:a("tools.permissions.reset")}):null]})]})}var Ir=e=>{let a=e;try{let t=JSON.parse(e);typeof t=="object"&&t!==null&&!Array.isArray(t)&&(a=t)}catch{}try{return $t(a),a}catch{return null}};function eo(e){let{t:a}=k(),[t,o]=h(""),l=t.trim(),d=l?Ir(l):null,s=e.appId;return f(ne,{title:a("tools.push.title"),children:[r(za,{size:"sm",rows:4,className:"font-mono",placeholder:a("tools.push.placeholder"),"aria-label":a("tools.push.placeholder"),value:t,disabled:e.disabled||!s,onChange:u=>o(u.target.value)}),f("div",{className:"flex items-center gap-2",children:[r(I,{size:"xs",variant:"outline",disabled:e.disabled||!s||d===null,onClick:()=>{s&&d!==null&&e.act({type:"sendPush",appId:s,payload:d})},children:a("tools.push.send")}),s?l&&d===null?r("p",{className:"text-xs text-destructive-foreground",children:a("tools.push.invalid")}):null:r("p",{className:"text-xs text-muted-foreground",children:a("tools.push.needsApp")})]})]})}var Jt=100;function ao(e){let{t:a}=k(),[t,o]=h(!1),[l,d]=h([]),{transport:s,platform:u,deviceId:n}=e;return T(()=>{if(!t)return;let i=tt({transport:s,platform:u,deviceId:n},(c,m)=>{d(x=>{let g=m?[...c]:[...x,...c];return g.length>Jt?g.slice(-Jt):g})});return()=>{i(),d([])}},[t,s,u,n]),f(_e,{open:t,onOpenChange:o,children:[f(We,{className:"flex w-full items-center gap-1.5 border-b px-3 py-2.5 text-left text-xs font-medium text-muted-foreground",children:[a("tools.eventLog.title"),r(ve,{className:`ml-auto size-3.5 transition-transform ${t?"rotate-180":""}`})]}),r(Ke,{children:r("ol",{className:"max-h-64 overflow-y-auto px-3 py-2 font-mono text-ui-2xs leading-relaxed",children:l.length===0?r("li",{className:"text-muted-foreground",children:a("tools.eventLog.empty")}):l.map(i=>f("li",{className:"flex gap-2",children:[r("span",{className:"shrink-0 text-muted-foreground",children:i.timestamp.slice(11,19)}),r("span",{className:"truncate",children:i.summary})]},i.id))})})]})}var Cr=640,Sr={light:"tools.settings.light",dark:"tools.settings.dark"},vr={small:"tools.settings.textSmall",default:"tools.settings.textDefault",large:"tools.settings.textLarge","extra-large":"tools.settings.textExtraLarge"},yr={clear:"tools.settings.glassClear",tinted:"tools.settings.glassTinted"},wr={none:"tools.settings.filterNone",grayscale:"tools.settings.filterGrayscale","red-green":"tools.settings.filterRedGreen","green-red":"tools.settings.filterGreenRed","blue-yellow":"tools.settings.filterBlueYellow"},br={portrait:"tools.settings.orientationPortrait",landscape_left:"tools.settings.orientationLandscapeLeft",portrait_upside_down:"tools.settings.orientationUpsideDown",landscape_right:"tools.settings.orientationLandscapeRight"},kr=[{setting:"reduceMotion",labelKey:"tools.settings.reduceMotion"},{setting:"increaseContrast",labelKey:"tools.settings.increaseContrast"},{setting:"reduceTransparency",labelKey:"tools.settings.reduceTransparency"},{setting:"showBorders",labelKey:"tools.settings.showBorders"},{setting:"voiceOver",labelKey:"tools.settings.voiceOver"},{setting:"networkEnabled",labelKey:"tools.settings.network"}];function to(e){let{t:a}=k(),{device:t,controls:o}=e,{detail:l,pending:d,error:s,foregroundApp:u,disabled:n,act:i}=o,c=l?.settings,m=t.platform==="ios",x=V(null),[g,w]=h(!0);Aa(()=>{let L=x.current?.parentElement;if(!L)return;let D=()=>w(L.clientWidth<Cr);D();let P=new ResizeObserver(D);return P.observe(L),()=>P.disconnect()},[]);let v=zt.map(L=>({value:L,label:a(vr[L])})),C=kr.filter(L=>jt(t.platform,{type:"setToggle",setting:L.setting,value:!0}));return f("aside",{ref:x,"aria-label":a("tools.title"),className:`flex min-h-0 flex-col border-l bg-background text-sm ${g?"absolute inset-y-0 right-0 z-10 w-full max-w-72 shadow-lg":"w-72 shrink-0"}`,children:[f("div",{className:"flex h-9 shrink-0 items-center gap-2 border-b px-3",children:[r("span",{className:"font-medium",children:a("tools.title")}),d?r(H,{size:"sm"}):null,r(I,{size:"icon-xs",variant:"ghost-muted","aria-label":a("tools.close"),className:"ml-auto",onClick:e.onClose,children:r(Z,{})})]}),f("div",{className:"min-h-0 flex-1 overflow-y-auto",children:[s?r("p",{role:"alert",className:"border-b bg-destructive/10 px-3 py-2 text-xs text-destructive-foreground",children:s}):null,l===null&&!s?f("div",{className:"flex items-center gap-2 px-3 py-3 text-xs text-muted-foreground",children:[r(H,{size:"sm"}),a("tools.reading")]}):null,f(ne,{title:a("tools.app.title"),children:[r(le,{label:a("tools.app.foreground"),children:r("span",{className:"truncate font-mono text-xs",children:u?.id??a("tools.app.none")})}),u?f("div",{className:"flex gap-1.5",children:[r(I,{size:"xs",variant:"outline",disabled:n,onClick:()=>{i({type:"terminateApp",appId:u.id})},children:a("tools.app.terminate")}),r(I,{size:"xs",variant:"outline",disabled:n,onClick:()=>{i({type:"launchApp",appId:u.id})},children:a("tools.app.relaunch")})]}):null,r(wa,{placeholder:a("tools.app.urlPlaceholder"),action:a("tools.app.open"),disabled:n,onSubmit:L=>i({type:"openUrl",url:L})}),r(wa,{placeholder:a(m?"tools.app.bundleIdPlaceholder":"tools.app.packagePlaceholder"),action:a("tools.app.launch"),disabled:n,fallback:u?.id,onSubmit:L=>i({type:"launchApp",appId:L})})]}),f(ne,{title:a(m?"tools.settings.titleIos":"tools.settings.titleAndroid"),children:[r(le,{label:a("tools.settings.appearance"),children:r(ya,{label:a("tools.settings.appearance"),value:c?.appearance,options:Vt.map(L=>({value:L,label:a(Sr[L])})),disabled:n,onChange:L=>i({type:"setAppearance",value:L})})}),r(le,{label:a("tools.settings.textSize"),children:r(Fe,{ariaLabel:a("tools.settings.textSize"),value:c?.textSize??null,options:v,placeholder:a("tools.unknown"),disabled:n,onChange:L=>i({type:"setTextSize",value:L})})}),m?f($,{children:[r(le,{label:a("tools.settings.liquidGlass"),children:r(ya,{label:a("tools.settings.liquidGlass"),value:c?.liquidGlass,options:_t.map(L=>({value:L,label:a(yr[L])})),disabled:n,onChange:L=>i({type:"setLiquidGlass",value:L})})}),r(le,{label:a("tools.settings.colorFilter"),children:r(Fe,{ariaLabel:a("tools.settings.colorFilter"),value:c?.colorFilter??null,options:Wt.map(L=>({value:L,label:a(wr[L])})),placeholder:a("tools.unknown"),disabled:n,onChange:L=>i({type:"setColorFilter",value:L})})})]}):r(le,{label:a("tools.settings.orientation"),children:r(Fe,{ariaLabel:a("tools.settings.orientation"),value:null,options:Kt.map(L=>({value:L,label:a(br[L])})),placeholder:a("tools.settings.rotateTo"),disabled:n,onChange:L=>i({type:"setOrientation",value:L})})}),C.map(L=>r(va,{label:a(L.labelKey),checked:c?.[L.setting],disabled:n,onChange:D=>i({type:"setToggle",setting:L.setting,value:D})},L.setting))]}),r(ne,{title:a("tools.accessibility.title"),children:r(va,{label:a("tools.accessibility.overlay"),checked:e.axOverlay,disabled:!1,onChange:L=>(e.onAxOverlayChange(L),Promise.resolve())})}),r(Qt,{disabled:n,act:i}),r(Yt,{platform:t.platform,defaultAppId:u?.id??"",disabled:n,act:i}),m?r(eo,{appId:u?.id,disabled:n,act:i}):null,m?r(ao,{transport:e.transport,platform:t.platform,deviceId:t.id}):null]})]})}var Dr=2e4,ba=class extends Error{status;constructor(a){super(`Screenshot capture failed (${a}). Try again.`),this.status=a}};async function oo(e,a,t,o){let l=AbortSignal.timeout(Dr),d=await e.fetch(`${ce(a)}/api/screenshot?device=${encodeURIComponent(t)}`,{method:"POST",signal:o?AbortSignal.any([o,l]):l});if(!d.ok)throw new ba(d.status);let s=await d.blob();if(!s.size)throw new Error("The device returned an empty screenshot. Try again.");return s.type?s:new Blob([s],{type:"image/png"})}var ro=e=>e instanceof Error?e.message:String(e);function lo(e){let{environmentId:a,device:t}=e,o=ae(),[l,d]=h(null),[s,u]=h(!1),[n,i]=h(null),c=V(!1),m=V(0),x={hostId:t.hostId,deviceId:t.id},g=v=>o("detail",a,x).then(C=>{m.current===v&&(d(C),i(null))},C=>{m.current===v&&(d(null),i(ro(C)))});return T(()=>{let v=++m.current;return g(v),()=>{m.current++}},[a,t.hostId,t.id]),{detail:l,pending:s,error:n,act:async v=>{if(c.current||l===null)return;c.current=!0;let C=++m.current;u(!0),i(null);try{let L=await o("action",a,{...x,...v});m.current===C?d(L):await g(++m.current)}catch(L){m.current===C&&i(ro(L))}finally{c.current=!1,u(!1)}},disabled:s||l===null,foregroundApp:e.foreground===void 0?l?.foregroundApp??null:e.foreground}}var Pr=()=>typeof window<"u"&&"ReactNativeWebView"in window;function so(e){let{t:a}=k(),t=ta(e.environmentId),[o,l]=h(null),[d,s]=h(!1),[u,n]=h(!1),[i,c]=h(!1),[m,x]=h(),[g,w]=h(!1),[v,C]=h(null),[L,D]=h(null),P=V(null),F=V(null),N=t.status==="ready"?t.transport:null,B=lo({environmentId:e.environmentId,device:e.device,foreground:m}),E=de(M=>l(M),[]),J=de(M=>s(M),[]);T(()=>{if(!N)return;let M=at({transport:N,platform:e.device.platform,deviceId:e.device.id},x);return()=>{M(),x(void 0)}},[e.device.id,e.device.platform,N]),T(()=>()=>{P.current?.abort(),F.current&&URL.revokeObjectURL(F.current)},[]);let Q=()=>{if(!N||P.current)return;let M=new AbortController;P.current=M,w(!0),C(null),oo(N,e.device.platform,e.device.id,M.signal).then(_=>{if(M.signal.aborted)return;F.current&&URL.revokeObjectURL(F.current);let z=URL.createObjectURL(_);if(F.current=z,Pr()){D(z);return}let O=document.createElement("a");O.href=z,O.download=`${e.device.name.replace(/[^a-z0-9-]/gi,"-")}-${Date.now()}.png`,document.body.append(O),O.click(),O.remove()}).catch(_=>{M.signal.aborted||C(_ instanceof Error?_.message:a("workspace.screenshotFailed"))}).finally(()=>{P.current===M&&(P.current=null,w(!1))})};return t.status!=="ready"?r(Y,{name:e.device.name,description:e.device.version,stage:t.status==="failed"?"error":"connecting",message:t.status==="failed"?t.message??a("workspace.needsNewerApp"):a("stream.connecting"),children:r(I,{size:"sm",variant:"outline",onClick:e.onBack,children:a("workspace.allDevices")})}):f("div",{className:"relative flex min-h-0 min-w-0 flex-1",children:[f("div",{className:"relative flex min-h-0 min-w-0 flex-1 flex-col",children:[v||B.error&&!u?r("p",{role:"alert",className:"px-3 py-2 text-xs text-destructive-foreground",children:v??B.error}):null,f("div",{className:"relative min-h-0 flex-1",children:[r(ea,{transport:t.transport,platform:e.device.platform,deviceId:e.device.id,deviceName:e.device.name,deviceDescription:e.device.version,axOverlay:i,withControls:!0,onHandle:E,onStreaming:J}),r(Nt,{platform:e.device.platform,handle:o,streaming:d,controls:B,screenshotPending:g,onScreenshot:Q,toolsOpen:u,onTools:()=>n(!u),onClose:e.onClose,onPowerOff:e.onPowerOff,onFloat:e.onFloat})]})]}),u?r(to,{device:e.device,controls:B,transport:t.transport,axOverlay:i,onAxOverlayChange:c,onClose:()=>n(!1)}):null,L?f("div",{className:"absolute inset-0 z-20 flex flex-col items-center justify-center gap-3 bg-background/95 p-4",children:[r("img",{src:L,alt:a("workspace.screenshotAlt"),className:"max-h-[80%] max-w-full object-contain"}),r("p",{className:"text-xs text-muted-foreground",children:a("workspace.screenshotSaveHint")}),f(I,{size:"sm",variant:"outline",onClick:()=>D(null),children:[r(Z,{}),a("workspace.closeBrowser")]})]}):null]})}var ka=e=>e instanceof Error?e.message:String(e);function uo(e){let{environmentId:a,threadId:t}=e,{t:o}=k(),{state:l,loaded:d,error:s,unavailable:u}=me(a),n=ae(),[i,c]=h(null),[m,x]=h(null),g=Ea(a,t),w=p=>He(a,t,p),v=q(),C=ie(v,"floating"),L=()=>{c(null),n("refresh",a).catch(p=>c(ka(p)))};T(()=>{!d||u||n("refresh",a).catch(()=>{})},[a,d,n,u]);let D=ue(()=>l.sessions.filter(p=>p.threadId===t),[l.sessions,t]),P=Tr(D,g),F=P?l.devices.find(p=>p.hostId===P.hostId&&p.id===P.deviceId):void 0,N=F&&P?xe(F):null;T(()=>{v.floating?.present({environmentId:a,threadId:t},N)}),T(()=>()=>v.floating?.present({environmentId:a,threadId:t},null),[v,a,t]);let B=ue(()=>Br(l),[l]),E=l.hostStatuses[ge],J=E?.status==="ready",Q=E?.status==="installing"||E?.status==="starting",M=xa(),_=l.bootingDevices.filter(p=>p.threadId===t),z=l.hosts.flatMap(p=>p.platforms.filter(S=>!S.available)),O=async p=>{c(null),x(p),ua(a,t,X(p));try{await n("open",a,{threadId:t,hostId:p.hostId,deviceId:p.id,platform:p.platform}),w(X(p))}catch(S){ua(a,t,X(p),!1),c(ka(S))}finally{x(null)}},G=p=>{P&&(c(null),n("close",a,{threadId:t,hostId:P.hostId,deviceId:P.deviceId,shutdown:p}).then(()=>w(null)).catch(S=>c(ka(S))))};return u?r(Y,{name:o("panel.title"),stage:"error",message:o("panel.unavailable")}):f("div",{className:"flex size-full min-h-0 flex-col",children:[_.length>0?r("div",{role:"status",className:"border-b px-3 py-2 text-xs text-muted-foreground",children:o("panel.booting",{names:_.map(p=>p.name).join(", ")})}):null,Q&&!F?null:r(Bt,{detail:E,onRetry:()=>n("refresh",a).catch(()=>{})}),i||s?f("div",{role:"alert",className:"flex items-start gap-2 border-b bg-destructive/5 px-3 py-2 text-xs text-destructive-foreground",children:[r("p",{className:"min-w-0 flex-1 whitespace-pre-wrap break-words",children:i??s}),i?r(I,{size:"icon-xs",variant:"ghost","aria-label":o("panel.dismissError"),onClick:()=>c(null),children:r(Z,{className:"size-3"})}):null]}):null,r("div",{className:"relative flex min-h-0 flex-1",children:F&&P?r(so,{environmentId:a,device:F,onBack:()=>w(""),onFloat:C?()=>v.floating?.open({environmentId:a,threadId:t},{...xe(F),reason:"user"}):void 0,onPowerOff:()=>G(!0),onClose:()=>G(!1)},`${a}\0${X(F)}`):m||Q||!d?r(Y,{name:m?.name??o("panel.title"),...m?{description:m.version}:{},stage:"opening",message:m?m.booted?o("panel.opening"):o("panel.starting"):Q&&E?M(E):o("panel.finding")}):r(Ar,{environmentId:a,host:l.hosts.find(p=>p.id===ge),grouped:B,hostReady:J,hostFailed:E?.status==="failed",unavailableReasons:z,showNoAvdHint:J&&!l.devices.some(p=>p.platform==="android")&&!z.some(p=>p.platform==="android"),pendingKey:m?X(m):null,onOpen:p=>{O(p)},onRefresh:L})})]})}function Ar(e){let{t:a}=k(),t=e.grouped.length===0;return r("div",{className:"flex size-full flex-col overflow-y-auto px-4 py-6 text-sm text-muted-foreground",children:f("div",{className:`mx-auto flex w-full max-w-xl flex-col gap-5 ${t?"items-center text-center":""}`,children:[r(qt,{environmentId:e.environmentId,iosSupported:!e.unavailableReasons.some(o=>o.reasonCode==="ios-needs-macos")},e.environmentId),t?f($,{children:[r(he,{className:"size-6 opacity-60"}),r("p",{className:"max-w-sm",children:e.hostFailed?a("panel.hubFailed"):a("panel.empty")})]}):null,e.hostReady?e.grouped.map(o=>f("section",{className:"w-full space-y-2 text-left",children:[f("h3",{className:"flex items-center gap-2 font-medium",children:[r(he,{className:"size-4 shrink-0"}),o.platform==="ios"?a("panel.platformIos"):a("panel.platformAndroid")]}),r("ul",{className:"divide-y rounded-md border",children:o.devices.map(l=>r("li",{children:f(I,{variant:"ghost",className:"h-auto min-h-11 w-full justify-between gap-3 rounded-none px-3 py-2 text-left font-normal",disabled:e.pendingKey!==null,onClick:()=>e.onOpen(l),children:[f("span",{className:"min-w-0 flex-1",children:[r("span",{className:"block truncate text-foreground",children:l.name}),f("span",{className:"block text-xs",children:[l.version,","," ",l.booted?a("panel.running"):a("panel.stopped")]})]}),e.pendingKey===X(l)?r(H,{size:"xs"}):r("span",{className:"text-xs",children:l.booted?a("panel.open"):a("panel.start")})]})},X(l)))})]},o.platform)):null,e.unavailableReasons.map(o=>r("p",{className:"max-w-sm text-xs",children:o.reasonCode?a(`unavailable.${o.reasonCode}`,{root:o.sdkRoot??""}):o.reason},`${o.platform}:${o.reasonCode}`)),e.showNoAvdHint?r("p",{className:"max-w-sm text-xs",children:a("panel.noAvd")}):null,f("div",{className:`flex flex-wrap items-center gap-2 ${t?"self-center":"self-start"}`,children:[r(I,{variant:t?"outline":"ghost",size:"sm",onClick:e.onRefresh,children:a("panel.refresh")}),r(Mt,{environmentId:e.environmentId,host:e.host,busy:!1})]})]})})}function Tr(e,a){if(a!==""){if(a!==null){let t=e.find(o=>X({hostId:o.hostId,id:o.deviceId})===a);if(t)return t}return e.toSorted((t,o)=>o.openedAt.localeCompare(t.openedAt))[0]}}function Br(e){let a=[];for(let t of["ios","android"]){let o=e.devices.filter(l=>l.platform===t).toSorted((l,d)=>Number(d.booted)-Number(l.booted)||l.name.localeCompare(d.name));o.length>0&&a.push({platform:t,devices:o})}return a}function no({environmentId:e,threadId:a}){let t=q(),{state:o,loaded:l}=me(e),d=V(null);return T(()=>{if(!l||!ie(t,"floating"))return;let s=`${e}\0${a}`,u=d.current?.key===s?d.current.seen:null,{seen:n,opened:i}=Oa({environmentId:e,threadId:a,previous:u,sessions:o.sessions,devices:o.devices});d.current={key:s,seen:n};for(let c of i)t.floating?.open({environmentId:e,threadId:a},{...xe(c),reason:"agent",panelId:Ue})},[t,e,l,o.devices,o.sessions,a]),null}function Mr(e){return{panels:{device:function(t){return f(Oe,{value:e,children:[r("style",{children:ra}),r("div",{className:`${Ne} flex h-full min-h-0 flex-1 flex-col`,children:r(uo,{environmentId:t.environmentId,threadId:t.threadId})})]})}},views:{deviceFloat:function(t){return f(Oe,{value:e,children:[r("style",{children:ra}),r("div",{className:`${Ne} relative size-full`,children:r(bt,{...t})})]})},deviceSessions:function(t){return r(Oe,{value:e,children:r(no,{environmentId:t.environmentId,threadId:t.threadId})})}}}}export{Mr as default};
@@ -55,6 +55,26 @@ export function privateAndroidEnvironment(root, sdk, env = process.env) {
55
55
  };
56
56
  }
57
57
 
58
+ /** 与 `emulator -list-avds` 同一批目录,按 `avdmanager list avd` 的格式写:hub 只读 Name 和 Path。 */
59
+ export function avdListOutput(env = process.env) {
60
+ const userHome = env.ANDROID_USER_HOME || env.ANDROID_EMULATOR_HOME;
61
+ const home =
62
+ env.ANDROID_AVD_HOME ||
63
+ (userHome
64
+ ? NodePath.join(userHome, "avd")
65
+ : NodePath.join(env.HOME ?? env.USERPROFILE ?? "", ".android", "avd"));
66
+ const names = NodeFS.existsSync(home)
67
+ ? NodeFS.readdirSync(home).filter((name) => name.endsWith(".ini"))
68
+ : [];
69
+ const blocks = names.map((file) => {
70
+ const name = file.slice(0, -".ini".length);
71
+ const ini = NodeFS.readFileSync(NodePath.join(home, file), "utf8");
72
+ const path = /^path=(.+)$/mu.exec(ini)?.[1]?.trim() ?? NodePath.join(home, `${name}.avd`);
73
+ return ` Name: ${name}\n Path: ${path}\n`;
74
+ });
75
+ return `Available Android Virtual Devices:\n${blocks.join("---------\n")}`;
76
+ }
77
+
58
78
  /** adb 自身会结束协议版本不符的服务器;在调用客户端之前只读握手,发现冲突就让用户处理。 */
59
79
  export async function guardAdbServer(
60
80
  sdk,
package/dist/helper.mjs CHANGED
@@ -18,11 +18,14 @@ import * as NodeChildProcess from "node:child_process";
18
18
  import * as NodeCrypto from "node:crypto";
19
19
  import * as NodeDiagnosticsChannel from "node:diagnostics_channel";
20
20
  import * as NodeFS from "node:fs";
21
+ import * as NodeModule from "node:module";
21
22
  import * as NodePath from "node:path";
22
23
  import * as NodeURL from "node:url";
24
+ import * as NodeUtil from "node:util";
23
25
 
24
26
  import {
25
27
  applyPrivateAndroidEnvironment,
28
+ avdListOutput,
26
29
  probeXcode,
27
30
  probeVirtualization,
28
31
  checkAcceleration,
@@ -232,6 +235,25 @@ function applySdkEnvironment(sdk) {
232
235
  applyPrivateAndroidEnvironment(sdk);
233
236
  }
234
237
 
238
+ /**
239
+ * hub 开机、等上线都要先跑 `avdmanager list avd`,失败就当列不出设备。avdmanager 要 JDK,私有 SDK
240
+ * 不带它;外部 SDK 也可能没有,hub 在 Windows 上还调不起 `.bat`。这里直接读 AVD 目录作答,其它
241
+ * 命令照常执行。hub 改成不经 promisify(execFile) 调它时,这层失效,开机会回到报错。
242
+ */
243
+ export function answerAvdList(childProcess, listing) {
244
+ const execFile = childProcess.execFile;
245
+ const promisified = NodeUtil.promisify(execFile);
246
+ const isAvdList = (file, args) =>
247
+ /^avdmanager(\.bat)?$/iu.test(NodePath.win32.basename(String(file))) &&
248
+ args?.[0] === "list" &&
249
+ args[1] === "avd";
250
+ const patched = (...call) => execFile(...call);
251
+ patched[NodeUtil.promisify.custom] = async (file, args, ...rest) =>
252
+ isAvdList(file, args) ? { stdout: listing(), stderr: "" } : promisified(file, args, ...rest);
253
+ childProcess.execFile = patched;
254
+ NodeModule.syncBuiltinESMExports();
255
+ }
256
+
235
257
  /** 在本进程里装载一个 Node 入口脚本,就像 `node entry …args` 起的一样。 */
236
258
  async function loadEntry(entry, args) {
237
259
  process.argv = [process.argv[0], entry, ...args];
@@ -316,6 +338,7 @@ async function main() {
316
338
  env: process.env,
317
339
  });
318
340
  if (shim) observeEmulatorLaunches(shim);
341
+ answerAvdList(NodeChildProcess.default, () => avdListOutput());
319
342
  await loadEntry(entry, args);
320
343
  return;
321
344
  }
package/dist/index.js CHANGED
@@ -358,6 +358,12 @@ var SETTINGS_CARD = {
358
358
  labelKey: "settings.androidSdk.label",
359
359
  descriptionKey: "settings.androidSdk.description",
360
360
  placeholderKey: "settings.androidSdk.placeholder"
361
+ },
362
+ {
363
+ key: "downloadProxy",
364
+ kind: "proxy",
365
+ labelKey: "settings.downloadProxy.label",
366
+ descriptionKey: "settings.downloadProxy.description"
361
367
  }
362
368
  ]
363
369
  };
@@ -632,9 +638,10 @@ var childPath = (root, name) => {
632
638
  throw new Error("Archive path escapes its destination");
633
639
  return result;
634
640
  };
635
- var downloadArchive = async (item, directory, fetch) => {
641
+ var archivePath = (item, directory) => NodePath.join(directory, item.url.split("/").at(-1));
642
+ var downloadArchive = async (item, directory, fetch, received = () => void 0) => {
636
643
  await NodeFSP.mkdir(directory, { recursive: true });
637
- const target2 = NodePath.join(directory, item.url.split("/").at(-1));
644
+ const target2 = archivePath(item, directory);
638
645
  if ((await NodeFSP.lstat(target2).catch(() => null))?.isSymbolicLink())
639
646
  throw new Error("Download cache entry must not be linked");
640
647
  const verify = async () => {
@@ -665,6 +672,7 @@ var downloadArchive = async (item, directory, fetch) => {
665
672
  return;
666
673
  }
667
674
  hash.update(chunk);
675
+ received(size);
668
676
  callback(null, chunk);
669
677
  }
670
678
  });
@@ -793,6 +801,27 @@ var extractEnvironmentZip = async (file, destination, signal) => {
793
801
  }
794
802
  };
795
803
 
804
+ // src/environmentProgress.ts
805
+ var PUBLISH_INTERVAL_MS = 1e3;
806
+ var SPEED_SMOOTHING = 0.3;
807
+ var throttledEnvironmentProgress = (publish, now = Date.now) => {
808
+ let last = null;
809
+ let speed;
810
+ return (stage) => {
811
+ const time = now();
812
+ const same = last?.stage.phase === stage.phase && last.stage.component === stage.component;
813
+ if (last !== null && same && time - last.time < PUBLISH_INTERVAL_MS) return;
814
+ if (last !== null && same && stage.receivedBytes !== void 0) {
815
+ const received = stage.receivedBytes - (last.stage.receivedBytes ?? stage.receivedBytes);
816
+ const sample = received * 1e3 / (time - last.time);
817
+ speed = speed === void 0 ? sample : speed + (sample - speed) * SPEED_SMOOTHING;
818
+ }
819
+ if (stage.phase !== "download") speed = void 0;
820
+ last = { stage, time };
821
+ publish(stage, speed);
822
+ };
823
+ };
824
+
796
825
  // src/environmentStorage.ts
797
826
  import * as NodeFSP2 from "node:fs/promises";
798
827
  import * as NodePath2 from "node:path";
@@ -920,7 +949,7 @@ var privateEnvironmentReady = async (root) => {
920
949
  await assertPrivatePath(root, NodePath2.join(avd, "config.ini"));
921
950
  await assertPrivatePath(root, NodePath2.join(paths.avd, "Ycodium_API_35.ini"));
922
951
  const config = await NodeFSP2.readFile(NodePath2.join(avd, "config.ini"), "utf8");
923
- const image = /^image\.sysdir\.1=(system-images\/android-35\/default\/(?:x86_64|arm64-v8a)\/)\r?$/m.exec(
952
+ const image = /^image\.sysdir\.1\s*=\s*(system-images\/android-35\/default\/(?:x86_64|arm64-v8a)\/)\s*$/m.exec(
924
953
  config
925
954
  )?.[1];
926
955
  if (!image) return false;
@@ -980,6 +1009,7 @@ var DeviceEnvironments = class {
980
1009
  progress = { status: "idle" };
981
1010
  listeners = /* @__PURE__ */ new Set();
982
1011
  active = null;
1012
+ job = null;
983
1013
  nextJobId = 1;
984
1014
  options;
985
1015
  constructor(options) {
@@ -1000,19 +1030,36 @@ var DeviceEnvironments = class {
1000
1030
  if (this.busy)
1001
1031
  throw new DeviceError("invalid-input", "Another simulator preparation is already running");
1002
1032
  const id = this.nextJobId++;
1033
+ const job = new AbortController();
1034
+ this.job = job;
1003
1035
  this.publish({ id, status: "working" });
1004
- this.active = this.prepare(
1005
- input,
1006
- (stage) => this.publish({ id, status: "working", stage })
1007
- ).then(
1036
+ const report = throttledEnvironmentProgress(
1037
+ (stage, bytesPerSecond) => this.publish({
1038
+ id,
1039
+ status: "working",
1040
+ ...stage,
1041
+ ...bytesPerSecond === void 0 ? {} : { bytesPerSecond }
1042
+ })
1043
+ );
1044
+ this.active = this.prepare(input, report, job.signal).then(
1008
1045
  (plan) => this.publish({ id, status: "done", plan }),
1009
1046
  (error) => {
1010
- this.options.log?.warn("Simulator preparation failed", {
1011
- detail: error instanceof Error ? error.message : String(error)
1012
- });
1013
- this.publish({ id, status: "failed" });
1047
+ if (job.signal.aborted) {
1048
+ this.publish({ id, status: "cancelled" });
1049
+ return;
1050
+ }
1051
+ const message = error instanceof Error ? error.message : String(error);
1052
+ this.options.log?.warn("Simulator preparation failed", { detail: message });
1053
+ this.publish({ id, status: "failed", message });
1014
1054
  }
1015
- );
1055
+ ).finally(() => {
1056
+ this.job = null;
1057
+ });
1058
+ return this.progress;
1059
+ }
1060
+ /** 只中止正在跑的准备;已下完并校验过的组件留在缓存里,下次不用重下。 */
1061
+ cancel() {
1062
+ this.job?.abort();
1016
1063
  return this.progress;
1017
1064
  }
1018
1065
  async dispose() {
@@ -1071,6 +1118,13 @@ var DeviceEnvironments = class {
1071
1118
  const archives = androidArchives(probe.platform, probe.arch);
1072
1119
  const sdk = await this.options.externalSdk();
1073
1120
  const prepared = await privateEnvironmentReady(root);
1121
+ const installed = await NodeFSP3.lstat(paths.sdk).catch(() => null) !== null;
1122
+ const missing = installed ? [] : await Promise.all(
1123
+ (archives ?? []).map(async (item) => {
1124
+ const cached = await NodeFSP3.lstat(archivePath(item, paths.cache)).catch(() => null);
1125
+ return cached?.size === item.bytes ? 0 : item.bytes;
1126
+ })
1127
+ );
1074
1128
  return {
1075
1129
  platform: "android",
1076
1130
  supported: archives !== null && probe.virtualization.available,
@@ -1078,7 +1132,7 @@ var DeviceEnvironments = class {
1078
1132
  ...sdk.available && sdk.root ? { existingSdkRoot: sdk.root } : {},
1079
1133
  root,
1080
1134
  version: ANDROID_ENVIRONMENT_VERSION,
1081
- downloadBytes: archives?.reduce((sum, item) => sum + item.bytes, 0) ?? null,
1135
+ downloadBytes: archives ? missing.reduce((sum, bytes) => sum + bytes, 0) : null,
1082
1136
  requiredFreeBytes: 12 * GIB,
1083
1137
  freeBytes: free,
1084
1138
  ready: sdk.available && (sdk.root !== paths.sdk || prepared),
@@ -1106,10 +1160,11 @@ var DeviceEnvironments = class {
1106
1160
  this.busy = false;
1107
1161
  }
1108
1162
  }
1109
- async prepare(input, progress = () => void 0) {
1163
+ async prepare(input, progress = () => void 0, cancelled) {
1164
+ const signal = cancelled ? AbortSignal.any([this.abort.signal, cancelled]) : this.abort.signal;
1110
1165
  return this.exclusively(async () => {
1111
1166
  const plan = await this.plan(input);
1112
- this.abort.signal.throwIfAborted();
1167
+ signal.throwIfAborted();
1113
1168
  if (!input.acceptLicenses)
1114
1169
  throw new DeviceError(
1115
1170
  "invalid-input",
@@ -1143,8 +1198,8 @@ var DeviceEnvironments = class {
1143
1198
  NodePath3.join(plan.root, "config")
1144
1199
  ])
1145
1200
  await NodeFSP3.mkdir(directory, { recursive: true });
1146
- if (input.platform === "ios") await this.prepareIos(plan, progress);
1147
- else await this.prepareAndroid(plan, progress);
1201
+ if (input.platform === "ios") await this.prepareIos(plan, progress, signal);
1202
+ else await this.prepareAndroid(plan, progress, signal);
1148
1203
  } finally {
1149
1204
  await release?.();
1150
1205
  }
@@ -1152,7 +1207,7 @@ var DeviceEnvironments = class {
1152
1207
  return this.plan(input);
1153
1208
  });
1154
1209
  }
1155
- async prepareAndroid(plan, progress) {
1210
+ async prepareAndroid(plan, progress, signal) {
1156
1211
  const probe = await this.probe();
1157
1212
  const archives = androidArchives(probe.platform, probe.arch);
1158
1213
  if (!archives) throw new Error("Android host target is unsupported");
@@ -1168,26 +1223,43 @@ var DeviceEnvironments = class {
1168
1223
  "An unrecognized private SDK already exists; its installation will not be overwritten"
1169
1224
  );
1170
1225
  } else {
1226
+ const totalBytes = archives.reduce((sum, item) => sum + item.bytes, 0);
1227
+ let finished = 0;
1171
1228
  for (const item of archives) {
1172
- progress(item.name);
1173
- this.abort.signal.throwIfAborted();
1229
+ const received = (bytes) => progress({
1230
+ phase: "download",
1231
+ component: item.name,
1232
+ receivedBytes: finished + bytes,
1233
+ totalBytes
1234
+ });
1235
+ received(0);
1236
+ signal.throwIfAborted();
1174
1237
  const file = await downloadArchive(
1175
1238
  item,
1176
1239
  paths.cache,
1177
- (url2, init) => this.options.fetch(url2, { ...init, signal: this.abort.signal })
1240
+ (url2, init) => this.options.fetch(url2, { ...init, signal }),
1241
+ received
1178
1242
  );
1243
+ finished += item.bytes;
1244
+ progress({
1245
+ phase: "extract",
1246
+ component: item.name,
1247
+ receivedBytes: finished,
1248
+ totalBytes
1249
+ });
1179
1250
  await extractEnvironmentZip(
1180
1251
  file,
1181
1252
  item.destination === "sdk" ? staging : NodePath3.join(staging, "system-images", "android-35", "default"),
1182
- this.abort.signal
1253
+ signal
1183
1254
  );
1184
1255
  }
1185
1256
  await NodeFSP3.writeFile(NodePath3.join(staging, ".ycodium-components"), plan.version);
1186
1257
  await NodeFSP3.rename(staging, paths.sdk);
1187
1258
  }
1259
+ progress({ phase: "device" });
1188
1260
  await this.createPrivateAvd(paths.root, probe.arch === "arm64" ? "arm64-v8a" : "x86_64");
1189
- this.abort.signal.throwIfAborted();
1190
- progress("validate");
1261
+ signal.throwIfAborted();
1262
+ progress({ phase: "validate" });
1191
1263
  const validated = await this.options.process.run({
1192
1264
  program: "host:node",
1193
1265
  args: [this.options.helperPath, "validate-android", "--sdk", paths.sdk],
@@ -1253,41 +1325,37 @@ target=android-35
1253
1325
  { flag: "wx" }
1254
1326
  );
1255
1327
  }
1256
- async prepareIos(plan, progress) {
1328
+ async prepareIos(plan, progress, cancelled) {
1257
1329
  if (plan.ready) return;
1258
1330
  const cache = NodePath3.join(plan.root, "cache", `ios-${plan.version}`);
1259
1331
  await NodeFSP3.mkdir(cache, { recursive: true });
1260
- progress(`iOS ${plan.version}`);
1261
- if (await this.runApple([
1262
- "-downloadPlatform",
1263
- "iOS",
1264
- "-exportPath",
1265
- cache,
1266
- "-buildVersion",
1267
- plan.version
1268
- ]) !== 0)
1332
+ progress({ phase: "apple-download", component: `iOS ${plan.version}` });
1333
+ if (await this.runApple(
1334
+ ["-downloadPlatform", "iOS", "-exportPath", cache, "-buildVersion", plan.version],
1335
+ cancelled
1336
+ ) !== 0)
1269
1337
  throw new Error(
1270
1338
  "Apple could not download this iOS runtime; check the selected Xcode version, network and Apple account in Xcode"
1271
1339
  );
1272
1340
  const names = (await NodeFSP3.readdir(cache)).filter((name) => name.endsWith(".dmg"));
1273
1341
  if (names.length !== 1)
1274
1342
  throw new Error("Apple did not return a unique simulator runtime archive");
1275
- progress("apple-install");
1276
- if (await this.runApple(["-importPlatform", NodePath3.join(cache, names[0])]) !== 0)
1343
+ progress({ phase: "apple-install" });
1344
+ if (await this.runApple(["-importPlatform", NodePath3.join(cache, names[0])], cancelled) !== 0)
1277
1345
  throw new Error(
1278
1346
  "Apple could not import the runtime. Complete any required permissions in Xcode; Ycodium will not elevate privileges"
1279
1347
  );
1280
1348
  if (!(await this.probe()).xcode.runtimes.some((runtime) => runtime.version === plan.version))
1281
1349
  throw new Error("The requested iOS runtime is still unavailable after Apple's import");
1282
1350
  }
1283
- async runApple(args) {
1284
- this.abort.signal.throwIfAborted();
1351
+ async runApple(args, cancelled) {
1352
+ cancelled.throwIfAborted();
1285
1353
  const handle = await this.options.process.spawn({
1286
1354
  program: "host:node",
1287
1355
  args: [this.options.helperPath, "run", "--", "xcodebuild", ...args],
1288
1356
  cwd: this.options.dataDir
1289
1357
  });
1290
- const signal = AbortSignal.any([this.abort.signal, AbortSignal.timeout(36e5)]);
1358
+ const signal = AbortSignal.any([cancelled, AbortSignal.timeout(36e5)]);
1291
1359
  const terminate = () => {
1292
1360
  void handle.kill().catch(() => void 0);
1293
1361
  };
@@ -1364,6 +1432,13 @@ var registerEnvironmentCommands = (ctx, environments) => {
1364
1432
  confirmAppleInstall: payload["confirmAppleInstall"] === true
1365
1433
  })
1366
1434
  });
1435
+ ctx.command({
1436
+ name: "cancelEnvironment",
1437
+ description: "Cancel the running simulator preparation. Components already downloaded and verified stay in the cache.",
1438
+ scope: "operate",
1439
+ payloadSchema: { type: "object", properties: {}, additionalProperties: false },
1440
+ handle: () => environments.cancel()
1441
+ });
1367
1442
  ctx.stream({
1368
1443
  name: "environmentProgress",
1369
1444
  description: "Current user-triggered simulator preparation progress; subscribing does not start preparation.",
@@ -2022,7 +2097,10 @@ var HubProcess = class {
2022
2097
  "--host",
2023
2098
  "127.0.0.1",
2024
2099
  "--hide-sidebar",
2025
- "--hide-boot-device"
2100
+ "--hide-boot-device",
2101
+ // hub 默认的 grpc-screenshot 要机器上有 ffmpeg,缺了就一帧都没有;scrcpy 只靠随包的 server。
2102
+ "--stream-source",
2103
+ "scrcpy"
2026
2104
  );
2027
2105
  let handle;
2028
2106
  try {
@@ -2840,7 +2918,18 @@ var parseHubDeviceList = (value) => {
2840
2918
  var parseHubActionResult = (value) => {
2841
2919
  if (!isRecord3(value) || typeof value["ok"] !== "boolean") return null;
2842
2920
  const text2 = (key2) => typeof value[key2] === "string" ? value[key2] : void 0;
2843
- return { ok: value["ok"], id: text2("id"), serial: text2("serial"), error: text2("error") };
2921
+ const causes = Array.isArray(value["errors"]) ? value["errors"].flatMap(
2922
+ (item) => isRecord3(item) && typeof item["message"] === "string" ? [
2923
+ [item["message"], typeof item["error"] === "string" ? item["error"] : ""].join(" ").split("\n")[0].trim()
2924
+ ] : []
2925
+ ) : [];
2926
+ const error = [text2("error"), ...causes].filter(Boolean).join(": ");
2927
+ return {
2928
+ ok: value["ok"],
2929
+ id: text2("id"),
2930
+ serial: text2("serial"),
2931
+ error: error === "" ? void 0 : error
2932
+ };
2844
2933
  };
2845
2934
  var HubClient = class {
2846
2935
  origin;
@@ -3592,12 +3681,16 @@ var index_default = definePlugin({
3592
3681
  });
3593
3682
  ctx.toolkit(deviceToolkit(service));
3594
3683
  registerCommands(ctx, service);
3684
+ const downloadProxy = ctx.config.downloadProxy;
3685
+ const environmentFetch = (input, init) => ctx.proxies.fetch(
3686
+ !downloadProxy ? void 0 : downloadProxy === PLUGIN_PROXY_DIRECT ? null : downloadProxy
3687
+ ).then((fetchThroughProxy) => fetchThroughProxy(input, init));
3595
3688
  const environments = new DeviceEnvironments({
3596
3689
  dataDir: ctx.paths.dataDir,
3597
3690
  helperPath: NodePath9.join(ctx.paths.pluginDir, "dist", "helper.mjs"),
3598
3691
  runtimeDir: bundledToolPaths(ctx.paths.pluginDir, HUB_SPEC, ctx.paths.runtimeDir).installDir,
3599
3692
  process: ctx.process,
3600
- fetch: ctx.http,
3693
+ fetch: environmentFetch,
3601
3694
  log: ctx.log,
3602
3695
  externalSdk: async () => {
3603
3696
  const probe = await host.machine(true);
@@ -3609,6 +3702,7 @@ var index_default = definePlugin({
3609
3702
  beforeMutation: () => service.beginEnvironmentMutation(),
3610
3703
  afterPrepared: async () => {
3611
3704
  await service.inspect(true);
3705
+ await service.list();
3612
3706
  }
3613
3707
  });
3614
3708
  registerEnvironmentCommands(ctx, environments);
package/locales/en.json CHANGED
@@ -41,9 +41,7 @@
41
41
  "confirmData": "I understand this permanently deletes apps and data in the private Android virtual device",
42
42
  "cleanDevices": "Delete private virtual device data",
43
43
  "working": "Checking the machine…",
44
- "preparing": "Preparing components. Downloads and Apple's installation can take several minutes. You can return to this panel to check progress.",
45
44
  "failed": "The operation could not finish. Check the official guidance, selected disk, network and whether the virtual device is powered off, then retry. More detail is available in this machine's plugin logs.",
46
- "done": "Operation completed. Refresh the device list to check and open the simulator.",
47
45
  "reasons": {
48
46
  "ios-needs-macos": "iOS simulators require a Mac with Xcode.",
49
47
  "ios-tools-missing": "The bundled iOS Simulator helpers are missing or could not load on this machine. Repair or update Ycodium with the matching platform components.",
@@ -59,7 +57,27 @@
59
57
  "virtualization-probe-failed": "The emulator acceleration status could not be determined. This is not evidence that hardware virtualization is disabled. Retry the check or consult the official setup guidance."
60
58
  },
61
59
  "unsupported": "This machine can't run the emulator yet, so preparation is unavailable. See the official setup guidance above.",
62
- "notEnoughSpace": "Not enough free space on this disk. Choose a directory on another disk above, then check again."
60
+ "notEnoughSpace": "Not enough free space on this disk. Choose a directory on another disk above, then check again.",
61
+ "stages": {
62
+ "starting": "Getting ready…",
63
+ "download": "Downloading {{component}}",
64
+ "extract": "Unpacking {{component}}",
65
+ "device": "Creating the virtual device",
66
+ "validate": "Checking the installation",
67
+ "apple-download": "Apple is downloading {{component}}",
68
+ "apple-install": "Apple is installing the runtime"
69
+ },
70
+ "transferred": "{{done}} of {{total}}",
71
+ "speed": "{{speed}}/s",
72
+ "timeLeft": "about {{minutes}} min left",
73
+ "slowDownload": "This download is slow. If this machine uses a proxy, try another one or none under Download proxy in the Devices settings. Cancelling keeps the components that finished.",
74
+ "continues": "This keeps running if you leave this panel.",
75
+ "cancel": "Cancel",
76
+ "cancelled": "Preparation cancelled. Components that finished downloading are kept for next time.",
77
+ "prepareFailed": "Preparation couldn't finish. Fix the problem below, then try again. Components that finished downloading are kept.",
78
+ "ready": "This environment is ready. Start the emulator from the list below.",
79
+ "nothingToDownload": "Nothing to download",
80
+ "cleaned": "Cleaned up."
63
81
  },
64
82
  "settings": {
65
83
  "card": {
@@ -78,6 +96,10 @@
78
96
  "path": "found through adb on PATH"
79
97
  }
80
98
  },
99
+ "downloadProxy": {
100
+ "label": "Download proxy",
101
+ "description": "Used when downloading emulator components. If downloads are slow, try a different proxy or no proxy."
102
+ },
81
103
  "checkTools": {
82
104
  "label": "Check tool versions",
83
105
  "description": "Reads the installed device tools without installing or starting anything.",
@@ -41,9 +41,7 @@
41
41
  "confirmData": "我理解此操作会永久删除私有 Android 虚拟设备中的应用和数据",
42
42
  "cleanDevices": "删除私有虚拟设备数据",
43
43
  "working": "正在检查这台机器…",
44
- "preparing": "正在准备组件。下载与 Apple 安装可能需要几分钟,可稍后回到此面板查看进度。",
45
44
  "failed": "操作未能完成。请按官方指引检查所选磁盘、网络及虚拟设备是否已关机,再重试。具体原因可在这台机器的插件日志中查看。",
46
- "done": "操作已完成。刷新设备列表以检查并打开模拟器。",
47
45
  "reasons": {
48
46
  "ios-needs-macos": "iOS 模拟器需要装有 Xcode 的 Mac。",
49
47
  "ios-tools-missing": "这台机器上的随包 iOS 模拟器助手缺失或无法加载。请使用匹配的平台组件修复或更新 Ycodium。",
@@ -59,7 +57,27 @@
59
57
  "virtualization-probe-failed": "无法确定模拟器加速状态,不能据此认定硬件虚拟化未开启。请重试检查或参考官方设置指引。"
60
58
  },
61
59
  "unsupported": "这台机器暂时跑不了模拟器,所以现在不能准备。请看上面的官方设置指引。",
62
- "notEnoughSpace": "这块磁盘剩余空间不够。请在上面换一个其他磁盘上的目录,再检查一次。"
60
+ "notEnoughSpace": "这块磁盘剩余空间不够。请在上面换一个其他磁盘上的目录,再检查一次。",
61
+ "stages": {
62
+ "starting": "正在准备…",
63
+ "download": "正在下载 {{component}}",
64
+ "extract": "正在解包 {{component}}",
65
+ "device": "正在创建虚拟设备",
66
+ "validate": "正在检查安装结果",
67
+ "apple-download": "Apple 正在下载 {{component}}",
68
+ "apple-install": "Apple 正在安装运行时"
69
+ },
70
+ "transferred": "{{done}} / {{total}}",
71
+ "speed": "{{speed}}/s",
72
+ "timeLeft": "还需约 {{minutes}} 分钟",
73
+ "slowDownload": "下载很慢。如果这台机器用了代理,可以在设备设置的「下载代理」里换一个或不走代理。取消后,已下完的组件会保留。",
74
+ "continues": "离开这个面板后会继续进行。",
75
+ "cancel": "取消",
76
+ "cancelled": "已取消准备。已下完的组件会保留,下次不用重下。",
77
+ "prepareFailed": "准备没能完成。请处理下面的问题后重试,已下完的组件会保留。",
78
+ "ready": "环境已就绪。请从下方列表启动模拟器。",
79
+ "nothingToDownload": "无需下载",
80
+ "cleaned": "已清理。"
63
81
  },
64
82
  "settings": {
65
83
  "card": {
@@ -78,6 +96,10 @@
78
96
  "path": "按 PATH 上的 adb 找到"
79
97
  }
80
98
  },
99
+ "downloadProxy": {
100
+ "label": "下载代理",
101
+ "description": "下载模拟器组件时使用。下载很慢时,可以换一个代理或不走代理。"
102
+ },
81
103
  "checkTools": {
82
104
  "label": "检查工具版本",
83
105
  "description": "读取已安装的设备工具,不安装也不启动任何东西。",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ycodium-ai/plugin-devices",
3
- "version": "0.2.3799",
3
+ "version": "0.2.3817",
4
4
  "description": "Lets agents drive iOS Simulators and Android Emulators on this machine.",
5
5
  "keywords": [
6
6
  "android",
@@ -33,7 +33,7 @@
33
33
  "tailwindcss": "^4.0.0",
34
34
  "typescript": "~6.0.3",
35
35
  "vite-plus": "0.2.2",
36
- "@ycodium-ai/plugin-api": "0.2.3799",
36
+ "@ycodium-ai/plugin-api": "0.2.3817",
37
37
  "ycodium-fetch-ports": "0.0.0",
38
38
  "ycodium-sse-stream": "0.0.0"
39
39
  },