@ycodium-ai/plugin-devices 0.2.3817 → 0.2.3851

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
@@ -2,7 +2,8 @@
2
2
 
3
3
  Lets agents list, open, screenshot and operate iOS Simulators and Android Emulators
4
4
  on the connected Ycodium machine. The plugin is off by default. Turn it on under
5
- Settings → Plugins, then open the Devices panel in a conversation.
5
+ Settings → Plugins, then open the Devices panel in a conversation. The bundled
6
+ `mobile-devices` skill tells agents how to build, install and verify an app on a device.
6
7
 
7
8
  ## What it does
8
9
 
package/assets/ui.js CHANGED
@@ -1,4 +1,4 @@
1
- var ra=`/*! tailwindcss v4.3.0 | MIT License | https://tailwindcss.com */
1
+ var la=`/*! 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 {
@@ -557,7 +557,7 @@ var ra=`/*! tailwindcss v4.3.0 | MIT License | https://tailwindcss.com */
557
557
  }
558
558
  }
559
559
  }
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!==`
560
+ `;var mo=window.__ycodiumPluginHost.react;var{Activity:Er,Children:Or,Component:Ur,Fragment:qr,Profiler:Hr,PureComponent:Nr,StrictMode:Gr,Suspense:Vr,__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE:zr,__COMPILER_RUNTIME:_r,act:Wr,cache:Kr,cacheSignal:Xr,captureOwnerStack:$r,cloneElement:jr,createContext:Aa,createElement:ue,createRef:Zr,forwardRef:Oe,isValidElement:Jr,lazy:Qr,memo:Yr,startTransition:el,unstable_useCacheRefresh:al,use:tl,useActionState:ol,useCallback:ee,useContext:Ta,useDebugValue:rl,useDeferredValue:ll,useEffect:T,useEffectEvent:sl,useId:dl,useImperativeHandle:ul,useInsertionEffect:nl,useLayoutEffect:Ba,useMemo:ne,useOptimistic:il,useReducer:fl,useRef:z,useState:L,useSyncExternalStore:Ma,useTransition:cl,version:pl}=mo;var Ra=Aa(null),Ue=Ra.Provider;function q(){let e=Ta(Ra);if(e===null)throw new Error("The devices panel has not been registered.");return e}var Fa=window.__ycodiumPluginHost.modules?.["@ycodium-ai/plugin-api/ui"];if(!Fa)throw new Error("This plugin needs a newer Ycodium app. Update the app.");var{HOST_TEAM_VIEW_PREFIX:hl,PLUGIN_UI_BRIDGE_VERSION:xl,PLUGIN_UI_FLOATING_VIEW_PROP:Ea,PLUGIN_UI_GLOBAL_KEY:Il,PLUGIN_UI_HOST_CAPABILITIES:Cl,PLUGIN_UI_HOST_COMMAND_PALETTE_UNAVAILABLE_MESSAGE:Sl,PLUGIN_UI_HOST_UPGRADE_MESSAGE:vl,TEAM_VIEW_KEY_PATTERN:yl,communicationRecordStage:wl,defineTeamView:bl,isTeamViewKey:kl,pluginUiHostHasCapability:fe}=Fa;var go="deviceFloat",qe="device",Z=e=>`${e.hostId}\0${e.id}`;function Ie(e){let a={hostId:e.hostId,deviceId:e.id,platform:e.platform};return{viewId:go,key:Z(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 Oa(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 sa=new Map,da=new Set,He=(e,a)=>`${e}\0${a}`;function Ua(e,a){return Ma(t=>(da.add(t),()=>{da.delete(t)}),()=>sa.get(He(e,a))??null)}function Ne(e,a,t){let o=He(e,a);if((sa.get(o)??null)!==t){sa.set(o,t);for(let l of da)l()}}var ua=new Set;function na(e,a,t,o=!0){let l=`${He(e,a)}\0${t}`;o?ua.add(l):ua.delete(l)}function qa(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=Z(l);if(a.add(d),e.previous===null||e.previous.has(d))continue;let s=`${He(e.environmentId,e.threadId)}\0${d}`;ua.delete(s)||t.push(l)}return{seen:a,opened:t}}var Ge="ycodium-devices-ui";function P(e){return(a=>ue(q().ui[e],{...a,className:`${Ge} ${typeof a.className=="string"?a.className:""}`}))}var S=P("Button"),H=P("Spinner"),ce=P("Switch"),Ha=P("Tooltip"),Na=P("TooltipPopup"),Ga=P("TooltipTrigger"),Ve=P("Menu"),ze=P("MenuPopup"),Ce=P("MenuItem"),Va=P("MenuSeparator"),_e=P("MenuTrigger"),za=P("MenuRadioGroup"),_a=P("MenuRadioItem"),te=P("Input"),Wa=P("Textarea"),ia=P("Select"),fa=P("SelectTrigger"),ca=P("SelectValue"),pa=P("SelectPopup"),ma=P("SelectItem"),We=P("Collapsible"),Ke=P("CollapsibleTrigger"),Xe=P("CollapsiblePanel"),Ka=P("ToggleGroup"),Xa=P("Toggle"),$a=P("Popover"),ja=P("PopoverTrigger"),Za=P("PopoverPopup");var{jsx:r,jsxs:f,Fragment:J}=window.__ycodiumPluginHost.jsxRuntime;function ae(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 $e=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!==`
561
561
  `&&n!=="\r")continue;if(n==="\r"&&u===d.length-1)break;let i=d.slice(s,u);n==="\r"&&d[u+1]===`
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(`
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};
562
+ `&&u++,t&&(this.raw+=d.slice(s,u+1));let p=this.line(i);i===""&&(o(this.raw,p),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(`
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 je(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 $e;await je(e,l=>{for(let d of o.push(l))a(d)},t)}var pe=e=>e==="ios"?"/vendor/serve-sim":"/vendor/serve-emu";var Lo=1e3,ho=500,Ze=(e,a,t)=>`${pe(e.platform)}${a}${t?`?${new URLSearchParams(t).toString()}`:""}`,Qa=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()},Q=e=>typeof e=="object"&&e!==null,$=(e,a)=>typeof e=="number"&&Number.isFinite(e)?e:a,xo=e=>{let a=e[0],t=Q(a)&&Q(a.frame)?a.frame:null,o=Math.max(1,$(t?.width,1)),l=Math.max(1,$(t?.height,1)),d=[],s=(u,n)=>{if(d.length>=ho||!Q(u)||!Q(u.frame))return;let i=u.frame,p=$(i.width,0),g=$(i.height,0);!(Math.abs(p-o)<.5&&Math.abs(g-l)<.5)&&p>0&&g>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:$(i.x,0)/o,y:$(i.y,0)/l,width:p/o,height:g/l}),(Array.isArray(u.children)?u.children:[]).forEach((h,b)=>s(h,`${n}.${b}`))};return e.forEach((u,n)=>s(u,String(n))),d},Ya=e=>Q(e)&&typeof e.error=="string"?e.error:"Unexpected accessibility payload.";async function at(e,a){if(e.platform==="ios"){let n=await Qa(e,Ze(e,`/helper/${encodeURIComponent(e.deviceId)}/ax`),a);return Array.isArray(n)?{elements:xo(n),errors:[]}:{elements:[],errors:[Ya(n)]}}let t=await Qa(e,Ze(e,"/api/accessibility",{device:e.deviceId}),a);if(!Q(t)||!Array.isArray(t.nodes))return{elements:[],errors:[Ya(t)]};let o=t.nodes.filter(n=>Q(n)&&Q(n.bounds)),l=o[0]?.bounds,d=Math.max(1,$(l?.right,1)),s=Math.max(1,$(l?.bottom,1));return{elements:o.slice(1).flatMap(n=>{let i=n.bounds,p=$(i.left,0),g=$(i.top,0),v=($(i.right,p)-p)/d,c=($(i.bottom,g)-g)/s,h=typeof n.text=="string"?n.text:"",b=typeof n.contentDescription=="string"?n.contentDescription:"",R=h||b;if(v>=.95&&c>=.9)return[];if(!R&&n.clickable!==!0)return[];let m=typeof n.className=="string"?n.className:"";return[{id:String(n.id??""),label:R,role:m.split(".").at(-1)??"",x:p/d,y:g/s,width:v,height:c}]}),errors:[]}}var tt=(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 ot(e,a){return e.platform!=="ios"?()=>{}:tt(e,Ze(e,"/appstate",{device:e.deviceId}),t=>{if(Q(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 et=e=>!Q(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 rt(e,a){return e.platform!=="ios"?()=>{}:tt(e,Ze(e,"/api/event-log/events",{device:e.deviceId,limit:"100"}),t=>{if(!Q(t))return;if(Array.isArray(t.events)){a(t.events.flatMap(l=>et(l)??[]),!0);return}let o=et(t.event);o&&a([o],!1)})}function B(){return{t:q().i18n.usePluginTranslation()}}function Qe(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 lt(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 st=e=>{try{return JSON.parse(e)?.type==="video-session"}catch{return!1}};function dt(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"},Je=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 ut(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 nt={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 ga(e){if(e.stopped)return;let a=d=>{e.configuring=!1,e.connecting(d),e.scheduleRetry("input",()=>ga(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"){st(d.data)&&(e.closeDecoder(),e.configuring=!1,o=[],l=!1,e.connecting());return}let s=lt(d.data),u=!e.videoDecoder||e.videoDecoder.state!=="configured",i=s.isKey===null||s.isKey&&u?dt(s.data):null,p=s.isKey??i?.isKey??!1,g={isKey:p,data:s.data,timestamp:s.timestamp};if(e.configuring){o.push(g);return}if(i?.sps&&u){e.configuring=!0,o=[g];let v=e.decoderEpoch,c=()=>!e.stopped&&e.socket===t;e.configureDecoder({codec:Qe(i.sps)},c).then(h=>{if(!c()||v!==e.decoderEpoch)return;e.configuring=!1,e.awaitingKeyframe=!0;let b=o;if(o=[],!!h){for(let R of b)e.decode(R.isKey,R.data,R.timestamp);e.awaitingKeyframe&&e.requestKeyframe()}});return}if(u){!p&&!l&&(l=!0,e.requestKeyframe());return}e.decode(p,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 it(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=nt[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 ft(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 ct=new TextEncoder,pt=new TextDecoder;function gt(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 mt(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 Ye=class{delimiter;buffer=new Uint8Array(64*1024);length=0;pos=0;state="boundary";contentLength=null;scanFrom=0;constructor(a){this.delimiter=a?ct.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=pt.decode(a.subarray(this.pos,s)).trim();if(this.pos=s+1,u.startsWith("--"))return this.delimiter=ct.encode(u),this.state="headers",!0}let t=this.delimiter,o=mt(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=pt.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=mt(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 Ye(gt(e.headers.get("content-type")));await je(e,l=>{for(let d of o.push(l))a(d)},t)}function Se(e){e.stopped||e.mjpeg||(e.mjpeg=!0,e.controller?.abort(),e.controller=null,e.closeDecoder(),e.connecting(),e.events.onMjpegFallback?.(),Lt(e))}var La=e=>`${e.vendor}/helper/${e.device}/stream.mjpeg`;async function Lt(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 p=await e.createBitmap(new Blob([i],{type:"image/jpeg"}));try{l()&&e.paint(p,p.width,p.height)}finally{p.close()}}catch{}}}finally{s=!1}},n;try{let i=await e.transport.fetch(La(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,p=>{l()&&(d=p,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",()=>{Lt(e)}))}var vo=1e3,ha=15e3,yo=16667,wo=8,bo=e=>typeof e=="object"&&e!==null&&"present"in e;function xt(e){let{transport:a,platform:t,events:o}=e,l=bo(e.output)?e.output:ft(e.output),d=u=>e.globals?.[u]??globalThis[u],s={platform:t,transport:a,events:o,preferMjpeg:e.preferMjpeg===!0,vendor:pe(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."),ha)),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"?Se(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 p=s.decoderEpoch,g={...u,optimizeForLatency:!0},v=await i.VideoDecoder.isConfigSupported(g).catch(()=>({supported:!1}));if(!n()||p!==s.decoderEpoch)return!1;if(!v.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(g),!0}catch(c){return t==="android"&&s.fail(`Video decoder: ${c.message}`),!1}},decode(u,n,i){let p=s.videoDecoder,g=s.webCodecs();if(!(!p||p.state!=="configured"||!g)){if(s.awaitingKeyframe){if(!u)return;s.awaitingKeyframe=!1}if(p.decodeQueueSize>wo){s.recoverDecoder();return}try{p.decode(new g.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,It=7,To=13,Bo=130,Mo=2e3,Ro=new TextEncoder,Fo=new TextDecoder,ea=["portrait","landscape_left","portrait_upside_down","landscape_right"],Eo=new Set(ea);function me(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 Ct(e,a){vt(e),a?St(e):Se(e)}async function St(e){let a=e.generation,t=++e.videoGeneration,o=new Je,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.")},ha);e.videoReadTimer=i;let p;try{p=await n.read()}finally{clearTimeout(i),e.videoReadTimer===i&&(e.videoReadTimer=null)}let{done:g,value:v}=p;if(!d())return;if(g)break;for(let c of o.push(v))switch(c.type){case"seed":e.createBitmap(new Blob([c.payload],{type:"image/jpeg"})).then(h=>{try{d()&&e.paint(h,h.width,h.height)}finally{h.close()}}).catch(()=>{});break;case"description":{e.awaitingKeyframe=!0;let h=await e.configureDecoder({codec:Qe(c.payload),description:c.payload},d);if(!d())return;if(!h){if(await n.cancel().catch(()=>{}),!d())return;Se(e);return}break}case"keyframe":case"delta":e.decode(c.type==="keyframe",c.payload);break}}}catch(u){if(!d())return;s=u.message}d()&&(e.controller=null,l.abort(),e.closeDecoder(),e.connecting(s),e.scheduleRetry("video",()=>{St(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(La(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 vt(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",()=>{vt(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(me(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 yt(e){return{sendTouch(a,t,o){e.send(me(Do,{type:a,...qo(e,t,o)}))},sendKey(a,t){let o=ut(a.code);o!==null&&e.send(me(Ao,{type:t,usage:o}))},pressButton(a){let t=a==="home"?"home":a==="appSwitcher"?"app_switcher":a==="power"?"lock":null;t&&e.send(me(Po,{button:t}))},rotate(){let a=e.screen?.orientation??"portrait",t=ea[(ea.indexOf(a)+1)%ea.length];e.send(me(It,{orientation:t}))},setOrientation(a){e.send(me(It,{orientation:a}))}}}function wt(e){let a=xt(e),t=e.platform==="ios"?yt(a):it(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"?Ct(a,l):l?ga(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 aa(e){let{t:a}=B(),t=z(null),o=z(null),[l,d]=L("connecting"),[s,u]=L(),[n,i]=L(!1),[p,g]=L(null),[v,c]=L({connected:!1}),{onHandle:h,onStreaming:b,onScreen:R,transport:m,platform:w,deviceId:C}=e;T(()=>R?.(p),[R,p]),T(()=>{let x=t.current;if(!x)return;let D=wt({transport:m,platform:w,deviceId:C,output:x,preferMjpeg:_o(),events:{onStatus:(A,V)=>{d(A),u(V),A==="streaming"&&i(!0),b(A==="streaming")},onScreen:g,onInputConnected:(A,V)=>{c({connected:A,...V?{detail:V}:{}}),h({pressButton:D.pressButton,rotate:D.rotate,inputConnected:A})}}});return o.current=D,c({connected:!1}),D.start(),h({pressButton:D.pressButton,rotate:D.rotate,inputConnected:!1}),()=>{D.stop(),o.current=null,h(null),b(!1),i(!1),g(null)}},[C,h,b,w,m]);let k=z(null),[F,_]=L({width:0,height:0});T(()=>{let x=k.current;if(!x)return;let D=()=>{let V=x.getBoundingClientRect();_(M=>M.width===V.width&&M.height===V.height?M:{width:V.width,height:V.height})};D();let A=new ResizeObserver(D);return A.observe(x),()=>A.disconnect()},[]);let N=e.withControls?Ho:0,E=ne(()=>Go(Vo(w,p),F.width,F.height,N),[F,N,w,p]),W=zo(w,p),j=W===90||W===-90?{width:E.height,height:E.width,left:(E.width-E.height)/2,top:(E.height-E.width)/2,transform:`rotate(${W}deg)`}:{width:E.width,height:E.height,...W?{transform:`rotate(${W}deg)`}:{}},[K,G]=L([]);T(()=>{if(!e.axOverlay)return;let x=null,D=null,A=!1,V=async()=>{x=new AbortController;try{let M=await at({transport:m,platform:w,deviceId:C},x.signal);A||G(M.elements)}catch{}A||(D=setTimeout(()=>{V()},No))};return V(),()=>{A=!0,x?.abort(),D&&clearTimeout(D),G([])}},[C,w,e.axOverlay,m]);let U=z(!1),I=x=>{let D=x.currentTarget.getBoundingClientRect(),A=(x.clientX-D.left)/D.width,V=(x.clientY-D.top)/D.height;return{x:Math.min(1,Math.max(0,A)),y:Math.min(1,Math.max(0,V))}},X=x=>{if(!U.current)return;U.current=!1;let{x:D,y:A}=I(x);o.current?.sendTouch("end",D,A)};return f("div",{ref:k,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(w==="ios"?"stream.iosScreen":"stream.androidScreen"),onKeyDown:x=>{x.target===x.currentTarget&&(x.metaKey&&!["r","R"].includes(x.key)||(x.preventDefault(),o.current?.sendKey(x.nativeEvent,"down")))},onKeyUp:x=>{x.target===x.currentTarget&&o.current?.sendKey(x.nativeEvent,"up")},children:[f("div",{className:"relative touch-none select-none",style:{width:E.width,height:E.height},onPointerDown:x=>{x.currentTarget.setPointerCapture(x.pointerId),x.currentTarget.parentElement?.focus(),U.current=!0;let{x:D,y:A}=I(x);o.current?.sendTouch("begin",D,A)},onPointerMove:x=>{if(!U.current)return;let{x:D,y:A}=I(x);o.current?.sendTouch("move",D,A)},onPointerUp:X,onPointerCancel:X,children:[r("canvas",{ref:t,className:"absolute top-0 left-0",style:j}),K.length>0?r("div",{className:"pointer-events-none absolute inset-0","aria-hidden":!0,children:K.map(x=>r("div",{className:"absolute border border-info/80 bg-info/10",style:{left:`${x.x*100}%`,top:`${x.y*100}%`,width:`${x.width*100}%`,height:`${x.height*100}%`},children:x.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:x.label}):null},x.id))}):null]}),l==="streaming"&&!v.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:v.detail?a("stream.inputLostDetail",{detail:v.detail}):a("stream.inputLost")})}):null,l==="connecting"&&n?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:a("stream.connecting")})}):null,l==="error"||l!=="streaming"&&!n?r("div",{className:"absolute inset-0 bg-background",children:r(ae,{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(S,{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 ge(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 oe(){let e=q();return ee((a,t,o={})=>e.commands.invoke(a,o,{environmentId:t}),[e])}var Le="local",ta=class extends Error{code;constructor(a,t,o){super(t,o),this.name="DeviceError",this.code=a}};var bt="hub";function oa(e){let a=q(),[t,o]=L({status:"connecting"});return T(()=>{let l=a.network;if(!fe(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(bt,u,{...n,instance:Le}),connect:u=>s.connect(bt,u,{instance:Le})}})},s=>{d||o({status:"failed",message:s instanceof Error?s.message:String(s)})}),()=>{d=!0}},[a,e]),t}var kt=()=>{};function Dt(e){let{environmentId:a,threadId:t,hostId:o,deviceId:l,platform:d}=e,s=e[Ea],u=q(),{t:n}=B(),{state:i,loaded:p}=ge(a),g=oa(a),v=ne(()=>({environmentId:a,threadId:t}),[a,t]),c=i.devices.find(w=>w.hostId===o&&w.id===l),h=i.sessions.some(w=>w.threadId===t&&w.hostId===o&&w.deviceId===l);T(()=>{p&&!h&&u.floating?.close(v,s.key)},[u,s.key,p,h,v]),T(()=>(s.setOpenInPanel(()=>{Ne(a,t,s.key),u.floating?.openPanel(v,qe),u.floating?.close(v,s.key)}),()=>s.setOpenInPanel(null)),[u,a,s,v,t]);let b=ee(w=>s.reportSourceSize(w===null?null:Oa(w)),[s]),R=c?.name??l,m=c?.version??d;return g.status!=="ready"?r(ae,{name:R,description:m,stage:g.status==="failed"?"error":"connecting",message:g.status==="failed"?g.message??n("workspace.needsNewerApp"):n("stream.connecting")}):r(aa,{transport:g.transport,platform:d,deviceId:l,deviceName:R,deviceDescription:m,axOverlay:!1,withControls:!1,onHandle:kt,onStreaming:kt,onScreen:b})}var ra=(...e)=>e.filter((a,t,o)=>!!a&&a.trim()!==""&&o.indexOf(a)===t).join(" ").trim();var Pt=e=>e.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase();var At=e=>e.replace(/^([A-Z])|[\s-_]+(\w)/g,(a,t,o)=>o?o.toUpperCase():t.toLowerCase());var xa=e=>{let a=At(e);return a.charAt(0).toUpperCase()+a.slice(1)};var Tt={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 Bt=e=>{for(let a in e)if(a.startsWith("aria-")||a==="role"||a==="title")return!0;return!1};var Mt=Oe(({color:e="currentColor",size:a=24,strokeWidth:t=2,absoluteStrokeWidth:o,className:l="",children:d,iconNode:s,...u},n)=>ue("svg",{ref:n,...Tt,width:a,height:a,stroke:e,strokeWidth:o?Number(t)*24/Number(a):t,className:ra("lucide",l),...!d&&!Bt(u)&&{"aria-hidden":"true"},...u},[...s.map(([i,p])=>ue(i,p)),...Array.isArray(d)?d:[d]]));var y=(e,a)=>{let t=Oe(({className:o,...l},d)=>ue(Mt,{ref:d,iconNode:a,className:ra(`lucide-${Pt(xa(e))}`,`lucide-${e}`,o),...l}));return t.displayName=xa(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"}]],ve=y("camera",Ko);var Xo=[["path",{d:"m6 9 6 6 6-6",key:"qrunsl"}]],ye=y("chevron-down",Xo);var $o=[["path",{d:"m15 18-6-6 6-6",key:"1wnfg3"}]],we=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"}]],re=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"}]],le=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"}]],be=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"}]],ke=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"}]],De=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"}]],Pe=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"}]],he=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"}]],Ae=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"}]],Te=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"}]],xe=y("smartphone",rr);var lr=[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}]],Be=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"}]],Me=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"}]],Re=y("type",dr);var ur=[["path",{d:"M18 6 6 18",key:"1bl5f8"}],["path",{d:"m6 6 12 12",key:"d8bk6v"}]],Y=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 Ia(){let{t:e}=B();return a=>nr(a,e)}function Rt(e){let{t:a}=B(),t=Ia(),[o,l]=L(!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(S,{size:"xs",variant:"outline",disabled:o,onClick:()=>{l(!0),e.onRetry().finally(()=>l(!1))},children:[o?r(H,{size:"xs"}):r(Ae,{}),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 Ca=["hub","agent"],Sa=e=>e!==void 0&&!e.installedVersions.includes(e.requiredVersion);function Ft(e){let{t:a}=B(),t=oe(),[o,l]=L(null),[d,s]=L(null),[u,n]=L(!1),i=e.host?.tools,p=e.busy||o!==null,g=c=>{l(c),s(null),n(!1),(c==="check"?t("inspect",e.environmentId):t("updateTool",e.environmentId,{tool:c})).then(()=>n(c==="check")).catch(()=>s(a(c==="check"?"versions.checkFailed":"versions.updateFailed"))).finally(()=>l(null))},v=c=>c??a("versions.none");return f($a,{children:[f(ja,{render:r(S,{size:"xs",variant:"ghost","aria-label":a("versions.title")}),children:[r(be,{}),a("versions.title"),Ca.some(c=>Sa(i?.[c]))?r("span",{className:"size-1.5 rounded-full bg-warning","aria-hidden":!0}):null]}),r(Za,{side:"bottom",align:"start",className:"w-80",children:f("div",{className:"space-y-3 text-xs",children:[Ca.map(c=>{let h=i?.[c];return f("section",{className:"space-y-1",children:[r("h4",{className:"font-medium text-foreground",children:a(c==="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:v(h?.requiredVersion)}),r("dt",{children:a("versions.installed")}),r("dd",{className:"font-mono",children:h&&h.installedVersions.length>0?h.installedVersions.join(", "):a("versions.none")}),r("dt",{children:a("versions.running")}),r("dd",{className:"font-mono",children:v(h?.runningVersion)})]}),Sa(h)?f(S,{size:"xs",variant:"outline",disabled:p,onClick:()=>g(c),children:[o===c?r(H,{size:"xs"}):null,a("versions.updateTo",{version:h?.requiredVersion??""})]}):null]},c)}),i===void 0?r("p",{className:"text-muted-foreground",children:a("versions.unknown")}):null,Ca.some(c=>Sa(i?.[c]))?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",{role:"status",className:"text-muted-foreground",children:a(u?"versions.checked":"versions.checkHint")}),f(S,{size:"xs",variant:"ghost",disabled:p,onClick:()=>g("check"),children:[o==="check"?r(H,{size:"xs"}):null,a("versions.check")]})]})]})})]})}var Fe=e=>e>=1073741824?`${(e/1073741824).toFixed(2)} GB`:`${(e/1048576).toFixed(1)} MB`;function Et(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:Fe(d.received),total:Fe(d.total)}:null,speed:d&&l?Fe(l):null,minutesLeft:s===null?null:Math.ceil(s/60),slow:s!==null&&s>1200}}var Ot=e=>e.source==="private"&&e.ready;function Ut(e){return e.supported?e.freeBytes!==null&&e.freeBytes<e.requiredFreeBytes?"environment.notEnoughSpace":null:e.reasonCode?`environment.reasons.${e.reasonCode}`:"environment.unsupported"}function qt(e,a){return e.cacheBytes>0||a==="android"&&e.deviceDataBytes>0}function Ht(e){let{t:a}=B(),t=Et(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(S,{size:"sm",variant:"outline",disabled:e.cancelling,onClick:e.onCancel,children:a("environment.cancel")})]})}function Nt(e){let{t:a}=B(),t=oe(),l=q().commands.useSubscription("environmentProgress",{},{environmentId:e.environmentId}).data,[d,s]=L(!1),[u,n]=L("android"),[i,p]=L(""),[g,v]=L(""),[c,h]=L(null),[b,R]=L(!1),[m,w]=L(!1),[C,k]=L(!1),[F,_]=L(null),[N,E]=L(!1),[W,O]=L(!1),[j,K]=L(void 0),G=l?.status==="working",U=F!==null||G,I=l&&l.id!==j?l:null;T(()=>{(G||I?.status==="failed")&&s(!0),I?.status==="done"&&I.plan?.platform===u&&h(I.plan)},[I,u,G]);let X=()=>{h(null),R(!1),w(!1),k(!1),O(!1),K(l?.id)},x=async(M,fo={})=>{_(M),E(!1),O(!1),K(l?.id);try{let co=await t(M,e.environmentId,{platform:u,directory:i,version:g,...fo});M==="cleanupEnvironment"?h(await t("environmentPlan",e.environmentId,{platform:u,directory:i,version:g})):M!=="prepareEnvironment"&&h(co),O(M==="cleanupEnvironment")}catch{E(!0)}finally{_(null)}},D=c?Ut(c):null,A=M=>M===null?a("environment.unknownSize"):Fe(M),V=c!==null&&Ot(c);return f(We,{open:d,onOpenChange:s,className:"w-full text-left",children:[r(Ke,{render:r(S,{variant:"outline",size:"sm",className:"w-full"}),children:a("environment.title")}),r(Xe,{children:f("div",{className:"space-y-3 rounded-md border p-3 text-xs",children:[G?r(Ht,{progress:l,cancelling:F==="cancelEnvironment",onCancel:()=>{_("cancelEnvironment"),t("cancelEnvironment",e.environmentId,{}).catch(()=>E(!0)).finally(()=>_(null))}}):f(J,{children:[r("p",{children:a("environment.description")}),e.iosSupported?r("div",{className:"flex gap-2",children:["android","ios"].map(M=>r(S,{size:"sm",variant:u===M?"default":"outline",disabled:U,onClick:()=>{n(M),X()},children:a(M==="ios"?"panel.platformIos":"panel.platformAndroid")},M))}):null,f("label",{className:"block space-y-1",children:[r("span",{children:a("environment.directory")}),r(te,{value:i,disabled:U,onChange:M=>{p(M.target.value),X()},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(te,{value:g,disabled:U,onChange:M=>{v(M.target.value),X()},placeholder:a("environment.iosVersionPlaceholder")})]}):null,r(S,{size:"sm",variant:"outline",disabled:U,onClick:()=>{x("environmentPlan")},children:a("environment.inspect")}),c?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.${c.source}`)}),r("dt",{children:a("environment.version")}),r("dd",{children:c.version||a("environment.versionRequired")}),r("dt",{children:a("environment.location")}),r("dd",{children:c.root}),c.existingSdkRoot?f(J,{children:[r("dt",{children:a("environment.existingSdk")}),r("dd",{children:c.existingSdkRoot})]}):null,r("dt",{children:a("environment.download")}),r("dd",{children:c.downloadBytes===0?a("environment.nothingToDownload"):A(c.downloadBytes)}),r("dt",{children:a("environment.free")}),r("dd",{children:A(c.freeBytes)}),r("dt",{children:a("environment.required")}),r("dd",{children:A(c.requiredFreeBytes)})]}),c.source==="external"?r("p",{children:a("environment.external")}):null,c.reasonCode&&c.supported?r("p",{role:"status",children:a(`environment.reasons.${c.reasonCode}`)}):null,r("a",{className:"underline",href:c.guidanceUrl,target:"_blank",rel:"noreferrer",children:a("environment.guide")}),u==="ios"?r("p",{children:a("environment.appleOwnership")}):r("p",{children:a("environment.privateOwnership")}),V?r("p",{role:"status",className:"font-medium text-foreground",children:a("environment.ready")}):f(J,{children:[r("ul",{children:c.licenses.map(M=>r("li",{children:r("a",{className:"underline",href:M.url,target:"_blank",rel:"noreferrer",children:a(u==="ios"?"environment.appleLicense":"environment.androidLicense")})},M.url))}),f("label",{className:"flex items-center gap-2",children:[r(ce,{checked:b,disabled:U,onCheckedChange:R}),r("span",{children:a("environment.acceptLicense")})]}),u==="ios"?f("label",{className:"flex items-center gap-2",children:[r(ce,{checked:m,disabled:U,onCheckedChange:w}),r("span",{children:a("environment.confirmApple")})]}):null,D?r("p",{role:"alert",className:"font-medium text-warning-foreground",children:a(D)}):null,r(S,{size:"sm",disabled:U||!c.supported||!b||u==="ios"&&(!m||!g)||c.freeBytes===null||c.freeBytes<c.requiredFreeBytes,onClick:()=>{x("prepareEnvironment",{acceptLicenses:b,confirmAppleInstall:m})},children:a("environment.prepare")})]}),qt(c,u)?f("div",{className:"space-y-2 border-t pt-2",children:[r("p",{children:a("environment.retention")}),r(S,{size:"sm",variant:"outline",disabled:U||c.cacheBytes===0,onClick:()=>{x("cleanupEnvironment",{category:"cache",confirm:!0})},children:a("environment.cleanCache",{size:A(c.cacheBytes)})}),u==="android"?f(J,{children:[r("p",{children:a("environment.deviceData",{size:A(c.deviceDataBytes)})}),f("label",{className:"flex items-center gap-2",children:[r(ce,{checked:C,disabled:U,onCheckedChange:k}),r("span",{children:a("environment.confirmData")})]}),r(S,{size:"sm",variant:"destructive",disabled:U||!C||c.deviceDataBytes===0,onClick:()=>{x("cleanupEnvironment",{category:"devices",confirm:C})},children:a("environment.cleanDevices")})]}):null]}):null]}):null]}),F!==null&&!G?f("p",{role:"status",className:"flex items-center gap-2",children:[r(H,{size:"xs"}),a("environment.working")]}):null,N?r("p",{role:"alert",className:"text-destructive-foreground",children:a("environment.failed")}):null,I?.status==="failed"?f("div",{role:"alert",className:"space-y-1 text-destructive-foreground",children:[r("p",{children:a("environment.prepareFailed")}),I.message?r("p",{className:"whitespace-pre-wrap break-words text-muted-foreground",children:I.message}):null]}):null,I?.status==="cancelled"?r("p",{role:"status",children:a("environment.cancelled")}):null,W?r("p",{role:"status",children:a("environment.cleaned")}):null]})})]})}var Gt=["small","default","large","extra-large"],ir=e=>Gt.includes(e);function Vt(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(se,{label:a("rail.home"),disabled:d,onClick:()=>t?.pressButton("home"),children:r(le,{})}),e.platform==="android"?f(J,{children:[r(se,{label:a("rail.back"),disabled:d,onClick:()=>t?.pressButton("back"),children:r(we,{})}),r(se,{label:a("rail.recents"),disabled:d,onClick:()=>t?.pressButton("recents"),children:r(Be,{})}),f(Ve,{children:[r(_e,{render:r(S,{size:"icon-sm",variant:"ghost","aria-label":a("rail.rotate"),disabled:o.disabled}),children:r(he,{})}),f(ze,{side:"left",children:[r(Ce,{onClick:()=>{o.act({type:"setOrientation",value:"portrait"})},children:a("rail.portrait")}),r(Ce,{onClick:()=>{o.act({type:"setOrientation",value:"landscape_left"})},children:a("rail.landscape")})]})]})]}):r(se,{label:a("rail.rotate"),disabled:d,onClick:()=>t?.rotate(),children:r(he,{})}),r(fr,{}),r(se,{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(Me,{}):r(ke,{})}),f(Ve,{children:[r(_e,{render:r(S,{size:"icon-sm",variant:"ghost","aria-label":a("rail.textSize"),title:a("rail.textSize"),disabled:o.disabled||!l?.textSize}),children:r(Re,{})}),r(ze,{side:"left",children:r(za,{value:l?.textSize??"",onValueChange:n=>{ir(n)&&o.act({type:"setTextSize",value:n})},children:Gt.map(n=>r(_a,{value:n,children:u(n)},n))})})]}),r(se,{label:a("rail.tools"),pressed:e.toolsOpen,onClick:e.onTools,children:r(Te,{})}),r(se,{label:e.screenshotPending?a("rail.capturing"):a("rail.screenshot"),disabled:!e.streaming||e.screenshotPending,onClick:e.onScreenshot,children:r(ve,{})}),e.onFloat?r(se,{label:a("rail.float"),onClick:e.onFloat,children:r(De,{})}):null,f(Ve,{children:[r(_e,{render:r(S,{size:"icon-sm",variant:"ghost","aria-label":a("rail.more"),title:a("rail.more")}),children:r(re,{})}),f(ze,{side:"left",align:"end",children:[f(Ce,{onClick:e.onClose,children:[r(Y,{}),a("rail.closePanel")]}),r(Va,{}),f(Ce,{variant:"destructive",onClick:e.onPowerOff,children:[r(Pe,{}),a("rail.powerOff")]})]})]})]})})}function fr(){return r("div",{"aria-hidden":!0,className:"my-1 h-px w-5 shrink-0 bg-border/70"})}function se(e){return f(Ha,{children:[r(Ga,{render:r(S,{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(Na,{side:"left",children:e.label})]})}var va=(e,a)=>new ta("invalid-input",`Invalid ${e}: ${a}.`);var zt=4096,_t=["light","dark"],Wt=["small","default","large","extra-large"];var Kt=["clear","tinted"],Xt=["none","grayscale","red-green","green-red","blue-yellow"],$t=["portrait","landscape_left","portrait_upside_down","landscape_right"],jt=["camera","microphone","photos","contacts","calendar","reminders","location","notifications","motion","media-library","faceid"];var cr=e=>typeof e=="object"&&e!==null&&!Array.isArray(e);var Zt=e=>{let a=typeof e=="string"?{aps:{alert:e}}:e;if(!cr(a))throw va("push payload","expected a string or an object");let t;try{t=JSON.stringify(a)}catch{t=void 0}if(t===void 0)throw va("push payload","could not be encoded as JSON");if(new TextEncoder().encode(t).length>zt)throw va("push payload",`larger than ${String(zt)} bytes`);return t};var pr=new Set(["setAppearance","setTextSize","setToggle","setLiquidGlass","setColorFilter","setLocation","clearLocation","setPermission","openUrl","launchApp","relaunchApp","terminateApp","sendPush"]),mr=new Set(["setAppearance","setTextSize","setToggle","setOrientation","setLocation","setPermission","openUrl","launchApp","relaunchApp","terminateApp"]),gr=new Set(["reduceMotion","increaseContrast","reduceTransparency","showBorders","voiceOver"]),Lr=new Set(["reduceMotion","networkEnabled"]),ya=(e,a)=>(e==="ios"?pr:mr).has(a.type)?a.type==="setToggle"?(e==="ios"?gr:Lr).has(a.setting):!0:!1;function ie(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 de(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 wa(e){return r(de,{label:e.label,children:r(ce,{"aria-label":e.label,checked:e.checked??!1,disabled:e.disabled||e.checked===void 0,onCheckedChange:a=>{e.onChange(a)}})})}function ba(e){return r(Ka,{"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(Xa,{size:"xs",value:a.value,children:a.label},a.value))})}function Ee(e){let a=e.options.find(t=>t.value===e.value);return f(ia,{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(fa,{size:"xs",className:e.width??"w-40","aria-label":e.ariaLabel,children:r(ca,{children:a?a.label:r("span",{className:"text-muted-foreground",children:e.placeholder})})}),r(pa,{align:"end",alignItemWithTrigger:!1,children:e.options.map(t=>r(ma,{value:t.value,children:t.label},t.value))})]})}function ka(e){let[a,t]=L(""),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(te,{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(S,{type:"submit",size:"xs",variant:"outline",disabled:e.disabled||!o,children:e.action})]})}var Jt=[{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 Yt(e){let{t:a}=B(),[t,o]=L(e.current?String(e.current.latitude):""),[l,d]=L(e.current?String(e.current.longitude):""),s={latitude:Number(t),longitude:Number(l)},u=t.trim()!==""&&l.trim()!==""&&Math.abs(s.latitude)<=90&&Math.abs(s.longitude)<=180,n=(i,p)=>e.act({type:"setLocation",latitude:i,longitude:p});return f(ie,{title:a("tools.location.title"),children:[f("div",{className:"flex gap-1.5",children:[r(te,{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(te,{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(ia,{value:null,disabled:e.disabled,onValueChange:i=>{let p=Jt.find(g=>g.key===i);p&&(o(String(p.latitude)),d(String(p.longitude)),n(p.latitude,p.longitude))},children:[r(fa,{size:"xs",className:"w-32","aria-label":a("tools.location.preset"),children:r(ca,{children:r("span",{className:"text-muted-foreground",children:a("tools.location.presetPlaceholder")})})}),r(pa,{align:"start",alignItemWithTrigger:!1,children:Jt.map(i=>r(ma,{value:i.key,children:a(i.key)},i.key))})]}),r(S,{size:"xs",variant:"outline",disabled:e.disabled||!u,onClick:()=>{n(s.latitude,s.longitude)},children:a("tools.location.set")}),e.canClear?r(S,{size:"xs",variant:"ghost",disabled:e.disabled,onClick:()=>{o(""),d(""),e.act({type:"clearLocation"})},children:a("tools.location.clear")}):null]}),e.current?r("p",{role:"status",className:"text-xs text-muted-foreground",children:a("tools.location.current",{latitude:e.current.latitude,longitude:e.current.longitude})}):null]})}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 eo(e){let{t:a}=B(),t=e.platform==="ios",[o,l]=L(""),[d,s]=L("camera"),u=o.trim()||e.defaultAppId,n=jt.filter(p=>t||xr.has(p)).map(p=>({value:p,label:a(!t&&p==="motion"?"tools.permissions.activity":hr[p])})),i=p=>{e.act({type:"setPermission",appId:u,permission:d,decision:p})};return f(ie,{title:a("tools.permissions.title"),children:[r(te,{size:"compact",className:"font-mono",placeholder:e.defaultAppId||a("tools.permissions.appId"),"aria-label":a("tools.permissions.appId"),value:o,disabled:e.disabled,onChange:p=>l(p.target.value)}),f("div",{className:"flex flex-wrap items-center gap-1.5",children:[r(Ee,{ariaLabel:a("tools.permissions.permission"),value:d,options:n,placeholder:a("tools.unknown"),disabled:e.disabled,onChange:p=>(s(p),Promise.resolve())}),r(S,{size:"xs",variant:"outline",disabled:e.disabled||!u,onClick:()=>i("grant"),children:a("tools.permissions.grant")}),r(S,{size:"xs",variant:"outline",disabled:e.disabled||!u,onClick:()=>i("revoke"),children:a("tools.permissions.revoke")}),t?r(S,{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 Zt(a),a}catch{return null}};function ao(e){let{t:a}=B(),[t,o]=L(""),l=t.trim(),d=l?Ir(l):null,s=e.appId;return f(ie,{title:a("tools.push.title"),children:[r(Wa,{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(S,{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 Qt=100;function to(e){let{t:a}=B(),[t,o]=L(!1),[l,d]=L([]),{transport:s,platform:u,deviceId:n}=e;return T(()=>{if(!t)return;let i=rt({transport:s,platform:u,deviceId:n},(p,g)=>{d(v=>{let c=g?[...p]:[...v,...p];return c.length>Qt?c.slice(-Qt):c})});return()=>{i(),d([])}},[t,s,u,n]),f(We,{open:t,onOpenChange:o,children:[f(Ke,{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(ye,{className:`ml-auto size-3.5 transition-transform ${t?"rotate-180":""}`})]}),r(Xe,{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 oo(e){let{t:a}=B(),{device:t,controls:o}=e,{detail:l,pending:d,error:s,foregroundApp:u,disabled:n,act:i}=o,p=l?.settings,g=t.platform==="ios",v=z(null),[c,h]=L(!0);Ba(()=>{let m=v.current?.parentElement;if(!m)return;let w=()=>h(m.clientWidth<Cr);w();let C=new ResizeObserver(w);return C.observe(m),()=>C.disconnect()},[]),T(()=>o.followDevice(),[o.followDevice]);let b=Wt.map(m=>({value:m,label:a(vr[m])})),R=kr.filter(m=>ya(t.platform,{type:"setToggle",setting:m.setting,value:!0}));return f("aside",{ref:v,"aria-label":a("tools.title"),className:`flex min-h-0 flex-col border-l bg-background text-sm ${c?"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(S,{size:"icon-xs",variant:"ghost-muted","aria-label":a("tools.close"),className:"ml-auto",onClick:e.onClose,children:r(Y,{})})]}),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(ie,{title:a("tools.app.title"),children:[r(de,{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(S,{size:"xs",variant:"outline",disabled:n,onClick:()=>{i({type:"terminateApp",appId:u.id})},children:a("tools.app.terminate")}),r(S,{size:"xs",variant:"outline",disabled:n,onClick:()=>{i({type:"relaunchApp",appId:u.id})},children:a("tools.app.relaunch")})]}):null,r(ka,{placeholder:a("tools.app.urlPlaceholder"),action:a("tools.app.open"),disabled:n,onSubmit:m=>i({type:"openUrl",url:m})}),r(ka,{placeholder:a(g?"tools.app.bundleIdPlaceholder":"tools.app.packagePlaceholder"),action:a("tools.app.launch"),disabled:n,fallback:u?.id,onSubmit:m=>i({type:"launchApp",appId:m})})]}),f(ie,{title:a(g?"tools.settings.titleIos":"tools.settings.titleAndroid"),children:[r(de,{label:a("tools.settings.appearance"),children:r(ba,{label:a("tools.settings.appearance"),value:p?.appearance,options:_t.map(m=>({value:m,label:a(Sr[m])})),disabled:n,onChange:m=>i({type:"setAppearance",value:m})})}),r(de,{label:a("tools.settings.textSize"),children:r(Ee,{ariaLabel:a("tools.settings.textSize"),value:p?.textSize??null,options:b,placeholder:a("tools.unknown"),disabled:n,onChange:m=>i({type:"setTextSize",value:m})})}),g?f(J,{children:[r(de,{label:a("tools.settings.liquidGlass"),children:r(ba,{label:a("tools.settings.liquidGlass"),value:p?.liquidGlass,options:Kt.map(m=>({value:m,label:a(yr[m])})),disabled:n,onChange:m=>i({type:"setLiquidGlass",value:m})})}),r(de,{label:a("tools.settings.colorFilter"),children:r(Ee,{ariaLabel:a("tools.settings.colorFilter"),value:p?.colorFilter??null,options:Xt.map(m=>({value:m,label:a(wr[m])})),placeholder:a("tools.unknown"),disabled:n,onChange:m=>i({type:"setColorFilter",value:m})})})]}):r(de,{label:a("tools.settings.orientation"),children:r(Ee,{ariaLabel:a("tools.settings.orientation"),value:null,options:$t.map(m=>({value:m,label:a(br[m])})),placeholder:a("tools.settings.rotateTo"),disabled:n,onChange:m=>i({type:"setOrientation",value:m})})}),R.map(m=>r(wa,{label:a(m.labelKey),checked:p?.[m.setting],disabled:n,onChange:w=>i({type:"setToggle",setting:m.setting,value:w})},m.setting))]}),r(ie,{title:a("tools.accessibility.title"),children:r(wa,{label:a("tools.accessibility.overlay"),checked:e.axOverlay,disabled:!1,onChange:m=>(e.onAxOverlayChange(m),Promise.resolve())})}),r(Yt,{current:o.location,canClear:ya(t.platform,{type:"clearLocation"}),disabled:n,act:i}),r(eo,{platform:t.platform,defaultAppId:u?.id??"",disabled:n,act:i}),g?r(ao,{appId:u?.id,disabled:n,act:i}):null,g?r(to,{transport:e.transport,platform:t.platform,deviceId:t.id}):null]})]})}var Dr=2e4,Da=class extends Error{status;constructor(a){super(`Screenshot capture failed (${a}). Try again.`),this.status=a}};async function ro(e,a,t,o){let l=AbortSignal.timeout(Dr),d=await e.fetch(`${pe(a)}/api/screenshot?device=${encodeURIComponent(t)}`,{method:"POST",signal:o?AbortSignal.any([o,l]):l});if(!d.ok)throw new Da(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 Pr=3e3,lo=e=>e instanceof Error?e.message:String(e);function so(e){let{environmentId:a,device:t}=e,o=oe(),[l,d]=L(null),[s,u]=L(null),[n,i]=L(!1),[p,g]=L(null),v=z(!1),c=z(0),h={hostId:t.hostId,deviceId:t.id},b=C=>o("detail",a,h).then(k=>{c.current===C&&(d(k),g(null))},k=>{c.current===C&&(d(null),g(lo(k)))});T(()=>{let C=++c.current;return b(C),()=>{c.current++}},[a,t.hostId,t.id]);let R=async C=>{if(v.current||l===null)return!1;v.current=!0;let k=++c.current;i(!0),g(null);try{let F=await o("action",a,{...h,...C});return c.current===k?d(F):await b(++c.current),C.type==="setLocation"?u({latitude:C.latitude,longitude:C.longitude}):C.type==="clearLocation"&&u(null),!0}catch(F){return c.current===k&&g(lo(F)),!1}finally{v.current=!1,i(!1)}},m=z(()=>{});m.current=()=>{if(v.current)return;let C=++c.current;o("detail",a,h).then(k=>{c.current===C&&d(k)},()=>{})};let w=ee(()=>{m.current();let C=setInterval(()=>m.current(),Pr);return()=>clearInterval(C)},[]);return{detail:l,location:s,pending:n,error:p,act:R,followDevice:w,disabled:n||l===null,foregroundApp:e.foreground===void 0?l?.foregroundApp??null:e.foreground}}var Ar=()=>typeof window<"u"&&"ReactNativeWebView"in window;function uo(e){let{t:a}=B(),t=oa(e.environmentId),[o,l]=L(null),[d,s]=L(!1),[u,n]=L(!1),[i,p]=L(!1),[g,v]=L(),[c,h]=L(!1),[b,R]=L(null),[m,w]=L(null),C=z(null),k=z(null),F=t.status==="ready"?t.transport:null,_=so({environmentId:e.environmentId,device:e.device,foreground:g}),N=ee(O=>l(O),[]),E=ee(O=>s(O),[]);T(()=>{if(!F)return;let O=ot({transport:F,platform:e.device.platform,deviceId:e.device.id},v);return()=>{O(),v(void 0)}},[e.device.id,e.device.platform,F]),T(()=>()=>{C.current?.abort(),k.current&&URL.revokeObjectURL(k.current)},[]);let W=()=>{if(!F||C.current)return;let O=new AbortController;C.current=O,h(!0),R(null),ro(F,e.device.platform,e.device.id,O.signal).then(j=>{if(O.signal.aborted)return;k.current&&URL.revokeObjectURL(k.current);let K=URL.createObjectURL(j);if(k.current=K,Ar()){w(K);return}let G=document.createElement("a");G.href=K,G.download=`${e.device.name.replace(/[^a-z0-9-]/gi,"-")}-${Date.now()}.png`,document.body.append(G),G.click(),G.remove()}).catch(j=>{O.signal.aborted||R(j instanceof Error?j.message:a("workspace.screenshotFailed"))}).finally(()=>{C.current===O&&(C.current=null,h(!1))})};return t.status!=="ready"?r(ae,{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(S,{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:[b||_.error&&!u?r("p",{role:"alert",className:"px-3 py-2 text-xs text-destructive-foreground",children:b??_.error}):null,f("div",{className:"relative min-h-0 flex-1",children:[r(aa,{transport:t.transport,platform:e.device.platform,deviceId:e.device.id,deviceName:e.device.name,deviceDescription:e.device.version,axOverlay:i,withControls:!0,onHandle:N,onStreaming:E}),r(Vt,{platform:e.device.platform,handle:o,streaming:d,controls:_,screenshotPending:c,onScreenshot:W,toolsOpen:u,onTools:()=>n(!u),onClose:e.onClose,onPowerOff:e.onPowerOff,onFloat:e.onFloat})]})]}),u?r(oo,{device:e.device,controls:_,transport:t.transport,axOverlay:i,onAxOverlayChange:p,onClose:()=>n(!1)}):null,m?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:m,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(S,{size:"sm",variant:"outline",onClick:()=>w(null),children:[r(Y,{}),a("workspace.closeBrowser")]})]}):null]})}var Pa=e=>e instanceof Error?e.message:String(e);function no(e){let{environmentId:a,threadId:t}=e,{t:o}=B(),{state:l,loaded:d,error:s,unavailable:u}=ge(a),n=oe(),[i,p]=L(null),[g,v]=L(null),c=Ua(a,t),h=I=>Ne(a,t,I),b=q(),R=fe(b,"floating"),m=()=>{p(null),n("refresh",a).catch(I=>p(Pa(I)))};T(()=>{!d||u||n("refresh",a).catch(()=>{})},[a,d,n,u]);let w=ne(()=>l.sessions.filter(I=>I.threadId===t),[l.sessions,t]),C=Br(w,c),k=C?l.devices.find(I=>I.hostId===C.hostId&&I.id===C.deviceId):void 0,F=k&&C?Ie(k):null;T(()=>{b.floating?.present({environmentId:a,threadId:t},F)}),T(()=>()=>b.floating?.present({environmentId:a,threadId:t},null),[b,a,t]);let _=ne(()=>Mr(l),[l]),N=l.hostStatuses[Le],E=N?.status==="ready",W=N?.status==="installing"||N?.status==="starting",O=Ia(),j=l.bootingDevices.filter(I=>I.threadId===t),K=l.hosts.flatMap(I=>I.platforms.filter(X=>!X.available)),G=async I=>{p(null),v(I),na(a,t,Z(I));try{await n("open",a,{threadId:t,hostId:I.hostId,deviceId:I.id,platform:I.platform}),h(Z(I))}catch(X){na(a,t,Z(I),!1),p(Pa(X))}finally{v(null)}},U=I=>{C&&(p(null),n("close",a,{threadId:t,hostId:C.hostId,deviceId:C.deviceId,shutdown:I}).then(()=>h(null)).catch(X=>p(Pa(X))))};return u?r(ae,{name:o("panel.title"),stage:"error",message:o("panel.unavailable")}):f("div",{className:"flex size-full min-h-0 flex-col",children:[j.length>0?r("div",{role:"status",className:"border-b px-3 py-2 text-xs text-muted-foreground",children:o("panel.booting",{names:j.map(I=>I.name).join(", ")})}):null,W&&!k?null:r(Rt,{detail:N,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(S,{size:"icon-xs",variant:"ghost","aria-label":o("panel.dismissError"),onClick:()=>p(null),children:r(Y,{className:"size-3"})}):null]}):null,r("div",{className:"relative flex min-h-0 flex-1",children:k&&C?r(uo,{environmentId:a,device:k,onBack:()=>h(""),onFloat:R?()=>b.floating?.open({environmentId:a,threadId:t},{...Ie(k),reason:"user"}):void 0,onPowerOff:()=>U(!0),onClose:()=>U(!1)},`${a}\0${Z(k)}`):g||W||!d?r(ae,{name:g?.name??o("panel.title"),...g?{description:g.version}:{},stage:"opening",message:g?g.booted?o("panel.opening"):o("panel.starting"):W&&N?O(N):o("panel.finding")}):r(Tr,{environmentId:a,host:l.hosts.find(I=>I.id===Le),grouped:_,hostReady:E,hostFailed:N?.status==="failed",unavailableReasons:K,showNoAvdHint:E&&!l.devices.some(I=>I.platform==="android")&&!K.some(I=>I.platform==="android"),pendingKey:g?Z(g):null,onOpen:I=>{G(I)},onRefresh:m})})]})}function Tr(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(Nt,{environmentId:e.environmentId,iosSupported:!e.unavailableReasons.some(o=>o.reasonCode==="ios-needs-macos")},e.environmentId),t?f(J,{children:[r(xe,{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(xe,{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(S,{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===Z(l)?r(H,{size:"xs"}):r("span",{className:"text-xs",children:l.booted?a("panel.open"):a("panel.start")})]})},Z(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(S,{variant:t?"outline":"ghost",size:"sm",onClick:e.onRefresh,children:a("panel.refresh")}),r(Ft,{environmentId:e.environmentId,host:e.host,busy:!1})]})]})})}function Br(e,a){if(a!==""){if(a!==null){let t=e.find(o=>Z({hostId:o.hostId,id:o.deviceId})===a);if(t)return t}return e.toSorted((t,o)=>o.openedAt.localeCompare(t.openedAt))[0]}}function Mr(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 io({environmentId:e,threadId:a}){let t=q(),{state:o,loaded:l}=ge(e),d=z(null);return T(()=>{if(!l||!fe(t,"floating"))return;let s=`${e}\0${a}`,u=d.current?.key===s?d.current.seen:null,{seen:n,opened:i}=qa({environmentId:e,threadId:a,previous:u,sessions:o.sessions,devices:o.devices});d.current={key:s,seen:n};for(let p of i)t.floating?.open({environmentId:e,threadId:a},{...Ie(p),reason:"agent",panelId:qe})},[t,e,l,o.devices,o.sessions,a]),null}function Rr(e){return{panels:{device:function(t){return f(Ue,{value:e,children:[r("style",{children:la}),r("div",{className:`${Ge} flex h-full min-h-0 flex-1 flex-col`,children:r(no,{environmentId:t.environmentId,threadId:t.threadId})})]})}},views:{deviceFloat:function(t){return f(Ue,{value:e,children:[r("style",{children:la}),r("div",{className:`${Ge} relative size-full`,children:r(Dt,{...t})})]})},deviceSessions:function(t){return r(Ue,{value:e,children:r(io,{environmentId:t.environmentId,threadId:t.threadId})})}}}}export{Rr as default};
@@ -0,0 +1,42 @@
1
+ // adb 按 MAX_PATH 打开本地文件;随包路径常超过它,push 和 install 只报 cannot stat 或 No such file。
2
+ // hub 的 scrcpy 和 agent-device 都自己起 adb,路径又在随包代码里,只能改写它们起 adb 的参数。
3
+ //
4
+ // agent-device 的 adb 跑在它另起的守护进程里,所以装上补丁的进程再起 Node 时带上 `--import`,
5
+ // 让补丁跟着子进程走。Node 模式由 helper.mjs 导入;只用 node 内置模块。
6
+ import * as NodeChildProcess from "node:child_process";
7
+ import * as NodeModule from "node:module";
8
+ import * as NodePath from "node:path";
9
+ import * as NodeUtil from "node:util";
10
+
11
+ export const extendLongAdbPaths = (args) =>
12
+ args.map((argument) =>
13
+ typeof argument === "string" && argument.length >= 260 && /^[A-Za-z]:[\\/]/u.test(argument)
14
+ ? `\\\\?\\${NodePath.win32.normalize(argument)}`
15
+ : argument,
16
+ );
17
+
18
+ export function patchAdbLongPaths(
19
+ childProcess,
20
+ { execPath = process.execPath, moduleUrl = import.meta.url } = {},
21
+ ) {
22
+ const isAdb = (file) => /^adb(\.exe)?$/iu.test(NodePath.win32.basename(String(file)));
23
+ const rewrite = (file, args) => {
24
+ if (!Array.isArray(args)) return args;
25
+ if (isAdb(file)) return extendLongAdbPaths(args);
26
+ return file === execPath && !args.includes(moduleUrl) ? ["--import", moduleUrl, ...args] : args;
27
+ };
28
+ for (const name of ["spawn", "spawnSync", "execFile", "execFileSync"]) {
29
+ const original = childProcess[name];
30
+ const patched = (file, args, ...rest) => original(file, rewrite(file, args), ...rest);
31
+ if (name === "execFile") {
32
+ const promisified = NodeUtil.promisify(original);
33
+ patched[NodeUtil.promisify.custom] = (file, args, ...rest) =>
34
+ promisified(file, rewrite(file, args), ...rest);
35
+ }
36
+ childProcess[name] = patched;
37
+ }
38
+ NodeModule.syncBuiltinESMExports();
39
+ }
40
+
41
+ // oxlint-disable-next-line ycodium/no-global-process-runtime -- 独立子进程脚本,没有 Effect 运行时可注入。
42
+ if (process.platform === "win32") patchAdbLongPaths(NodeChildProcess.default);
package/dist/helper.mjs CHANGED
@@ -23,6 +23,7 @@ import * as NodePath from "node:path";
23
23
  import * as NodeURL from "node:url";
24
24
  import * as NodeUtil from "node:util";
25
25
 
26
+ import "./adb-long-paths.mjs";
26
27
  import {
27
28
  applyPrivateAndroidEnvironment,
28
29
  avdListOutput,
package/dist/index.js CHANGED
@@ -135,6 +135,7 @@ var parseDeviceAction = (platform2, input) => {
135
135
  "setPermission",
136
136
  "openUrl",
137
137
  "launchApp",
138
+ "relaunchApp",
138
139
  "terminateApp",
139
140
  "shake",
140
141
  "sendPush"
@@ -178,6 +179,7 @@ var parseDeviceAction = (platform2, input) => {
178
179
  case "openUrl":
179
180
  return { type, url: url(input["url"]) };
180
181
  case "launchApp":
182
+ case "relaunchApp":
181
183
  case "terminateApp":
182
184
  return { type, appId: appId(platform2, input["appId"]) };
183
185
  case "sendPush":
@@ -199,6 +201,7 @@ var IOS_ACTIONS = /* @__PURE__ */ new Set([
199
201
  "setPermission",
200
202
  "openUrl",
201
203
  "launchApp",
204
+ "relaunchApp",
202
205
  "terminateApp",
203
206
  "sendPush"
204
207
  ]);
@@ -208,10 +211,10 @@ var ANDROID_ACTIONS = /* @__PURE__ */ new Set([
208
211
  "setToggle",
209
212
  "setOrientation",
210
213
  "setLocation",
211
- "clearLocation",
212
214
  "setPermission",
213
215
  "openUrl",
214
216
  "launchApp",
217
+ "relaunchApp",
215
218
  "terminateApp"
216
219
  ]);
217
220
  var IOS_TOGGLES = /* @__PURE__ */ new Set([
@@ -279,6 +282,7 @@ var actionPayload = {
279
282
  ),
280
283
  branch("openUrl", { url: { type: "string", minLength: 1, maxLength: 2048 } }, ["url"]),
281
284
  branch("launchApp", { appId: appId2 }, ["appId"]),
285
+ branch("relaunchApp", { appId: appId2 }, ["appId"]),
282
286
  branch("terminateApp", { appId: appId2 }, ["appId"]),
283
287
  branch("shake"),
284
288
  branch("sendPush", { appId: appId2, payload: { type: ["string", "object"] } }, ["appId", "payload"])
@@ -2696,6 +2700,10 @@ var runIos = async (tools, udid, action) => {
2696
2700
  case "launchApp":
2697
2701
  await simctl(tools, udid, ["launch", action.appId], "launch");
2698
2702
  return;
2703
+ case "relaunchApp":
2704
+ await simctl(tools, udid, ["terminate", action.appId], "terminate").catch(() => void 0);
2705
+ await simctl(tools, udid, ["launch", action.appId], "launch");
2706
+ return;
2699
2707
  case "terminateApp":
2700
2708
  await simctl(tools, udid, ["terminate", action.appId], "terminate");
2701
2709
  return;
@@ -2712,6 +2720,7 @@ var runIos = async (tools, udid, action) => {
2712
2720
  var adb = (tools, serial, args, operation) => checked(tools.run("adb", ["-s", serial, ...args]), operation);
2713
2721
  var runAndroid = async (tools, serial, action) => {
2714
2722
  const shell = (args, operation) => adb(tools, serial, ["shell", ...args], operation);
2723
+ const launch = (appId3) => shell(["monkey", "-p", appId3, "-c", "android.intent.category.LAUNCHER", "1"], "launch");
2715
2724
  switch (action.type) {
2716
2725
  case "setAppearance":
2717
2726
  await shell(["cmd", "uimode", "night", action.value === "dark" ? "yes" : "no"], "appearance");
@@ -2768,13 +2777,21 @@ var runAndroid = async (tools, serial, action) => {
2768
2777
  "location"
2769
2778
  );
2770
2779
  return;
2771
- case "clearLocation":
2772
- return;
2773
2780
  case "setPermission": {
2774
2781
  const permissions = ANDROID_PERMISSIONS[action.permission];
2775
2782
  if (permissions === void 0) throw unsupported("permission", "android");
2776
2783
  const verb = action.decision === "grant" ? "grant" : "revoke";
2777
- for (const permission of permissions) {
2784
+ const declared = new Set(
2785
+ (await shell(["dumpsys", "package", action.appId], "permission")).split(/[\s:,]+/u)
2786
+ );
2787
+ const requested = permissions.filter((permission) => declared.has(permission));
2788
+ if (requested.length === 0) {
2789
+ throw new DeviceError(
2790
+ "command-failed",
2791
+ `${action.appId} does not declare this permission, so Android cannot change it.`
2792
+ );
2793
+ }
2794
+ for (const permission of requested) {
2778
2795
  await shell(["pm", verb, action.appId, permission], "permission").catch(() => void 0);
2779
2796
  }
2780
2797
  return;
@@ -2786,14 +2803,16 @@ var runAndroid = async (tools, serial, action) => {
2786
2803
  );
2787
2804
  return;
2788
2805
  case "launchApp":
2789
- await shell(
2790
- ["monkey", "-p", action.appId, "-c", "android.intent.category.LAUNCHER", "1"],
2791
- "launch"
2792
- );
2806
+ await launch(action.appId);
2807
+ return;
2808
+ case "relaunchApp":
2809
+ await shell(["am", "force-stop", action.appId], "terminate");
2810
+ await launch(action.appId);
2793
2811
  return;
2794
2812
  case "terminateApp":
2795
2813
  await shell(["am", "force-stop", action.appId], "terminate");
2796
2814
  return;
2815
+ case "clearLocation":
2797
2816
  case "setLiquidGlass":
2798
2817
  case "setColorFilter":
2799
2818
  case "shake":
@@ -2874,7 +2893,8 @@ var readAndroid = async (tools, serial) => {
2874
2893
  const settings = {
2875
2894
  ...night?.includes("yes") ? { appearance: "dark" } : night?.includes("no") ? { appearance: "light" } : {},
2876
2895
  ...Number.isFinite(scale) ? { textSize: textSizeFromAndroid(scale) } : {},
2877
- ...animator !== void 0 && animator !== "null" ? { reduceMotion: Number(animator) === 0 } : {},
2896
+ // 没动过这项设置时系统读出 "null",含义是默认动画,不是未知。
2897
+ ...animator === void 0 ? {} : { reduceMotion: animator !== "null" && Number(animator) === 0 },
2878
2898
  ...wifi === "1" || wifi === "0" ? { networkEnabled: wifi === "1" } : {}
2879
2899
  };
2880
2900
  const foregroundApp = focused?.[1] === void 0 ? null : { id: focused[1] };
@@ -3161,7 +3181,9 @@ var DeviceService = class {
3161
3181
  }
3162
3182
  }
3163
3183
  }
3164
- return list.errors.length > 0 ? { devices, detail: list.errors.join("\n") } : { devices };
3184
+ const iosAvailable = (await this.host.platformAvailability("ios")).available;
3185
+ const errors = iosAvailable ? list.errors : list.errors.filter((error) => !error.startsWith("[apple-utils]"));
3186
+ return errors.length > 0 ? { devices, detail: errors.join("\n") } : { devices };
3165
3187
  }
3166
3188
  async refresh(ready) {
3167
3189
  const generation = this.environmentGeneration;
@@ -3652,7 +3674,7 @@ var deviceToolkit = (service) => ({
3652
3674
  var HUB_SERVICE = "hub";
3653
3675
  var index_default = definePlugin({
3654
3676
  id: "devices",
3655
- apiVersion: 60,
3677
+ apiVersion: 63,
3656
3678
  activate: async (ctx) => {
3657
3679
  const direct = (input, init) => ctx.proxies.fetch(PLUGIN_PROXY_DIRECT).then((fetchDirect) => fetchDirect(input, init));
3658
3680
  const host = new LocalDeviceHost({
package/locales/en.json CHANGED
@@ -244,6 +244,7 @@
244
244
  "presetPlaceholder": "Preset…",
245
245
  "set": "Set",
246
246
  "clear": "Clear",
247
+ "current": "Set to {{latitude}}, {{longitude}}",
247
248
  "sanFrancisco": "San Francisco",
248
249
  "newYork": "New York",
249
250
  "london": "London",
@@ -294,6 +295,7 @@
294
295
  "updateTo": "Verify bundled {{version}}",
295
296
  "pendingPolicy": "Device helpers are included with Ycodium. Missing or incomplete components require repairing or updating Ycodium on this machine.",
296
297
  "checkHint": "Checking reads the installed tools without installing or starting anything.",
298
+ "checked": "Checked. The versions above are current.",
297
299
  "check": "Check versions",
298
300
  "checkFailed": "Could not read the tool versions. Try again.",
299
301
  "updateFailed": "Bundled components are missing or incomplete. Repair or update Ycodium on this machine."
@@ -244,6 +244,7 @@
244
244
  "presetPlaceholder": "预设…",
245
245
  "set": "设置",
246
246
  "clear": "清除",
247
+ "current": "已设为 {{latitude}}, {{longitude}}",
247
248
  "sanFrancisco": "旧金山",
248
249
  "newYork": "纽约",
249
250
  "london": "伦敦",
@@ -294,6 +295,7 @@
294
295
  "updateTo": "校验随包版本 {{version}}",
295
296
  "pendingPolicy": "设备辅助工具随 Ycodium 提供。组件缺失或不完整时,请修复或更新这台机器上的 Ycodium。",
296
297
  "checkHint": "检查只读取已装的工具,不安装也不启动任何东西。",
298
+ "checked": "检查完成,上面的版本是最新读取的结果。",
297
299
  "check": "检查版本",
298
300
  "checkFailed": "读不到工具版本,请重试。",
299
301
  "updateFailed": "随包组件缺失或不完整,请修复或更新这台机器上的 Ycodium。"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ycodium-ai/plugin-devices",
3
- "version": "0.2.3817",
3
+ "version": "0.2.3851",
4
4
  "description": "Lets agents drive iOS Simulators and Android Emulators on this machine.",
5
5
  "keywords": [
6
6
  "android",
@@ -16,6 +16,7 @@
16
16
  "dist",
17
17
  "locales",
18
18
  "assets",
19
+ "skills",
19
20
  "README.md"
20
21
  ],
21
22
  "type": "module",
@@ -33,9 +34,9 @@
33
34
  "tailwindcss": "^4.0.0",
34
35
  "typescript": "~6.0.3",
35
36
  "vite-plus": "0.2.2",
36
- "@ycodium-ai/plugin-api": "0.2.3817",
37
- "ycodium-fetch-ports": "0.0.0",
38
- "ycodium-sse-stream": "0.0.0"
37
+ "ycodium-sse-stream": "0.0.0",
38
+ "@ycodium-ai/plugin-api": "0.2.3851",
39
+ "ycodium-fetch-ports": "0.0.0"
39
40
  },
40
41
  "ycodium": {
41
42
  "plugin": "./dist/index.js",
@@ -44,6 +45,11 @@
44
45
  "description": "Lets agents drive iOS Simulators and Android Emulators on this machine.",
45
46
  "descriptionKey": "presentation.description",
46
47
  "icon": "./assets/icon.svg",
48
+ "skills": [
49
+ {
50
+ "dir": "./skills/mobile-devices"
51
+ }
52
+ ],
47
53
  "ui": {
48
54
  "assets": "./assets",
49
55
  "entry": "ui.js",
@@ -0,0 +1,110 @@
1
+ ---
2
+ name: mobile-devices
3
+ description: Build, install, run, and operate a mobile app on an Android Emulator or iOS Simulator through the Devices plugin, then verify its screens, forms, and logs. Use when a task needs an app running on a device, not only unit tests. Covers React Native and Expo, Flutter, and native projects, and what to do when build tools are missing.
4
+ ---
5
+
6
+ # Mobile devices
7
+
8
+ Use the Devices plugin to run a mobile app on an emulator or simulator on the machine hosting this conversation, and to check what the app really does. The user can watch the same device in the Devices panel.
9
+
10
+ ## Find the tools
11
+
12
+ The plugin provides `devices_device_list`, `devices_device_open`, `devices_device_screenshot`, and `devices_device_close`. Your harness may add its usual MCP server prefix. If the plugin was enabled during the conversation and these names are missing, use `ycodium_plugin_tools` with `pluginId: "devices"` and call the returned tools through `ycodium_plugin_call`.
13
+
14
+ Everything else goes through the `agent-device` command that `devices_device_open` returns.
15
+
16
+ ## Open a device
17
+
18
+ 1. Call `devices_device_list`. It reports which platforms this machine can run, why one is unavailable, and which devices exist.
19
+ 2. Call `devices_device_open` with a `deviceId`, or with a `platform` to use the booted device or the first one. It boots the device and shows it to the user.
20
+ 3. Keep the returned `agentDevice.command` and `targetArgs`. Use that exact executable and pass those flags on every command, because a login shell may reset `PATH`.
21
+
22
+ iOS Simulators need macOS with Xcode. On Windows and Linux, test Android and say that iOS was not run.
23
+
24
+ If no Android device exists, ask the user to choose **Prepare simulator environment** in the Devices panel. It downloads a private SDK and one API 35 emulator; it needs no system-wide install and takes several minutes.
25
+
26
+ ## Drive and inspect
27
+
28
+ ```text
29
+ <agent-device> open <package-or-bundle-id> <flags> # or: open <app> <deep-link-url>
30
+ <agent-device> snapshot -i <flags> # accessibility tree with @eN refs
31
+ <agent-device> click @e3 <flags>
32
+ <agent-device> fill @e5 "text" <flags>
33
+ <agent-device> screenshot <file.png> <flags>
34
+ <agent-device> install <app> <path-to-.apk-or-.app> <flags>
35
+ <agent-device> help # workflow guides
36
+ ```
37
+
38
+ Prefer snapshot refs to coordinates, and take a new snapshot after every navigation because refs go stale. The first Android snapshot installs a small helper app on the device. `devices_device_screenshot` shows you what the user sees.
39
+
40
+ `adb`, `xcrun simctl`, and the like remain available for anything `agent-device` does not cover. The private Android SDK is not on `PATH`: its tools are under `<Ycodium home>/plugin-data/devices/environments/android/sdk/platform-tools`.
41
+
42
+ ## Build and install
43
+
44
+ Pick the lightest route that covers the change. JavaScript-only changes need a bundler, not a native rebuild. Native code, native dependencies, and config plugins need a rebuild.
45
+
46
+ ### React Native and Expo
47
+
48
+ Start the bundler on a free port, then make it reachable from the emulator and open the development client:
49
+
50
+ ```sh
51
+ npx expo start --dev-client --lan --port <port>
52
+ adb -s <serial> reverse tcp:<port> tcp:<port>
53
+ adb -s <serial> shell am start -W -a android.intent.action.VIEW \
54
+ -d '<scheme>://expo-development-client/?url=http%3A%2F%2Flocalhost%3A<port>'
55
+ ```
56
+
57
+ Set `REACT_NATIVE_PACKAGER_HOSTNAME=localhost` so the client asks for `localhost`. Build a development APK once with `npx expo prebuild` and `./gradlew :app:assembleDebug -PreactNativeArchitectures=x86_64`, then install it. Only that one ABI is needed for an x86_64 emulator, and building it is much faster.
58
+
59
+ The development client opens a developer menu on first launch. Dismiss it before sending the app a deep link, or the link is dropped without an error. Changing the device font scale recreates the activity and reopens that menu.
60
+
61
+ ### Flutter
62
+
63
+ ```sh
64
+ flutter devices
65
+ flutter run -d <serial>
66
+ ```
67
+
68
+ ### Native Android and iOS
69
+
70
+ ```sh
71
+ ./gradlew :app:assembleDebug # then install app/build/outputs/apk/debug/app-debug.apk
72
+ xcodebuild -scheme <scheme> -sdk iphonesimulator -derivedDataPath build
73
+ ```
74
+
75
+ The Android Emulator reaches the host machine at `10.0.2.2`. The iOS Simulator shares the host's `127.0.0.1`.
76
+
77
+ ## Check the result
78
+
79
+ - Confirm the running code is the code you changed: the bundle came from this project's bundler, or the APK was built after the edit.
80
+ - Exercise the real flow on the device, then read the screen with a snapshot or screenshot. A successful command only means input was delivered.
81
+ - Read logs for failures: `adb -s <serial> logcat -d -t 400`. React Native sends JavaScript logs to the bundler's output rather than to logcat.
82
+ - Report what was not run, such as iOS on a Windows machine.
83
+
84
+ ## Missing tools
85
+
86
+ | Missing | What to do |
87
+ | --------------------------- | -------------------------------------------------------------------------------------------------------------- |
88
+ | Android SDK or emulator | Have the user prepare the environment in the Devices panel |
89
+ | Gradle, NDK, or build-tools | Install with `sdkmanager` into a project-owned SDK. The private Devices SDK holds only what the emulator needs |
90
+ | JDK | Install JDK 17 and set `JAVA_HOME`. The private environment does not include one |
91
+ | Xcode | Tell the user iOS needs Xcode on macOS, and continue on Android if the change allows it |
92
+
93
+ ## Windows path limits
94
+
95
+ Native Android builds fail on Windows when a path reaches 260 characters, which `node_modules` managed by pnpm makes easy. The usual signs are `build.ninja still dirty` and `Stat failed`.
96
+
97
+ - Move CMake output to a short directory, for example through `gradle.beforeProject` in `settings.gradle`, setting `android.externalNativeBuild.cmake.buildStagingDirectory` to a path such as `C:/cx/<project>`.
98
+ - With pnpm, set `virtualStoreDirMaxLength: 40` in `pnpm-workspace.yaml` and reinstall.
99
+ - If Metro crashes with `EMFILE`, limit file concurrency or exclude large directories from its watcher.
100
+ - If Gradle fails a TLS handshake through a local proxy, pass `-Djava.net.useSystemProxies=false` and add download retries.
101
+
102
+ ## When something stalls
103
+
104
+ - If `adb` hangs or the panel says the ADB server did not answer, a target of `adb reverse` may have died. On Windows this stalls the whole adb server until something listens on that port again. Listen on the port briefly, then remove the rule with `adb reverse --remove`.
105
+ - If a phone-sized app runs out of memory, debug React Native builds can use more than 1.5 GB. The private emulator has 2 GB, so a release build is the fair test of memory.
106
+ - If the panel shows no video, read the error in the panel first, then check `adb devices`.
107
+
108
+ ## Finish
109
+
110
+ Remove rules you added with `adb reverse` first, then stop only the bundlers and servers you started. Stopping a server while its rule is still in place can stall adb. Call `devices_device_close` when done, with `shutdown: true` only if the user wants the device off.