diff --git a/server/public/assets/index-DQrF-vew.js b/server/public/assets/index-B9FTYMRe.js similarity index 95% rename from server/public/assets/index-DQrF-vew.js rename to server/public/assets/index-B9FTYMRe.js index 1c35739f..430c85d0 100644 --- a/server/public/assets/index-DQrF-vew.js +++ b/server/public/assets/index-B9FTYMRe.js @@ -14,7 +14,7 @@ Please change the parent to Ae.session?.assignment?.roverId??null),u=n??o,f=oe(Ae=>Ae.session?.mode||null),p=oe(Ae=>Ae.session?.roster??[]),h=oe(Ae=>Ae.session?.users??[]),g=oe(Ae=>Ae.session?.turnQueues??{}),x=oe(Ae=>Ae.session?.socketId||null),v=oe(Ae=>Ae.session?.activeDrivers??{}),b=oe(Ae=>(Ae.session?.socials||[]).find(de=>String(de?.id||de?.label||"").toLowerCase()==="discord")?.url||null||Ae.session?.discord?.invite||null),{state:{lastControlIntentAt:S}}=yt(),C=r||b,[E,N]=m.useState(()=>Date.now()),[w,j]=m.useState(!1),[T,k]=m.useState(null),[M,D]=m.useState(!1),[V,B]=m.useState(0),L=m.useRef({initialized:!1,roverId:null,activeDriverId:null}),Y=m.useRef(S||0),U=a?"text-[0.5rem]":"text-[0.7rem]",X=a?"px-0.5 py-0.25":"px-1 py-0.5",Q=a?"text-3xl":"text-5xl",ce=a?"text-xs":"text-sm",ue=a?"text-[0.55rem]":"text-[0.75rem]",W=a?"px-4 py-3":"px-6 py-4",O=u?g?.[u]:null,I=u?v?.[u]:null,K=!!(x&&I===x),P=m.useMemo(()=>{const Ae=O?.queue||[];if(!Ae.length||!O?.current||Ae.length<=1)return null;const ae=Ae.findIndex(re=>re===O.current);return ae===-1?Ae[0]||null:Ae[(ae+1)%Ae.length]||null},[O?.queue,O?.current]),ie=!!(x&&P===x),R=O?.deadline||null,q=O?.idleDeadline||null,Z=R?R-E:null,le=q?q-E:null,he=f==="turns",we=p.length,pe=m.useMemo(()=>{const Ae=new Set;return h.forEach(ae=>{if(String(ae?.role||"")==="spectator")return;const de=String(ae?.roverId||"").trim(),fe=String(ae?.socketId||"").trim();!de||!fe||Ae.add(fe)}),Ae.size},[h]),xe=he&&pe>we,ge=he&&ie&&Z!=null&&Z<=5e3&&Z>0,Se=he&&!K,be=Se&&!ge&&xe,$e=Z!=null&&Number.isFinite(Z)?Math.max(0,Math.ceil(Z/1e3)):null,Ze=le!=null&&Number.isFinite(le)?Math.max(0,Math.ceil(le/1e3)):null,je=m.useMemo(()=>!he||!K?null:$e!=null?`${$e}s left`:"Your turn",[he,K,$e]),lt=m.useMemo(()=>!Se||!ie||$e==null?null:`${$e} seconds until your turn.`,[Se,ie,$e]),Ie=K&&typeof Ze=="number",ft=M;return m.useEffect(()=>{if(f!=="turns")return;const Ae=setInterval(()=>N(Date.now()),250);return()=>clearInterval(Ae)},[f]),m.useEffect(()=>{if(f!=="turns"){j(!1),k(null),L.current={initialized:!1,roverId:null,activeDriverId:null};return}const Ae=L.current,ae=I||null;if(!x||!u){j(!1),k(null),L.current={initialized:!1,roverId:null,activeDriverId:null};return}if(!Ae.initialized||Ae.roverId!==u){L.current={initialized:!0,roverId:u,activeDriverId:ae};return}!!Ae.activeDriverId&&Ae.activeDriverId!==x&&ae===x?(j(!0),k(Date.now())):ae!==x&&w&&(j(!1),k(null)),L.current={initialized:!0,roverId:u,activeDriverId:ae}},[I,f,u,x,w]),m.useEffect(()=>{!w||!T||S>T&&j(!1)},[S,w,T]),m.useEffect(()=>{const Ae=Number(Y.current)||0,ae=Number(S)||0;ae>Ae&&Se&&B(Date.now()),Y.current=ae},[S,Se]),m.useEffect(()=>{if(!Se||!V)return;D(!0);const Ae=setTimeout(()=>D(!1),650);return()=>clearTimeout(Ae)},[Se,V]),l.jsxs(l.Fragment,{children:[w?l.jsx("div",{className:"pointer-events-none absolute inset-0 z-30 flex items-center justify-center bg-black/55",children:l.jsxs("div",{className:`flex flex-col items-center gap-0.5 rounded border border-amber-300/80 bg-black/70 ${W}`,children:[l.jsx("div",{className:`font-semibold text-amber-200 ${Q}`,children:"IT IS YOUR TURN!"}),l.jsx("div",{className:`text-amber-200/80 ${ce}`,children:"Start driving!"}),Ie?l.jsxs("div",{className:`text-red-100/90 ${ue}`,children:["Idle skip in ",Ze,"s"]}):null]})}):null,je?l.jsx("div",{className:`pointer-events-none absolute bottom-1 left-1 rounded border ${ft?"border-red-300/90 bg-red-900/80 text-red-100":"border-amber-300/80 bg-black/75 text-amber-200"} ${X} ${U}`,children:je}):null,Se?l.jsx("div",{className:"pointer-events-none absolute bottom-1 left-1 z-40",children:l.jsxs("div",{className:`w-fit rounded border ${M?"border-red-300/90 bg-red-900/80 text-red-100":"border-amber-300/80 bg-black/75 text-amber-200"} ${a?"px-2 py-1 text-[0.6rem]":"px-3 py-1.5 text-sm"}`,children:[l.jsx("div",{className:M?"text-[0.82rem] font-semibold text-red-50":"text-[0.82rem] font-semibold text-white",children:"Not your turn to drive!"}),lt?l.jsx("div",{className:M?"text-red-100/95":"text-amber-100",children:lt}):null,be?l.jsx("div",{className:M?"text-red-100/90":"text-amber-200/85",children:"Video switched to preview mode to save bandwidth."}):null,l.jsx("div",{className:"pointer-events-auto mt-0.5",children:l.jsx(wo,{id:"discord",label:"Join our Discord while you wait!",url:C})})]})}):null]})}const iw=Dt.memo(rw);function $g(){const{value:n,save:a}=Ve("page",{hudMapDesktop:!1});return[!!n?.hudMapDesktop,u=>{a({hudMapDesktop:!!u})}]}function cx({variant:n="default",label:a,roverColor:r=null,driverLabel:o=null,mobileHud:u=!1,labelScale:f=1}){const p=u?"px-0.25 py-0.25":"px-0.5 py-0.5",h=u?"text-[0.55rem]":"text-[0.8rem]",g="bottom-0.5",x={transform:`translateX(-50%) scale(${f})`,transformOrigin:"center bottom"};return n==="spectator"?l.jsx("div",{className:`absolute ${g} left-1/2`,style:x,children:l.jsxs("div",{className:`flex items-center gap-0.5 bg-black/80 text-slate-100 ${p} ${h}`,children:[l.jsx("span",{className:"font-semibold text-white rounded px-1 py-[1px] border border-transparent",style:ns(r,.18),children:a||"No rover"}),o?l.jsxs("span",{className:"text-slate-300",children:["• ",o]}):null]})}):l.jsx("div",{className:`absolute ${g} left-1/2`,style:x,children:l.jsx("div",{className:`flex gap-0.5 bg-black/80 text-slate-100 ${p} ${h}`,children:l.jsxs("span",{children:["Rover:"," ",l.jsxs("span",{className:"rounded px-1 py-[1px] border border-transparent",style:ns(r,.18),children:['"',a||"No rover",'"']})]})})})}function ow({sensors:n,mobileHud:a=!1}){const r=a?"px-0.25 py-0.25":"px-1 py-0.5",o=a?"left-0.5 top-1/2":"left-1 top-1/2",u=a?"text-[0.45rem]":"text-[0.65rem]",f=[["Voltage",n?.voltageMv!=null?`${(n.voltageMv/1e3).toFixed(2)} V`:"--"],["Current",n?.currentMa!=null?`${n.currentMa} mA`:"--"],["Charge",n?.batteryChargeMah!=null?`${n.batteryChargeMah}`:"--"],["OI",n?.oiMode?.label||"--"]],p=!!n?.chargingSources?.homeBase,h=n?.chargingState?.label||"",g=!!(h&&h.toLowerCase()!=="not charging"),x=n?.oiMode?.label||"Unknown",v=x.toLowerCase(),b=v==="full"?"bg-emerald-500/80 text-emerald-50":v==="safe"?"bg-amber-400/80 text-amber-950":v==="passive"?"bg-slate-700/80 text-slate-100":"bg-slate-700/60 text-slate-200",S=p?"bg-emerald-500/80 text-emerald-50":"bg-slate-700/70 text-slate-200",C=g?"bg-emerald-500/80 text-emerald-50":p?"bg-amber-400/80 text-amber-950":"bg-slate-700/70 text-slate-200";return l.jsx("div",{className:`absolute ${o} flex -translate-y-1/2 flex-col gap-0.5 bg-black/70 text-slate-100 ${u} ${r}`,children:l.jsxs("div",{className:"space-y-0.5 leading-tight",children:[l.jsxs("div",{className:"flex flex-col gap-0.5 text-[0.75rem] font-semibold uppercase tracking-wide",children:[l.jsx("span",{className:`rounded px-1.5 py-0.5 ${S}`,children:p?"Docked":"Undocked"}),l.jsx("span",{className:`rounded px-1.5 py-0.5 ${C}`,children:g?"Charging":"Not charging"}),l.jsxs("span",{className:`rounded px-1.5 py-0.5 ${b}`,children:["OI: ",x]})]}),f.map(([E,N])=>l.jsxs("span",{className:"flex items-center justify-between gap-0.5",children:[l.jsx("span",{className:"text-slate-400",children:E}),l.jsx("span",{className:"font-semibold text-white",children:N})]},E))]})})}function Ao(n){return Math.max(0,Math.min(1,n))}function Gg(n){return(n-90)*Math.PI/180}function or(n,a,r,o){const u=Gg(o);return{x:n+r*Math.cos(u),y:a+r*Math.sin(u)}}function cw(n,a,r,o,u){let f=o,p=u;p<=f&&(p+=360);const h=or(n,a,r,f),g=or(n,a,r,p);return["M",h.x,h.y,"A",r,r,0,0,1,g.x,g.y].join(" ")}function df(n,a){if(a)return"#ef4444";const r=Math.abs(n);return r>900?"#f59e0b":r>300?"#22c55e":"#64748b"}function uw(n,a){if(n==null||n<=0)return"hsl(200 60% 18%)";const o=Ao(n/(a||1));return`hsl(${(200+Math.pow(o,.45)*360)%360} 100% 60%)`}function dw(n,a){if(a)return"#ef4444";const r=Ao(n==null?0:n/4095),o=[47,55,69],u=[245,158,11],[f,p,h]=o.map((g,x)=>Math.round(g+(u[x]-g)*r));return`rgb(${f}, ${p}, ${h})`}function fw({count:n,totalSpan:a,gap:r,startAngle:o}){const f=(a-r*(n-1))/n,p=[];let h=o;for(let g=0;g0?.65:null;return l.jsxs("g",{style:{transformOrigin:`${n}px ${a}px`,animation:h?`spin ${h}s linear infinite`:"none",animationDirection:h?"reverse":"normal"},children:[l.jsx("circle",{cx:n,cy:a,r:10,fill:"#64748b",stroke:"#64748b",strokeWidth:"1"}),[0,120,240].map(x=>{const v=Gg(x),b=n+p*Math.cos(v),S=a+p*Math.sin(v);return l.jsx("line",{x1:n,y1:a,x2:b,y2:S,stroke:f,strokeWidth:"4",strokeLinecap:"round"},x)}),o?l.jsx("circle",{cx:n,cy:a,r:p+8,stroke:"#ef4444",strokeWidth:"3",fill:"none",className:"animate-pulse"}):null]})}function pw({cx:n,cy:a,current:r,overcurrent:o,variant:u,dirtLeft:f,dirtRight:p}){const h=Math.abs(r),g=df(r,o),x=1,v=96,b=12,S=`main-brush-pattern-a-${u}`,C=`main-brush-pattern-b-${u}`,E=h>0?.6:null,N=r>=0?1:-1;return l.jsxs("g",{children:[l.jsx("defs",{children:[S,C].map((w,j)=>l.jsxs("pattern",{id:w,patternUnits:"userSpaceOnUse",width:"6",height:"6",children:[l.jsx("rect",{width:"6",height:"6",fill:g,opacity:x}),l.jsx("path",{d:"M0 6 L6 0",stroke:"#0f172a",strokeWidth:"1"}),E?l.jsx("animateTransform",{attributeName:"patternTransform",type:"translate",from:"0 0",to:`0 ${N*(j===0?6:-6)}`,dur:`${E}s`,repeatCount:"indefinite"}):null]},w))}),l.jsx("rect",{x:n-v/2,y:a-14,width:v,height:b,rx:"3",fill:`url(#${S})`,stroke:"#64748b",strokeWidth:"1"}),l.jsx("rect",{x:n-v/2,y:a+4,width:v,height:b,rx:"3",fill:`url(#${C})`,stroke:"#64748b",strokeWidth:"1"}),l.jsx("circle",{cx:n-v/4,cy:a-8,r:3.5,fill:"#fbbf24"}),l.jsx("circle",{cx:n+v/4,cy:a+8,r:3.5,fill:"#fbbf24"}),o?l.jsx("rect",{x:n-v/2-4,y:a-16,width:v+8,height:b*2+16,rx:"6",stroke:"#ef4444",strokeWidth:"3",fill:"none",className:"animate-pulse"}):null]})}function xw({sensors:n={},variant:a="full",size:r,overlay:o=!1}){const u=r||(a==="mini"?190:260),f=u/2,p=u*.07,h=f,g=f+p,x=f*.8,v=x-4,b=x+4,S=x-14,C=x-6,E=x*.65,N=n?.bumpsAndWheelDrops||{},w=n?.wheelOvercurrents||{},j=n?.wheelLeftCurrentMa??0,T=n?.wheelRightCurrentMa??0,k=n?.sideBrushCurrentMa??0,M=n?.mainBrushCurrentMa??0,D=6,V=N.bumpLeft?D:0,B=N.bumpRight?D:0,L=fw({count:6,totalSpan:140,gap:6,startAngle:-70}),Y=["L","FL","CL","CR","FR","R"],U=[n?.lightBumpLeftSignal,n?.lightBumpFrontLeftSignal,n?.lightBumpCenterLeftSignal,n?.lightBumpCenterRightSignal,n?.lightBumpFrontRightSignal,n?.lightBumpRightSignal],X=L.map((W,O)=>({label:Y[O],start:W.start,end:W.end,value:U[O]})),Q=[{label:"Cliff L",start:-60,end:-46,value:n?.cliffLeftSignal,active:n?.cliffLeft},{label:"Cliff FL",start:-32,end:-16,value:n?.cliffFrontLeftSignal,active:n?.cliffFrontLeft},{label:"Cliff FR",start:16,end:32,value:n?.cliffFrontRightSignal,active:n?.cliffFrontRight},{label:"Cliff R",start:46,end:60,value:n?.cliffRightSignal,active:n?.cliffRight}],ce=U.filter(W=>W!=null),ue=ce.length?Math.max(...ce,1200):1200;return l.jsxs("div",{className:`${o?"relative":"surface relative p-1"}`,style:o?{width:`${u}px`,height:`${u}px`}:{height:"100%",width:"100%",aspectRatio:"1 / 1"},children:[o?null:l.jsxs(l.Fragment,{children:[l.jsx("div",{className:"absolute left-1 top-1 text-xs text-slate-400",children:"Top-down"}),l.jsxs("div",{className:"absolute right-1 top-1 text-[0.65rem] text-slate-500",children:["0–",ue]})]}),l.jsxs("svg",{width:"100%",height:"100%",viewBox:`0 0 ${u} ${u}`,preserveAspectRatio:"xMidYMid meet",className:"mx-auto block",children:[l.jsx("circle",{cx:h,cy:g,r:x,fill:"#0f172a",stroke:"#334155",strokeWidth:"2"}),l.jsx(ux,{cx:h-E,cy:g,current:j,drop:N.wheelDropLeft,overcurrent:w.leftWheel,label:"L"}),l.jsx(ux,{cx:h+E,cy:g,current:T,drop:N.wheelDropRight,overcurrent:w.rightWheel,label:"R"}),l.jsx(hw,{cx:h+x*.65,cy:g-x*.55,current:k,overcurrent:w.sideBrush}),l.jsx(pw,{cx:h,cy:g,current:M,overcurrent:w.mainBrush,variant:a,dirtLeft:n?.dirtDetectLeft,dirtRight:n?.dirtDetect}),X.map(W=>{const O=uw(W.value,ue),I=b+4,K=I+28;return l.jsx(mw,{cx:h,cy:g,rBase:K,rTip:I,startDeg:W.start,endDeg:W.end,color:O,value:W.value,max:ue},W.label)}),Q.map(W=>l.jsx(xd,{cx:h,cy:g,rInner:S,rOuter:C,startDeg:W.start,endDeg:W.end,color:dw(W.value,W.active),opacity:1,pulse:!!W.active},W.label)),l.jsx(xd,{cx:h,cy:g,rInner:v-V,rOuter:b-V,startDeg:-70,endDeg:-6,color:N.bumpLeft?"#ef4444":"#475569",opacity:1,pulse:!!N.bumpLeft}),l.jsx(xd,{cx:h,cy:g,rInner:v-B,rOuter:b-B,startDeg:6,endDeg:70,color:N.bumpRight?"#ef4444":"#475569",opacity:1,pulse:!!N.bumpRight})]})]})}const Yg=Dt.memo(xw);function dx({sensors:n,show:a=!0,mapPosition:r="top-center",layoutFormat:o="desktop",mobileHud:u=!1}){if(!a)return null;const f=o==="mobile-portrait",p="240px",h=f?.3:u?.33:.7,x={width:p,height:p,opacity:u?.6:.7,transform:r==="top-center"?`translateX(-50%) scale(${h})`:`scale(${h})`,transformOrigin:r==="bottom-left"?"bottom left":r==="top-center"?"top center":"top right",...r==="bottom-left"?{left:"0.25rem",bottom:"0.25rem"}:r==="top-center"?{left:"50%",top:"0.25rem"}:{right:"0.25rem",top:"0.25rem"}};return l.jsx("div",{className:"pointer-events-none absolute rounded",style:x,children:l.jsx(Yg,{sensors:n,size:240,overlay:!0})})}function gw({roverId:n=null,sensors:a,label:r,roverColor:o=null,layoutFormat:u="desktop",variant:f="default",driverLabel:p=null,showTopDown:h=void 0,mobileHud:g=!1,mapPosition:x=null,labelScale:v=1}){const b=oe(L=>L.session?.assignment?.roverId??null),S=n??b,C=Wt(S),E=oe(L=>{if(!S)return{label:null,roverColor:null};const U=(L.session?.roster||[]).find(X=>String(X.id)===String(S));return{label:U?.name||null,roverColor:U?.color||null}}),N=oe(L=>{if(!S||f!=="spectator")return null;const Y=L.session?.activeDrivers?.[S]||null,X=(L.session?.users||[]).find(Q=>String(Q.socketId||"")===String(Y||""));return X?.nickname||X?.name||null}),w=a??C?.sensors??null,j=r??E.label??null,T=o??E.roverColor??null,k=p??N,M=g,[D]=$g(),V=typeof h=="boolean"?h:f==="spectator"||M?!0:D,B=x||(f==="spectator"?"top-center":M?"top-right":"top-center");return f==="none"?null:f==="spectator"?l.jsxs(l.Fragment,{children:[l.jsxs("div",{className:"pointer-events-none absolute inset-0 flex items-center justify-center",children:[l.jsx(ow,{sensors:w,mobileHud:M}),l.jsx(cx,{variant:"spectator",label:j,roverColor:T,driverLabel:k,mobileHud:M,labelScale:v})]}),l.jsx(dx,{sensors:w,show:V,mapPosition:B,layoutFormat:u,mobileHud:M})]}):l.jsxs("div",{className:"pointer-events-none absolute inset-0 flex items-center justify-center",children:[l.jsx(cx,{variant:"default",label:j,roverColor:T,mobileHud:M,labelScale:v}),l.jsx(dx,{sensors:w,show:V&&f!=="spectator",mapPosition:B,layoutFormat:u,mobileHud:M})]})}const Fg=Dt.memo(gw);function vw({mobileHud:n=!1}){const{visible:a,statusLabel:r,statusTone:o,active:u,charging:f}=al({manageLifecycle:!0}),[p,h]=m.useState(""),g=m.useRef(null),x=m.useRef(u);if(m.useEffect(()=>{const b=x.current;u&&!b?h("Dock assist mode enabled"):!u&&b&&f&&h("Docking successful! Thank you!"),x.current=u},[u,f]),m.useEffect(()=>{if(p)return g.current&&clearTimeout(g.current),g.current=setTimeout(()=>{h(""),g.current=null},2500),()=>{g.current&&(clearTimeout(g.current),g.current=null)}},[p]),!a)return null;const v=o==="good"?"border-emerald-200/85 bg-emerald-900/96 text-emerald-50":o==="warn"?"border-amber-200/85 bg-amber-900/96 text-amber-50":"border-indigo-200/85 bg-indigo-900/96 text-indigo-50";return l.jsx("div",{className:"pointer-events-none absolute inset-0",children:p?l.jsx("div",{className:"absolute inset-0 flex items-center justify-center",children:l.jsx("div",{className:`rounded-xl border border-indigo-200/95 bg-black/92 px-4 py-2 text-center font-semibold text-indigo-50 shadow-2xl ${n?"text-lg":"text-2xl"}`,children:p})}):l.jsx("div",{className:`absolute right-2 top-1/2 -translate-y-1/2 rounded-lg border bg-black/88 px-2 py-1 font-semibold shadow-lg ${v} ${n?"text-[0.65rem]":"text-xs"}`,children:r})})}const bw=Dt.memo(vw),fx=5e3,yw=700;function Ig({roverId:n=null,description:a,variant:r="default",mobileHud:o=!1,displayKey:u="",controlIntentAt:f}){const p=oe(T=>T.session?.assignment?.roverId??null),h=n??p,g=oe(T=>h&&(T.session?.roster||[]).find(D=>String(D.id)===String(h))?.description||null),x=a??g,v=typeof f=="number"?f:0,b=u||`${h||""}::${x||""}`,[S,C]=m.useState(!1),[E,N]=m.useState(!1),w=m.useRef(null),j=m.useRef(null);return m.useEffect(()=>()=>{clearTimeout(w.current),clearTimeout(j.current)},[]),m.useEffect(()=>{if(r!=="default"||!x){C(!1),N(!1),clearTimeout(w.current),clearTimeout(j.current);return}clearTimeout(w.current),clearTimeout(j.current),C(!0),N(!1)},[x,b,r]),m.useEffect(()=>{r!=="default"||!x||!S||E||(Number(v)||0)<=0||w.current||j.current||(w.current=setTimeout(()=>{N(!0),w.current=null},fx),j.current=setTimeout(()=>{C(!1),j.current=null},fx+yw))},[v,x,E,S,r]),x?r==="spectator"?l.jsx("div",{className:"pointer-events-none absolute inset-x-0 top-1 z-50 flex justify-center",children:l.jsx("div",{className:"surface max-w-[92%] border border-slate-600/80 px-1 py-0.5 text-center text-[0.62rem] leading-tight text-slate-100 shadow-lg",children:x})}):r!=="default"||!S?null:l.jsx("div",{className:"pointer-events-none absolute inset-0 z-50 flex items-center justify-center",children:l.jsxs("div",{className:`surface max-w-[94%] border border-slate-400 bg-neutral-900 px-2 py-1 text-center font-semibold text-slate-100 shadow-xl transition-opacity duration-700 ${E?"opacity-0":"opacity-100"} ${o?"text-[1rem] leading-tight":"text-[1.5rem] leading-tight"}`,children:[l.jsx("p",{children:"Just so you know, this rover"}),l.jsx("p",{children:x}),l.jsx("p",{className:`${o?"text-[0.58rem]":"text-[0.72rem]"} mt-0.5 font-normal text-slate-300`,children:"This fades 5 seconds after your first control input."})]})}):null}const Sw={leftWheel:"Left wheel",rightWheel:"Right wheel",mainBrush:"Main brush",sideBrush:"Side brush",limiter:"Overcurrent limit"};function jw({roverId:n=null,sensors:a,overcurrentLimiter:r=null,compact:o=!1}){const u=oe(L=>L.session?.assignment?.roverId??null),f=n??u,p=Wt(f),h=jg(f),g=a??p?.sensors??null,x=r??h??null,v=g?.wheelOvercurrents||null,b=m.useMemo(()=>v==null?[]:Object.entries(v).filter(([,L])=>!!L).map(([L])=>L),[v]),S=x?.caps||null,C=m.useMemo(()=>{if(!S)return null;const L=Number.isFinite(S?.drive?.cap)?S.drive.cap:1,Y=Number.isFinite(S?.aux?.cap)?S.aux.cap:1;return Math.max(0,Math.min(1,1-Math.min(L,Y)))},[S]),E=!!x?.isActive,N=m.useMemo(()=>b.length?b:E?["limiter"]:[],[b,E]),w=C??(b.length?1:0);if(!N?.length)return null;const j=N.map(L=>Sw[L]||L),T=o?"w-[12rem] h-[3.5rem]":"w-[20rem] h-[7rem]",k=o?"px-2 py-1":"px-4 py-2",M=o?"text-lg":"text-4xl",D=o?"text-xs":"text-xl",V=Math.max(0,Math.min(1,w)),B=`${Math.round(V*100)}%`;return l.jsx("div",{className:`pointer-events-none absolute flex items-center justify-center bg-red-900/50 top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 ${T}`,children:l.jsxs("div",{className:"relative h-full w-full",children:[l.jsx("div",{className:"absolute inset-0 overflow-hidden",children:l.jsx("div",{className:"h-full bg-red-700/60",style:{width:B}})}),l.jsxs("div",{className:`relative z-10 flex h-full w-full flex-col items-center justify-center text-center font-semibold text-white animate-pulse ${M} ${k}`,children:[l.jsx("div",{children:"OVERCURRENT"}),l.jsx("div",{className:`mt-0 font-medium text-white ${D}`,children:j.join(", ")})]})]})})}const Xg=Dt.memo(jw),mr=10;function Co({batteryState:n=null,charge:a=null,config:r=null}){const o=n?.percentDisplay!=null&&Number.isFinite(n.percentDisplay)?Math.round(n.percentDisplay):null,u=n?.warnActive??null,f=n?.urgentActive??null,p=r?.Full??null,h=r?.Warn??null,g=r?.Urgent??null,x=a??n?.charge??null;let v=o;if(v==null&&(v=Nw({charge:x,full:p,warn:h,urgent:g})),v==null)return{available:!1};const b=Math.max(0,Math.min(1,v/100)),S=u??(h!=null&&x!=null&&x<=h),C=f??(g!=null&&x!=null&&x<=g);return{available:!0,percent:b,percentDisplay:v,warnActive:S,urgentActive:C,warnDisplayPercent:mr}}function Nw({charge:n,full:a,warn:r,urgent:o}){if(n!=null&&a!=null&&r!=null&&o!=null&&a>r&&r>o){const u=mr/100,f=1-u;if(n<=o)return 0;if(n<=r){const h=(n-o)/(r-o);return Math.round(Math.max(0,Math.min(1,h))*mr)}if(n>=a)return 100;const p=(n-r)/(a-r);return Math.round((u+Math.max(0,Math.min(1,p))*f)*100)}return null}function ww({roverId:n=null,sensors:a,batteryConfig:r,compact:o=!1}){const u=oe(E=>E.session?.assignment?.roverId??null),f=n??u,p=Wt(f),h=oe(E=>f?(E.session?.roster||[]).find(j=>String(j.id)===String(f))?.battery??null:null),g=a??p?.sensors??null,x=r??h,v=Co({charge:g?.batteryChargeMah??null,config:x});if(!v?.available||!v.warnActive&&!v.urgentActive)return null;const b=v.urgentActive?"BATTERY VERY LOW, DOCK THE ROVER AND CHARGE IMMEDIATELY!!":"Battery low! please dock and charge the rover soon.",S=o?"p-2 top-6":"p-4 top-10",C=o?"text-sm":"text-2xl";return l.jsx("div",{className:`pointer-events-none absolute flex items-center justify-center bg-amber-900/60 left-1/2 -translate-x-1/2 ${S}`,children:l.jsx("div",{className:`text-center font-semibold text-white animate-pulse ${C}`,children:l.jsx("div",{children:b})})})}const Qg=Dt.memo(ww);function Aw({roverId:n=null,sensors:a}){const r=oe(S=>S.session?.assignment?.roverId??null),u=Wt(n??r),f=a??u?.sensors??null,p=[f?.lightBumpLeftSignal,f?.lightBumpFrontLeftSignal,f?.lightBumpCenterLeftSignal,f?.lightBumpCenterRightSignal,f?.lightBumpFrontRightSignal,f?.lightBumpRightSignal],h=p.filter(S=>S!=null).reduce((S,C)=>Math.max(S,C),1200),g=S=>Math.pow(Math.max(0,Math.min(1,(S??0)/h)),.35),x=S=>S==null||S<=0?"hsl(200 60% 18%)":`hsl(${(200+g(S)*360)%360} 100% 60%)`,v=6,b=12;return l.jsx("div",{className:"flex w-full items-center justify-center gap-0.5",children:p.map((S,C)=>{const E=g(S),N=Cg.session?.assignment?.roverId??null),o=n??r,f=Wt(o)?.sensors??null,p=oe(g=>o?(g.session?.roster||[]).find(b=>String(b.id)===String(o))?.battery??null:null),h=Co({charge:f?.batteryChargeMah??null,config:p});return l.jsxs("div",{className:"space-y-0.5",children:[l.jsx(Cw,{roverId:o}),l.jsx("div",{className:"panel-section space-y-0.5 text-sm",children:l.jsx(ff,{visual:h,compact:a})})]})}function Tw({compact:n=!1}){const a=oe(L=>L.session?.role||null),r=oe(L=>L.session?.assignment?.roverId||null),o=oe(L=>L.session?.roster||[]),{sendMessage:u,onInputFocus:f,onInputBlur:p,blurChat:h,registerInputRef:g,setTypingActive:x}=lf(),{value:v}=Ve("tts",{engine:"flite",voice:"rms",pitch:50}),[b,S]=m.useState(""),[C,E]=m.useState(!1),N=a!=="spectator",w=a==="spectator",T=!!m.useMemo(()=>o.find(L=>String(L.id)===String(r))||null,[r,o])?.audio?.ttsEnabled,k=m.useMemo(()=>{if(!T)return null;const L=v?.engine==="espeak"?"espeak":"flite";if(L==="espeak"){let U=Number.isFinite(v?.pitch)?Math.round(v.pitch):void 0;return typeof U=="number"&&(U=Math.max(0,Math.min(99,U))),{speak:!0,engine:L,pitch:U}}const Y=typeof v?.voice=="string"?v.voice:void 0;return{speak:!0,engine:L,voice:Y}},[v?.engine,v?.pitch,v?.voice,T]),M=n?"pointer-events-auto absolute bottom-0.5 right-0.5 flex w-[9rem] max-w-[70vw] items-center gap-0.5 rounded bg-black/70 px-0.4 py-0.2":"pointer-events-auto absolute bottom-1 right-1 flex w-[12rem] max-w-[70vw] items-center gap-0.5 rounded bg-black/70 px-0.5 py-0.25",D=n?"min-w-0 flex-1 bg-transparent text-[0.55rem] text-slate-100 placeholder:text-slate-400 focus:outline-none":"min-w-0 flex-1 bg-transparent text-[0.7rem] text-slate-100 placeholder:text-slate-400 focus:outline-none",V=n?"rounded bg-cyan-500/80 px-0.35 py-0.2 text-[0.55rem] font-semibold text-black disabled:opacity-50":"rounded bg-cyan-500/80 px-0.5 py-0.25 text-[0.7rem] font-semibold text-black disabled:opacity-50";async function B(L){if(L.preventDefault(),!N)return;const Y=b.trim();if(Y){E(!0);try{await u(Y,k),S(""),h(),x(!1)}catch(U){alert(U.message)}finally{E(!1)}}}return w?null:l.jsxs("form",{onSubmit:B,className:M,children:[l.jsx("input",{className:D,value:b,onChange:L=>{const Y=L.target.value;S(Y),x(!!Y.trim())},onFocus:L=>{f(L),x(!!b.trim())},onBlur:L=>{p(L),x(!1)},onKeyDown:L=>{L.key==="Enter"&&!b.trim()&&(L.preventDefault(),h(),x(!1))},ref:L=>g(L,{target:"hud"}),placeholder:N?"Chat (TTS)":"Spectator",disabled:!N}),l.jsx("button",{type:"submit",disabled:!N||C,className:V,children:"Speak"})]})}const qw=m.memo(Tw);function mf({layoutFormat:n="desktop"}){const a=oe(f=>f.session?.assignment?.roverId??null),r=tw(a),{state:{lastControlIntentAt:o}}=yt();if(!a)return l.jsx("section",{className:"panel",children:l.jsxs("div",{className:"panel-muted content-center text-center text-sm text-slate-400 aspect-[4/3]",children:[l.jsx("p",{children:"You are not assigned to a rover."}),l.jsx("p",{className:"mt-0",children:l.jsx("a",{href:"/spectate",className:"text-blue-400 underline hover:text-blue-500",children:"Click here to visit the spectator page."})})]})});const u=n!=="desktop";return l.jsx("section",{className:"panel",children:l.jsxs("div",{className:"flex flex-col gap-0.5",children:[l.jsxs("div",{className:"relative w-full overflow-hidden bg-black aspect-[4/3]",children:[l.jsx(fr,{roverId:a,videoMode:r}),l.jsx(iw,{mobileHud:u}),l.jsx(Ig,{variant:"default",mobileHud:u,controlIntentAt:o}),l.jsx(Fg,{layoutFormat:n,variant:"default",mobileHud:u,labelScale:1}),l.jsx(bw,{mobileHud:u}),l.jsx(qw,{compact:u}),l.jsx(Xg,{compact:u}),l.jsx(Qg,{compact:u})]}),l.jsx(Rw,{mobileHud:u})]})})}function xo({label:n,tone:a="muted"}){const r=a==="success"?"bg-emerald-900 text-emerald-100":a==="warn"?"bg-amber-900 text-amber-100":"bg-slate-800 text-slate-200";return l.jsx("span",{className:`rounded px-1 py-0.5 text-xs font-semibold leading-none ${r}`,children:n})}function ko(n){if(!Number.isFinite(n))return 0;const a=n%360;return a<0?a+360:a}function Dw(n){if(!Array.isArray(n)||n.length<3)return 0;const[a,r,o]=n,u=Math.max(0,Math.min(255,Number(a)))/255,f=Math.max(0,Math.min(255,Number(r)))/255,p=Math.max(0,Math.min(255,Number(o)))/255,h=Math.max(u,f,p),g=Math.min(u,f,p),x=h-g;if(x===0)return 0;let v=0;return h===u?v=(f-p)/x%6:h===f?v=(p-u)/x+2:v=(u-f)/x+4,ko(Math.round(v*60))}function mx(n){const a=ko(n),r=1,o=1-Math.abs(a/60%2-1);let u=0,f=0,p=0;return a<60?(u=r,f=o):a<120?(u=o,f=r):a<180?(f=r,p=o):a<240?(f=o,p=r):a<300?(u=o,p=r):(u=r,p=o),[Math.round(u*255),Math.round(f*255),Math.round(p*255)]}function hx(n){return n?Array.isArray(n.hsColor)?ko(Number(n.hsColor[0])):Array.isArray(n.rgbColor)?Dw(n.rgbColor):0:0}function _w({entity:n,connected:a,controlsLocked:r,onToggle:o,onSetColor:u,onSetWhite:f}){const p=n.state==="unavailable"||!n.available,h=n.state==="on",g=n.type==="light"&&n.supportsColor,x=p?"warn":h?"success":"muted",v=p?"Unavailable":h?"On":"Off",b=r||!a||p,S=b||!g,[C,E]=m.useState(()=>hx(n)),N=m.useRef(C),w=m.useRef(!1),j=p?"border-slate-800 bg-slate-900 text-slate-400 cursor-not-allowed":r?"border-slate-800 bg-slate-900 text-slate-300 cursor-not-allowed":h?"border-emerald-700 bg-emerald-900/80 text-emerald-50 hover:bg-emerald-800":"border-rose-800 bg-rose-900/80 text-rose-50 hover:bg-rose-800";m.useEffect(()=>{if(!g||w.current)return;const L=hx(n);N.current=L,E(L)},[n.rgbColor,n.hsColor,g]);const T=L=>{const Y=ko(Number(L.target.value));N.current=Y,E(Y)},k=()=>{S||!u||u(n.id,mx(N.current))},M=L=>{L.stopPropagation()},D=L=>{M(L),!(S||!f)&&f(n.id)},B=`rgb(${(g?mx(N.current):[255,255,255]).join(",")})`;return l.jsxs("button",{type:"button",onClick:()=>o(n.id),disabled:b,className:`relative flex min-w-[12rem] flex-[1_1_12rem] items-start justify-between gap-0.5 rounded px-1 py-0.5 text-left transition-colors ${j} disabled:opacity-60 disabled:hover:bg-inherit`,children:[l.jsxs("div",{className:"min-w-0 flex-1",children:[l.jsxs("div",{className:"flex items-center gap-0.5 text-sm leading-normal",children:[l.jsx("span",{className:"truncate font-semibold text-white",children:n.name||n.id}),g&&l.jsxs(l.Fragment,{children:[l.jsx(xo,{label:v,tone:x}),!a&&l.jsx("span",{className:"text-xs text-amber-200",children:"Offline"})]})]}),g?l.jsx("div",{className:"-mt-0.5 w-full",onClick:M,onPointerDown:L=>{M(L),w.current=!0},onPointerUp:L=>{M(L),w.current=!1,k()},onPointerCancel:L=>{M(L),w.current=!1,k()},onKeyUp:L=>{M(L),k()},onBlur:k,children:l.jsx("div",{className:"relative w-full",children:l.jsx("input",{type:"range",min:"0",max:"360",step:"1",value:C,onChange:T,disabled:S,"aria-label":`Set color for ${n.name||n.id}`,className:"ha-hue-slider w-full"})})}):l.jsxs("div",{className:"flex items-center gap-0.5 text-xs text-slate-400",children:[l.jsx(xo,{label:v,tone:x}),!a&&l.jsx("span",{className:"text-amber-200",children:" · Offline"})]})]}),g&&l.jsxs("div",{className:"absolute right-1 top-1 flex items-center gap-0.5",children:[l.jsx("span",{role:"button",tabIndex:S?-1:0,onClick:D,onPointerDown:M,onKeyDown:L=>{S||(L.key==="Enter"||L.key===" ")&&(L.preventDefault(),D(L))},title:"Set white color temperature","aria-label":`Set ${n.name||n.id} to white`,"aria-disabled":S,className:`inline-flex items-center justify-center rounded border border-slate-200 bg-white px-1 py-0.5 text-xs font-semibold leading-none text-slate-900 ${S?"cursor-not-allowed opacity-60":"cursor-pointer hover:bg-slate-100"}`,children:"white"}),l.jsx("span",{className:"pointer-events-none h-2.5 w-2.5 rounded-full border border-white/60",style:{backgroundColor:B}})]}),!g&&l.jsx("div",{className:"self-center text-xs font-semibold text-white/90",children:h?"Turn off":"Turn on"})]})}function Kg(){const{state:{keymap:n}}=yt(),a=oe(S=>S.session?.homeAssistant||null),{homeAssistantToggle:r,homeAssistantSetLightColor:o,homeAssistantSetLightWhite:u}=$t(),f=m.useMemo(()=>a?.entities||[],[a?.entities]),p=a?.lightPolicy||null,h=!!(p?.locked||p?.lockedOn),g=p?.lockState||(p?.lockedOn?"on":null),x=Tt(n?.homeAssistantOn?.[0]),v=Tt(n?.homeAssistantOff?.[0]);if(!a?.enabled)return l.jsxs("section",{className:"panel-section space-y-0.5 text-sm text-slate-400",children:[l.jsx("p",{className:"text-slate-300",children:"Room Controls"}),l.jsx("p",{className:"text-slate-500",children:"Not configured on the server."})]});if(f.length===0)return l.jsxs("section",{className:"panel-section space-y-0.5 text-sm text-slate-400",children:[l.jsx("p",{className:"text-slate-300",children:"Room Controls"}),l.jsx("p",{className:"text-slate-500",children:"No lights or switches configured."})]});const b=!!a?.connected;return l.jsxs("section",{className:"panel-section space-y-0.5 text-base",children:[l.jsxs("header",{className:"flex items-center justify-between gap-0.5 text-sm text-slate-400",children:[l.jsxs("div",{className:"flex items-center gap-0.5",children:[l.jsx("p",{children:"Room Controls"}),l.jsx("span",{className:"text-xs text-slate-500",children:f.length}),h?l.jsx(xo,{label:g==="off"?"Locked Off":"Locked On",tone:"warn"}):null,l.jsxs("div",{className:"flex items-center gap-0.5 text-xs text-slate-300 background-black",children:[l.jsxs("span",{className:"flex items-center gap-0.5",children:[l.jsx("span",{children:"On"}),x?l.jsx(px,{label:x}):null]}),l.jsxs("span",{className:"flex items-center gap-0.5",children:[l.jsx("span",{children:"Off"}),v?l.jsx(px,{label:v}):null]})]})]}),l.jsx(xo,{label:b?"Connected":"Offline",tone:b?"success":"warn"})]}),h?l.jsx("p",{className:"rounded border border-amber-600/60 bg-amber-900/40 px-1 py-0.5 text-xs text-amber-100",children:g==="off"?"Lights are locked off. Room controls are disabled.":"Lights are locked on. Room controls are disabled."}):null,l.jsx("div",{className:"flex flex-wrap gap-0.5",children:f.map(S=>l.jsx(_w,{entity:S,connected:b,controlsLocked:h,onToggle:r,onSetColor:o,onSetWhite:u},S.id))})]})}function px({label:n}){return n?l.jsx("span",{className:"rounded border border-white/40 px-1 text-[0.7rem] text-white",children:n}):null}function Zg(){const{login:n,setRole:a}=$t(),[r,o]=m.useState(""),[u,f]=m.useState(""),[p,h]=m.useState(!1);async function g(x){x.preventDefault(),h(!0);try{await n(r,u),o(""),f("")}catch(v){alert(v.message)}finally{h(!1)}}return l.jsxs("div",{className:"panel-section space-y-0.5 text-base",children:[l.jsx("p",{className:"text-sm text-slate-400",children:"Admin login"}),l.jsxs("form",{className:"flex flex-col gap-0.5",onSubmit:g,children:[l.jsx("input",{className:"field-input",placeholder:"Username",value:r,onChange:x=>o(x.target.value)}),l.jsx("input",{className:"field-input",placeholder:"Password",type:"password",value:u,onChange:x=>f(x.target.value)}),l.jsx("button",{type:"submit",disabled:p,className:"button-dark w-full disabled:opacity-50",children:p?"Logging in…":"Login"})]})]})}function xx(...n){return n.filter(Boolean).join(" ")}function Ow(n){const a=n?.batteryState?.percentDisplay;return a==null?"--":`${a}%`}function Bw(n){return n?.batteryState?n.batteryState.urgentActive?"text-red-400":n.batteryState.warnActive?"text-amber-300":"text-emerald-300":"text-slate-400"}function Lw({title:n,roster:a=[],emptyText:r="No roster data.",renderActions:o=null}){return l.jsxs("div",{className:"space-y-0.5 text-sm",children:[n&&l.jsx("p",{className:"text-sm text-slate-400",children:n}),a.length===0?l.jsx("p",{className:"text-sm text-slate-500",children:r}):l.jsx("ul",{className:"space-y-0.5 text-sm",children:a.map(u=>{const f=!!(u?.private?.enabled&&u?.private?.open),p=!!u?.locked;return l.jsxs("li",{className:xx("surface flex flex-wrap items-center justify-between gap-0.5",p?"bg-red-900/40":f?"bg-amber-700/35 border border-amber-200/30":null),children:[l.jsxs("div",{children:[l.jsx("p",{className:"text-slate-200",children:l.jsx("span",{className:"rounded px-1 py-[1px] border border-transparent",style:ns(u.color,.16),children:u.name})}),l.jsxs("p",{className:"text-xs text-slate-500 flex flex-wrap items-center gap-0.5",children:[l.jsx("span",{children:u.locked?"locked":"free"}),u.lockReason&&l.jsx("span",{className:"rounded bg-black/30 px-1",children:u.lockReason}),l.jsxs("span",{className:xx("font-semibold",Bw(u)),children:["Battery ",Ow(u)]})]})]}),o?o(u):null]},u.id)})})]})}function zw(n){const a=n?.runtime||{},r=n?.output||{},o=n?.errors||{};return a.inFlight?{label:"IN FLIGHT",detail:a.reason||"Generating commentary now",className:"border-amber-400/60 bg-amber-700/20 text-amber-200"}:a.outcome==="posted"?{label:"POSTED",detail:r.posted?`Last: ${r.posted}`:"Commentary posted",className:"border-emerald-400/60 bg-emerald-700/20 text-emerald-200"}:a.outcome==="skipped"?{label:"SKIPPED",detail:a.reason||"Model chose to skip",className:"border-slate-400/60 bg-slate-700/30 text-slate-200"}:a.outcome==="failed"?{label:"FAILED",detail:o.message||a.reason||"Tick failed",className:"border-red-400/60 bg-red-700/20 text-red-200"}:{label:a.running?"IDLE":"STOPPED",detail:a.reason||"Waiting for next tick",className:"border-sky-400/50 bg-sky-700/20 text-sky-200"}}function Uw(n,a){const r=Date.now(),u=(Array.isArray(n)?n:[]).map((f,p)=>{const h=String(f?.role||"").toLowerCase(),g=typeof f?.content=="string"?f.content:JSON.stringify(f?.content??null,null,2),x=h==="system"?"LLM System":h==="assistant"?"LLM Context":h==="user"?"LLM Input":"LLM Message";return{id:`llm-msg-${p}`,message:{ts:r+p,nickname:x,text:g,role:"spectator",bot:h==="system"}}});if(a!=null){const f=String(a);u.push({id:"llm-output",message:{ts:r+u.length+1,nickname:"LLM Output",text:f.trim()?f:"",role:"spectator",bot:!0}})}return u}function Hw({state:n,onClearHistory:a,clearingHistory:r}){const[o,u]=m.useState(null);if(!n)return l.jsxs("div",{className:"space-y-0.5",children:[l.jsx("div",{className:"panel-muted text-xs uppercase",children:"LLM Commentary"}),l.jsx("div",{className:"surface text-xs text-slate-300",children:"No status received yet."})]});const f=n.runtime||{},p=n.counters||{},h=n.timings||{},g=n.input||{},x=n.output||{},v=n.errors||{},b=Array.isArray(n.history)?n.history:[],S=b.find(w=>w.runId===o)||(b.length?b[b.length-1]:null),C=zw(n),E=Uw(g.modelMessages,x.raw),N=[{label:"running",value:f.running?"yes":"no"},{label:"in flight",value:f.inFlight?"yes":"no"},{label:"phase",value:f.phase||"--"},{label:"run id",value:f.currentRunId??"--"},{label:"tick count",value:f.tickCount??0},{label:"last tick",value:f.lastTickAt?new Date(f.lastTickAt).toLocaleString():"never"},{label:"next run",value:f.nextRunAt?new Date(f.nextRunAt).toLocaleString():"n/a"},{label:"outcome",value:f.outcome||"--"},{label:"reason",value:f.reason||"--"},{label:"skip streak",value:p.skipStreak??0},{label:"clear count",value:p.clearCount??0},{label:"last gen",value:h.lastGenerationMs!=null?`${h.lastGenerationMs} ms`:"--"},{label:"avg gen",value:h.avgGenerationMs!=null?`${h.avgGenerationMs} ms`:"--"},{label:"gen count",value:h.generationCount??0},{label:"prompt chars",value:p.promptChars??0},{label:"active drivers",value:p.snapshotSummary?.activeDrivers??0},{label:"snapshot rovers",value:p.snapshotSummary?.rovers??0},{label:"snapshot chat",value:p.snapshotSummary?.chatMessages??0}];return l.jsxs("div",{className:"space-y-0.5",children:[l.jsx("div",{className:"panel-muted text-xs uppercase",children:"LLM Commentary"}),l.jsx("div",{className:"flex gap-0.5 text-xs",children:l.jsx("button",{type:"button",onClick:a,disabled:!!r,className:"button-danger disabled:cursor-not-allowed disabled:opacity-60",children:r?"Clearing...":"Clear LLM History"})}),l.jsxs("div",{className:`surface border text-center ${C.className}`,children:[l.jsx("div",{className:"text-[1.1rem] font-bold tracking-wide",children:C.label}),l.jsx("div",{className:"text-xs text-slate-200",children:C.detail})]}),l.jsx("div",{className:"surface flex flex-wrap gap-0.5 text-xs",children:N.map(w=>l.jsxs("span",{className:"rounded border border-slate-600/60 bg-slate-800/70 px-0.5 py-0.25 text-[0.72rem] leading-tight text-slate-200",children:[w.label,": ",w.value]},w.label))}),v.message?l.jsxs("div",{className:"surface text-xs text-red-300 break-words",children:["Error: ",v.message]}):null,v.details?l.jsxs("details",{className:"surface text-xs text-red-200",children:[l.jsx("summary",{className:"cursor-pointer select-none text-red-300",children:"Failure details"}),l.jsx("pre",{className:"mt-0.5 whitespace-pre-wrap break-words text-[0.72rem] text-red-200",children:JSON.stringify(v.details,null,2)})]}):null,x.generated?l.jsxs("div",{className:"surface text-xs text-slate-200 break-words",children:["Generated: ",x.generated]}):null,x.posted?l.jsxs("div",{className:"surface text-xs text-emerald-200 break-words",children:["Posted: ",x.posted]}):null,l.jsxs("div",{className:"grid gap-0.5 md:grid-cols-2",children:[l.jsxs("div",{className:"space-y-0.5",children:[l.jsx("div",{className:"panel-muted text-xs uppercase",children:"Live Input Conversation"}),l.jsx("div",{className:"surface max-h-72 space-y-0.5 overflow-y-auto",children:E.length?E.map(w=>l.jsx(nf,{message:w.message},w.id)):l.jsx("div",{className:"text-xs text-slate-300",children:"No model conversation captured yet."})})]}),l.jsxs("div",{className:"space-y-0.5",children:[l.jsx("div",{className:"panel-muted text-xs uppercase",children:"Output + Error"}),l.jsxs("div",{className:"surface space-y-0.5 text-xs text-slate-200",children:[l.jsxs("div",{children:["Raw output: ",x.raw?.trim()?x.raw:""]}),l.jsxs("div",{children:["Posted: ",x.posted||""]}),l.jsxs("div",{children:["Output at: ",x.modelOutputAt?new Date(x.modelOutputAt).toLocaleString():"n/a"]}),l.jsxs("div",{children:["Failed at: ",v.failedAt?new Date(v.failedAt).toLocaleString():"n/a"]})]})]})]}),l.jsxs("details",{className:"surface text-xs text-slate-200",children:[l.jsx("summary",{className:"cursor-pointer select-none text-slate-300",children:"Full Monitor Payload"}),l.jsx("pre",{className:"mt-0.5 whitespace-pre-wrap break-words text-[0.72rem] text-slate-200",children:JSON.stringify(n,null,2)})]}),l.jsxs("div",{className:"space-y-0.5",children:[l.jsx("div",{className:"panel-muted text-xs uppercase",children:"Recent Runs"}),l.jsx("div",{className:"surface max-h-52 space-y-0.5 overflow-y-auto text-xs",children:b.length?b.slice().reverse().map(w=>l.jsxs("button",{type:"button",onClick:()=>u(w.runId),className:`w-full text-left surface ${S?.runId===w.runId?"border border-sky-400/50":""}`,children:[l.jsxs("span",{className:"text-slate-300",children:["#",w.runId]})," ",l.jsx("span",{className:"text-slate-200",children:w.outcome||w.phase||"--"})," ",l.jsx("span",{className:"text-slate-400",children:w.durationMs!=null?`${w.durationMs}ms`:"--"})," ",l.jsx("span",{className:"text-slate-500",children:w.reason||""})]},w.runId)):l.jsx("div",{className:"text-slate-300",children:"No runs recorded yet."})})]}),S?l.jsxs("details",{className:"surface text-xs text-slate-200",open:!0,children:[l.jsxs("summary",{className:"cursor-pointer select-none text-slate-300",children:["Run #",S.runId," details"]}),l.jsx("pre",{className:"mt-0.5 whitespace-pre-wrap break-words text-[0.72rem] text-slate-200",children:JSON.stringify(S,null,2)})]}):null]})}function Vw({state:n,onClearHistory:a,clearingHistory:r}){const[o,u]=m.useState(!1);if(!n)return l.jsxs("div",{className:"space-y-0.5",children:[l.jsx("div",{className:"panel-muted text-xs uppercase",children:"Overseer Control"}),l.jsx("div",{className:"surface text-xs text-slate-300",children:"No status received yet."})]});const f=n.runtime||{},p=n.config||{},h=n.output||{},g=n.timings||{},x=n.input||{},v=n.errors||{},b=()=>{const S=Array.isArray(x.modelMessages)?x.modelMessages:[];return S.length?S.map((C,E)=>{const N=String(C?.role||"unknown").toUpperCase(),w=String(C?.content||"");return`#${E+1} ${N} + `,document.head.appendChild(a)},[])}function lw(n,a){return typeof n=="string"&&n.trim()?n.trim().toLowerCase():typeof a=="string"&&a.trim()?a.trim().toLowerCase().replace(/\s+/g,"-").replace(/[^a-z0-9-]/g,""):""}function wo({id:n,label:a,url:r,className:o=""}){if(!r)return null;aw();const u=lw(n,a),f=nw[u]||_j,p=sw[u]||null,h=a||n||"Link";return l.jsxs("a",{href:r,target:"_blank",rel:"noopener noreferrer","aria-label":h,className:`inline-flex items-center w-full px-0.5 py-0.5 text-sm font-medium text-white transition justify-center gap-1 rounded-md ${p?"":"bg-slate-700 hover:bg-slate-600"} ${o}`,style:p||void 0,children:[l.jsx(f,{className:"mr-0"}),h]})}function rw({roverId:n=null,mobileHud:a=!1,discordUrl:r=null}){const o=oe(Ae=>Ae.session?.assignment?.roverId??null),u=n??o,f=oe(Ae=>Ae.session?.mode||null),p=oe(Ae=>Ae.session?.roster??[]),h=oe(Ae=>Ae.session?.users??[]),g=oe(Ae=>Ae.session?.turnQueues??{}),x=oe(Ae=>Ae.session?.socketId||null),v=oe(Ae=>Ae.session?.activeDrivers??{}),b=oe(Ae=>(Ae.session?.socials||[]).find(de=>String(de?.id||de?.label||"").toLowerCase()==="discord")?.url||null||Ae.session?.discord?.invite||null),{state:{lastControlIntentAt:S}}=yt(),C=r||b,[E,N]=m.useState(()=>Date.now()),[w,j]=m.useState(!1),[T,k]=m.useState(null),[M,D]=m.useState(!1),[V,B]=m.useState(0),L=m.useRef({initialized:!1,roverId:null,activeDriverId:null}),Y=m.useRef(S||0),U=a?"text-[0.5rem]":"text-[0.7rem]",X=a?"px-0.5 py-0.25":"px-1 py-0.5",Q=a?"text-3xl":"text-5xl",ce=a?"text-xs":"text-sm",ue=a?"text-[0.55rem]":"text-[0.75rem]",W=a?"px-4 py-3":"px-6 py-4",O=u?g?.[u]:null,I=u?v?.[u]:null,K=!!(x&&I===x),P=m.useMemo(()=>{const Ae=O?.queue||[];if(!Ae.length||!O?.current||Ae.length<=1)return null;const ae=Ae.findIndex(re=>re===O.current);return ae===-1?Ae[0]||null:Ae[(ae+1)%Ae.length]||null},[O?.queue,O?.current]),ie=!!(x&&P===x),R=O?.deadline||null,q=O?.idleDeadline||null,Z=R?R-E:null,le=q?q-E:null,he=f==="turns",we=p.length,pe=m.useMemo(()=>{const Ae=new Set;return h.forEach(ae=>{if(String(ae?.role||"")==="spectator")return;const de=String(ae?.roverId||"").trim(),fe=String(ae?.socketId||"").trim();!de||!fe||Ae.add(fe)}),Ae.size},[h]),xe=he&&pe>we,ge=he&&ie&&Z!=null&&Z<=5e3&&Z>0,Se=he&&!K,be=Se&&!ge&&xe,$e=Z!=null&&Number.isFinite(Z)?Math.max(0,Math.ceil(Z/1e3)):null,Ze=le!=null&&Number.isFinite(le)?Math.max(0,Math.ceil(le/1e3)):null,je=m.useMemo(()=>!he||!K?null:$e!=null?`${$e}s left`:"Your turn",[he,K,$e]),lt=m.useMemo(()=>!Se||!ie||$e==null?null:`${$e} seconds until your turn.`,[Se,ie,$e]),Ie=K&&typeof Ze=="number",ft=M;return m.useEffect(()=>{if(f!=="turns")return;const Ae=setInterval(()=>N(Date.now()),250);return()=>clearInterval(Ae)},[f]),m.useEffect(()=>{if(f!=="turns"){j(!1),k(null),L.current={initialized:!1,roverId:null,activeDriverId:null};return}const Ae=L.current,ae=I||null;if(!x||!u){j(!1),k(null),L.current={initialized:!1,roverId:null,activeDriverId:null};return}if(!Ae.initialized||Ae.roverId!==u){L.current={initialized:!0,roverId:u,activeDriverId:ae};return}!!Ae.activeDriverId&&Ae.activeDriverId!==x&&ae===x?(j(!0),k(Date.now())):ae!==x&&w&&(j(!1),k(null)),L.current={initialized:!0,roverId:u,activeDriverId:ae}},[I,f,u,x,w]),m.useEffect(()=>{!w||!T||S>T&&j(!1)},[S,w,T]),m.useEffect(()=>{const Ae=Number(Y.current)||0,ae=Number(S)||0;ae>Ae&&Se&&B(Date.now()),Y.current=ae},[S,Se]),m.useEffect(()=>{if(!Se||!V)return;D(!0);const Ae=setTimeout(()=>D(!1),650);return()=>clearTimeout(Ae)},[Se,V]),l.jsxs(l.Fragment,{children:[w?l.jsx("div",{className:"pointer-events-none absolute inset-0 z-30 flex items-center justify-center bg-black/55",children:l.jsxs("div",{className:`flex flex-col items-center gap-0.5 rounded border border-amber-300/80 bg-black/70 ${W}`,children:[l.jsx("div",{className:`font-semibold text-amber-200 ${Q}`,children:"IT IS YOUR TURN!"}),l.jsx("div",{className:`text-amber-200/80 ${ce}`,children:"Start driving!"}),Ie?l.jsxs("div",{className:`text-red-100/90 ${ue}`,children:["Idle skip in ",Ze,"s"]}):null]})}):null,je?l.jsx("div",{className:`pointer-events-none absolute bottom-1 left-1 rounded border ${ft?"border-red-300/90 bg-red-900/80 text-red-100":"border-amber-300/80 bg-black/75 text-amber-200"} ${X} ${U}`,children:je}):null,Se?l.jsx("div",{className:"pointer-events-none absolute bottom-1 left-1 z-40",children:l.jsxs("div",{className:`w-fit rounded border ${M?"border-red-300/90 bg-red-900/80 text-red-100":"border-amber-300/80 bg-black/75 text-amber-200"} ${a?"px-2 py-1 text-[0.6rem]":"px-3 py-1.5 text-sm"}`,children:[l.jsx("div",{className:M?"text-[0.82rem] font-semibold text-red-50":"text-[0.82rem] font-semibold text-white",children:"Not your turn to drive!"}),lt?l.jsx("div",{className:M?"text-red-100/95":"text-amber-100",children:lt}):null,be?l.jsx("div",{className:M?"text-red-100/90":"text-amber-200/85",children:"Video switched to preview mode to save bandwidth."}):null,l.jsx("div",{className:"pointer-events-auto mt-0.5",children:l.jsx(wo,{id:"discord",label:"Join our Discord while you wait!",url:C})})]})}):null]})}const iw=Dt.memo(rw);function $g(){const{value:n,save:a}=Ve("page",{hudMapDesktop:!1});return[!!n?.hudMapDesktop,u=>{a({hudMapDesktop:!!u})}]}function cx({variant:n="default",label:a,roverColor:r=null,driverLabel:o=null,mobileHud:u=!1,labelScale:f=1}){const p=u?"px-0.25 py-0.25":"px-0.5 py-0.5",h=u?"text-[0.55rem]":"text-[0.8rem]",g="bottom-0.5",x={transform:`translateX(-50%) scale(${f})`,transformOrigin:"center bottom"};return n==="spectator"?l.jsx("div",{className:`absolute ${g} left-1/2`,style:x,children:l.jsxs("div",{className:`flex items-center gap-0.5 bg-black/80 text-slate-100 ${p} ${h}`,children:[l.jsx("span",{className:"font-semibold text-white rounded px-1 py-[1px] border border-transparent",style:ns(r,.18),children:a||"No rover"}),o?l.jsxs("span",{className:"text-slate-300",children:["• ",o]}):null]})}):l.jsx("div",{className:`absolute ${g} left-1/2`,style:x,children:l.jsx("div",{className:`flex gap-0.5 bg-black/80 text-slate-100 ${p} ${h}`,children:l.jsxs("span",{children:["Rover:"," ",l.jsxs("span",{className:"rounded px-1 py-[1px] border border-transparent",style:ns(r,.18),children:['"',a||"No rover",'"']})]})})})}function ow({sensors:n,mobileHud:a=!1}){const r=a?"px-0.25 py-0.25":"px-1 py-0.5",o=a?"left-0.5 top-1/2":"left-1 top-1/2",u=a?"text-[0.45rem]":"text-[0.65rem]",f=[["Voltage",n?.voltageMv!=null?`${(n.voltageMv/1e3).toFixed(2)} V`:"--"],["Current",n?.currentMa!=null?`${n.currentMa} mA`:"--"],["Charge",n?.batteryChargeMah!=null?`${n.batteryChargeMah}`:"--"],["OI",n?.oiMode?.label||"--"]],p=!!n?.chargingSources?.homeBase,h=n?.chargingState?.label||"",g=!!(h&&h.toLowerCase()!=="not charging"),x=n?.oiMode?.label||"Unknown",v=x.toLowerCase(),b=v==="full"?"bg-emerald-500/80 text-emerald-50":v==="safe"?"bg-amber-400/80 text-amber-950":v==="passive"?"bg-slate-700/80 text-slate-100":"bg-slate-700/60 text-slate-200",S=p?"bg-emerald-500/80 text-emerald-50":"bg-slate-700/70 text-slate-200",C=g?"bg-emerald-500/80 text-emerald-50":p?"bg-amber-400/80 text-amber-950":"bg-slate-700/70 text-slate-200";return l.jsx("div",{className:`absolute ${o} flex -translate-y-1/2 flex-col gap-0.5 bg-black/70 text-slate-100 ${u} ${r}`,children:l.jsxs("div",{className:"space-y-0.5 leading-tight",children:[l.jsxs("div",{className:"flex flex-col gap-0.5 text-[0.75rem] font-semibold uppercase tracking-wide",children:[l.jsx("span",{className:`rounded px-1.5 py-0.5 ${S}`,children:p?"Docked":"Undocked"}),l.jsx("span",{className:`rounded px-1.5 py-0.5 ${C}`,children:g?"Charging":"Not charging"}),l.jsxs("span",{className:`rounded px-1.5 py-0.5 ${b}`,children:["OI: ",x]})]}),f.map(([E,N])=>l.jsxs("span",{className:"flex items-center justify-between gap-0.5",children:[l.jsx("span",{className:"text-slate-400",children:E}),l.jsx("span",{className:"font-semibold text-white",children:N})]},E))]})})}function Ao(n){return Math.max(0,Math.min(1,n))}function Gg(n){return(n-90)*Math.PI/180}function or(n,a,r,o){const u=Gg(o);return{x:n+r*Math.cos(u),y:a+r*Math.sin(u)}}function cw(n,a,r,o,u){let f=o,p=u;p<=f&&(p+=360);const h=or(n,a,r,f),g=or(n,a,r,p);return["M",h.x,h.y,"A",r,r,0,0,1,g.x,g.y].join(" ")}function df(n,a){if(a)return"#ef4444";const r=Math.abs(n);return r>900?"#f59e0b":r>300?"#22c55e":"#64748b"}function uw(n,a){if(n==null||n<=0)return"hsl(200 60% 18%)";const o=Ao(n/(a||1));return`hsl(${(200+Math.pow(o,.45)*360)%360} 100% 60%)`}function dw(n,a){if(a)return"#ef4444";const r=Ao(n==null?0:n/4095),o=[47,55,69],u=[245,158,11],[f,p,h]=o.map((g,x)=>Math.round(g+(u[x]-g)*r));return`rgb(${f}, ${p}, ${h})`}function fw({count:n,totalSpan:a,gap:r,startAngle:o}){const f=(a-r*(n-1))/n,p=[];let h=o;for(let g=0;g0?.65:null;return l.jsxs("g",{style:{transformOrigin:`${n}px ${a}px`,animation:h?`spin ${h}s linear infinite`:"none",animationDirection:h?"reverse":"normal"},children:[l.jsx("circle",{cx:n,cy:a,r:10,fill:"#64748b",stroke:"#64748b",strokeWidth:"1"}),[0,120,240].map(x=>{const v=Gg(x),b=n+p*Math.cos(v),S=a+p*Math.sin(v);return l.jsx("line",{x1:n,y1:a,x2:b,y2:S,stroke:f,strokeWidth:"4",strokeLinecap:"round"},x)}),o?l.jsx("circle",{cx:n,cy:a,r:p+8,stroke:"#ef4444",strokeWidth:"3",fill:"none",className:"animate-pulse"}):null]})}function pw({cx:n,cy:a,current:r,overcurrent:o,variant:u,dirtLeft:f,dirtRight:p}){const h=Math.abs(r),g=df(r,o),x=1,v=96,b=12,S=`main-brush-pattern-a-${u}`,C=`main-brush-pattern-b-${u}`,E=h>0?.6:null,N=r>=0?1:-1;return l.jsxs("g",{children:[l.jsx("defs",{children:[S,C].map((w,j)=>l.jsxs("pattern",{id:w,patternUnits:"userSpaceOnUse",width:"6",height:"6",children:[l.jsx("rect",{width:"6",height:"6",fill:g,opacity:x}),l.jsx("path",{d:"M0 6 L6 0",stroke:"#0f172a",strokeWidth:"1"}),E?l.jsx("animateTransform",{attributeName:"patternTransform",type:"translate",from:"0 0",to:`0 ${N*(j===0?6:-6)}`,dur:`${E}s`,repeatCount:"indefinite"}):null]},w))}),l.jsx("rect",{x:n-v/2,y:a-14,width:v,height:b,rx:"3",fill:`url(#${S})`,stroke:"#64748b",strokeWidth:"1"}),l.jsx("rect",{x:n-v/2,y:a+4,width:v,height:b,rx:"3",fill:`url(#${C})`,stroke:"#64748b",strokeWidth:"1"}),l.jsx("circle",{cx:n-v/4,cy:a-8,r:3.5,fill:"#fbbf24"}),l.jsx("circle",{cx:n+v/4,cy:a+8,r:3.5,fill:"#fbbf24"}),o?l.jsx("rect",{x:n-v/2-4,y:a-16,width:v+8,height:b*2+16,rx:"6",stroke:"#ef4444",strokeWidth:"3",fill:"none",className:"animate-pulse"}):null]})}function xw({sensors:n={},variant:a="full",size:r,overlay:o=!1}){const u=r||(a==="mini"?190:260),f=u/2,p=u*.07,h=f,g=f+p,x=f*.8,v=x-4,b=x+4,S=x-14,C=x-6,E=x*.65,N=n?.bumpsAndWheelDrops||{},w=n?.wheelOvercurrents||{},j=n?.wheelLeftCurrentMa??0,T=n?.wheelRightCurrentMa??0,k=n?.sideBrushCurrentMa??0,M=n?.mainBrushCurrentMa??0,D=6,V=N.bumpLeft?D:0,B=N.bumpRight?D:0,L=fw({count:6,totalSpan:140,gap:6,startAngle:-70}),Y=["L","FL","CL","CR","FR","R"],U=[n?.lightBumpLeftSignal,n?.lightBumpFrontLeftSignal,n?.lightBumpCenterLeftSignal,n?.lightBumpCenterRightSignal,n?.lightBumpFrontRightSignal,n?.lightBumpRightSignal],X=L.map((W,O)=>({label:Y[O],start:W.start,end:W.end,value:U[O]})),Q=[{label:"Cliff L",start:-60,end:-46,value:n?.cliffLeftSignal,active:n?.cliffLeft},{label:"Cliff FL",start:-32,end:-16,value:n?.cliffFrontLeftSignal,active:n?.cliffFrontLeft},{label:"Cliff FR",start:16,end:32,value:n?.cliffFrontRightSignal,active:n?.cliffFrontRight},{label:"Cliff R",start:46,end:60,value:n?.cliffRightSignal,active:n?.cliffRight}],ce=U.filter(W=>W!=null),ue=ce.length?Math.max(...ce,1200):1200;return l.jsxs("div",{className:`${o?"relative":"surface relative p-1"}`,style:o?{width:`${u}px`,height:`${u}px`}:{height:"100%",width:"100%",aspectRatio:"1 / 1"},children:[o?null:l.jsxs(l.Fragment,{children:[l.jsx("div",{className:"absolute left-1 top-1 text-xs text-slate-400",children:"Top-down"}),l.jsxs("div",{className:"absolute right-1 top-1 text-[0.65rem] text-slate-500",children:["0–",ue]})]}),l.jsxs("svg",{width:"100%",height:"100%",viewBox:`0 0 ${u} ${u}`,preserveAspectRatio:"xMidYMid meet",className:"mx-auto block",children:[l.jsx("circle",{cx:h,cy:g,r:x,fill:"#0f172a",stroke:"#334155",strokeWidth:"2"}),l.jsx(ux,{cx:h-E,cy:g,current:j,drop:N.wheelDropLeft,overcurrent:w.leftWheel,label:"L"}),l.jsx(ux,{cx:h+E,cy:g,current:T,drop:N.wheelDropRight,overcurrent:w.rightWheel,label:"R"}),l.jsx(hw,{cx:h+x*.65,cy:g-x*.55,current:k,overcurrent:w.sideBrush}),l.jsx(pw,{cx:h,cy:g,current:M,overcurrent:w.mainBrush,variant:a,dirtLeft:n?.dirtDetectLeft,dirtRight:n?.dirtDetect}),X.map(W=>{const O=uw(W.value,ue),I=b+4,K=I+28;return l.jsx(mw,{cx:h,cy:g,rBase:K,rTip:I,startDeg:W.start,endDeg:W.end,color:O,value:W.value,max:ue},W.label)}),Q.map(W=>l.jsx(xd,{cx:h,cy:g,rInner:S,rOuter:C,startDeg:W.start,endDeg:W.end,color:dw(W.value,W.active),opacity:1,pulse:!!W.active},W.label)),l.jsx(xd,{cx:h,cy:g,rInner:v-V,rOuter:b-V,startDeg:-70,endDeg:-6,color:N.bumpLeft?"#ef4444":"#475569",opacity:1,pulse:!!N.bumpLeft}),l.jsx(xd,{cx:h,cy:g,rInner:v-B,rOuter:b-B,startDeg:6,endDeg:70,color:N.bumpRight?"#ef4444":"#475569",opacity:1,pulse:!!N.bumpRight})]})]})}const Yg=Dt.memo(xw);function dx({sensors:n,show:a=!0,mapPosition:r="top-center",layoutFormat:o="desktop",mobileHud:u=!1}){if(!a)return null;const f=o==="mobile-portrait",p="240px",h=f?.3:u?.33:.7,x={width:p,height:p,opacity:u?.6:.7,transform:r==="top-center"?`translateX(-50%) scale(${h})`:`scale(${h})`,transformOrigin:r==="bottom-left"?"bottom left":r==="top-center"?"top center":"top right",...r==="bottom-left"?{left:"0.25rem",bottom:"0.25rem"}:r==="top-center"?{left:"50%",top:"0.25rem"}:{right:"0.25rem",top:"0.25rem"}};return l.jsx("div",{className:"pointer-events-none absolute rounded",style:x,children:l.jsx(Yg,{sensors:n,size:240,overlay:!0})})}function gw({roverId:n=null,sensors:a,label:r,roverColor:o=null,layoutFormat:u="desktop",variant:f="default",driverLabel:p=null,showTopDown:h=void 0,mobileHud:g=!1,mapPosition:x=null,labelScale:v=1}){const b=oe(L=>L.session?.assignment?.roverId??null),S=n??b,C=Wt(S),E=oe(L=>{if(!S)return{label:null,roverColor:null};const U=(L.session?.roster||[]).find(X=>String(X.id)===String(S));return{label:U?.name||null,roverColor:U?.color||null}}),N=oe(L=>{if(!S||f!=="spectator")return null;const Y=L.session?.activeDrivers?.[S]||null,X=(L.session?.users||[]).find(Q=>String(Q.socketId||"")===String(Y||""));return X?.nickname||X?.name||null}),w=a??C?.sensors??null,j=r??E.label??null,T=o??E.roverColor??null,k=p??N,M=g,[D]=$g(),V=typeof h=="boolean"?h:f==="spectator"||M?!0:D,B=x||(f==="spectator"?"top-center":M?"top-right":"top-center");return f==="none"?null:f==="spectator"?l.jsxs(l.Fragment,{children:[l.jsxs("div",{className:"pointer-events-none absolute inset-0 flex items-center justify-center",children:[l.jsx(ow,{sensors:w,mobileHud:M}),l.jsx(cx,{variant:"spectator",label:j,roverColor:T,driverLabel:k,mobileHud:M,labelScale:v})]}),l.jsx(dx,{sensors:w,show:V,mapPosition:B,layoutFormat:u,mobileHud:M})]}):l.jsxs("div",{className:"pointer-events-none absolute inset-0 flex items-center justify-center",children:[l.jsx(cx,{variant:"default",label:j,roverColor:T,mobileHud:M,labelScale:v}),l.jsx(dx,{sensors:w,show:V&&f!=="spectator",mapPosition:B,layoutFormat:u,mobileHud:M})]})}const Fg=Dt.memo(gw);function vw({mobileHud:n=!1}){const{visible:a,statusLabel:r,statusTone:o,active:u,charging:f}=al({manageLifecycle:!0}),[p,h]=m.useState(""),g=m.useRef(null),x=m.useRef(u);if(m.useEffect(()=>{const b=x.current;u&&!b?h("Dock assist mode enabled"):!u&&b&&f&&h("Docking successful! Thank you!"),x.current=u},[u,f]),m.useEffect(()=>{if(p)return g.current&&clearTimeout(g.current),g.current=setTimeout(()=>{h(""),g.current=null},2500),()=>{g.current&&(clearTimeout(g.current),g.current=null)}},[p]),!a)return null;const v=o==="good"?"border-emerald-200/85 text-emerald-50":o==="warn"?"border-amber-200/85 text-amber-50":"border-indigo-200/85 text-indigo-50";return l.jsx("div",{className:"pointer-events-none absolute inset-0",children:p?l.jsx("div",{className:"absolute inset-0 flex items-center justify-center",children:l.jsx("div",{className:`rounded-xl border border-indigo-200/95 bg-black/92 px-4 py-2 text-center font-semibold text-indigo-50 shadow-2xl ${n?"text-lg":"text-2xl"}`,children:p})}):l.jsx("div",{className:`absolute right-2 top-1/2 -translate-y-1/2 rounded-lg border bg-black/88 px-2 py-1 font-semibold shadow-lg ${v} ${n?"text-[0.65rem]":"text-xs"}`,children:r})})}const bw=Dt.memo(vw),fx=5e3,yw=700;function Ig({roverId:n=null,description:a,variant:r="default",mobileHud:o=!1,displayKey:u="",controlIntentAt:f}){const p=oe(T=>T.session?.assignment?.roverId??null),h=n??p,g=oe(T=>h&&(T.session?.roster||[]).find(D=>String(D.id)===String(h))?.description||null),x=a??g,v=typeof f=="number"?f:0,b=u||`${h||""}::${x||""}`,[S,C]=m.useState(!1),[E,N]=m.useState(!1),w=m.useRef(null),j=m.useRef(null);return m.useEffect(()=>()=>{clearTimeout(w.current),clearTimeout(j.current)},[]),m.useEffect(()=>{if(r!=="default"||!x){C(!1),N(!1),clearTimeout(w.current),clearTimeout(j.current);return}clearTimeout(w.current),clearTimeout(j.current),C(!0),N(!1)},[x,b,r]),m.useEffect(()=>{r!=="default"||!x||!S||E||(Number(v)||0)<=0||w.current||j.current||(w.current=setTimeout(()=>{N(!0),w.current=null},fx),j.current=setTimeout(()=>{C(!1),j.current=null},fx+yw))},[v,x,E,S,r]),x?r==="spectator"?l.jsx("div",{className:"pointer-events-none absolute inset-x-0 top-1 z-50 flex justify-center",children:l.jsx("div",{className:"surface max-w-[92%] border border-slate-600/80 px-1 py-0.5 text-center text-[0.62rem] leading-tight text-slate-100 shadow-lg",children:x})}):r!=="default"||!S?null:l.jsx("div",{className:"pointer-events-none absolute inset-0 z-50 flex items-center justify-center",children:l.jsxs("div",{className:`surface max-w-[94%] border border-slate-400 bg-neutral-900 px-2 py-1 text-center font-semibold text-slate-100 shadow-xl transition-opacity duration-700 ${E?"opacity-0":"opacity-100"} ${o?"text-[1rem] leading-tight":"text-[1.5rem] leading-tight"}`,children:[l.jsx("p",{children:"Just so you know, this rover"}),l.jsx("p",{children:x}),l.jsx("p",{className:`${o?"text-[0.58rem]":"text-[0.72rem]"} mt-0.5 font-normal text-slate-300`,children:"This fades 5 seconds after your first control input."})]})}):null}const Sw={leftWheel:"Left wheel",rightWheel:"Right wheel",mainBrush:"Main brush",sideBrush:"Side brush",limiter:"Overcurrent limit"};function jw({roverId:n=null,sensors:a,overcurrentLimiter:r=null,compact:o=!1}){const u=oe(L=>L.session?.assignment?.roverId??null),f=n??u,p=Wt(f),h=jg(f),g=a??p?.sensors??null,x=r??h??null,v=g?.wheelOvercurrents||null,b=m.useMemo(()=>v==null?[]:Object.entries(v).filter(([,L])=>!!L).map(([L])=>L),[v]),S=x?.caps||null,C=m.useMemo(()=>{if(!S)return null;const L=Number.isFinite(S?.drive?.cap)?S.drive.cap:1,Y=Number.isFinite(S?.aux?.cap)?S.aux.cap:1;return Math.max(0,Math.min(1,1-Math.min(L,Y)))},[S]),E=!!x?.isActive,N=m.useMemo(()=>b.length?b:E?["limiter"]:[],[b,E]),w=C??(b.length?1:0);if(!N?.length)return null;const j=N.map(L=>Sw[L]||L),T=o?"w-[12rem] h-[3.5rem]":"w-[20rem] h-[7rem]",k=o?"px-2 py-1":"px-4 py-2",M=o?"text-lg":"text-4xl",D=o?"text-xs":"text-xl",V=Math.max(0,Math.min(1,w)),B=`${Math.round(V*100)}%`;return l.jsx("div",{className:`pointer-events-none absolute flex items-center justify-center bg-red-900/50 top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 ${T}`,children:l.jsxs("div",{className:"relative h-full w-full",children:[l.jsx("div",{className:"absolute inset-0 overflow-hidden",children:l.jsx("div",{className:"h-full bg-red-700/60",style:{width:B}})}),l.jsxs("div",{className:`relative z-10 flex h-full w-full flex-col items-center justify-center text-center font-semibold text-white animate-pulse ${M} ${k}`,children:[l.jsx("div",{children:"OVERCURRENT"}),l.jsx("div",{className:`mt-0 font-medium text-white ${D}`,children:j.join(", ")})]})]})})}const Xg=Dt.memo(jw),mr=10;function Co({batteryState:n=null,charge:a=null,config:r=null}){const o=n?.percentDisplay!=null&&Number.isFinite(n.percentDisplay)?Math.round(n.percentDisplay):null,u=n?.warnActive??null,f=n?.urgentActive??null,p=r?.Full??null,h=r?.Warn??null,g=r?.Urgent??null,x=a??n?.charge??null;let v=o;if(v==null&&(v=Nw({charge:x,full:p,warn:h,urgent:g})),v==null)return{available:!1};const b=Math.max(0,Math.min(1,v/100)),S=u??(h!=null&&x!=null&&x<=h),C=f??(g!=null&&x!=null&&x<=g);return{available:!0,percent:b,percentDisplay:v,warnActive:S,urgentActive:C,warnDisplayPercent:mr}}function Nw({charge:n,full:a,warn:r,urgent:o}){if(n!=null&&a!=null&&r!=null&&o!=null&&a>r&&r>o){const u=mr/100,f=1-u;if(n<=o)return 0;if(n<=r){const h=(n-o)/(r-o);return Math.round(Math.max(0,Math.min(1,h))*mr)}if(n>=a)return 100;const p=(n-r)/(a-r);return Math.round((u+Math.max(0,Math.min(1,p))*f)*100)}return null}function ww({roverId:n=null,sensors:a,batteryConfig:r,compact:o=!1}){const u=oe(E=>E.session?.assignment?.roverId??null),f=n??u,p=Wt(f),h=oe(E=>f?(E.session?.roster||[]).find(j=>String(j.id)===String(f))?.battery??null:null),g=a??p?.sensors??null,x=r??h,v=Co({charge:g?.batteryChargeMah??null,config:x});if(!v?.available||!v.warnActive&&!v.urgentActive)return null;const b=v.urgentActive?"BATTERY VERY LOW, DOCK THE ROVER AND CHARGE IMMEDIATELY!!":"Battery low! please dock and charge the rover soon.",S=o?"p-2 top-6":"p-4 top-10",C=o?"text-sm":"text-2xl";return l.jsx("div",{className:`pointer-events-none absolute flex items-center justify-center bg-amber-900/60 left-1/2 -translate-x-1/2 ${S}`,children:l.jsx("div",{className:`text-center font-semibold text-white animate-pulse ${C}`,children:l.jsx("div",{children:b})})})}const Qg=Dt.memo(ww);function Aw({roverId:n=null,sensors:a}){const r=oe(S=>S.session?.assignment?.roverId??null),u=Wt(n??r),f=a??u?.sensors??null,p=[f?.lightBumpLeftSignal,f?.lightBumpFrontLeftSignal,f?.lightBumpCenterLeftSignal,f?.lightBumpCenterRightSignal,f?.lightBumpFrontRightSignal,f?.lightBumpRightSignal],h=p.filter(S=>S!=null).reduce((S,C)=>Math.max(S,C),1200),g=S=>Math.pow(Math.max(0,Math.min(1,(S??0)/h)),.35),x=S=>S==null||S<=0?"hsl(200 60% 18%)":`hsl(${(200+g(S)*360)%360} 100% 60%)`,v=6,b=12;return l.jsx("div",{className:"flex w-full items-center justify-center gap-0.5",children:p.map((S,C)=>{const E=g(S),N=Cg.session?.assignment?.roverId??null),o=n??r,f=Wt(o)?.sensors??null,p=oe(g=>o?(g.session?.roster||[]).find(b=>String(b.id)===String(o))?.battery??null:null),h=Co({charge:f?.batteryChargeMah??null,config:p});return l.jsxs("div",{className:"space-y-0.5",children:[l.jsx(Cw,{roverId:o}),l.jsx("div",{className:"panel-section space-y-0.5 text-sm",children:l.jsx(ff,{visual:h,compact:a})})]})}function Tw({compact:n=!1}){const a=oe(L=>L.session?.role||null),r=oe(L=>L.session?.assignment?.roverId||null),o=oe(L=>L.session?.roster||[]),{sendMessage:u,onInputFocus:f,onInputBlur:p,blurChat:h,registerInputRef:g,setTypingActive:x}=lf(),{value:v}=Ve("tts",{engine:"flite",voice:"rms",pitch:50}),[b,S]=m.useState(""),[C,E]=m.useState(!1),N=a!=="spectator",w=a==="spectator",T=!!m.useMemo(()=>o.find(L=>String(L.id)===String(r))||null,[r,o])?.audio?.ttsEnabled,k=m.useMemo(()=>{if(!T)return null;const L=v?.engine==="espeak"?"espeak":"flite";if(L==="espeak"){let U=Number.isFinite(v?.pitch)?Math.round(v.pitch):void 0;return typeof U=="number"&&(U=Math.max(0,Math.min(99,U))),{speak:!0,engine:L,pitch:U}}const Y=typeof v?.voice=="string"?v.voice:void 0;return{speak:!0,engine:L,voice:Y}},[v?.engine,v?.pitch,v?.voice,T]),M=n?"pointer-events-auto absolute bottom-0.5 right-0.5 flex w-[9rem] max-w-[70vw] items-center gap-0.5 rounded bg-black/70 px-0.4 py-0.2":"pointer-events-auto absolute bottom-1 right-1 flex w-[12rem] max-w-[70vw] items-center gap-0.5 rounded bg-black/70 px-0.5 py-0.25",D=n?"min-w-0 flex-1 bg-transparent text-[0.55rem] text-slate-100 placeholder:text-slate-400 focus:outline-none":"min-w-0 flex-1 bg-transparent text-[0.7rem] text-slate-100 placeholder:text-slate-400 focus:outline-none",V=n?"rounded bg-cyan-500/80 px-0.35 py-0.2 text-[0.55rem] font-semibold text-black disabled:opacity-50":"rounded bg-cyan-500/80 px-0.5 py-0.25 text-[0.7rem] font-semibold text-black disabled:opacity-50";async function B(L){if(L.preventDefault(),!N)return;const Y=b.trim();if(Y){E(!0);try{await u(Y,k),S(""),h(),x(!1)}catch(U){alert(U.message)}finally{E(!1)}}}return w?null:l.jsxs("form",{onSubmit:B,className:M,children:[l.jsx("input",{className:D,value:b,onChange:L=>{const Y=L.target.value;S(Y),x(!!Y.trim())},onFocus:L=>{f(L),x(!!b.trim())},onBlur:L=>{p(L),x(!1)},onKeyDown:L=>{L.key==="Enter"&&!b.trim()&&(L.preventDefault(),h(),x(!1))},ref:L=>g(L,{target:"hud"}),placeholder:N?"Chat (TTS)":"Spectator",disabled:!N}),l.jsx("button",{type:"submit",disabled:!N||C,className:V,children:"Speak"})]})}const qw=m.memo(Tw);function mf({layoutFormat:n="desktop"}){const a=oe(f=>f.session?.assignment?.roverId??null),r=tw(a),{state:{lastControlIntentAt:o}}=yt();if(!a)return l.jsx("section",{className:"panel",children:l.jsxs("div",{className:"panel-muted content-center text-center text-sm text-slate-400 aspect-[4/3]",children:[l.jsx("p",{children:"You are not assigned to a rover."}),l.jsx("p",{className:"mt-0",children:l.jsx("a",{href:"/spectate",className:"text-blue-400 underline hover:text-blue-500",children:"Click here to visit the spectator page."})})]})});const u=n!=="desktop";return l.jsx("section",{className:"panel",children:l.jsxs("div",{className:"flex flex-col gap-0.5",children:[l.jsxs("div",{className:"relative w-full overflow-hidden bg-black aspect-[4/3]",children:[l.jsx(fr,{roverId:a,videoMode:r}),l.jsx(iw,{mobileHud:u}),l.jsx(Ig,{variant:"default",mobileHud:u,controlIntentAt:o}),l.jsx(Fg,{layoutFormat:n,variant:"default",mobileHud:u,labelScale:1}),l.jsx(bw,{mobileHud:u}),l.jsx(qw,{compact:u}),l.jsx(Xg,{compact:u}),l.jsx(Qg,{compact:u})]}),l.jsx(Rw,{mobileHud:u})]})})}function xo({label:n,tone:a="muted"}){const r=a==="success"?"bg-emerald-900 text-emerald-100":a==="warn"?"bg-amber-900 text-amber-100":"bg-slate-800 text-slate-200";return l.jsx("span",{className:`rounded px-1 py-0.5 text-xs font-semibold leading-none ${r}`,children:n})}function ko(n){if(!Number.isFinite(n))return 0;const a=n%360;return a<0?a+360:a}function Dw(n){if(!Array.isArray(n)||n.length<3)return 0;const[a,r,o]=n,u=Math.max(0,Math.min(255,Number(a)))/255,f=Math.max(0,Math.min(255,Number(r)))/255,p=Math.max(0,Math.min(255,Number(o)))/255,h=Math.max(u,f,p),g=Math.min(u,f,p),x=h-g;if(x===0)return 0;let v=0;return h===u?v=(f-p)/x%6:h===f?v=(p-u)/x+2:v=(u-f)/x+4,ko(Math.round(v*60))}function mx(n){const a=ko(n),r=1,o=1-Math.abs(a/60%2-1);let u=0,f=0,p=0;return a<60?(u=r,f=o):a<120?(u=o,f=r):a<180?(f=r,p=o):a<240?(f=o,p=r):a<300?(u=o,p=r):(u=r,p=o),[Math.round(u*255),Math.round(f*255),Math.round(p*255)]}function hx(n){return n?Array.isArray(n.hsColor)?ko(Number(n.hsColor[0])):Array.isArray(n.rgbColor)?Dw(n.rgbColor):0:0}function _w({entity:n,connected:a,controlsLocked:r,onToggle:o,onSetColor:u,onSetWhite:f}){const p=n.state==="unavailable"||!n.available,h=n.state==="on",g=n.type==="light"&&n.supportsColor,x=p?"warn":h?"success":"muted",v=p?"Unavailable":h?"On":"Off",b=r||!a||p,S=b||!g,[C,E]=m.useState(()=>hx(n)),N=m.useRef(C),w=m.useRef(!1),j=p?"border-slate-800 bg-slate-900 text-slate-400 cursor-not-allowed":r?"border-slate-800 bg-slate-900 text-slate-300 cursor-not-allowed":h?"border-emerald-700 bg-emerald-900/80 text-emerald-50 hover:bg-emerald-800":"border-rose-800 bg-rose-900/80 text-rose-50 hover:bg-rose-800";m.useEffect(()=>{if(!g||w.current)return;const L=hx(n);N.current=L,E(L)},[n.rgbColor,n.hsColor,g]);const T=L=>{const Y=ko(Number(L.target.value));N.current=Y,E(Y)},k=()=>{S||!u||u(n.id,mx(N.current))},M=L=>{L.stopPropagation()},D=L=>{M(L),!(S||!f)&&f(n.id)},B=`rgb(${(g?mx(N.current):[255,255,255]).join(",")})`;return l.jsxs("button",{type:"button",onClick:()=>o(n.id),disabled:b,className:`relative flex min-w-[12rem] flex-[1_1_12rem] items-start justify-between gap-0.5 rounded px-1 py-0.5 text-left transition-colors ${j} disabled:opacity-60 disabled:hover:bg-inherit`,children:[l.jsxs("div",{className:"min-w-0 flex-1",children:[l.jsxs("div",{className:"flex items-center gap-0.5 text-sm leading-normal",children:[l.jsx("span",{className:"truncate font-semibold text-white",children:n.name||n.id}),g&&l.jsxs(l.Fragment,{children:[l.jsx(xo,{label:v,tone:x}),!a&&l.jsx("span",{className:"text-xs text-amber-200",children:"Offline"})]})]}),g?l.jsx("div",{className:"-mt-0.5 w-full",onClick:M,onPointerDown:L=>{M(L),w.current=!0},onPointerUp:L=>{M(L),w.current=!1,k()},onPointerCancel:L=>{M(L),w.current=!1,k()},onKeyUp:L=>{M(L),k()},onBlur:k,children:l.jsx("div",{className:"relative w-full",children:l.jsx("input",{type:"range",min:"0",max:"360",step:"1",value:C,onChange:T,disabled:S,"aria-label":`Set color for ${n.name||n.id}`,className:"ha-hue-slider w-full"})})}):l.jsxs("div",{className:"flex items-center gap-0.5 text-xs text-slate-400",children:[l.jsx(xo,{label:v,tone:x}),!a&&l.jsx("span",{className:"text-amber-200",children:" · Offline"})]})]}),g&&l.jsxs("div",{className:"absolute right-1 top-1 flex items-center gap-0.5",children:[l.jsx("span",{role:"button",tabIndex:S?-1:0,onClick:D,onPointerDown:M,onKeyDown:L=>{S||(L.key==="Enter"||L.key===" ")&&(L.preventDefault(),D(L))},title:"Set white color temperature","aria-label":`Set ${n.name||n.id} to white`,"aria-disabled":S,className:`inline-flex items-center justify-center rounded border border-slate-200 bg-white px-1 py-0.5 text-xs font-semibold leading-none text-slate-900 ${S?"cursor-not-allowed opacity-60":"cursor-pointer hover:bg-slate-100"}`,children:"white"}),l.jsx("span",{className:"pointer-events-none h-2.5 w-2.5 rounded-full border border-white/60",style:{backgroundColor:B}})]}),!g&&l.jsx("div",{className:"self-center text-xs font-semibold text-white/90",children:h?"Turn off":"Turn on"})]})}function Kg(){const{state:{keymap:n}}=yt(),a=oe(S=>S.session?.homeAssistant||null),{homeAssistantToggle:r,homeAssistantSetLightColor:o,homeAssistantSetLightWhite:u}=$t(),f=m.useMemo(()=>a?.entities||[],[a?.entities]),p=a?.lightPolicy||null,h=!!(p?.locked||p?.lockedOn),g=p?.lockState||(p?.lockedOn?"on":null),x=Tt(n?.homeAssistantOn?.[0]),v=Tt(n?.homeAssistantOff?.[0]);if(!a?.enabled)return l.jsxs("section",{className:"panel-section space-y-0.5 text-sm text-slate-400",children:[l.jsx("p",{className:"text-slate-300",children:"Room Controls"}),l.jsx("p",{className:"text-slate-500",children:"Not configured on the server."})]});if(f.length===0)return l.jsxs("section",{className:"panel-section space-y-0.5 text-sm text-slate-400",children:[l.jsx("p",{className:"text-slate-300",children:"Room Controls"}),l.jsx("p",{className:"text-slate-500",children:"No lights or switches configured."})]});const b=!!a?.connected;return l.jsxs("section",{className:"panel-section space-y-0.5 text-base",children:[l.jsxs("header",{className:"flex items-center justify-between gap-0.5 text-sm text-slate-400",children:[l.jsxs("div",{className:"flex items-center gap-0.5",children:[l.jsx("p",{children:"Room Controls"}),l.jsx("span",{className:"text-xs text-slate-500",children:f.length}),h?l.jsx(xo,{label:g==="off"?"Locked Off":"Locked On",tone:"warn"}):null,l.jsxs("div",{className:"flex items-center gap-0.5 text-xs text-slate-300 background-black",children:[l.jsxs("span",{className:"flex items-center gap-0.5",children:[l.jsx("span",{children:"On"}),x?l.jsx(px,{label:x}):null]}),l.jsxs("span",{className:"flex items-center gap-0.5",children:[l.jsx("span",{children:"Off"}),v?l.jsx(px,{label:v}):null]})]})]}),l.jsx(xo,{label:b?"Connected":"Offline",tone:b?"success":"warn"})]}),h?l.jsx("p",{className:"rounded border border-amber-600/60 bg-amber-900/40 px-1 py-0.5 text-xs text-amber-100",children:g==="off"?"Lights are locked off. Room controls are disabled.":"Lights are locked on. Room controls are disabled."}):null,l.jsx("div",{className:"flex flex-wrap gap-0.5",children:f.map(S=>l.jsx(_w,{entity:S,connected:b,controlsLocked:h,onToggle:r,onSetColor:o,onSetWhite:u},S.id))})]})}function px({label:n}){return n?l.jsx("span",{className:"rounded border border-white/40 px-1 text-[0.7rem] text-white",children:n}):null}function Zg(){const{login:n,setRole:a}=$t(),[r,o]=m.useState(""),[u,f]=m.useState(""),[p,h]=m.useState(!1);async function g(x){x.preventDefault(),h(!0);try{await n(r,u),o(""),f("")}catch(v){alert(v.message)}finally{h(!1)}}return l.jsxs("div",{className:"panel-section space-y-0.5 text-base",children:[l.jsx("p",{className:"text-sm text-slate-400",children:"Admin login"}),l.jsxs("form",{className:"flex flex-col gap-0.5",onSubmit:g,children:[l.jsx("input",{className:"field-input",placeholder:"Username",value:r,onChange:x=>o(x.target.value)}),l.jsx("input",{className:"field-input",placeholder:"Password",type:"password",value:u,onChange:x=>f(x.target.value)}),l.jsx("button",{type:"submit",disabled:p,className:"button-dark w-full disabled:opacity-50",children:p?"Logging in…":"Login"})]})]})}function xx(...n){return n.filter(Boolean).join(" ")}function Ow(n){const a=n?.batteryState?.percentDisplay;return a==null?"--":`${a}%`}function Bw(n){return n?.batteryState?n.batteryState.urgentActive?"text-red-400":n.batteryState.warnActive?"text-amber-300":"text-emerald-300":"text-slate-400"}function Lw({title:n,roster:a=[],emptyText:r="No roster data.",renderActions:o=null}){return l.jsxs("div",{className:"space-y-0.5 text-sm",children:[n&&l.jsx("p",{className:"text-sm text-slate-400",children:n}),a.length===0?l.jsx("p",{className:"text-sm text-slate-500",children:r}):l.jsx("ul",{className:"space-y-0.5 text-sm",children:a.map(u=>{const f=!!(u?.private?.enabled&&u?.private?.open),p=!!u?.locked;return l.jsxs("li",{className:xx("surface flex flex-wrap items-center justify-between gap-0.5",p?"bg-red-900/40":f?"bg-amber-700/35 border border-amber-200/30":null),children:[l.jsxs("div",{children:[l.jsx("p",{className:"text-slate-200",children:l.jsx("span",{className:"rounded px-1 py-[1px] border border-transparent",style:ns(u.color,.16),children:u.name})}),l.jsxs("p",{className:"text-xs text-slate-500 flex flex-wrap items-center gap-0.5",children:[l.jsx("span",{children:u.locked?"locked":"free"}),u.lockReason&&l.jsx("span",{className:"rounded bg-black/30 px-1",children:u.lockReason}),l.jsxs("span",{className:xx("font-semibold",Bw(u)),children:["Battery ",Ow(u)]})]})]}),o?o(u):null]},u.id)})})]})}function zw(n){const a=n?.runtime||{},r=n?.output||{},o=n?.errors||{};return a.inFlight?{label:"IN FLIGHT",detail:a.reason||"Generating commentary now",className:"border-amber-400/60 bg-amber-700/20 text-amber-200"}:a.outcome==="posted"?{label:"POSTED",detail:r.posted?`Last: ${r.posted}`:"Commentary posted",className:"border-emerald-400/60 bg-emerald-700/20 text-emerald-200"}:a.outcome==="skipped"?{label:"SKIPPED",detail:a.reason||"Model chose to skip",className:"border-slate-400/60 bg-slate-700/30 text-slate-200"}:a.outcome==="failed"?{label:"FAILED",detail:o.message||a.reason||"Tick failed",className:"border-red-400/60 bg-red-700/20 text-red-200"}:{label:a.running?"IDLE":"STOPPED",detail:a.reason||"Waiting for next tick",className:"border-sky-400/50 bg-sky-700/20 text-sky-200"}}function Uw(n,a){const r=Date.now(),u=(Array.isArray(n)?n:[]).map((f,p)=>{const h=String(f?.role||"").toLowerCase(),g=typeof f?.content=="string"?f.content:JSON.stringify(f?.content??null,null,2),x=h==="system"?"LLM System":h==="assistant"?"LLM Context":h==="user"?"LLM Input":"LLM Message";return{id:`llm-msg-${p}`,message:{ts:r+p,nickname:x,text:g,role:"spectator",bot:h==="system"}}});if(a!=null){const f=String(a);u.push({id:"llm-output",message:{ts:r+u.length+1,nickname:"LLM Output",text:f.trim()?f:"",role:"spectator",bot:!0}})}return u}function Hw({state:n,onClearHistory:a,clearingHistory:r}){const[o,u]=m.useState(null);if(!n)return l.jsxs("div",{className:"space-y-0.5",children:[l.jsx("div",{className:"panel-muted text-xs uppercase",children:"LLM Commentary"}),l.jsx("div",{className:"surface text-xs text-slate-300",children:"No status received yet."})]});const f=n.runtime||{},p=n.counters||{},h=n.timings||{},g=n.input||{},x=n.output||{},v=n.errors||{},b=Array.isArray(n.history)?n.history:[],S=b.find(w=>w.runId===o)||(b.length?b[b.length-1]:null),C=zw(n),E=Uw(g.modelMessages,x.raw),N=[{label:"running",value:f.running?"yes":"no"},{label:"in flight",value:f.inFlight?"yes":"no"},{label:"phase",value:f.phase||"--"},{label:"run id",value:f.currentRunId??"--"},{label:"tick count",value:f.tickCount??0},{label:"last tick",value:f.lastTickAt?new Date(f.lastTickAt).toLocaleString():"never"},{label:"next run",value:f.nextRunAt?new Date(f.nextRunAt).toLocaleString():"n/a"},{label:"outcome",value:f.outcome||"--"},{label:"reason",value:f.reason||"--"},{label:"skip streak",value:p.skipStreak??0},{label:"clear count",value:p.clearCount??0},{label:"last gen",value:h.lastGenerationMs!=null?`${h.lastGenerationMs} ms`:"--"},{label:"avg gen",value:h.avgGenerationMs!=null?`${h.avgGenerationMs} ms`:"--"},{label:"gen count",value:h.generationCount??0},{label:"prompt chars",value:p.promptChars??0},{label:"active drivers",value:p.snapshotSummary?.activeDrivers??0},{label:"snapshot rovers",value:p.snapshotSummary?.rovers??0},{label:"snapshot chat",value:p.snapshotSummary?.chatMessages??0}];return l.jsxs("div",{className:"space-y-0.5",children:[l.jsx("div",{className:"panel-muted text-xs uppercase",children:"LLM Commentary"}),l.jsx("div",{className:"flex gap-0.5 text-xs",children:l.jsx("button",{type:"button",onClick:a,disabled:!!r,className:"button-danger disabled:cursor-not-allowed disabled:opacity-60",children:r?"Clearing...":"Clear LLM History"})}),l.jsxs("div",{className:`surface border text-center ${C.className}`,children:[l.jsx("div",{className:"text-[1.1rem] font-bold tracking-wide",children:C.label}),l.jsx("div",{className:"text-xs text-slate-200",children:C.detail})]}),l.jsx("div",{className:"surface flex flex-wrap gap-0.5 text-xs",children:N.map(w=>l.jsxs("span",{className:"rounded border border-slate-600/60 bg-slate-800/70 px-0.5 py-0.25 text-[0.72rem] leading-tight text-slate-200",children:[w.label,": ",w.value]},w.label))}),v.message?l.jsxs("div",{className:"surface text-xs text-red-300 break-words",children:["Error: ",v.message]}):null,v.details?l.jsxs("details",{className:"surface text-xs text-red-200",children:[l.jsx("summary",{className:"cursor-pointer select-none text-red-300",children:"Failure details"}),l.jsx("pre",{className:"mt-0.5 whitespace-pre-wrap break-words text-[0.72rem] text-red-200",children:JSON.stringify(v.details,null,2)})]}):null,x.generated?l.jsxs("div",{className:"surface text-xs text-slate-200 break-words",children:["Generated: ",x.generated]}):null,x.posted?l.jsxs("div",{className:"surface text-xs text-emerald-200 break-words",children:["Posted: ",x.posted]}):null,l.jsxs("div",{className:"grid gap-0.5 md:grid-cols-2",children:[l.jsxs("div",{className:"space-y-0.5",children:[l.jsx("div",{className:"panel-muted text-xs uppercase",children:"Live Input Conversation"}),l.jsx("div",{className:"surface max-h-72 space-y-0.5 overflow-y-auto",children:E.length?E.map(w=>l.jsx(nf,{message:w.message},w.id)):l.jsx("div",{className:"text-xs text-slate-300",children:"No model conversation captured yet."})})]}),l.jsxs("div",{className:"space-y-0.5",children:[l.jsx("div",{className:"panel-muted text-xs uppercase",children:"Output + Error"}),l.jsxs("div",{className:"surface space-y-0.5 text-xs text-slate-200",children:[l.jsxs("div",{children:["Raw output: ",x.raw?.trim()?x.raw:""]}),l.jsxs("div",{children:["Posted: ",x.posted||""]}),l.jsxs("div",{children:["Output at: ",x.modelOutputAt?new Date(x.modelOutputAt).toLocaleString():"n/a"]}),l.jsxs("div",{children:["Failed at: ",v.failedAt?new Date(v.failedAt).toLocaleString():"n/a"]})]})]})]}),l.jsxs("details",{className:"surface text-xs text-slate-200",children:[l.jsx("summary",{className:"cursor-pointer select-none text-slate-300",children:"Full Monitor Payload"}),l.jsx("pre",{className:"mt-0.5 whitespace-pre-wrap break-words text-[0.72rem] text-slate-200",children:JSON.stringify(n,null,2)})]}),l.jsxs("div",{className:"space-y-0.5",children:[l.jsx("div",{className:"panel-muted text-xs uppercase",children:"Recent Runs"}),l.jsx("div",{className:"surface max-h-52 space-y-0.5 overflow-y-auto text-xs",children:b.length?b.slice().reverse().map(w=>l.jsxs("button",{type:"button",onClick:()=>u(w.runId),className:`w-full text-left surface ${S?.runId===w.runId?"border border-sky-400/50":""}`,children:[l.jsxs("span",{className:"text-slate-300",children:["#",w.runId]})," ",l.jsx("span",{className:"text-slate-200",children:w.outcome||w.phase||"--"})," ",l.jsx("span",{className:"text-slate-400",children:w.durationMs!=null?`${w.durationMs}ms`:"--"})," ",l.jsx("span",{className:"text-slate-500",children:w.reason||""})]},w.runId)):l.jsx("div",{className:"text-slate-300",children:"No runs recorded yet."})})]}),S?l.jsxs("details",{className:"surface text-xs text-slate-200",open:!0,children:[l.jsxs("summary",{className:"cursor-pointer select-none text-slate-300",children:["Run #",S.runId," details"]}),l.jsx("pre",{className:"mt-0.5 whitespace-pre-wrap break-words text-[0.72rem] text-slate-200",children:JSON.stringify(S,null,2)})]}):null]})}function Vw({state:n,onClearHistory:a,clearingHistory:r}){const[o,u]=m.useState(!1);if(!n)return l.jsxs("div",{className:"space-y-0.5",children:[l.jsx("div",{className:"panel-muted text-xs uppercase",children:"Overseer Control"}),l.jsx("div",{className:"surface text-xs text-slate-300",children:"No status received yet."})]});const f=n.runtime||{},p=n.config||{},h=n.output||{},g=n.timings||{},x=n.input||{},v=n.errors||{},b=()=>{const S=Array.isArray(x.modelMessages)?x.modelMessages:[];return S.length?S.map((C,E)=>{const N=String(C?.role||"unknown").toUpperCase(),w=String(C?.content||"");return`#${E+1} ${N} ${w}`}).join(` ---------------------------------------- diff --git a/server/public/index.html b/server/public/index.html index 6c478a4c..f9d689a0 100644 --- a/server/public/index.html +++ b/server/public/index.html @@ -11,7 +11,7 @@ Roomba Rover - +