@alexberardi/jarvis-admin 0.1.81 → 0.1.82
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/package.json +1 -1
- package/public/assets/{index-bkuKvNYj.js → index-4y8tSbZj.js} +1 -1
- package/public/index.html +1 -1
- package/server/dist/data/service-registry.json +1 -1
- package/server/dist/routes/llm-setup.js +9 -9
- package/server/dist/routes/llm-setup.js.map +1 -1
- package/server/src/data/service-registry.json +1 -1
package/package.json
CHANGED
|
@@ -15,4 +15,4 @@ Please change the parent <Route path="${M}"> to <Route path="${M==="/"?"*":`${M}
|
|
|
15
15
|
`):" "+Cx(m[0]):"as no adapter specified";throw new we("There is no suitable adapter to dispatch the request "+v,"ERR_NOT_SUPPORT")}return d}const Yv={getAdapter:cj,adapters:Dd};function Fu(a){if(a.cancelToken&&a.cancelToken.throwIfRequested(),a.signal&&a.signal.aborted)throw new El(null,a)}function Tx(a){return Fu(a),a.headers=Zt.from(a.headers),a.data=Vu.call(a,a.transformRequest),["post","put","patch"].indexOf(a.method)!==-1&&a.headers.setContentType("application/x-www-form-urlencoded",!1),Yv.getAdapter(a.adapter||wl.adapter,a)(a).then(function(i){return Fu(a),i.data=Vu.call(a,a.transformResponse,i),i.headers=Zt.from(i.headers),i},function(i){return Hv(i)||(Fu(a),i&&i.response&&(i.response.data=Vu.call(a,a.transformResponse,i.response),i.response.headers=Zt.from(i.response.headers))),Promise.reject(i)})}const Xv="1.13.4",pi={};["object","boolean","number","function","string","symbol"].forEach((a,s)=>{pi[a]=function(i){return typeof i===a||"a"+(s<1?"n ":" ")+a}});const _x={};pi.transitional=function(s,o,i){function d(f,m){return"[Axios v"+Xv+"] Transitional option '"+f+"'"+m+(i?". "+i:"")}return(f,m,v)=>{if(s===!1)throw new we(d(m," has been removed"+(o?" in "+o:"")),we.ERR_DEPRECATED);return o&&!_x[m]&&(_x[m]=!0,console.warn(d(m," has been deprecated since v"+o+" and will be removed in the near future"))),s?s(f,m,v):!0}};pi.spelling=function(s){return(o,i)=>(console.warn(`${i} is likely a misspelling of ${s}`),!0)};function uj(a,s,o){if(typeof a!="object")throw new we("options must be an object",we.ERR_BAD_OPTION_VALUE);const i=Object.keys(a);let d=i.length;for(;d-- >0;){const f=i[d],m=s[f];if(m){const v=a[f],g=v===void 0||m(v,f,a);if(g!==!0)throw new we("option "+f+" must be "+g,we.ERR_BAD_OPTION_VALUE);continue}if(o!==!0)throw new we("Unknown option "+f,we.ERR_BAD_OPTION)}}const ei={assertOptions:uj,validators:pi},Oa=ei.validators;let ir=class{constructor(s){this.defaults=s||{},this.interceptors={request:new xx,response:new xx}}async request(s,o){try{return await this._request(s,o)}catch(i){if(i instanceof Error){let d={};Error.captureStackTrace?Error.captureStackTrace(d):d=new Error;const f=d.stack?d.stack.replace(/^.+\n/,""):"";try{i.stack?f&&!String(i.stack).endsWith(f.replace(/^.+\n.+\n/,""))&&(i.stack+=`
|
|
16
16
|
`+f):i.stack=f}catch{}}throw i}}_request(s,o){typeof s=="string"?(o=o||{},o.url=s):o=s||{},o=dr(this.defaults,o);const{transitional:i,paramsSerializer:d,headers:f}=o;i!==void 0&&ei.assertOptions(i,{silentJSONParsing:Oa.transitional(Oa.boolean),forcedJSONParsing:Oa.transitional(Oa.boolean),clarifyTimeoutError:Oa.transitional(Oa.boolean)},!1),d!=null&&(F.isFunction(d)?o.paramsSerializer={serialize:d}:ei.assertOptions(d,{encode:Oa.function,serialize:Oa.function},!0)),o.allowAbsoluteUrls!==void 0||(this.defaults.allowAbsoluteUrls!==void 0?o.allowAbsoluteUrls=this.defaults.allowAbsoluteUrls:o.allowAbsoluteUrls=!0),ei.assertOptions(o,{baseUrl:Oa.spelling("baseURL"),withXsrfToken:Oa.spelling("withXSRFToken")},!0),o.method=(o.method||this.defaults.method||"get").toLowerCase();let m=f&&F.merge(f.common,f[o.method]);f&&F.forEach(["delete","get","head","post","put","patch","common"],w=>{delete f[w]}),o.headers=Zt.concat(m,f);const v=[];let g=!0;this.interceptors.request.forEach(function(E){typeof E.runWhen=="function"&&E.runWhen(o)===!1||(g=g&&E.synchronous,v.unshift(E.fulfilled,E.rejected))});const h=[];this.interceptors.response.forEach(function(E){h.push(E.fulfilled,E.rejected)});let y,x=0,j;if(!g){const w=[Tx.bind(this),void 0];for(w.unshift(...v),w.push(...h),j=w.length,y=Promise.resolve(o);x<j;)y=y.then(w[x++],w[x++]);return y}j=v.length;let k=o;for(;x<j;){const w=v[x++],E=v[x++];try{k=w(k)}catch(_){E.call(this,_);break}}try{y=Tx.call(this,k)}catch(w){return Promise.reject(w)}for(x=0,j=h.length;x<j;)y=y.then(h[x++],h[x++]);return y}getUri(s){s=dr(this.defaults,s);const o=Qv(s.baseURL,s.url,s.allowAbsoluteUrls);return Lv(o,s.params,s.paramsSerializer)}};F.forEach(["delete","get","head","options"],function(s){ir.prototype[s]=function(o,i){return this.request(dr(i||{},{method:s,url:o,data:(i||{}).data}))}});F.forEach(["post","put","patch"],function(s){function o(i){return function(f,m,v){return this.request(dr(v||{},{method:s,headers:i?{"Content-Type":"multipart/form-data"}:{},url:f,data:m}))}}ir.prototype[s]=o(),ir.prototype[s+"Form"]=o(!0)});let dj=class Kv{constructor(s){if(typeof s!="function")throw new TypeError("executor must be a function.");let o;this.promise=new Promise(function(f){o=f});const i=this;this.promise.then(d=>{if(!i._listeners)return;let f=i._listeners.length;for(;f-- >0;)i._listeners[f](d);i._listeners=null}),this.promise.then=d=>{let f;const m=new Promise(v=>{i.subscribe(v),f=v}).then(d);return m.cancel=function(){i.unsubscribe(f)},m},s(function(f,m,v){i.reason||(i.reason=new El(f,m,v),o(i.reason))})}throwIfRequested(){if(this.reason)throw this.reason}subscribe(s){if(this.reason){s(this.reason);return}this._listeners?this._listeners.push(s):this._listeners=[s]}unsubscribe(s){if(!this._listeners)return;const o=this._listeners.indexOf(s);o!==-1&&this._listeners.splice(o,1)}toAbortSignal(){const s=new AbortController,o=i=>{s.abort(i)};return this.subscribe(o),s.signal.unsubscribe=()=>this.unsubscribe(o),s.signal}static source(){let s;return{token:new Kv(function(d){s=d}),cancel:s}}};function fj(a){return function(o){return a.apply(null,o)}}function mj(a){return F.isObject(a)&&a.isAxiosError===!0}const md={Continue:100,SwitchingProtocols:101,Processing:102,EarlyHints:103,Ok:200,Created:201,Accepted:202,NonAuthoritativeInformation:203,NoContent:204,ResetContent:205,PartialContent:206,MultiStatus:207,AlreadyReported:208,ImUsed:226,MultipleChoices:300,MovedPermanently:301,Found:302,SeeOther:303,NotModified:304,UseProxy:305,Unused:306,TemporaryRedirect:307,PermanentRedirect:308,BadRequest:400,Unauthorized:401,PaymentRequired:402,Forbidden:403,NotFound:404,MethodNotAllowed:405,NotAcceptable:406,ProxyAuthenticationRequired:407,RequestTimeout:408,Conflict:409,Gone:410,LengthRequired:411,PreconditionFailed:412,PayloadTooLarge:413,UriTooLong:414,UnsupportedMediaType:415,RangeNotSatisfiable:416,ExpectationFailed:417,ImATeapot:418,MisdirectedRequest:421,UnprocessableEntity:422,Locked:423,FailedDependency:424,TooEarly:425,UpgradeRequired:426,PreconditionRequired:428,TooManyRequests:429,RequestHeaderFieldsTooLarge:431,UnavailableForLegalReasons:451,InternalServerError:500,NotImplemented:501,BadGateway:502,ServiceUnavailable:503,GatewayTimeout:504,HttpVersionNotSupported:505,VariantAlsoNegotiates:506,InsufficientStorage:507,LoopDetected:508,NotExtended:510,NetworkAuthenticationRequired:511,WebServerIsDown:521,ConnectionTimedOut:522,OriginIsUnreachable:523,TimeoutOccurred:524,SslHandshakeFailed:525,InvalidSslCertificate:526};Object.entries(md).forEach(([a,s])=>{md[s]=a});function $v(a){const s=new ir(a),o=Cv(ir.prototype.request,s);return F.extend(o,ir.prototype,s,{allOwnKeys:!0}),F.extend(o,s,null,{allOwnKeys:!0}),o.create=function(d){return $v(dr(a,d))},o}const nt=$v(wl);nt.Axios=ir;nt.CanceledError=El;nt.CancelToken=dj;nt.isCancel=Hv;nt.VERSION=Xv;nt.toFormData=hi;nt.AxiosError=we;nt.Cancel=nt.CanceledError;nt.all=function(s){return Promise.all(s)};nt.spread=fj;nt.isAxiosError=mj;nt.mergeConfig=dr;nt.AxiosHeaders=Zt;nt.formToJSON=a=>qv(F.isHTMLForm(a)?new FormData(a):a);nt.getAdapter=Yv.getAdapter;nt.HttpStatusCode=md;nt.default=nt;const{Axios:d3,AxiosError:f3,CanceledError:m3,isCancel:h3,CancelToken:p3,VERSION:x3,all:v3,Cancel:g3,isAxiosError:y3,spread:b3,toFormData:N3,AxiosHeaders:j3,HttpStatusCode:S3,formToJSON:w3,getAdapter:E3,mergeConfig:C3}=nt,ge=nt.create({baseURL:""});function rs(a){a?ge.defaults.headers.common.Authorization=`Bearer ${a}`:delete ge.defaults.headers.common.Authorization}let hd=null;function hj(a){hd=a}let Zv=null;function pj(a){Zv=a}ge.interceptors.request.use(a=>{if(!a.headers.Authorization){const s=localStorage.getItem("jarvis-admin:access_token")??localStorage.getItem("access_token");s&&(a.headers.Authorization=`Bearer ${s}`)}return a});ge.interceptors.response.use(a=>a,async a=>{const s=a.config;if(s.url?.startsWith("/api/auth/"))return Promise.reject(a);if(a.response?.status===401&&!s._retry&&hd){s._retry=!0;const o=await hd();if(o)return s.headers.Authorization=`Bearer ${o}`,ge(s);Zv?.()}return Promise.reject(a)});async function xj(){const{data:a}=await ge.get("/api/auth/setup-status");return a}async function Jv(a,s,o){const{data:i}=await ge.post("/api/auth/setup",{email:a,password:s,username:o});return i}async function vj(a,s){const{data:o}=await ge.post("/api/auth/login",{email:a,password:s});return o}async function gj(a){const{data:s}=await ge.post("/api/auth/refresh",{refresh_token:a});return s}const Pv=N.createContext(void 0),ml="jarvis-admin:access_token",ts="jarvis-admin:refresh_token",Yo="jarvis-admin:user",yj=600*1e3;function bj({children:a}){const[s,o]=N.useState(()=>{const g=localStorage.getItem(ml),h=localStorage.getItem(ts),y=localStorage.getItem(Yo);if(g&&h&&y)try{const x=JSON.parse(y);return rs(g),{user:x,accessToken:g,refreshToken:h,isAuthenticated:!0,isLoading:!1,error:null}}catch{}return{user:null,accessToken:null,refreshToken:null,isAuthenticated:!1,isLoading:!1,error:null}}),i=N.useCallback(()=>{localStorage.removeItem(ml),localStorage.removeItem(ts),localStorage.removeItem(Yo),rs(null),o({user:null,accessToken:null,refreshToken:null,isAuthenticated:!1,isLoading:!1,error:null})},[]),d=N.useCallback(async()=>{const g=localStorage.getItem(ts);if(!g)return null;try{const h=await gj(g),y=h.access_token,x=h.refresh_token??g;return localStorage.setItem(ml,y),localStorage.setItem(ts,x),rs(y),o(j=>({...j,accessToken:y,refreshToken:x})),y}catch{return i(),null}},[i]);N.useEffect(()=>{hj(d),pj(i)},[d,i]),N.useEffect(()=>{if(!s.isAuthenticated)return;const g=setInterval(()=>{d()},yj);return()=>clearInterval(g)},[s.isAuthenticated,d]);const f=N.useCallback(async(g,h)=>{o(y=>({...y,error:null,isLoading:!0}));try{const y=await vj(g,h);if(!y.user.is_superuser){o(x=>({...x,isLoading:!1,error:"Admin access required. This account is not a superuser."}));return}localStorage.setItem(ml,y.access_token),localStorage.setItem(ts,y.refresh_token),localStorage.setItem(Yo,JSON.stringify(y.user)),rs(y.access_token),o({user:y.user,accessToken:y.access_token,refreshToken:y.refresh_token,isAuthenticated:!0,isLoading:!1,error:null})}catch(y){const x=y?.response?.data?.detail??"Login failed";o(j=>({...j,isLoading:!1,error:x}))}},[]),m=N.useCallback(async(g,h,y)=>{o(x=>({...x,error:null,isLoading:!0}));try{const x=await Jv(g,h,y);localStorage.setItem(ml,x.access_token),localStorage.setItem(ts,x.refresh_token),localStorage.setItem(Yo,JSON.stringify(x.user)),rs(x.access_token),o({user:x.user,accessToken:x.access_token,refreshToken:x.refresh_token,isAuthenticated:!0,isLoading:!1,error:null})}catch(x){const j=x?.response?.data?.detail??"Setup failed";o(k=>({...k,isLoading:!1,error:j}))}},[]),v=N.useMemo(()=>({state:s,login:f,setup:m,logout:i}),[s,f,m,i]);return l.jsx(Pv.Provider,{value:v,children:a})}function Ud(){const a=N.useContext(Pv);if(!a)throw new Error("useAuth must be used within AuthProvider");return a}const Iv=(...a)=>a.filter((s,o,i)=>!!s&&s.trim()!==""&&i.indexOf(s)===o).join(" ").trim();const Nj=a=>a.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase();const jj=a=>a.replace(/^([A-Z])|[\s-_]+(\w)/g,(s,o,i)=>i?i.toUpperCase():o.toLowerCase());const Rx=a=>{const s=jj(a);return s.charAt(0).toUpperCase()+s.slice(1)};var Sj={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"};const wj=a=>{for(const s in a)if(s.startsWith("aria-")||s==="role"||s==="title")return!0;return!1};const Ej=N.forwardRef(({color:a="currentColor",size:s=24,strokeWidth:o=2,absoluteStrokeWidth:i,className:d="",children:f,iconNode:m,...v},g)=>N.createElement("svg",{ref:g,...Sj,width:s,height:s,stroke:a,strokeWidth:i?Number(o)*24/Number(s):o,className:Iv("lucide",d),...!f&&!wj(v)&&{"aria-hidden":"true"},...v},[...m.map(([h,y])=>N.createElement(h,y)),...Array.isArray(f)?f:[f]]));const ye=(a,s)=>{const o=N.forwardRef(({className:i,...d},f)=>N.createElement(Ej,{ref:f,iconNode:s,className:Iv(`lucide-${Nj(Rx(a))}`,`lucide-${a}`,i),...d}));return o.displayName=Rx(a),o};const Cj=[["path",{d:"M22 12h-2.48a2 2 0 0 0-1.93 1.46l-2.35 8.36a.25.25 0 0 1-.48 0L9.24 2.18a.25.25 0 0 0-.48 0l-2.35 8.36A2 2 0 0 1 4.49 12H2",key:"169zse"}]],Tj=ye("activity",Cj);const _j=[["path",{d:"M21 8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16Z",key:"hh9hay"}],["path",{d:"m3.3 7 8.7 5 8.7-5",key:"g66t2b"}],["path",{d:"M12 22V12",key:"d0xqtd"}]],Rj=ye("box",_j);const kj=[["path",{d:"M2.97 12.92A2 2 0 0 0 2 14.63v3.24a2 2 0 0 0 .97 1.71l3 1.8a2 2 0 0 0 2.06 0L12 19v-5.5l-5-3-4.03 2.42Z",key:"lc1i9w"}],["path",{d:"m7 16.5-4.74-2.85",key:"1o9zyk"}],["path",{d:"m7 16.5 5-3",key:"va8pkn"}],["path",{d:"M7 16.5v5.17",key:"jnp8gn"}],["path",{d:"M12 13.5V19l3.97 2.38a2 2 0 0 0 2.06 0l3-1.8a2 2 0 0 0 .97-1.71v-3.24a2 2 0 0 0-.97-1.71L17 10.5l-5 3Z",key:"8zsnat"}],["path",{d:"m17 16.5-5-3",key:"8arw3v"}],["path",{d:"m17 16.5 4.74-2.85",key:"8rfmw"}],["path",{d:"M17 16.5v5.17",key:"k6z78m"}],["path",{d:"M7.97 4.42A2 2 0 0 0 7 6.13v4.37l5 3 5-3V6.13a2 2 0 0 0-.97-1.71l-3-1.8a2 2 0 0 0-2.06 0l-3 1.8Z",key:"1xygjf"}],["path",{d:"M12 8 7.26 5.15",key:"1vbdud"}],["path",{d:"m12 8 4.74-2.85",key:"3rx089"}],["path",{d:"M12 13.5V8",key:"1io7kd"}]],Mj=ye("boxes",kj);const Aj=[["path",{d:"M12 18V5",key:"adv99a"}],["path",{d:"M15 13a4.17 4.17 0 0 1-3-4 4.17 4.17 0 0 1-3 4",key:"1e3is1"}],["path",{d:"M17.598 6.5A3 3 0 1 0 12 5a3 3 0 1 0-5.598 1.5",key:"1gqd8o"}],["path",{d:"M17.997 5.125a4 4 0 0 1 2.526 5.77",key:"iwvgf7"}],["path",{d:"M18 18a4 4 0 0 0 2-7.464",key:"efp6ie"}],["path",{d:"M19.967 17.483A4 4 0 1 1 12 18a4 4 0 1 1-7.967-.517",key:"1gq6am"}],["path",{d:"M6 18a4 4 0 0 1-2-7.464",key:"k1g0md"}],["path",{d:"M6.003 5.125a4 4 0 0 0-2.526 5.77",key:"q97ue3"}]],pd=ye("brain",Aj);const Oj=[["path",{d:"M20 6 9 17l-5-5",key:"1gmf2c"}]],xi=ye("check",Oj);const zj=[["path",{d:"m6 9 6 6 6-6",key:"qrunsl"}]],Ld=ye("chevron-down",zj);const Dj=[["path",{d:"m9 18 6-6-6-6",key:"mthhwq"}]],Wv=ye("chevron-right",Dj);const Uj=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["line",{x1:"12",x2:"12",y1:"8",y2:"12",key:"1pkeuh"}],["line",{x1:"12",x2:"12.01",y1:"16",y2:"16",key:"4dfq90"}]],Bd=ye("circle-alert",Uj);const Lj=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"m16 12-4-4-4 4",key:"177agl"}],["path",{d:"M12 16V8",key:"1sbj14"}]],eg=ye("circle-arrow-up",Lj);const Bj=[["path",{d:"M21.801 10A10 10 0 1 1 17 3.335",key:"yps3ct"}],["path",{d:"m9 11 3 3L22 4",key:"1pflzl"}]],qj=ye("circle-check-big",Bj);const Hj=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"m9 12 2 2 4-4",key:"dzmm74"}]],ht=ye("circle-check",Hj);const Gj=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"m15 9-6 6",key:"1uzhvr"}],["path",{d:"m9 9 6 6",key:"z0biqf"}]],xl=ye("circle-x",Gj);const Qj=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}]],os=ye("circle",Qj);const Vj=[["path",{d:"M12 6v6l4 2",key:"mmk7yg"}],["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}]],Fj=ye("clock",Vj);const Yj=[["rect",{width:"14",height:"14",x:"8",y:"8",rx:"2",ry:"2",key:"17jyea"}],["path",{d:"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2",key:"zix9uf"}]],qd=ye("copy",Yj);const Xj=[["path",{d:"M12 20v2",key:"1lh1kg"}],["path",{d:"M12 2v2",key:"tus03m"}],["path",{d:"M17 20v2",key:"1rnc9c"}],["path",{d:"M17 2v2",key:"11trls"}],["path",{d:"M2 12h2",key:"1t8f8n"}],["path",{d:"M2 17h2",key:"7oei6x"}],["path",{d:"M2 7h2",key:"asdhe0"}],["path",{d:"M20 12h2",key:"1q8mjw"}],["path",{d:"M20 17h2",key:"1fpfkl"}],["path",{d:"M20 7h2",key:"1o8tra"}],["path",{d:"M7 20v2",key:"4gnj0m"}],["path",{d:"M7 2v2",key:"1i4yhu"}],["rect",{x:"4",y:"4",width:"16",height:"16",rx:"2",key:"1vbyd7"}],["rect",{x:"8",y:"8",width:"8",height:"8",rx:"1",key:"z9xiuo"}]],On=ye("cpu",Xj);const Kj=[["ellipse",{cx:"12",cy:"5",rx:"9",ry:"3",key:"msslwz"}],["path",{d:"M3 5V19A9 3 0 0 0 21 19V5",key:"1wlel7"}],["path",{d:"M3 12A9 3 0 0 0 21 12",key:"mv7ke4"}]],$j=ye("database",Kj);const Zj=[["path",{d:"M12 15V3",key:"m9g1x1"}],["path",{d:"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4",key:"ih7n3h"}],["path",{d:"m7 10 5 5 5-5",key:"brsn70"}]],en=ye("download",Zj);const Jj=[["path",{d:"M15 3h6v6",key:"1q9fwt"}],["path",{d:"M10 14 21 3",key:"gplh6r"}],["path",{d:"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6",key:"a6xqqp"}]],Pj=ye("external-link",Jj);const Ij=[["path",{d:"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z",key:"1oefj6"}],["path",{d:"M14 2v5a1 1 0 0 0 1 1h5",key:"wfsgrz"}],["path",{d:"M10 9H8",key:"b1mrlr"}],["path",{d:"M16 13H8",key:"t4e002"}],["path",{d:"M16 17H8",key:"z1uh3a"}]],tg=ye("file-text",Ij);const Wj=[["circle",{cx:"18",cy:"18",r:"3",key:"1xkwt0"}],["circle",{cx:"6",cy:"6",r:"3",key:"1lh9wr"}],["path",{d:"M6 21V9a9 9 0 0 0 9 9",key:"7kw0sc"}]],xd=ye("git-merge",Wj);const eS=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20",key:"13o1zl"}],["path",{d:"M2 12h20",key:"9i4pu4"}]],tS=ye("globe",eS);const aS=[["line",{x1:"22",x2:"2",y1:"12",y2:"12",key:"1y58io"}],["path",{d:"M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z",key:"oot6mr"}],["line",{x1:"6",x2:"6.01",y1:"16",y2:"16",key:"sgf278"}],["line",{x1:"10",x2:"10.01",y1:"16",y2:"16",key:"1l4acy"}]],Hd=ye("hard-drive",aS);const nS=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M12 16v-4",key:"1dtifu"}],["path",{d:"M12 8h.01",key:"e9boi3"}]],rS=ye("info",nS);const sS=[["path",{d:"M2.586 17.414A2 2 0 0 0 2 18.828V21a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h1a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h.172a2 2 0 0 0 1.414-.586l.814-.814a6.5 6.5 0 1 0-4-4z",key:"1s6t7t"}],["circle",{cx:"16.5",cy:"7.5",r:".5",fill:"currentColor",key:"w0ekpg"}]],lS=ye("key-round",sS);const oS=[["path",{d:"m15.5 7.5 2.3 2.3a1 1 0 0 0 1.4 0l2.1-2.1a1 1 0 0 0 0-1.4L19 4",key:"g0fldk"}],["path",{d:"m21 2-9.6 9.6",key:"1j0ho8"}],["circle",{cx:"7.5",cy:"15.5",r:"5.5",key:"yqb3hr"}]],iS=ye("key",oS);const cS=[["rect",{width:"7",height:"9",x:"3",y:"3",rx:"1",key:"10lvy0"}],["rect",{width:"7",height:"5",x:"14",y:"3",rx:"1",key:"16une8"}],["rect",{width:"7",height:"9",x:"14",y:"12",rx:"1",key:"1hutg5"}],["rect",{width:"7",height:"5",x:"3",y:"16",rx:"1",key:"ldoo1y"}]],uS=ye("layout-dashboard",cS);const dS=[["path",{d:"M21 12a9 9 0 1 1-6.219-8.56",key:"13zald"}]],Ct=ye("loader-circle",dS);const fS=[["rect",{width:"18",height:"11",x:"3",y:"11",rx:"2",ry:"2",key:"1w4ew1"}],["path",{d:"M7 11V7a5 5 0 0 1 9.9-1",key:"1mm8w8"}]],mS=ye("lock-open",fS);const hS=[["rect",{width:"18",height:"11",x:"3",y:"11",rx:"2",ry:"2",key:"1w4ew1"}],["path",{d:"M7 11V7a5 5 0 0 1 10 0v4",key:"fwvmzm"}]],vi=ye("lock",hS);const pS=[["path",{d:"m16 17 5-5-5-5",key:"1bji2h"}],["path",{d:"M21 12H9",key:"dn1m92"}],["path",{d:"M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4",key:"1uf3rs"}]],xS=ye("log-out",pS);const vS=[["path",{d:"M12 19v3",key:"npa21l"}],["path",{d:"M19 10v2a7 7 0 0 1-14 0v-2",key:"1vc78b"}],["rect",{x:"9",y:"2",width:"6",height:"13",rx:"3",key:"s6n7sd"}]],kx=ye("mic",vS);const gS=[["rect",{width:"20",height:"14",x:"2",y:"3",rx:"2",key:"48i651"}],["line",{x1:"8",x2:"16",y1:"21",y2:"21",key:"1svkeh"}],["line",{x1:"12",x2:"12",y1:"17",y2:"21",key:"vw1qmm"}]],yS=ye("monitor",gS);const bS=[["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"}]],NS=ye("moon",bS);const jS=[["path",{d:"M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z",key:"1a8usu"}],["path",{d:"m15 5 4 4",key:"1mk7zo"}]],SS=ye("pencil",jS);const wS=[["path",{d:"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z",key:"10ikf1"}]],ag=ye("play",wS);const ES=[["path",{d:"M5 12h14",key:"1ays0h"}],["path",{d:"M12 5v14",key:"s699le"}]],ti=ye("plus",ES);const CS=[["path",{d:"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8",key:"v9h5vc"}],["path",{d:"M21 3v5h-5",key:"1q7to0"}],["path",{d:"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16",key:"3uifl3"}],["path",{d:"M8 16H3v5",key:"1cv678"}]],it=ye("refresh-cw",CS);const TS=[["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"}]],gi=ye("rotate-ccw",TS);const _S=[["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"}]],Gd=ye("rotate-cw",_S);const RS=[["path",{d:"m21 21-4.34-4.34",key:"14j7rj"}],["circle",{cx:"11",cy:"11",r:"8",key:"4ej97u"}]],kS=ye("search",RS);const MS=[["rect",{width:"20",height:"8",x:"2",y:"2",rx:"2",ry:"2",key:"ngkwjq"}],["rect",{width:"20",height:"8",x:"2",y:"14",rx:"2",ry:"2",key:"iecqi9"}],["line",{x1:"6",x2:"6.01",y1:"6",y2:"6",key:"16zg32"}],["line",{x1:"6",x2:"6.01",y1:"18",y2:"18",key:"nzw8ys"}]],Qd=ye("server",MS);const AS=[["path",{d:"M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915",key:"1i5ecw"}],["circle",{cx:"12",cy:"12",r:"3",key:"1v7zrd"}]],ng=ye("settings",AS);const OS=[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z",key:"oel41y"}],["path",{d:"m9 12 2 2 4-4",key:"dzmm74"}]],zS=ye("shield-check",OS);const DS=[["path",{d:"M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594z",key:"1s2grr"}],["path",{d:"M20 2v4",key:"1rf3ol"}],["path",{d:"M22 4h-4",key:"gwowj6"}],["circle",{cx:"4",cy:"20",r:"2",key:"6kqj1y"}]],US=ye("sparkles",DS);const LS=[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}]],BS=ye("square",LS);const qS=[["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"}]],HS=ye("sun",qS);const GS=[["path",{d:"M10 11v6",key:"nco0om"}],["path",{d:"M14 11v6",key:"outv1u"}],["path",{d:"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6",key:"miytrc"}],["path",{d:"M3 6h18",key:"d0wm0j"}],["path",{d:"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2",key:"e791ji"}]],yi=ye("trash-2",GS);const QS=[["path",{d:"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3",key:"wmoenq"}],["path",{d:"M12 9v4",key:"juzpu7"}],["path",{d:"M12 17h.01",key:"p32p05"}]],ra=ye("triangle-alert",QS);const VS=[["path",{d:"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2",key:"1yyitq"}],["circle",{cx:"9",cy:"7",r:"4",key:"nufk8"}],["line",{x1:"17",x2:"22",y1:"8",y2:"13",key:"3nzzx3"}],["line",{x1:"22",x2:"17",y1:"8",y2:"13",key:"1swrse"}]],FS=ye("user-x",VS);const YS=[["path",{d:"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2",key:"1yyitq"}],["path",{d:"M16 3.128a4 4 0 0 1 0 7.744",key:"16gr8j"}],["path",{d:"M22 21v-2a4 4 0 0 0-3-3.87",key:"kshegd"}],["circle",{cx:"9",cy:"7",r:"4",key:"nufk8"}]],XS=ye("users",YS);const KS=[["path",{d:"M18 6 6 18",key:"1bl5f8"}],["path",{d:"m6 6 12 12",key:"d8bk6v"}]],Vd=ye("x",KS);const $S=[["path",{d:"M10.513 4.856 13.12 2.17a.5.5 0 0 1 .86.46l-1.377 4.317",key:"193nxd"}],["path",{d:"M15.656 10H20a1 1 0 0 1 .78 1.63l-1.72 1.773",key:"27a7lr"}],["path",{d:"M16.273 16.273 10.88 21.83a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14H4a1 1 0 0 1-.78-1.63l4.507-4.643",key:"1e0qe9"}],["path",{d:"m2 2 20 20",key:"1ooewy"}]],ZS=ye("zap-off",$S);const JS=[["path",{d:"M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z",key:"1xq2db"}]],oi=ye("zap",JS);function rg(a){var s,o,i="";if(typeof a=="string"||typeof a=="number")i+=a;else if(typeof a=="object")if(Array.isArray(a)){var d=a.length;for(s=0;s<d;s++)a[s]&&(o=rg(a[s]))&&(i&&(i+=" "),i+=o)}else for(o in a)a[o]&&(i&&(i+=" "),i+=o);return i}function PS(){for(var a,s,o=0,i="",d=arguments.length;o<d;o++)(a=arguments[o])&&(s=rg(a))&&(i&&(i+=" "),i+=s);return i}const IS=(a,s)=>{const o=new Array(a.length+s.length);for(let i=0;i<a.length;i++)o[i]=a[i];for(let i=0;i<s.length;i++)o[a.length+i]=s[i];return o},WS=(a,s)=>({classGroupId:a,validator:s}),sg=(a=new Map,s=null,o)=>({nextPart:a,validators:s,classGroupId:o}),ii="-",Mx=[],ew="arbitrary..",tw=a=>{const s=nw(a),{conflictingClassGroups:o,conflictingClassGroupModifiers:i}=a;return{getClassGroupId:m=>{if(m.startsWith("[")&&m.endsWith("]"))return aw(m);const v=m.split(ii),g=v[0]===""&&v.length>1?1:0;return lg(v,g,s)},getConflictingClassGroupIds:(m,v)=>{if(v){const g=i[m],h=o[m];return g?h?IS(h,g):g:h||Mx}return o[m]||Mx}}},lg=(a,s,o)=>{if(a.length-s===0)return o.classGroupId;const d=a[s],f=o.nextPart.get(d);if(f){const h=lg(a,s+1,f);if(h)return h}const m=o.validators;if(m===null)return;const v=s===0?a.join(ii):a.slice(s).join(ii),g=m.length;for(let h=0;h<g;h++){const y=m[h];if(y.validator(v))return y.classGroupId}},aw=a=>a.slice(1,-1).indexOf(":")===-1?void 0:(()=>{const s=a.slice(1,-1),o=s.indexOf(":"),i=s.slice(0,o);return i?ew+i:void 0})(),nw=a=>{const{theme:s,classGroups:o}=a;return rw(o,s)},rw=(a,s)=>{const o=sg();for(const i in a){const d=a[i];Fd(d,o,i,s)}return o},Fd=(a,s,o,i)=>{const d=a.length;for(let f=0;f<d;f++){const m=a[f];sw(m,s,o,i)}},sw=(a,s,o,i)=>{if(typeof a=="string"){lw(a,s,o);return}if(typeof a=="function"){ow(a,s,o,i);return}iw(a,s,o,i)},lw=(a,s,o)=>{const i=a===""?s:og(s,a);i.classGroupId=o},ow=(a,s,o,i)=>{if(cw(a)){Fd(a(i),s,o,i);return}s.validators===null&&(s.validators=[]),s.validators.push(WS(o,a))},iw=(a,s,o,i)=>{const d=Object.entries(a),f=d.length;for(let m=0;m<f;m++){const[v,g]=d[m];Fd(g,og(s,v),o,i)}},og=(a,s)=>{let o=a;const i=s.split(ii),d=i.length;for(let f=0;f<d;f++){const m=i[f];let v=o.nextPart.get(m);v||(v=sg(),o.nextPart.set(m,v)),o=v}return o},cw=a=>"isThemeGetter"in a&&a.isThemeGetter===!0,uw=a=>{if(a<1)return{get:()=>{},set:()=>{}};let s=0,o=Object.create(null),i=Object.create(null);const d=(f,m)=>{o[f]=m,s++,s>a&&(s=0,i=o,o=Object.create(null))};return{get(f){let m=o[f];if(m!==void 0)return m;if((m=i[f])!==void 0)return d(f,m),m},set(f,m){f in o?o[f]=m:d(f,m)}}},vd="!",Ax=":",dw=[],Ox=(a,s,o,i,d)=>({modifiers:a,hasImportantModifier:s,baseClassName:o,maybePostfixModifierPosition:i,isExternal:d}),fw=a=>{const{prefix:s,experimentalParseClassName:o}=a;let i=d=>{const f=[];let m=0,v=0,g=0,h;const y=d.length;for(let E=0;E<y;E++){const _=d[E];if(m===0&&v===0){if(_===Ax){f.push(d.slice(g,E)),g=E+1;continue}if(_==="/"){h=E;continue}}_==="["?m++:_==="]"?m--:_==="("?v++:_===")"&&v--}const x=f.length===0?d:d.slice(g);let j=x,k=!1;x.endsWith(vd)?(j=x.slice(0,-1),k=!0):x.startsWith(vd)&&(j=x.slice(1),k=!0);const w=h&&h>g?h-g:void 0;return Ox(f,k,j,w)};if(s){const d=s+Ax,f=i;i=m=>m.startsWith(d)?f(m.slice(d.length)):Ox(dw,!1,m,void 0,!0)}if(o){const d=i;i=f=>o({className:f,parseClassName:d})}return i},mw=a=>{const s=new Map;return a.orderSensitiveModifiers.forEach((o,i)=>{s.set(o,1e6+i)}),o=>{const i=[];let d=[];for(let f=0;f<o.length;f++){const m=o[f],v=m[0]==="[",g=s.has(m);v||g?(d.length>0&&(d.sort(),i.push(...d),d=[]),i.push(m)):d.push(m)}return d.length>0&&(d.sort(),i.push(...d)),i}},hw=a=>({cache:uw(a.cacheSize),parseClassName:fw(a),sortModifiers:mw(a),...tw(a)}),pw=/\s+/,xw=(a,s)=>{const{parseClassName:o,getClassGroupId:i,getConflictingClassGroupIds:d,sortModifiers:f}=s,m=[],v=a.trim().split(pw);let g="";for(let h=v.length-1;h>=0;h-=1){const y=v[h],{isExternal:x,modifiers:j,hasImportantModifier:k,baseClassName:w,maybePostfixModifierPosition:E}=o(y);if(x){g=y+(g.length>0?" "+g:g);continue}let _=!!E,A=i(_?w.substring(0,E):w);if(!A){if(!_){g=y+(g.length>0?" "+g:g);continue}if(A=i(w),!A){g=y+(g.length>0?" "+g:g);continue}_=!1}const M=j.length===0?"":j.length===1?j[0]:f(j).join(":"),X=k?M+vd:M,I=X+A;if(m.indexOf(I)>-1)continue;m.push(I);const ne=d(A,_);for(let W=0;W<ne.length;++W){const G=ne[W];m.push(X+G)}g=y+(g.length>0?" "+g:g)}return g},vw=(...a)=>{let s=0,o,i,d="";for(;s<a.length;)(o=a[s++])&&(i=ig(o))&&(d&&(d+=" "),d+=i);return d},ig=a=>{if(typeof a=="string")return a;let s,o="";for(let i=0;i<a.length;i++)a[i]&&(s=ig(a[i]))&&(o&&(o+=" "),o+=s);return o},gw=(a,...s)=>{let o,i,d,f;const m=g=>{const h=s.reduce((y,x)=>x(y),a());return o=hw(h),i=o.cache.get,d=o.cache.set,f=v,v(g)},v=g=>{const h=i(g);if(h)return h;const y=xw(g,o);return d(g,y),y};return f=m,(...g)=>f(vw(...g))},yw=[],dt=a=>{const s=o=>o[a]||yw;return s.isThemeGetter=!0,s},cg=/^\[(?:(\w[\w-]*):)?(.+)\]$/i,ug=/^\((?:(\w[\w-]*):)?(.+)\)$/i,bw=/^\d+\/\d+$/,Nw=/^(\d+(\.\d+)?)?(xs|sm|md|lg|xl)$/,jw=/\d+(%|px|r?em|[sdl]?v([hwib]|min|max)|pt|pc|in|cm|mm|cap|ch|ex|r?lh|cq(w|h|i|b|min|max))|\b(calc|min|max|clamp)\(.+\)|^0$/,Sw=/^(rgba?|hsla?|hwb|(ok)?(lab|lch)|color-mix)\(.+\)$/,ww=/^(inset_)?-?((\d+)?\.?(\d+)[a-z]+|0)_-?((\d+)?\.?(\d+)[a-z]+|0)/,Ew=/^(url|image|image-set|cross-fade|element|(repeating-)?(linear|radial|conic)-gradient)\(.+\)$/,as=a=>bw.test(a),Ae=a=>!!a&&!Number.isNaN(Number(a)),Mn=a=>!!a&&Number.isInteger(Number(a)),Yu=a=>a.endsWith("%")&&Ae(a.slice(0,-1)),Wa=a=>Nw.test(a),Cw=()=>!0,Tw=a=>jw.test(a)&&!Sw.test(a),dg=()=>!1,_w=a=>ww.test(a),Rw=a=>Ew.test(a),kw=a=>!ue(a)&&!de(a),Mw=a=>ms(a,hg,dg),ue=a=>cg.test(a),sr=a=>ms(a,pg,Tw),Xu=a=>ms(a,Uw,Ae),zx=a=>ms(a,fg,dg),Aw=a=>ms(a,mg,Rw),Xo=a=>ms(a,xg,_w),de=a=>ug.test(a),hl=a=>hs(a,pg),Ow=a=>hs(a,Lw),Dx=a=>hs(a,fg),zw=a=>hs(a,hg),Dw=a=>hs(a,mg),Ko=a=>hs(a,xg,!0),ms=(a,s,o)=>{const i=cg.exec(a);return i?i[1]?s(i[1]):o(i[2]):!1},hs=(a,s,o=!1)=>{const i=ug.exec(a);return i?i[1]?s(i[1]):o:!1},fg=a=>a==="position"||a==="percentage",mg=a=>a==="image"||a==="url",hg=a=>a==="length"||a==="size"||a==="bg-size",pg=a=>a==="length",Uw=a=>a==="number",Lw=a=>a==="family-name",xg=a=>a==="shadow",Bw=()=>{const a=dt("color"),s=dt("font"),o=dt("text"),i=dt("font-weight"),d=dt("tracking"),f=dt("leading"),m=dt("breakpoint"),v=dt("container"),g=dt("spacing"),h=dt("radius"),y=dt("shadow"),x=dt("inset-shadow"),j=dt("text-shadow"),k=dt("drop-shadow"),w=dt("blur"),E=dt("perspective"),_=dt("aspect"),A=dt("ease"),M=dt("animate"),X=()=>["auto","avoid","all","avoid-page","page","left","right","column"],I=()=>["center","top","bottom","left","right","top-left","left-top","top-right","right-top","bottom-right","right-bottom","bottom-left","left-bottom"],ne=()=>[...I(),de,ue],W=()=>["auto","hidden","clip","visible","scroll"],G=()=>["auto","contain","none"],U=()=>[de,ue,g],oe=()=>[as,"full","auto",...U()],Ne=()=>[Mn,"none","subgrid",de,ue],le=()=>["auto",{span:["full",Mn,de,ue]},Mn,de,ue],pe=()=>[Mn,"auto",de,ue],Ee=()=>["auto","min","max","fr",de,ue],Re=()=>["start","end","center","between","around","evenly","stretch","baseline","center-safe","end-safe"],ae=()=>["start","end","center","stretch","center-safe","end-safe"],C=()=>["auto",...U()],Y=()=>[as,"auto","full","dvw","dvh","lvw","lvh","svw","svh","min","max","fit",...U()],K=()=>[a,de,ue],xe=()=>[...I(),Dx,zx,{position:[de,ue]}],ee=()=>["no-repeat",{repeat:["","x","y","space","round"]}],S=()=>["auto","cover","contain",zw,Mw,{size:[de,ue]}],D=()=>[Yu,hl,sr],Q=()=>["","none","full",h,de,ue],Z=()=>["",Ae,hl,sr],re=()=>["solid","dashed","dotted","double"],fe=()=>["normal","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","hue","saturation","color","luminosity"],ce=()=>[Ae,Yu,Dx,zx],je=()=>["","none",w,de,ue],L=()=>["none",Ae,de,ue],z=()=>["none",Ae,de,ue],Se=()=>[Ae,de,ue],he=()=>[as,"full",...U()];return{cacheSize:500,theme:{animate:["spin","ping","pulse","bounce"],aspect:["video"],blur:[Wa],breakpoint:[Wa],color:[Cw],container:[Wa],"drop-shadow":[Wa],ease:["in","out","in-out"],font:[kw],"font-weight":["thin","extralight","light","normal","medium","semibold","bold","extrabold","black"],"inset-shadow":[Wa],leading:["none","tight","snug","normal","relaxed","loose"],perspective:["dramatic","near","normal","midrange","distant","none"],radius:[Wa],shadow:[Wa],spacing:["px",Ae],text:[Wa],"text-shadow":[Wa],tracking:["tighter","tight","normal","wide","wider","widest"]},classGroups:{aspect:[{aspect:["auto","square",as,ue,de,_]}],container:["container"],columns:[{columns:[Ae,ue,de,v]}],"break-after":[{"break-after":X()}],"break-before":[{"break-before":X()}],"break-inside":[{"break-inside":["auto","avoid","avoid-page","avoid-column"]}],"box-decoration":[{"box-decoration":["slice","clone"]}],box:[{box:["border","content"]}],display:["block","inline-block","inline","flex","inline-flex","table","inline-table","table-caption","table-cell","table-column","table-column-group","table-footer-group","table-header-group","table-row-group","table-row","flow-root","grid","inline-grid","contents","list-item","hidden"],sr:["sr-only","not-sr-only"],float:[{float:["right","left","none","start","end"]}],clear:[{clear:["left","right","both","none","start","end"]}],isolation:["isolate","isolation-auto"],"object-fit":[{object:["contain","cover","fill","none","scale-down"]}],"object-position":[{object:ne()}],overflow:[{overflow:W()}],"overflow-x":[{"overflow-x":W()}],"overflow-y":[{"overflow-y":W()}],overscroll:[{overscroll:G()}],"overscroll-x":[{"overscroll-x":G()}],"overscroll-y":[{"overscroll-y":G()}],position:["static","fixed","absolute","relative","sticky"],inset:[{inset:oe()}],"inset-x":[{"inset-x":oe()}],"inset-y":[{"inset-y":oe()}],start:[{start:oe()}],end:[{end:oe()}],top:[{top:oe()}],right:[{right:oe()}],bottom:[{bottom:oe()}],left:[{left:oe()}],visibility:["visible","invisible","collapse"],z:[{z:[Mn,"auto",de,ue]}],basis:[{basis:[as,"full","auto",v,...U()]}],"flex-direction":[{flex:["row","row-reverse","col","col-reverse"]}],"flex-wrap":[{flex:["nowrap","wrap","wrap-reverse"]}],flex:[{flex:[Ae,as,"auto","initial","none",ue]}],grow:[{grow:["",Ae,de,ue]}],shrink:[{shrink:["",Ae,de,ue]}],order:[{order:[Mn,"first","last","none",de,ue]}],"grid-cols":[{"grid-cols":Ne()}],"col-start-end":[{col:le()}],"col-start":[{"col-start":pe()}],"col-end":[{"col-end":pe()}],"grid-rows":[{"grid-rows":Ne()}],"row-start-end":[{row:le()}],"row-start":[{"row-start":pe()}],"row-end":[{"row-end":pe()}],"grid-flow":[{"grid-flow":["row","col","dense","row-dense","col-dense"]}],"auto-cols":[{"auto-cols":Ee()}],"auto-rows":[{"auto-rows":Ee()}],gap:[{gap:U()}],"gap-x":[{"gap-x":U()}],"gap-y":[{"gap-y":U()}],"justify-content":[{justify:[...Re(),"normal"]}],"justify-items":[{"justify-items":[...ae(),"normal"]}],"justify-self":[{"justify-self":["auto",...ae()]}],"align-content":[{content:["normal",...Re()]}],"align-items":[{items:[...ae(),{baseline:["","last"]}]}],"align-self":[{self:["auto",...ae(),{baseline:["","last"]}]}],"place-content":[{"place-content":Re()}],"place-items":[{"place-items":[...ae(),"baseline"]}],"place-self":[{"place-self":["auto",...ae()]}],p:[{p:U()}],px:[{px:U()}],py:[{py:U()}],ps:[{ps:U()}],pe:[{pe:U()}],pt:[{pt:U()}],pr:[{pr:U()}],pb:[{pb:U()}],pl:[{pl:U()}],m:[{m:C()}],mx:[{mx:C()}],my:[{my:C()}],ms:[{ms:C()}],me:[{me:C()}],mt:[{mt:C()}],mr:[{mr:C()}],mb:[{mb:C()}],ml:[{ml:C()}],"space-x":[{"space-x":U()}],"space-x-reverse":["space-x-reverse"],"space-y":[{"space-y":U()}],"space-y-reverse":["space-y-reverse"],size:[{size:Y()}],w:[{w:[v,"screen",...Y()]}],"min-w":[{"min-w":[v,"screen","none",...Y()]}],"max-w":[{"max-w":[v,"screen","none","prose",{screen:[m]},...Y()]}],h:[{h:["screen","lh",...Y()]}],"min-h":[{"min-h":["screen","lh","none",...Y()]}],"max-h":[{"max-h":["screen","lh",...Y()]}],"font-size":[{text:["base",o,hl,sr]}],"font-smoothing":["antialiased","subpixel-antialiased"],"font-style":["italic","not-italic"],"font-weight":[{font:[i,de,Xu]}],"font-stretch":[{"font-stretch":["ultra-condensed","extra-condensed","condensed","semi-condensed","normal","semi-expanded","expanded","extra-expanded","ultra-expanded",Yu,ue]}],"font-family":[{font:[Ow,ue,s]}],"fvn-normal":["normal-nums"],"fvn-ordinal":["ordinal"],"fvn-slashed-zero":["slashed-zero"],"fvn-figure":["lining-nums","oldstyle-nums"],"fvn-spacing":["proportional-nums","tabular-nums"],"fvn-fraction":["diagonal-fractions","stacked-fractions"],tracking:[{tracking:[d,de,ue]}],"line-clamp":[{"line-clamp":[Ae,"none",de,Xu]}],leading:[{leading:[f,...U()]}],"list-image":[{"list-image":["none",de,ue]}],"list-style-position":[{list:["inside","outside"]}],"list-style-type":[{list:["disc","decimal","none",de,ue]}],"text-alignment":[{text:["left","center","right","justify","start","end"]}],"placeholder-color":[{placeholder:K()}],"text-color":[{text:K()}],"text-decoration":["underline","overline","line-through","no-underline"],"text-decoration-style":[{decoration:[...re(),"wavy"]}],"text-decoration-thickness":[{decoration:[Ae,"from-font","auto",de,sr]}],"text-decoration-color":[{decoration:K()}],"underline-offset":[{"underline-offset":[Ae,"auto",de,ue]}],"text-transform":["uppercase","lowercase","capitalize","normal-case"],"text-overflow":["truncate","text-ellipsis","text-clip"],"text-wrap":[{text:["wrap","nowrap","balance","pretty"]}],indent:[{indent:U()}],"vertical-align":[{align:["baseline","top","middle","bottom","text-top","text-bottom","sub","super",de,ue]}],whitespace:[{whitespace:["normal","nowrap","pre","pre-line","pre-wrap","break-spaces"]}],break:[{break:["normal","words","all","keep"]}],wrap:[{wrap:["break-word","anywhere","normal"]}],hyphens:[{hyphens:["none","manual","auto"]}],content:[{content:["none",de,ue]}],"bg-attachment":[{bg:["fixed","local","scroll"]}],"bg-clip":[{"bg-clip":["border","padding","content","text"]}],"bg-origin":[{"bg-origin":["border","padding","content"]}],"bg-position":[{bg:xe()}],"bg-repeat":[{bg:ee()}],"bg-size":[{bg:S()}],"bg-image":[{bg:["none",{linear:[{to:["t","tr","r","br","b","bl","l","tl"]},Mn,de,ue],radial:["",de,ue],conic:[Mn,de,ue]},Dw,Aw]}],"bg-color":[{bg:K()}],"gradient-from-pos":[{from:D()}],"gradient-via-pos":[{via:D()}],"gradient-to-pos":[{to:D()}],"gradient-from":[{from:K()}],"gradient-via":[{via:K()}],"gradient-to":[{to:K()}],rounded:[{rounded:Q()}],"rounded-s":[{"rounded-s":Q()}],"rounded-e":[{"rounded-e":Q()}],"rounded-t":[{"rounded-t":Q()}],"rounded-r":[{"rounded-r":Q()}],"rounded-b":[{"rounded-b":Q()}],"rounded-l":[{"rounded-l":Q()}],"rounded-ss":[{"rounded-ss":Q()}],"rounded-se":[{"rounded-se":Q()}],"rounded-ee":[{"rounded-ee":Q()}],"rounded-es":[{"rounded-es":Q()}],"rounded-tl":[{"rounded-tl":Q()}],"rounded-tr":[{"rounded-tr":Q()}],"rounded-br":[{"rounded-br":Q()}],"rounded-bl":[{"rounded-bl":Q()}],"border-w":[{border:Z()}],"border-w-x":[{"border-x":Z()}],"border-w-y":[{"border-y":Z()}],"border-w-s":[{"border-s":Z()}],"border-w-e":[{"border-e":Z()}],"border-w-t":[{"border-t":Z()}],"border-w-r":[{"border-r":Z()}],"border-w-b":[{"border-b":Z()}],"border-w-l":[{"border-l":Z()}],"divide-x":[{"divide-x":Z()}],"divide-x-reverse":["divide-x-reverse"],"divide-y":[{"divide-y":Z()}],"divide-y-reverse":["divide-y-reverse"],"border-style":[{border:[...re(),"hidden","none"]}],"divide-style":[{divide:[...re(),"hidden","none"]}],"border-color":[{border:K()}],"border-color-x":[{"border-x":K()}],"border-color-y":[{"border-y":K()}],"border-color-s":[{"border-s":K()}],"border-color-e":[{"border-e":K()}],"border-color-t":[{"border-t":K()}],"border-color-r":[{"border-r":K()}],"border-color-b":[{"border-b":K()}],"border-color-l":[{"border-l":K()}],"divide-color":[{divide:K()}],"outline-style":[{outline:[...re(),"none","hidden"]}],"outline-offset":[{"outline-offset":[Ae,de,ue]}],"outline-w":[{outline:["",Ae,hl,sr]}],"outline-color":[{outline:K()}],shadow:[{shadow:["","none",y,Ko,Xo]}],"shadow-color":[{shadow:K()}],"inset-shadow":[{"inset-shadow":["none",x,Ko,Xo]}],"inset-shadow-color":[{"inset-shadow":K()}],"ring-w":[{ring:Z()}],"ring-w-inset":["ring-inset"],"ring-color":[{ring:K()}],"ring-offset-w":[{"ring-offset":[Ae,sr]}],"ring-offset-color":[{"ring-offset":K()}],"inset-ring-w":[{"inset-ring":Z()}],"inset-ring-color":[{"inset-ring":K()}],"text-shadow":[{"text-shadow":["none",j,Ko,Xo]}],"text-shadow-color":[{"text-shadow":K()}],opacity:[{opacity:[Ae,de,ue]}],"mix-blend":[{"mix-blend":[...fe(),"plus-darker","plus-lighter"]}],"bg-blend":[{"bg-blend":fe()}],"mask-clip":[{"mask-clip":["border","padding","content","fill","stroke","view"]},"mask-no-clip"],"mask-composite":[{mask:["add","subtract","intersect","exclude"]}],"mask-image-linear-pos":[{"mask-linear":[Ae]}],"mask-image-linear-from-pos":[{"mask-linear-from":ce()}],"mask-image-linear-to-pos":[{"mask-linear-to":ce()}],"mask-image-linear-from-color":[{"mask-linear-from":K()}],"mask-image-linear-to-color":[{"mask-linear-to":K()}],"mask-image-t-from-pos":[{"mask-t-from":ce()}],"mask-image-t-to-pos":[{"mask-t-to":ce()}],"mask-image-t-from-color":[{"mask-t-from":K()}],"mask-image-t-to-color":[{"mask-t-to":K()}],"mask-image-r-from-pos":[{"mask-r-from":ce()}],"mask-image-r-to-pos":[{"mask-r-to":ce()}],"mask-image-r-from-color":[{"mask-r-from":K()}],"mask-image-r-to-color":[{"mask-r-to":K()}],"mask-image-b-from-pos":[{"mask-b-from":ce()}],"mask-image-b-to-pos":[{"mask-b-to":ce()}],"mask-image-b-from-color":[{"mask-b-from":K()}],"mask-image-b-to-color":[{"mask-b-to":K()}],"mask-image-l-from-pos":[{"mask-l-from":ce()}],"mask-image-l-to-pos":[{"mask-l-to":ce()}],"mask-image-l-from-color":[{"mask-l-from":K()}],"mask-image-l-to-color":[{"mask-l-to":K()}],"mask-image-x-from-pos":[{"mask-x-from":ce()}],"mask-image-x-to-pos":[{"mask-x-to":ce()}],"mask-image-x-from-color":[{"mask-x-from":K()}],"mask-image-x-to-color":[{"mask-x-to":K()}],"mask-image-y-from-pos":[{"mask-y-from":ce()}],"mask-image-y-to-pos":[{"mask-y-to":ce()}],"mask-image-y-from-color":[{"mask-y-from":K()}],"mask-image-y-to-color":[{"mask-y-to":K()}],"mask-image-radial":[{"mask-radial":[de,ue]}],"mask-image-radial-from-pos":[{"mask-radial-from":ce()}],"mask-image-radial-to-pos":[{"mask-radial-to":ce()}],"mask-image-radial-from-color":[{"mask-radial-from":K()}],"mask-image-radial-to-color":[{"mask-radial-to":K()}],"mask-image-radial-shape":[{"mask-radial":["circle","ellipse"]}],"mask-image-radial-size":[{"mask-radial":[{closest:["side","corner"],farthest:["side","corner"]}]}],"mask-image-radial-pos":[{"mask-radial-at":I()}],"mask-image-conic-pos":[{"mask-conic":[Ae]}],"mask-image-conic-from-pos":[{"mask-conic-from":ce()}],"mask-image-conic-to-pos":[{"mask-conic-to":ce()}],"mask-image-conic-from-color":[{"mask-conic-from":K()}],"mask-image-conic-to-color":[{"mask-conic-to":K()}],"mask-mode":[{mask:["alpha","luminance","match"]}],"mask-origin":[{"mask-origin":["border","padding","content","fill","stroke","view"]}],"mask-position":[{mask:xe()}],"mask-repeat":[{mask:ee()}],"mask-size":[{mask:S()}],"mask-type":[{"mask-type":["alpha","luminance"]}],"mask-image":[{mask:["none",de,ue]}],filter:[{filter:["","none",de,ue]}],blur:[{blur:je()}],brightness:[{brightness:[Ae,de,ue]}],contrast:[{contrast:[Ae,de,ue]}],"drop-shadow":[{"drop-shadow":["","none",k,Ko,Xo]}],"drop-shadow-color":[{"drop-shadow":K()}],grayscale:[{grayscale:["",Ae,de,ue]}],"hue-rotate":[{"hue-rotate":[Ae,de,ue]}],invert:[{invert:["",Ae,de,ue]}],saturate:[{saturate:[Ae,de,ue]}],sepia:[{sepia:["",Ae,de,ue]}],"backdrop-filter":[{"backdrop-filter":["","none",de,ue]}],"backdrop-blur":[{"backdrop-blur":je()}],"backdrop-brightness":[{"backdrop-brightness":[Ae,de,ue]}],"backdrop-contrast":[{"backdrop-contrast":[Ae,de,ue]}],"backdrop-grayscale":[{"backdrop-grayscale":["",Ae,de,ue]}],"backdrop-hue-rotate":[{"backdrop-hue-rotate":[Ae,de,ue]}],"backdrop-invert":[{"backdrop-invert":["",Ae,de,ue]}],"backdrop-opacity":[{"backdrop-opacity":[Ae,de,ue]}],"backdrop-saturate":[{"backdrop-saturate":[Ae,de,ue]}],"backdrop-sepia":[{"backdrop-sepia":["",Ae,de,ue]}],"border-collapse":[{border:["collapse","separate"]}],"border-spacing":[{"border-spacing":U()}],"border-spacing-x":[{"border-spacing-x":U()}],"border-spacing-y":[{"border-spacing-y":U()}],"table-layout":[{table:["auto","fixed"]}],caption:[{caption:["top","bottom"]}],transition:[{transition:["","all","colors","opacity","shadow","transform","none",de,ue]}],"transition-behavior":[{transition:["normal","discrete"]}],duration:[{duration:[Ae,"initial",de,ue]}],ease:[{ease:["linear","initial",A,de,ue]}],delay:[{delay:[Ae,de,ue]}],animate:[{animate:["none",M,de,ue]}],backface:[{backface:["hidden","visible"]}],perspective:[{perspective:[E,de,ue]}],"perspective-origin":[{"perspective-origin":ne()}],rotate:[{rotate:L()}],"rotate-x":[{"rotate-x":L()}],"rotate-y":[{"rotate-y":L()}],"rotate-z":[{"rotate-z":L()}],scale:[{scale:z()}],"scale-x":[{"scale-x":z()}],"scale-y":[{"scale-y":z()}],"scale-z":[{"scale-z":z()}],"scale-3d":["scale-3d"],skew:[{skew:Se()}],"skew-x":[{"skew-x":Se()}],"skew-y":[{"skew-y":Se()}],transform:[{transform:[de,ue,"","none","gpu","cpu"]}],"transform-origin":[{origin:ne()}],"transform-style":[{transform:["3d","flat"]}],translate:[{translate:he()}],"translate-x":[{"translate-x":he()}],"translate-y":[{"translate-y":he()}],"translate-z":[{"translate-z":he()}],"translate-none":["translate-none"],accent:[{accent:K()}],appearance:[{appearance:["none","auto"]}],"caret-color":[{caret:K()}],"color-scheme":[{scheme:["normal","dark","light","light-dark","only-dark","only-light"]}],cursor:[{cursor:["auto","default","pointer","wait","text","move","help","not-allowed","none","context-menu","progress","cell","crosshair","vertical-text","alias","copy","no-drop","grab","grabbing","all-scroll","col-resize","row-resize","n-resize","e-resize","s-resize","w-resize","ne-resize","nw-resize","se-resize","sw-resize","ew-resize","ns-resize","nesw-resize","nwse-resize","zoom-in","zoom-out",de,ue]}],"field-sizing":[{"field-sizing":["fixed","content"]}],"pointer-events":[{"pointer-events":["auto","none"]}],resize:[{resize:["none","","y","x"]}],"scroll-behavior":[{scroll:["auto","smooth"]}],"scroll-m":[{"scroll-m":U()}],"scroll-mx":[{"scroll-mx":U()}],"scroll-my":[{"scroll-my":U()}],"scroll-ms":[{"scroll-ms":U()}],"scroll-me":[{"scroll-me":U()}],"scroll-mt":[{"scroll-mt":U()}],"scroll-mr":[{"scroll-mr":U()}],"scroll-mb":[{"scroll-mb":U()}],"scroll-ml":[{"scroll-ml":U()}],"scroll-p":[{"scroll-p":U()}],"scroll-px":[{"scroll-px":U()}],"scroll-py":[{"scroll-py":U()}],"scroll-ps":[{"scroll-ps":U()}],"scroll-pe":[{"scroll-pe":U()}],"scroll-pt":[{"scroll-pt":U()}],"scroll-pr":[{"scroll-pr":U()}],"scroll-pb":[{"scroll-pb":U()}],"scroll-pl":[{"scroll-pl":U()}],"snap-align":[{snap:["start","end","center","align-none"]}],"snap-stop":[{snap:["normal","always"]}],"snap-type":[{snap:["none","x","y","both"]}],"snap-strictness":[{snap:["mandatory","proximity"]}],touch:[{touch:["auto","none","manipulation"]}],"touch-x":[{"touch-pan":["x","left","right"]}],"touch-y":[{"touch-pan":["y","up","down"]}],"touch-pz":["touch-pinch-zoom"],select:[{select:["none","text","all","auto"]}],"will-change":[{"will-change":["auto","scroll","contents","transform",de,ue]}],fill:[{fill:["none",...K()]}],"stroke-w":[{stroke:[Ae,hl,sr,Xu]}],stroke:[{stroke:["none",...K()]}],"forced-color-adjust":[{"forced-color-adjust":["auto","none"]}]},conflictingClassGroups:{overflow:["overflow-x","overflow-y"],overscroll:["overscroll-x","overscroll-y"],inset:["inset-x","inset-y","start","end","top","right","bottom","left"],"inset-x":["right","left"],"inset-y":["top","bottom"],flex:["basis","grow","shrink"],gap:["gap-x","gap-y"],p:["px","py","ps","pe","pt","pr","pb","pl"],px:["pr","pl"],py:["pt","pb"],m:["mx","my","ms","me","mt","mr","mb","ml"],mx:["mr","ml"],my:["mt","mb"],size:["w","h"],"font-size":["leading"],"fvn-normal":["fvn-ordinal","fvn-slashed-zero","fvn-figure","fvn-spacing","fvn-fraction"],"fvn-ordinal":["fvn-normal"],"fvn-slashed-zero":["fvn-normal"],"fvn-figure":["fvn-normal"],"fvn-spacing":["fvn-normal"],"fvn-fraction":["fvn-normal"],"line-clamp":["display","overflow"],rounded:["rounded-s","rounded-e","rounded-t","rounded-r","rounded-b","rounded-l","rounded-ss","rounded-se","rounded-ee","rounded-es","rounded-tl","rounded-tr","rounded-br","rounded-bl"],"rounded-s":["rounded-ss","rounded-es"],"rounded-e":["rounded-se","rounded-ee"],"rounded-t":["rounded-tl","rounded-tr"],"rounded-r":["rounded-tr","rounded-br"],"rounded-b":["rounded-br","rounded-bl"],"rounded-l":["rounded-tl","rounded-bl"],"border-spacing":["border-spacing-x","border-spacing-y"],"border-w":["border-w-x","border-w-y","border-w-s","border-w-e","border-w-t","border-w-r","border-w-b","border-w-l"],"border-w-x":["border-w-r","border-w-l"],"border-w-y":["border-w-t","border-w-b"],"border-color":["border-color-x","border-color-y","border-color-s","border-color-e","border-color-t","border-color-r","border-color-b","border-color-l"],"border-color-x":["border-color-r","border-color-l"],"border-color-y":["border-color-t","border-color-b"],translate:["translate-x","translate-y","translate-none"],"translate-none":["translate","translate-x","translate-y","translate-z"],"scroll-m":["scroll-mx","scroll-my","scroll-ms","scroll-me","scroll-mt","scroll-mr","scroll-mb","scroll-ml"],"scroll-mx":["scroll-mr","scroll-ml"],"scroll-my":["scroll-mt","scroll-mb"],"scroll-p":["scroll-px","scroll-py","scroll-ps","scroll-pe","scroll-pt","scroll-pr","scroll-pb","scroll-pl"],"scroll-px":["scroll-pr","scroll-pl"],"scroll-py":["scroll-pt","scroll-pb"],touch:["touch-x","touch-y","touch-pz"],"touch-x":["touch"],"touch-y":["touch"],"touch-pz":["touch"]},conflictingClassGroupModifiers:{"font-size":["leading"]},orderSensitiveModifiers:["*","**","after","backdrop","before","details-content","file","first-letter","first-line","marker","placeholder","selection"]}},qw=gw(Bw);function te(...a){return qw(PS(a))}async function Hw(){const{data:a}=await ge.get("/api/system/info");return a}function Gw(){return yt({queryKey:["system-info"],queryFn:Hw,staleTime:6e4})}function Qw(a){const s=Math.floor(a/86400),o=Math.floor(a%86400/3600);if(s>0)return`${s}d ${o}h`;const i=Math.floor(a%3600/60);return o>0?`${o}h ${i}m`:`${i}m`}function Vw(){const{data:a}=Gw();return a?l.jsxs("div",{className:"border-t border-[var(--color-border)] px-3 py-2 text-[10px] text-[var(--color-text-muted)]",children:[l.jsxs("div",{className:"flex items-center gap-1.5",children:[l.jsx(On,{size:10}),l.jsxs("span",{children:[a.cpuCount," cores"]}),l.jsx("span",{className:"mx-0.5",children:"|"}),l.jsx(Hd,{size:10}),l.jsxs("span",{children:[Math.round(a.totalMemoryMb/1024),"GB"]})]}),l.jsxs("div",{className:"mt-0.5",children:[a.hostname," · up ",Qw(a.uptime)," · v",a.version]})]}):null}const Fw=[{label:"Dashboard",icon:uS,path:"/dashboard"},{label:"Settings",icon:ng,path:"/settings"},{label:"Services",icon:Qd,path:"/services"},{label:"Models",icon:Rj,path:"/models"},{label:"Quick Sets",icon:oi,path:"/quick-sets"},{label:"Traces",icon:Tj,path:"/traces"},{label:"Nodes",icon:On,path:"/nodes"},{label:"Users",icon:XS,path:"/users"},{label:"Native",icon:Mj,path:"/native-services"}];function Yw(){return l.jsxs("aside",{className:"flex w-56 flex-col border-r border-[var(--color-border)] bg-[var(--color-surface)]",children:[l.jsx("div",{className:"flex h-14 items-center border-b border-[var(--color-border)] px-4",children:l.jsx("span",{className:"text-lg font-bold text-[var(--color-primary)]",children:"Jarvis"})}),l.jsx("nav",{className:"flex-1 space-y-1 p-2",children:Fw.map(a=>l.jsxs(fv,{to:a.path,className:({isActive:s})=>te("flex items-center gap-3 rounded-lg px-3 py-2 text-sm font-medium transition-colors",s?"bg-[var(--color-primary)]/10 text-[var(--color-primary)]":"text-[var(--color-text-muted)] hover:bg-[var(--color-surface-alt)] hover:text-[var(--color-text)]"),children:[l.jsx(a.icon,{size:18}),a.label]},a.path))}),l.jsx(Vw,{})]})}function Xw(){const{state:a,logout:s}=Ud(),{theme:o,toggleTheme:i}=B2();return l.jsxs("header",{className:"flex h-14 items-center justify-between border-b border-[var(--color-border)] bg-[var(--color-surface)] px-6",children:[l.jsx("h2",{className:"text-sm font-medium text-[var(--color-text-muted)]",children:"Admin Dashboard"}),l.jsxs("div",{className:"flex items-center gap-3",children:[a.user&&l.jsx("span",{className:"text-sm text-[var(--color-text-muted)]",children:a.user.email}),l.jsx("button",{onClick:i,className:"rounded-lg p-2 text-[var(--color-text-muted)] hover:bg-[var(--color-surface-alt)]",title:`Switch to ${o==="dark"?"light":"dark"} mode`,children:o==="dark"?l.jsx(HS,{size:18}):l.jsx(NS,{size:18})}),l.jsx("button",{onClick:s,className:"rounded-lg p-2 text-[var(--color-text-muted)] hover:bg-[var(--color-surface-alt)] hover:text-red-500",title:"Logout",children:l.jsx(xS,{size:18})})]})]})}function Kw(){const{state:a}=Ud();return a.isLoading?l.jsx("div",{className:"flex min-h-screen items-center justify-center bg-[var(--color-background)]",children:l.jsx("p",{className:"text-[var(--color-text-muted)]",children:"Loading..."})}):a.isAuthenticated?l.jsxs("div",{className:"flex h-screen bg-[var(--color-background)]",children:[l.jsx(Yw,{}),l.jsxs("div",{className:"flex flex-1 flex-col overflow-hidden",children:[l.jsx(Xw,{}),l.jsx("main",{className:"flex-1 overflow-y-auto p-6",children:l.jsx(F0,{})})]})]}):l.jsx(ni,{to:"/login",replace:!0})}function $w(){const{state:a,login:s,setup:o}=Ud(),i=wa(),[d,f]=N.useState("loading"),[m,v]=N.useState(""),[g,h]=N.useState(""),[y,x]=N.useState(""),[j,k]=N.useState(""),[w,E]=N.useState(null);if(N.useEffect(()=>{let I=!1;async function ne(){try{const{data:W}=await ge.get("/api/setup/status");if(!I&&!W.configured){i("/setup",{replace:!0});return}}catch{if(!I){i("/setup",{replace:!0});return}}try{const W=await xj();I||f(W.needs_setup?"setup":"login")}catch{I||f("login")}}return ne(),()=>{I=!0}},[i]),a.isAuthenticated)return l.jsx(ni,{to:"/settings",replace:!0});const _=I=>{I.preventDefault(),s(m,y)},A=I=>{if(I.preventDefault(),E(null),y!==j){E("Passwords do not match");return}if(y.length<8){E("Password must be at least 8 characters");return}o(m,y,g||void 0)},M=te("w-full rounded-lg border border-[var(--color-border)] bg-[var(--color-surface-alt)] px-3 py-2","text-[var(--color-text)] placeholder:text-[var(--color-text-muted)]","outline-none focus:ring-2 focus:ring-[var(--color-primary)]"),X=w??a.error;return d==="loading"?l.jsx("div",{className:"flex min-h-screen items-center justify-center bg-[var(--color-background)]",children:l.jsx("div",{className:"w-full max-w-sm rounded-xl border border-[var(--color-border)] bg-[var(--color-surface)] p-8 shadow-lg",children:l.jsx("div",{className:"flex justify-center",children:l.jsx("div",{className:"h-8 w-8 animate-spin rounded-full border-4 border-[var(--color-border)] border-t-[var(--color-primary)]"})})})}):l.jsx("div",{className:"flex min-h-screen items-center justify-center bg-[var(--color-background)]",children:l.jsx("div",{className:"w-full max-w-sm rounded-xl border border-[var(--color-border)] bg-[var(--color-surface)] p-8 shadow-lg",children:d==="setup"?l.jsxs(l.Fragment,{children:[l.jsx("h1",{className:"mb-1 text-center text-2xl font-bold text-[var(--color-text)]",children:"Welcome to Jarvis"}),l.jsx("p",{className:"mb-6 text-center text-sm text-[var(--color-text-muted)]",children:"Set up your first administrator account to get started."}),l.jsxs("form",{onSubmit:A,className:"space-y-4",children:[l.jsxs("div",{children:[l.jsx("label",{htmlFor:"email",className:"mb-1 block text-sm text-[var(--color-text-muted)]",children:"Email"}),l.jsx("input",{id:"email",type:"email",required:!0,autoComplete:"email",value:m,onChange:I=>v(I.target.value),className:M,placeholder:"admin@example.com"})]}),l.jsxs("div",{children:[l.jsx("label",{htmlFor:"username",className:"mb-1 block text-sm text-[var(--color-text-muted)]",children:"Username"}),l.jsx("input",{id:"username",type:"text",required:!0,autoComplete:"username",value:g,onChange:I=>h(I.target.value),className:M,placeholder:"admin"})]}),l.jsxs("div",{children:[l.jsx("label",{htmlFor:"password",className:"mb-1 block text-sm text-[var(--color-text-muted)]",children:"Password"}),l.jsx("input",{id:"password",type:"password",required:!0,minLength:8,autoComplete:"new-password",value:y,onChange:I=>x(I.target.value),className:M})]}),l.jsxs("div",{children:[l.jsx("label",{htmlFor:"confirm-password",className:"mb-1 block text-sm text-[var(--color-text-muted)]",children:"Confirm Password"}),l.jsx("input",{id:"confirm-password",type:"password",required:!0,minLength:8,autoComplete:"new-password",value:j,onChange:I=>k(I.target.value),className:M})]}),X&&l.jsx("p",{className:"rounded-lg bg-red-500/10 px-3 py-2 text-sm text-red-500",children:X}),l.jsx("button",{type:"submit",disabled:a.isLoading,className:te("w-full rounded-lg bg-[var(--color-primary)] px-4 py-2 font-medium text-white","hover:opacity-90 disabled:opacity-50","transition-opacity"),children:a.isLoading?"Creating account...":"Create Admin Account"})]})]}):l.jsxs(l.Fragment,{children:[l.jsx("h1",{className:"mb-6 text-center text-2xl font-bold text-[var(--color-text)]",children:"Jarvis Admin"}),l.jsxs("form",{onSubmit:_,className:"space-y-4",children:[l.jsxs("div",{children:[l.jsx("label",{htmlFor:"email",className:"mb-1 block text-sm text-[var(--color-text-muted)]",children:"Email"}),l.jsx("input",{id:"email",type:"email",required:!0,autoComplete:"email",value:m,onChange:I=>v(I.target.value),className:M,placeholder:"admin@example.com"})]}),l.jsxs("div",{children:[l.jsx("label",{htmlFor:"password",className:"mb-1 block text-sm text-[var(--color-text-muted)]",children:"Password"}),l.jsx("input",{id:"password",type:"password",required:!0,autoComplete:"current-password",value:y,onChange:I=>x(I.target.value),className:M})]}),X&&l.jsx("p",{className:"rounded-lg bg-red-500/10 px-3 py-2 text-sm text-red-500",children:X}),l.jsx("button",{type:"submit",disabled:a.isLoading,className:te("w-full rounded-lg bg-[var(--color-primary)] px-4 py-2 font-medium text-white","hover:opacity-90 disabled:opacity-50","transition-opacity"),children:a.isLoading?"Signing in...":"Sign in"})]})]})})})}async function Zw(){const{data:a}=await ge.get("/api/settings/");return a}async function Jw(a,s,o){const{data:i}=await ge.put(`/api/settings/${encodeURIComponent(a)}/${s}`,{value:o});return i}function Pw(){return yt({queryKey:["settings"],queryFn:Zw,staleTime:3e4})}function Iw(){const a=pt();return bt({mutationFn:({serviceName:s,key:o,value:i})=>Jw(s,o,i),onSuccess:()=>{a.invalidateQueries({queryKey:["settings"]})}})}function Ww({setting:a,onSave:s,onCancel:o,isSaving:i}){const[d,f]=N.useState(()=>a.value_type==="json"?JSON.stringify(a.value,null,2):a.value_type==="bool"?"":String(a.value??"")),[m,v]=N.useState(()=>!!a.value),[g,h]=N.useState(null),y=!!a.options?.length,x=y&&!a.options.includes(d),[j,k]=N.useState(x),w=_=>{_.preventDefault();let A;switch(a.value_type){case"bool":A=m;break;case"int":if(A=parseInt(d,10),isNaN(A)){h("Must be a whole number");return}h(null);break;case"float":if(A=parseFloat(d),isNaN(A)){h("Must be a number");return}h(null);break;case"json":try{A=JSON.parse(d),h(null)}catch{h("Invalid JSON");return}break;default:A=d}s(A)},E=te("w-full rounded-lg border border-[var(--color-border)] bg-[var(--color-surface-alt)] px-3 py-1.5","text-sm text-[var(--color-text)] outline-none focus:ring-2 focus:ring-[var(--color-primary)]");return l.jsxs("form",{onSubmit:w,className:"flex items-center gap-2",children:[y?l.jsxs("div",{className:"flex items-center gap-2",children:[l.jsxs("select",{value:j?"__other__":d,onChange:_=>{_.target.value==="__other__"?(k(!0),f("")):(k(!1),f(_.target.value))},className:te(E,"max-w-xs"),children:[a.options.map(_=>l.jsx("option",{value:String(_),children:String(_)},String(_))),l.jsx("option",{value:"__other__",children:"Other..."})]}),j&&l.jsx("input",{type:"text",value:d,onChange:_=>f(_.target.value),placeholder:"Custom value",className:te(E,"max-w-xs"),autoFocus:!0})]}):a.value_type==="bool"?l.jsx("button",{type:"button",onClick:()=>v(_=>!_),className:te("relative h-6 w-11 rounded-full transition-colors",m?"bg-[var(--color-primary)]":"bg-[var(--color-border)]"),children:l.jsx("span",{className:te("absolute left-0.5 top-0.5 h-5 w-5 rounded-full bg-white transition-transform",m&&"translate-x-5")})}):a.value_type==="json"?l.jsxs("div",{className:"flex-1",children:[l.jsx("textarea",{value:d,onChange:_=>{f(_.target.value),h(null)},rows:4,className:te(E,"font-mono text-xs")}),g&&l.jsx("p",{className:"mt-1 text-xs text-red-500",children:g})]}):l.jsxs("div",{children:[l.jsx("input",{type:a.value_type==="int"||a.value_type==="float"?"number":a.is_secret?"password":"text",step:a.value_type==="float"?"any":void 0,value:d,onChange:_=>{f(_.target.value),h(null)},className:te(E,"max-w-xs")}),g&&l.jsx("p",{className:"mt-1 text-xs text-red-500",children:g})]}),l.jsx("button",{type:"submit",disabled:i,className:"rounded-lg bg-[var(--color-primary)] px-3 py-1.5 text-xs font-medium text-white hover:opacity-90 disabled:opacity-50",children:i?"Saving...":"Save"}),l.jsx("button",{type:"button",onClick:o,className:"rounded-lg border border-[var(--color-border)] px-3 py-1.5 text-xs text-[var(--color-text-muted)] hover:bg-[var(--color-surface-alt)]",children:"Cancel"})]})}function eE(a){return a.is_secret?"********":a.value===null||a.value===void 0?"(not set)":a.value_type==="json"?JSON.stringify(a.value):String(a.value)}const tE={string:"bg-blue-500/10 text-blue-500",int:"bg-emerald-500/10 text-emerald-500",float:"bg-emerald-500/10 text-emerald-500",bool:"bg-amber-500/10 text-amber-500",json:"bg-purple-500/10 text-purple-500"};function aE({setting:a,serviceName:s,onRestartService:o}){const[i,d]=N.useState(!1),f=Iw(),m=v=>{f.mutate({serviceName:s,key:a.key,value:v},{onSuccess:g=>{d(!1),g.requires_reload?Me.warning(`Setting updated. ${s} requires a restart to apply.`,o?{action:{label:"Restart",onClick:o}}:void 0):Me.success("Setting updated")},onError:g=>{Me.error(`Failed to update: ${g.message}`)}})};return l.jsxs("div",{className:"flex items-start justify-between gap-4 rounded-lg px-3 py-2 hover:bg-[var(--color-surface-alt)]",children:[l.jsxs("div",{className:"min-w-0 flex-1",children:[l.jsxs("div",{className:"flex items-center gap-2",children:[l.jsx("code",{className:"text-sm font-medium text-[var(--color-text)]",children:a.key}),l.jsx("span",{className:te("rounded px-1.5 py-0.5 text-[10px] font-medium",tE[a.value_type]??"bg-gray-500/10 text-gray-500"),children:a.value_type}),a.from_db&&l.jsx("span",{title:"Stored in database",children:l.jsx($j,{size:12,className:"text-[var(--color-tertiary)]"})}),a.requires_reload&&l.jsx("span",{title:"Requires service restart",children:l.jsx(ra,{size:12,className:"text-amber-500"})})]}),a.description&&l.jsx("p",{className:"mt-0.5 text-xs text-[var(--color-text-muted)]",children:a.description}),i?l.jsx("div",{className:"mt-2",children:l.jsx(Ww,{setting:a,onSave:m,onCancel:()=>d(!1),isSaving:f.isPending})}):l.jsx("p",{className:"mt-1 font-mono text-xs text-[var(--color-text-muted)]",children:eE(a)})]}),!i&&l.jsx("button",{onClick:()=>d(!0),className:"shrink-0 rounded-lg p-1.5 text-[var(--color-text-muted)] hover:bg-[var(--color-surface-alt)] hover:text-[var(--color-primary)]",title:"Edit",children:l.jsx(SS,{size:14})})]})}function nE({category:a,settings:s,serviceName:o,onRestartService:i}){const[d,f]=N.useState(!0);return l.jsxs("div",{children:[l.jsxs("button",{onClick:()=>f(m=>!m),className:"flex w-full items-center gap-2 px-3 py-1.5 text-xs font-semibold uppercase tracking-wider text-[var(--color-text-muted)] hover:text-[var(--color-text)]",children:[d?l.jsx(Ld,{size:14}):l.jsx(Wv,{size:14}),a,l.jsxs("span",{className:"font-normal",children:["(",s.length,")"]})]}),d&&l.jsx("div",{className:"space-y-0.5",children:s.map(m=>l.jsx(aE,{setting:m,serviceName:o,onRestartService:i},m.key))})]})}async function rE(){const{data:a}=await ge.get("/api/containers");return a}async function sE(a){const{data:s}=await ge.post(`/api/containers/${a}/restart`);return s}function vg(){return yt({queryKey:["containers"],queryFn:rE,staleTime:1e4,refetchInterval:1e4})}function gg(){const a=pt();return bt({mutationFn:s=>sE(s),onSuccess:()=>{a.invalidateQueries({queryKey:["containers"]})}})}function lE({result:a,defaultExpanded:s=!1}){const[o,i]=N.useState(s),{data:d}=vg(),f=gg(),m=N.useCallback(()=>{const g=d?.containers.find(h=>h.name.includes(a.service_name)||h.name.includes(a.service_name.replace("jarvis-","")));g?f.mutate(g.id,{onSuccess:()=>Me.success(`${a.service_name} is restarting...`),onError:h=>Me.error(`Restart failed: ${h.message}`)}):Me.error(`Could not find container for ${a.service_name}`)},[d,a.service_name,f]),v=N.useMemo(()=>{const g=new Map;for(const h of a.settings){const y=g.get(h.category)??[];g.set(h.category,[...y,h])}return g},[a]);return l.jsxs("div",{className:"overflow-hidden rounded-xl border border-[var(--color-border)] bg-[var(--color-surface)]",children:[l.jsxs("button",{onClick:()=>i(g=>!g),className:"flex w-full items-center gap-3 px-4 py-3 text-left hover:bg-[var(--color-surface-alt)]",children:[o?l.jsx(Ld,{size:18,className:"text-[var(--color-text-muted)]"}):l.jsx(Wv,{size:18,className:"text-[var(--color-text-muted)]"}),l.jsx("span",{className:"font-medium text-[var(--color-text)]",children:a.service_name}),a.success?l.jsx(ht,{size:16,className:"text-[var(--color-secondary)]"}):l.jsx(xl,{size:16,className:"text-red-500"}),l.jsx("span",{className:"text-xs text-[var(--color-text-muted)]",children:a.success?`${a.settings.length} settings`:a.error??"Error"}),a.latency_ms!=null&&l.jsxs("span",{className:te("ml-auto text-xs",a.latency_ms>500?"text-amber-500":"text-[var(--color-text-muted)]"),children:[Math.round(a.latency_ms),"ms"]})]}),o&&a.success&&l.jsx("div",{className:"space-y-2 border-t border-[var(--color-border)] px-2 py-3",children:[...v.entries()].map(([g,h])=>l.jsx(nE,{category:g,settings:h,serviceName:a.service_name,onRestartService:m},g))}),o&&!a.success&&l.jsx("div",{className:"border-t border-[var(--color-border)] px-4 py-3",children:l.jsx("p",{className:"text-sm text-red-500",children:a.error??"Failed to fetch settings"})})]})}function oE(){const{data:a,isLoading:s,isError:o,error:i,refetch:d,isFetching:f}=Pw(),[m,v]=N.useState(""),g=N.useMemo(()=>{if(!a)return[];if(!m.trim())return a.services;const h=m.toLowerCase();return a.services.map(y=>({...y,settings:y.settings.filter(x=>x.key.toLowerCase().includes(h)||x.category.toLowerCase().includes(h)||(x.description?.toLowerCase().includes(h)??!1))})).filter(y=>y.settings.length>0||y.service_name.toLowerCase().includes(h))},[a,m]);return s?l.jsx("div",{className:"flex items-center justify-center py-20",children:l.jsx(it,{className:"animate-spin text-[var(--color-primary)]",size:24})}):o?l.jsxs("div",{className:"py-20 text-center",children:[l.jsx("p",{className:"mb-2 text-red-500",children:"Failed to load settings"}),l.jsx("p",{className:"mb-4 text-sm text-[var(--color-text-muted)]",children:i?.message??"Unknown error"}),l.jsx("button",{onClick:()=>d(),className:"rounded-lg bg-[var(--color-primary)] px-4 py-2 text-sm text-white hover:opacity-90",children:"Retry"})]}):l.jsxs("div",{className:"mx-auto max-w-4xl space-y-4",children:[l.jsxs("div",{className:"flex items-center justify-between",children:[l.jsx("h1",{className:"text-xl font-bold text-[var(--color-text)]",children:"Settings"}),l.jsxs("div",{className:"flex items-center gap-2 text-xs text-[var(--color-text-muted)]",children:[a&&l.jsxs("span",{children:[a.successful_services,"/",a.total_services," services"]}),l.jsx("button",{onClick:()=>d(),disabled:f,className:te("rounded-lg p-1.5 hover:bg-[var(--color-surface-alt)]",f&&"animate-spin"),title:"Refresh",children:l.jsx(it,{size:14})})]})]}),l.jsxs("div",{className:"relative",children:[l.jsx(kS,{size:16,className:"absolute left-3 top-1/2 -translate-y-1/2 text-[var(--color-text-muted)]"}),l.jsx("input",{type:"text",value:m,onChange:h=>v(h.target.value),placeholder:"Search settings...",className:te("w-full rounded-lg border border-[var(--color-border)] bg-[var(--color-surface)] py-2 pl-9 pr-3","text-sm text-[var(--color-text)] placeholder:text-[var(--color-text-muted)]","outline-none focus:ring-2 focus:ring-[var(--color-primary)]")})]}),l.jsxs("div",{className:"space-y-3",children:[g.map((h,y)=>l.jsx(lE,{result:h,defaultExpanded:y===0},h.service_name)),g.length===0&&l.jsx("p",{className:"py-8 text-center text-sm text-[var(--color-text-muted)]",children:m?"No settings match your search":"No services found"})]})]})}async function iE(){const{data:a}=await ge.get("/api/services/registry");return a}async function cE(a){const{data:s}=await ge.post("/api/services/register",a);return s}async function uE(a){const{data:s}=await ge.post("/api/services/rotate-key",a);return s}async function dE(a){const{data:s}=await ge.post("/api/services/probe",a);return s}async function fE(a){const{data:s}=await ge.post("/api/services/register",{services:[{name:a.name,host:a.host,port:a.port,scheme:a.scheme,health_path:a.health_path,description:a.description}]});return s}async function mE(a){await ge.delete(`/api/services/${encodeURIComponent(a)}`)}async function hE(){const{data:a}=await ge.get("/api/services/suggestions");return a}function pE(){return yt({queryKey:["service-registry"],queryFn:iE,staleTime:3e4})}function xE(){const a=pt();return bt({mutationFn:cE,onSuccess:()=>{a.invalidateQueries({queryKey:["service-registry"]})}})}function vE(){const a=pt();return bt({mutationFn:uE,onSuccess:()=>{a.invalidateQueries({queryKey:["service-registry"]})}})}function gE(){const a=pt();return bt({mutationFn:fE,onSuccess:()=>{a.invalidateQueries({queryKey:["service-registry"]})}})}function yE(){const a=pt();return bt({mutationFn:mE,onSuccess:()=>{a.invalidateQueries({queryKey:["service-registry"]})}})}function bE(){return yt({queryKey:["service-suggestions"],queryFn:hE,staleTime:6e4})}function Ux({ok:a,label:s}){return l.jsxs("span",{className:te("inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-xs font-medium",a?"bg-green-500/10 text-green-600 dark:text-green-400":"bg-[var(--color-surface-alt)] text-[var(--color-text-muted)]"),children:[a?l.jsx(xi,{size:12}):l.jsx(Vd,{size:12}),s]})}function NE({status:a,error:s,latency:o}){return a==="idle"?null:a==="probing"?l.jsx("span",{className:"flex items-center gap-1 text-xs text-[var(--color-text-muted)]",children:l.jsx(Ct,{size:12,className:"animate-spin"})}):a==="healthy"?l.jsxs("span",{className:"flex items-center gap-1 text-xs text-green-600 dark:text-green-400",children:[l.jsx(os,{size:8,fill:"currentColor"}),o!=null&&`${o}ms`]}):l.jsxs("span",{className:"flex items-center gap-1 text-xs text-red-500",title:s,children:[l.jsx(os,{size:8,fill:"currentColor"}),s||"Unreachable"]})}function jE({entry:a,checked:s,host:o,port:i,scheme:d,onToggle:f,onHostChange:m,onPortChange:v,onSchemeChange:g,onHostBlur:h,onPortBlur:y,onRotateKey:x,onDelete:j,disabled:k,rotating:w,deleting:E,healthStatus:_,healthError:A,healthLatency:M}){return l.jsxs("div",{className:te("flex flex-wrap items-center gap-3 rounded-lg border border-[var(--color-border)] p-3","bg-[var(--color-surface)] transition-colors",s&&"border-[var(--color-primary)]/30 bg-[var(--color-primary)]/5"),children:[l.jsx("input",{type:"checkbox",checked:s,onChange:f,disabled:k,className:"h-4 w-4 rounded border-[var(--color-border)] accent-[var(--color-primary)]"}),l.jsxs("div",{className:"min-w-[180px] flex-1",children:[l.jsxs("div",{className:"flex items-center gap-2 text-sm font-medium text-[var(--color-text)]",children:[a.name,a.custom&&l.jsx("span",{className:"rounded-full bg-blue-500/10 px-1.5 py-0.5 text-[10px] font-medium text-blue-600 dark:text-blue-400",children:"custom"})]}),l.jsx("div",{className:"text-xs text-[var(--color-text-muted)]",children:a.description})]}),l.jsxs("div",{className:"flex items-center gap-2",children:[l.jsx(Ux,{ok:a.config_registered,label:"Config"}),l.jsx(Ux,{ok:a.auth_registered,label:"Auth"}),a.custom&&j&&l.jsxs("button",{onClick:j,disabled:k||E,className:te("inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-xs font-medium","bg-red-500/10 text-red-600 dark:text-red-400","hover:bg-red-500/20","disabled:opacity-50"),title:"Remove custom service",children:[l.jsx(yi,{size:12,className:E?"animate-spin":""}),"Remove"]}),a.auth_registered&&l.jsxs("button",{onClick:x,disabled:k||w,className:te("inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-xs font-medium","bg-[var(--color-surface-alt)] text-[var(--color-text-muted)]","hover:bg-[var(--color-primary)]/10 hover:text-[var(--color-primary)]","disabled:opacity-50"),title:"Rotate app key",children:[l.jsx(Gd,{size:12,className:w?"animate-spin":""}),"Rotate Key"]})]}),l.jsxs("div",{className:"flex items-center gap-2",children:[l.jsxs("select",{value:d,onChange:X=>g(X.target.value),disabled:k,className:te("rounded border px-1.5 py-1 text-xs font-mono",d==="https"?"border-green-500/40 bg-green-500/10 text-green-600 dark:text-green-400":d==="mqtt"||d==="mqtts"?"border-purple-500/40 bg-purple-500/10 text-purple-600 dark:text-purple-400":d==="ws"||d==="wss"?"border-blue-500/40 bg-blue-500/10 text-blue-600 dark:text-blue-400":"border-[var(--color-border)] bg-[var(--color-background)] text-[var(--color-text-muted)]","disabled:opacity-50"),title:"Scheme",children:[l.jsx("option",{value:"http",children:"http"}),l.jsx("option",{value:"https",children:"https"}),l.jsx("option",{value:"mqtt",children:"mqtt"}),l.jsx("option",{value:"mqtts",children:"mqtts"}),l.jsx("option",{value:"ws",children:"ws"}),l.jsx("option",{value:"wss",children:"wss"})]}),l.jsx("input",{type:"text",value:o,onChange:X=>m(X.target.value),onBlur:h,disabled:k,placeholder:"host",className:te("w-36 rounded border border-[var(--color-border)] bg-[var(--color-background)] px-2 py-1","text-xs text-[var(--color-text)] outline-none focus:ring-1 focus:ring-[var(--color-primary)]","disabled:opacity-50")}),l.jsx("span",{className:"text-xs text-[var(--color-text-muted)]",children:":"}),l.jsx("input",{type:"number",value:i,onChange:X=>v(Number(X.target.value)),onBlur:y,disabled:k,className:te("w-20 rounded border border-[var(--color-border)] bg-[var(--color-background)] px-2 py-1","text-xs text-[var(--color-text)] outline-none focus:ring-1 focus:ring-[var(--color-primary)]","disabled:opacity-50")}),l.jsx(NE,{status:_,error:A,latency:M})]})]})}const Lx={name:"",host:"localhost",port:"",scheme:"http",health_path:"/health",description:""};function SE(){const{data:a,isLoading:s,isError:o,error:i,refetch:d,isFetching:f}=pE(),m=xE(),v=vE(),g=gE(),h=yE(),{data:y}=bE(),[x,j]=N.useState({}),[k,w]=N.useState(null),[E,_]=N.useState(null),[A,M]=N.useState(null),[X,I]=N.useState(null),[ne,W]=N.useState(null),[G,U]=N.useState({}),[oe,Ne]=N.useState(!1),[le,pe]=N.useState(Lx),[Ee,Re]=N.useState(!1),ae=N.useRef(null),C=N.useMemo(()=>new Set(a?.services.map(L=>L.name)??[]),[a]),Y=N.useMemo(()=>{const z=(y?.suggestions??[]).filter(he=>!C.has(he.id));if(!le.name.trim())return z;const Se=le.name.toLowerCase();return z.filter(he=>he.id.toLowerCase().includes(Se)||he.name.toLowerCase().includes(Se)||he.description.toLowerCase().includes(Se))},[y,C,le.name]),K=N.useCallback(L=>{pe({name:L.id,description:L.description,host:"localhost",port:String(L.port),scheme:"http",health_path:L.healthCheck}),Re(!1)},[]);N.useEffect(()=>{const L=z=>{ae.current&&!ae.current.contains(z.target)&&Re(!1)};return document.addEventListener("mousedown",L),()=>document.removeEventListener("mousedown",L)},[]);const xe=N.useCallback(L=>{if(x[L])return x[L];const z=a?.services.find(Se=>Se.name===L);return z?{checked:z.config_registered,host:z.current_host??"localhost",port:z.current_port??z.default_port,scheme:z.current_scheme??"http"}:{checked:!1,host:"localhost",port:0,scheme:"http"}},[x,a]),ee=N.useCallback((L,z)=>{j(Se=>{const he=Se[L]??{checked:!1,host:"localhost",port:0};return{...Se,[L]:{...he,...z}}})},[]),S=N.useCallback(async(L,z,Se,he,Ut="http")=>{if(!(!z||!Se)){U(ct=>({...ct,[L]:{status:"probing"}}));try{const ct=await dE({host:z,port:Se,health_path:he,scheme:Ut});U(Dn=>({...Dn,[L]:{status:ct.healthy?"healthy":"unhealthy",error:ct.error??void 0,latency:ct.latency_ms??void 0}}))}catch{U(ct=>({...ct,[L]:{status:"unhealthy",error:"Request failed"}}))}}},[]),D=N.useCallback(()=>{if(!a)return;const L=a.services.filter(z=>xe(z.name).checked).map(z=>{const Se=xe(z.name);return{name:z.name,host:Se.host,port:Se.port,scheme:Se.scheme}});if(L.length===0){Me.error("No services selected");return}w(null),_(null),m.mutate({services:L},{onSuccess:z=>{w(z.results);const Se=z.results.filter(Ut=>Ut.config_ok&&Ut.auth_ok).length,he=z.results.length;Se===he?Me.success(`All ${he} services registered`):Me.warning(`${Se}/${he} services registered successfully`)},onError:z=>{Me.error(`Registration failed: ${z.message}`)}})},[a,xe,m]),Q=N.useCallback(L=>{M(L),_(null),v.mutate({service_name:L},{onSuccess:z=>{_(z),M(null),Me.success(`Key rotated for ${L}`)},onError:z=>{M(null),Me.error(`Key rotation failed: ${z.message}`)}})},[v]),Z=N.useCallback(L=>{I(L),h.mutate(L,{onSuccess:()=>{I(null),Me.success(`Removed ${L}`)},onError:z=>{I(null),Me.error(`Failed to remove: ${z.message}`)}})},[h]),re=N.useCallback(()=>{const L=parseInt(le.port,10);if(!le.name.trim()){Me.error("Service name is required");return}if(!L||L<1||L>65535){Me.error("Port must be between 1 and 65535");return}g.mutate({name:le.name.trim(),host:le.host.trim()||"localhost",port:L,scheme:le.scheme,health_path:le.health_path.trim()||"/health",description:le.description.trim()},{onSuccess:z=>{const Se=z.results[0];Se?.config_ok?(Me.success(`Added ${le.name.trim()}`),pe(Lx),Ne(!1)):Me.error(`Failed to add: ${Se?.error??"Unknown error"}`)},onError:z=>{Me.error(`Failed to add service: ${z.message}`)}})},[le,g]),fe=N.useCallback(L=>{navigator.clipboard.writeText(L).then(()=>{W(L),setTimeout(()=>W(null),2e3)})},[]),ce=a?.services.filter(L=>xe(L.name).checked).length??0,je=k?.some(L=>L.env_written)||E?.env_written===!0;return s?l.jsx("div",{className:"flex items-center justify-center py-20",children:l.jsx(it,{className:"animate-spin text-[var(--color-primary)]",size:24})}):o?l.jsxs("div",{className:"py-20 text-center",children:[l.jsx("p",{className:"mb-2 text-red-500",children:"Failed to load service registry"}),l.jsx("p",{className:"mb-4 text-sm text-[var(--color-text-muted)]",children:i?.message??"Unknown error"}),l.jsx("button",{onClick:()=>d(),className:"rounded-lg bg-[var(--color-primary)] px-4 py-2 text-sm text-white hover:opacity-90",children:"Retry"})]}):l.jsxs("div",{className:"mx-auto max-w-4xl space-y-4",children:[l.jsxs("div",{className:"flex items-center justify-between",children:[l.jsxs("div",{className:"flex items-center gap-3",children:[l.jsx("h1",{className:"text-xl font-bold text-[var(--color-text)]",children:"Services"}),l.jsx("span",{className:"rounded-full bg-[var(--color-surface-alt)] px-2.5 py-0.5 text-xs font-medium text-[var(--color-text-muted)]",children:a?.services.length??0})]}),l.jsxs("div",{className:"flex items-center gap-2",children:[l.jsxs("button",{onClick:()=>Ne(L=>!L),className:te("flex items-center gap-1.5 rounded-lg px-3 py-1.5 text-xs font-medium",oe?"bg-[var(--color-surface-alt)] text-[var(--color-text)]":"bg-[var(--color-primary)] text-white hover:opacity-90"),children:[oe?l.jsx(Vd,{size:14}):l.jsx(ti,{size:14}),oe?"Cancel":"Add Service"]}),l.jsx("button",{onClick:()=>d(),disabled:f,className:te("rounded-lg p-1.5 text-[var(--color-text-muted)] hover:bg-[var(--color-surface-alt)]",f&&"animate-spin"),title:"Refresh",children:l.jsx(it,{size:14})})]})]}),oe&&l.jsxs("div",{className:"rounded-lg border border-[var(--color-primary)]/30 bg-[var(--color-primary)]/5 p-4",children:[l.jsx("h2",{className:"mb-3 text-sm font-semibold text-[var(--color-text)]",children:"Add Service"}),l.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[l.jsxs("div",{ref:ae,className:"relative",children:[l.jsx("label",{className:"mb-1 block text-xs text-[var(--color-text-muted)]",children:"Service"}),l.jsxs("div",{className:"relative",children:[l.jsx("input",{type:"text",value:le.name,onChange:L=>{pe(z=>({...z,name:L.target.value})),Re(!0)},onFocus:()=>Re(!0),placeholder:"Select or type a service name...",className:te("w-full rounded border border-[var(--color-border)] bg-[var(--color-background)] px-2.5 py-1.5 pr-8","text-sm text-[var(--color-text)] outline-none focus:ring-1 focus:ring-[var(--color-primary)]")}),l.jsx("button",{type:"button",onClick:()=>Re(L=>!L),className:"absolute right-1.5 top-1/2 -translate-y-1/2 rounded p-0.5 text-[var(--color-text-muted)] hover:text-[var(--color-text)]",children:l.jsx(Ld,{size:14})})]}),Ee&&Y.length>0&&l.jsx("div",{className:"absolute z-10 mt-1 max-h-48 w-full overflow-y-auto rounded-lg border border-[var(--color-border)] bg-[var(--color-surface)] shadow-lg",children:Y.map(L=>l.jsxs("button",{type:"button",onClick:()=>K(L),className:"flex w-full flex-col px-3 py-2 text-left hover:bg-[var(--color-surface-alt)]",children:[l.jsxs("span",{className:"text-sm font-medium text-[var(--color-text)]",children:[L.name,l.jsxs("span",{className:"ml-2 font-normal text-[var(--color-text-muted)]",children:[":",L.port]})]}),l.jsx("span",{className:"text-xs text-[var(--color-text-muted)]",children:L.description})]},L.id))})]}),l.jsxs("div",{children:[l.jsx("label",{className:"mb-1 block text-xs text-[var(--color-text-muted)]",children:"Description"}),l.jsx("input",{type:"text",value:le.description,onChange:L=>pe(z=>({...z,description:L.target.value})),placeholder:"e.g. Camera streaming via WebRTC",className:te("w-full rounded border border-[var(--color-border)] bg-[var(--color-background)] px-2.5 py-1.5","text-sm text-[var(--color-text)] outline-none focus:ring-1 focus:ring-[var(--color-primary)]")})]}),l.jsxs("div",{children:[l.jsx("label",{className:"mb-1 block text-xs text-[var(--color-text-muted)]",children:"Host"}),l.jsx("input",{type:"text",value:le.host,onChange:L=>pe(z=>({...z,host:L.target.value})),placeholder:"localhost",className:te("w-full rounded border border-[var(--color-border)] bg-[var(--color-background)] px-2.5 py-1.5","text-sm text-[var(--color-text)] outline-none focus:ring-1 focus:ring-[var(--color-primary)]")})]}),l.jsxs("div",{className:"flex gap-3",children:[l.jsxs("div",{className:"flex-1",children:[l.jsx("label",{className:"mb-1 block text-xs text-[var(--color-text-muted)]",children:"Port"}),l.jsx("input",{type:"number",value:le.port,onChange:L=>pe(z=>({...z,port:L.target.value})),placeholder:"e.g. 1984",className:te("w-full rounded border border-[var(--color-border)] bg-[var(--color-background)] px-2.5 py-1.5","text-sm text-[var(--color-text)] outline-none focus:ring-1 focus:ring-[var(--color-primary)]")})]}),l.jsxs("div",{className:"w-20",children:[l.jsx("label",{className:"mb-1 block text-xs text-[var(--color-text-muted)]",children:"Scheme"}),l.jsxs("select",{value:le.scheme,onChange:L=>pe(z=>({...z,scheme:L.target.value})),className:te("w-full rounded border border-[var(--color-border)] bg-[var(--color-background)] px-2 py-1.5","text-sm text-[var(--color-text)] outline-none focus:ring-1 focus:ring-[var(--color-primary)]"),children:[l.jsx("option",{value:"http",children:"http"}),l.jsx("option",{value:"https",children:"https"}),l.jsx("option",{value:"mqtt",children:"mqtt"}),l.jsx("option",{value:"mqtts",children:"mqtts"}),l.jsx("option",{value:"ws",children:"ws"}),l.jsx("option",{value:"wss",children:"wss"})]})]})]}),l.jsxs("div",{children:[l.jsx("label",{className:"mb-1 block text-xs text-[var(--color-text-muted)]",children:"Health Path"}),l.jsx("input",{type:"text",value:le.health_path,onChange:L=>pe(z=>({...z,health_path:L.target.value})),placeholder:"/health",className:te("w-full rounded border border-[var(--color-border)] bg-[var(--color-background)] px-2.5 py-1.5","text-sm text-[var(--color-text)] outline-none focus:ring-1 focus:ring-[var(--color-primary)]")})]})]}),l.jsx("div",{className:"mt-3 flex justify-end",children:l.jsx("button",{onClick:re,disabled:g.isPending||!le.name.trim()||!le.port,className:te("rounded-lg bg-[var(--color-primary)] px-4 py-1.5 text-sm font-medium text-white","hover:opacity-90 disabled:cursor-not-allowed disabled:opacity-50"),children:g.isPending?"Adding...":"Add Service"})})]}),l.jsx("div",{className:"space-y-2",children:a?.services.map(L=>{const z=xe(L.name),Se=G[L.name]??{status:"idle"};return l.jsx(jE,{entry:L,checked:z.checked,host:z.host,port:z.port,scheme:z.scheme,onToggle:()=>{const he=!z.checked;ee(L.name,{...z,checked:he}),he?S(L.name,z.host,z.port,L.health_path,z.scheme):U(Ut=>({...Ut,[L.name]:{status:"idle"}}))},onHostChange:he=>ee(L.name,{...z,host:he}),onPortChange:he=>ee(L.name,{...z,port:he}),onSchemeChange:he=>ee(L.name,{...z,scheme:he}),onHostBlur:()=>{z.checked&&S(L.name,z.host,z.port,L.health_path,z.scheme)},onPortBlur:()=>{z.checked&&S(L.name,z.host,z.port,L.health_path,z.scheme)},onRotateKey:()=>Q(L.name),onDelete:()=>Z(L.name),disabled:m.isPending,rotating:A===L.name,deleting:X===L.name,healthStatus:Se.status,healthError:Se.error,healthLatency:Se.latency},L.name)})}),l.jsx("button",{onClick:D,disabled:m.isPending||ce===0,className:te("rounded-lg bg-[var(--color-primary)] px-4 py-2 text-sm font-medium text-white","hover:opacity-90 disabled:cursor-not-allowed disabled:opacity-50"),children:m.isPending?"Registering...":`Register Selected (${ce})`}),E&&l.jsx(wE,{serviceName:E.service_name,appKey:E.app_key,envWritten:E.env_written,copiedKey:ne,onCopy:fe,label:"Rotated Key"}),k&&l.jsxs("div",{className:"space-y-2 rounded-lg border border-[var(--color-border)] bg-[var(--color-surface)] p-4",children:[l.jsx("h2",{className:"text-sm font-semibold text-[var(--color-text)]",children:"Registration Results"}),k.map(L=>l.jsxs("div",{className:te("flex flex-wrap items-center gap-3 rounded-lg border p-3 text-sm",L.config_ok&&L.auth_ok?"border-green-500/20 bg-green-500/5":"border-yellow-500/20 bg-yellow-500/5"),children:[l.jsx("span",{className:"min-w-[180px] font-medium text-[var(--color-text)]",children:L.name}),l.jsxs("span",{className:te("text-xs",L.config_ok?"text-green-600 dark:text-green-400":"text-red-500"),children:["Config: ",L.config_ok?"OK":"Failed"]}),l.jsxs("span",{className:te("text-xs",L.auth_ok?"text-green-600 dark:text-green-400":"text-red-500"),children:["Auth: ",L.auth_ok?L.auth_created?"Created":"Exists":"Failed"]}),L.env_written!==null&&l.jsxs("span",{className:te("text-xs",L.env_written?"text-green-600 dark:text-green-400":"text-red-500"),children:[".env: ",L.env_written?"Written":"Failed"]}),L.error&&l.jsxs("span",{className:"flex items-center gap-1 text-xs text-yellow-600 dark:text-yellow-400",children:[l.jsx(ra,{size:12}),L.error]}),L.auth_created&&L.app_key&&l.jsxs("div",{className:"mt-1 w-full",children:[l.jsxs("div",{className:"mb-1 flex items-center gap-1 text-xs font-medium text-yellow-600 dark:text-yellow-400",children:[l.jsx(ra,{size:12}),"App key (shown once only):"]}),l.jsxs("div",{className:"flex items-center gap-2",children:[l.jsx("code",{className:"flex-1 overflow-x-auto rounded bg-[var(--color-background)] px-2 py-1 font-mono text-xs text-[var(--color-text)]",children:L.app_key}),l.jsx("button",{onClick:()=>fe(L.app_key),className:"rounded p-1 hover:bg-[var(--color-surface-alt)]",title:"Copy to clipboard",children:ne===L.app_key?l.jsx(xi,{size:14,className:"text-green-500"}):l.jsx(qd,{size:14,className:"text-[var(--color-text-muted)]"})})]})]})]},L.name))]}),je&&l.jsxs("div",{className:"flex items-start gap-2 rounded-lg border border-blue-500/20 bg-blue-500/5 p-3",children:[l.jsx(rS,{size:16,className:"mt-0.5 shrink-0 text-blue-500"}),l.jsx("p",{className:"text-sm text-[var(--color-text)]",children:"Services whose .env files were updated need to be restarted to pick up the new credentials. Restart each affected service's container or process."})]})]})}function wE({serviceName:a,appKey:s,envWritten:o,copiedKey:i,onCopy:d,label:f}){return l.jsxs("div",{className:"space-y-2 rounded-lg border border-[var(--color-border)] bg-[var(--color-surface)] p-4",children:[l.jsxs("h2",{className:"text-sm font-semibold text-[var(--color-text)]",children:[f,": ",a]}),l.jsxs("div",{className:"rounded-lg border border-green-500/20 bg-green-500/5 p-3",children:[o!==null&&l.jsxs("span",{className:te("mb-2 inline-block text-xs",o?"text-green-600 dark:text-green-400":"text-red-500"),children:[".env: ",o?"Written":"Failed"]}),l.jsxs("div",{children:[l.jsxs("div",{className:"mb-1 flex items-center gap-1 text-xs font-medium text-yellow-600 dark:text-yellow-400",children:[l.jsx(ra,{size:12}),"New app key (shown once only):"]}),l.jsxs("div",{className:"flex items-center gap-2",children:[l.jsx("code",{className:"flex-1 overflow-x-auto rounded bg-[var(--color-background)] px-2 py-1 font-mono text-xs text-[var(--color-text)]",children:s}),l.jsx("button",{onClick:()=>d(s),className:"rounded p-1 hover:bg-[var(--color-surface-alt)]",title:"Copy to clipboard",children:i===s?l.jsx(xi,{size:14,className:"text-green-500"}):l.jsx(qd,{size:14,className:"text-[var(--color-text-muted)]"})})]})]})]})]})}async function EE(){const{data:a}=await ge.get("/api/llm-setup/status");return a}async function CE(a){const{data:s}=await ge.post("/api/llm-setup/configure",{settings:a});return s}async function TE(a,s,o){const{data:i}=await ge.post("/api/llm-setup/download",{repo:a,filename:s,token:o});return i}function _E(){return yt({queryKey:["llm-status"],queryFn:EE,staleTime:3e4,retry:1})}function yg(){const a=pt();return bt({mutationFn:s=>CE(s),onSuccess:()=>{a.invalidateQueries({queryKey:["llm-status"]}),a.invalidateQueries({queryKey:["containers"]})}})}function RE(){return bt({mutationFn:({repo:a,filename:s,token:o})=>TE(a,s,o)})}async function Yd(){const{data:a}=await ge.get("/api/install/status");return a}async function kE(a){const s=a?.length?{services:a.join(",")}:{},{data:o}=await ge.get("/api/install/preflight",{params:s});return o}async function ME(){const{data:a}=await ge.get("/api/install/hardware");return a}async function Bx(a){const{data:s}=await ge.post("/api/install/generate",a);return s}async function bg(){const{data:a}=await ge.get("/api/install/registry");return a}async function AE(){const{data:a}=await ge.get("/api/install/defaults");return a}const OE={running:"bg-emerald-500",exited:"bg-red-500",restarting:"bg-amber-500",paused:"bg-amber-500",created:"bg-gray-400",dead:"bg-red-700"};function zE(a){return a.match(/^Up (.+)$/)?.[1]??null}function qx({container:a,onRestart:s,isRestarting:o}){const i=zE(a.status),d=a.ports.find(f=>f.public)?.public;return l.jsxs("div",{className:"overflow-hidden rounded-xl border border-[var(--color-border)] bg-[var(--color-surface)]",children:[l.jsxs("div",{className:"flex items-center gap-3 px-4 py-3",children:[l.jsx("div",{className:te("h-2.5 w-2.5 rounded-full",OE[a.state]??"bg-gray-400")}),l.jsxs("div",{className:"min-w-0 flex-1",children:[l.jsx("p",{className:"truncate text-sm font-medium text-[var(--color-text)]",children:a.displayName??a.name}),a.description&&l.jsx("p",{className:"truncate text-xs text-[var(--color-text-muted)]",children:a.description})]}),l.jsx("span",{className:te("rounded-full px-2 py-0.5 text-xs font-medium",a.state==="running"?"bg-emerald-500/10 text-emerald-600 dark:text-emerald-400":"bg-red-500/10 text-red-600 dark:text-red-400"),children:a.state})]}),l.jsx("div",{className:"border-t border-[var(--color-border)] px-4 py-2",children:l.jsxs("div",{className:"flex items-center justify-between text-xs text-[var(--color-text-muted)]",children:[l.jsxs("div",{className:"flex items-center gap-3",children:[i&&l.jsxs("span",{children:["Up ",i]}),d&&l.jsxs("span",{children:[":",d]})]}),l.jsxs("div",{className:"flex items-center gap-1",children:[d&&l.jsx("a",{href:`http://localhost:${d}/health`,target:"_blank",rel:"noopener noreferrer",className:"rounded p-1 hover:bg-[var(--color-surface-alt)]",title:"Open health endpoint",children:l.jsx(Pj,{size:13})}),l.jsx("button",{onClick:()=>s(a.id),disabled:o,className:te("rounded p-1 hover:bg-[var(--color-surface-alt)]",o&&"animate-spin"),title:"Restart",children:l.jsx(Gd,{size:13})})]})]})})]})}async function DE(){const{data:a}=await ge.get("/api/update/check");return a}function Ng(){return yt({queryKey:["update-check"],queryFn:DE,staleTime:300*1e3,retry:1,refetchOnWindowFocus:!1})}const Hx="jarvis-update-dismissed-version";function Gx(){const a=wa(),{data:s}=Ng(),[o,i]=N.useState(()=>s?.latestVersion?localStorage.getItem(Hx)===s.latestVersion:!1);return!s?.updateAvailable||o?null:l.jsxs("div",{className:"flex items-center justify-between rounded-lg border border-green-500/30 bg-green-500/5 p-4",children:[l.jsxs("div",{className:"flex items-center gap-3",children:[l.jsx(eg,{size:20,className:"text-green-500"}),l.jsxs("div",{children:[l.jsxs("p",{className:"text-sm font-medium text-[var(--color-text)]",children:["Jarvis v",s.latestVersion," available"]}),l.jsxs("p",{className:"text-xs text-[var(--color-text-muted)]",children:["You have v",s.currentVersion]})]})]}),l.jsxs("div",{className:"flex items-center gap-2",children:[s.releaseUrl&&l.jsx("a",{href:s.releaseUrl,target:"_blank",rel:"noopener noreferrer",className:"text-xs text-[var(--color-text-muted)] hover:text-[var(--color-text)]",children:"Release notes"}),l.jsx("button",{onClick:()=>{localStorage.setItem(Hx,s.latestVersion),i(!0)},className:"text-xs text-[var(--color-text-muted)] hover:text-[var(--color-text)]",children:"Dismiss"}),l.jsx("button",{onClick:()=>a("/update"),className:"rounded-lg bg-green-600 px-3 py-1.5 text-xs text-white hover:opacity-90",children:"Update"})]})]})}const Ku="jarvis-admin:llm-setup-dismissed";function UE(){const a=wa(),[s,o]=N.useState(!1),{data:i,isLoading:d,isError:f,error:m,refetch:v,isFetching:g}=vg(),h=gg(),y=_E(),[x,j]=N.useState(()=>!!localStorage.getItem(Ku));N.useEffect(()=>{Yd().then(M=>{M.deployMode==="compose-export"&&o(!0)}).catch(()=>{})},[]);const k=!!y.data&&!y.data.configured&&!x,w=M=>{h.mutate(M,{onSuccess:()=>Me.success("Container restart initiated"),onError:X=>Me.error(`Restart failed: ${X.message}`)})};if(s)return l.jsxs("div",{className:"mx-auto max-w-4xl space-y-4",children:[l.jsx("h1",{className:"text-xl font-bold text-[var(--color-text)]",children:"Dashboard"}),l.jsx(Gx,{}),k&&l.jsxs("div",{className:"flex items-center justify-between rounded-lg border border-[var(--color-primary)]/30 bg-[var(--color-primary)]/5 p-4",children:[l.jsxs("div",{className:"flex items-center gap-3",children:[l.jsx(pd,{size:20,className:"text-[var(--color-primary)]"}),l.jsxs("div",{children:[l.jsx("p",{className:"text-sm font-medium text-[var(--color-text)]",children:"LLM not configured"}),l.jsx("p",{className:"text-xs text-[var(--color-text-muted)]",children:"Set up a language model to enable voice command processing"})]})]}),l.jsxs("div",{className:"flex items-center gap-2",children:[l.jsx("button",{onClick:()=>{localStorage.setItem(Ku,"true"),j(!0)},className:"text-xs text-[var(--color-text-muted)] hover:text-[var(--color-text)]",children:"Dismiss"}),l.jsx("button",{onClick:()=>a("/llm-setup"),className:"rounded-lg bg-[var(--color-primary)] px-3 py-1.5 text-xs text-white hover:opacity-90",children:"Set up LLM"})]})]}),l.jsxs("div",{className:"flex items-center justify-between rounded-lg border border-[var(--color-border)] bg-[var(--color-surface)] p-4",children:[l.jsxs("div",{className:"flex items-center gap-3",children:[l.jsx(xd,{size:20,className:"text-[var(--color-text-muted)]"}),l.jsxs("div",{children:[l.jsx("p",{className:"text-sm font-medium text-[var(--color-text)]",children:"Sync compose to latest registry"}),l.jsx("p",{className:"text-xs text-[var(--color-text-muted)]",children:"Regenerate docker-compose.yml, apply changes, and re-register services with config-service"})]})]}),l.jsx("button",{onClick:()=>a("/reconcile"),className:"rounded-lg border border-[var(--color-border)] px-3 py-1.5 text-xs text-[var(--color-text)] hover:bg-[var(--color-surface-alt)]",children:"Sync now"})]}),l.jsxs("div",{className:"rounded-lg border border-[var(--color-border)] bg-[var(--color-surface)] p-8 text-center",children:[l.jsx(Qd,{size:32,className:"mx-auto mb-3 text-[var(--color-text-muted)]"}),l.jsx("p",{className:"text-sm font-medium text-[var(--color-text)]",children:"Running in Docker Compose mode"}),l.jsx("p",{className:"mt-1 text-xs text-[var(--color-text-muted)]",children:"Container management is handled by your Docker environment (TrueNAS, Portainer, etc.). Use your platform's tools to view container status, logs, and restarts."})]})]});if(d)return l.jsx("div",{className:"flex items-center justify-center py-20",children:l.jsx(it,{className:"animate-spin text-[var(--color-primary)]",size:24})});if(f)return l.jsxs("div",{className:"py-20 text-center",children:[l.jsx("p",{className:"mb-2 text-red-500",children:"Failed to load containers"}),l.jsx("p",{className:"mb-4 text-sm text-[var(--color-text-muted)]",children:m?.message??"Unknown error"}),l.jsx("button",{onClick:()=>v(),className:"rounded-lg bg-[var(--color-primary)] px-4 py-2 text-sm text-white hover:opacity-90",children:"Retry"})]});const E=i?.containers??[],_=E.filter(M=>M.state==="running"),A=E.filter(M=>M.state!=="running");return l.jsxs("div",{className:"mx-auto max-w-4xl space-y-4",children:[l.jsxs("div",{className:"flex items-center justify-between",children:[l.jsx("h1",{className:"text-xl font-bold text-[var(--color-text)]",children:"Dashboard"}),l.jsxs("div",{className:"flex items-center gap-2 text-xs text-[var(--color-text-muted)]",children:[l.jsxs("span",{children:[_.length,"/",E.length," running"]}),l.jsx("button",{onClick:()=>v(),disabled:g,className:te("rounded-lg p-1.5 hover:bg-[var(--color-surface-alt)]",g&&"animate-spin"),title:"Refresh",children:l.jsx(it,{size:14})})]})]}),l.jsx(Gx,{}),k&&l.jsxs("div",{className:"flex items-center justify-between rounded-lg border border-[var(--color-primary)]/30 bg-[var(--color-primary)]/5 p-4",children:[l.jsxs("div",{className:"flex items-center gap-3",children:[l.jsx(pd,{size:20,className:"text-[var(--color-primary)]"}),l.jsxs("div",{children:[l.jsx("p",{className:"text-sm font-medium text-[var(--color-text)]",children:"LLM not configured"}),l.jsx("p",{className:"text-xs text-[var(--color-text-muted)]",children:"Set up a language model to enable voice command processing"})]})]}),l.jsxs("div",{className:"flex items-center gap-2",children:[l.jsx("button",{onClick:()=>{localStorage.setItem(Ku,"true"),j(!0)},className:"text-xs text-[var(--color-text-muted)] hover:text-[var(--color-text)]",children:"Dismiss"}),l.jsx("button",{onClick:()=>a("/llm-setup"),className:"rounded-lg bg-[var(--color-primary)] px-3 py-1.5 text-xs text-white hover:opacity-90",children:"Set up LLM"})]})]}),l.jsxs("div",{className:"flex items-center justify-between rounded-lg border border-[var(--color-border)] bg-[var(--color-surface)] p-4",children:[l.jsxs("div",{className:"flex items-center gap-3",children:[l.jsx(xd,{size:20,className:"text-[var(--color-text-muted)]"}),l.jsxs("div",{children:[l.jsx("p",{className:"text-sm font-medium text-[var(--color-text)]",children:"Sync compose to latest registry"}),l.jsx("p",{className:"text-xs text-[var(--color-text-muted)]",children:"Regenerate docker-compose.yml and apply changes — adds new background workers and services without recreating unchanged containers"})]})]}),l.jsx("button",{onClick:()=>a("/reconcile"),className:"rounded-lg border border-[var(--color-border)] px-3 py-1.5 text-xs text-[var(--color-text)] hover:bg-[var(--color-surface-alt)]",children:"Sync now"})]}),E.length===0&&l.jsx("div",{className:"py-12 text-center",children:l.jsx("p",{className:"text-sm text-[var(--color-text-muted)]",children:i?.error?i.error:"No Jarvis containers found. Is Docker running?"})}),_.length>0&&l.jsxs("div",{className:"space-y-2",children:[l.jsx("h2",{className:"text-xs font-semibold uppercase tracking-wider text-[var(--color-text-muted)]",children:"Running"}),l.jsx("div",{className:"grid grid-cols-1 gap-3 sm:grid-cols-2",children:_.map(M=>l.jsx(qx,{container:M,onRestart:w,isRestarting:h.isPending&&h.variables===M.id},M.id))})]}),A.length>0&&l.jsxs("div",{className:"space-y-2",children:[l.jsx("h2",{className:"text-xs font-semibold uppercase tracking-wider text-[var(--color-text-muted)]",children:"Stopped"}),l.jsx("div",{className:"grid grid-cols-1 gap-3 sm:grid-cols-2",children:A.map(M=>l.jsx(qx,{container:M,onRestart:w,isRestarting:h.isPending&&h.variables===M.id},M.id))})]})]})}async function LE(){const{data:a}=await ge.get("/api/nodes");return a}async function BE(a){const{data:s}=await ge.get(`/api/nodes/${a}/nodes`);return s}async function qE(a){const{data:s}=await ge.post(`/api/nodes/${a}/train-adapter`);return s}function HE(){return yt({queryKey:["households"],queryFn:LE,staleTime:3e4})}function GE(a){return yt({queryKey:["household-nodes",a],queryFn:()=>BE(a),enabled:!!a,staleTime:3e4})}function QE(){const a=pt();return bt({mutationFn:qE,onSuccess:()=>{a.invalidateQueries({queryKey:["household-nodes"]})}})}function VE({node:a,onTrain:s,isTraining:o}){return l.jsxs("div",{className:"rounded-lg border border-[var(--color-border)] bg-[var(--color-surface)] p-4",children:[l.jsxs("div",{className:"flex items-start justify-between",children:[l.jsxs("div",{className:"flex items-center gap-2",children:[l.jsx(On,{size:16,className:"text-[var(--color-text-muted)]"}),l.jsx("span",{className:"font-medium text-[var(--color-text)]",children:a.name})]}),l.jsxs("span",{className:te("inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-xs font-medium",a.is_active?"bg-green-500/10 text-green-500":"bg-red-500/10 text-red-500"),children:[a.is_active?l.jsx(oi,{size:10}):l.jsx(ZS,{size:10}),a.is_active?"Active":"Inactive"]})]}),l.jsxs("div",{className:"mt-3 space-y-1 text-xs text-[var(--color-text-muted)]",children:[l.jsxs("p",{children:[l.jsx("span",{className:"font-medium",children:"ID:"})," ",a.node_id]}),a.services.length>0&&l.jsxs("p",{children:[l.jsx("span",{className:"font-medium",children:"Services:"})," ",a.services.join(", ")]})]}),l.jsx("div",{className:"mt-4",children:l.jsx("button",{onClick:()=>s(a.node_id),disabled:o||!a.is_active,className:te("rounded-lg px-3 py-1.5 text-xs font-medium transition-colors",o||!a.is_active?"cursor-not-allowed bg-[var(--color-surface-alt)] text-[var(--color-text-muted)]":"bg-[var(--color-primary)] text-white hover:opacity-90"),children:o?l.jsxs("span",{className:"flex items-center gap-1.5",children:[l.jsx(it,{size:12,className:"animate-spin"}),"Training..."]}):"Train Adapter"})})]})}function FE({householdId:a,householdName:s}){const{data:o,isLoading:i,isError:d}=GE(a),f=QE(),m=v=>{f.mutate(v,{onSuccess:g=>Me.success(`Training triggered for ${v} (request: ${g.request_id.slice(0,8)}...)`),onError:g=>Me.error(`Training failed: ${g.message}`)})};return l.jsxs("div",{className:"space-y-2",children:[l.jsx("h2",{className:"text-xs font-semibold uppercase tracking-wider text-[var(--color-text-muted)]",children:s}),i&&l.jsx("div",{className:"flex items-center justify-center py-8",children:l.jsx(it,{className:"animate-spin text-[var(--color-primary)]",size:18})}),d&&l.jsx("p",{className:"py-4 text-center text-sm text-red-500",children:"Failed to load nodes"}),o&&o.length===0&&l.jsx("p",{className:"py-4 text-center text-sm text-[var(--color-text-muted)]",children:"No nodes registered in this household"}),o&&o.length>0&&l.jsx("div",{className:"grid grid-cols-1 gap-3 sm:grid-cols-2",children:o.map(v=>l.jsx(VE,{node:v,onTrain:m,isTraining:f.isPending&&f.variables===v.node_id},v.node_id))})]})}function YE(){const{data:a,isLoading:s,isError:o,error:i,refetch:d,isFetching:f}=HE();return s?l.jsx("div",{className:"flex items-center justify-center py-20",children:l.jsx(it,{className:"animate-spin text-[var(--color-primary)]",size:24})}):o?l.jsxs("div",{className:"py-20 text-center",children:[l.jsx("p",{className:"mb-2 text-red-500",children:"Failed to load households"}),l.jsx("p",{className:"mb-4 text-sm text-[var(--color-text-muted)]",children:i?.message??"Unknown error"}),l.jsx("button",{onClick:()=>d(),className:"rounded-lg bg-[var(--color-primary)] px-4 py-2 text-sm text-white hover:opacity-90",children:"Retry"})]}):l.jsxs("div",{className:"mx-auto max-w-4xl space-y-6",children:[l.jsxs("div",{className:"flex items-center justify-between",children:[l.jsx("h1",{className:"text-xl font-bold text-[var(--color-text)]",children:"Nodes"}),l.jsx("button",{onClick:()=>d(),disabled:f,className:te("rounded-lg p-1.5 hover:bg-[var(--color-surface-alt)]",f&&"animate-spin"),title:"Refresh",children:l.jsx(it,{size:14,className:"text-[var(--color-text-muted)]"})})]}),(!a||a.length===0)&&l.jsx("div",{className:"py-12 text-center",children:l.jsx("p",{className:"text-sm text-[var(--color-text-muted)]",children:"No households found. Register a household in jarvis-auth first."})}),a?.map(m=>l.jsx(FE,{householdId:m.id,householdName:m.name},m.id))]})}async function XE(){const{data:a}=await ge.get("/api/admin/households");return a}async function KE(){const{data:a}=await ge.get("/api/admin/nodes");return a}async function $E(){const{data:a}=await ge.get("/api/admin/users");return a}async function ZE(a,s={}){const{data:o}=await ge.post(`/api/admin/users/${a}/temp-password`,s);return o}function JE(){return yt({queryKey:["admin-users"],queryFn:$E,staleTime:3e4})}function PE(){const a=pt();return bt({mutationFn:({userId:s,options:o})=>ZE(s,o),onSuccess:()=>{a.invalidateQueries({queryKey:["admin-users"]})}})}function $u({tone:a,children:s}){const o={green:"bg-green-500/10 text-green-500",red:"bg-red-500/10 text-red-500",amber:"bg-amber-500/10 text-amber-500",blue:"bg-blue-500/10 text-blue-500"};return l.jsx("span",{className:te("inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-xs font-medium",o[a]),children:s})}function IE({result:a,email:s,onDismiss:o}){const i=async()=>{try{await navigator.clipboard.writeText(a.temp_password),Me.success("Temporary password copied")}catch{Me.error("Copy failed — select it manually")}};return l.jsxs("div",{className:"rounded-lg border border-amber-500/40 bg-amber-500/5 p-4",children:[l.jsxs("p",{className:"text-sm font-medium text-[var(--color-text)]",children:["Temporary password for ",s]}),l.jsxs("div",{className:"mt-2 flex items-center gap-2",children:[l.jsx("code",{className:"rounded bg-[var(--color-surface-alt)] px-3 py-1.5 font-mono text-base tracking-wide text-[var(--color-text)]",children:a.temp_password}),l.jsx("button",{onClick:i,className:"rounded-lg p-1.5 hover:bg-[var(--color-surface-alt)]",title:"Copy to clipboard",children:l.jsx(qd,{size:14,className:"text-[var(--color-text-muted)]"})})]}),l.jsxs("p",{className:"mt-2 text-xs text-[var(--color-text-muted)]",children:["Shown once — it is not stored anywhere. Valid until"," ",new Date(a.expires_at).toLocaleString(),". All of the user's sessions were signed out; on their next login they'll be asked to set a new password."]}),l.jsx("button",{onClick:o,className:"mt-3 rounded-lg bg-[var(--color-primary)] px-3 py-1.5 text-xs font-medium text-white hover:opacity-90",children:"Done"})]})}function WE({user:a,onCancel:s,onConfirm:o,isPending:i}){const[d,f]=N.useState(""),m=d.length>0&&d.length<8;return l.jsxs("div",{className:"rounded-lg border border-[var(--color-border)] bg-[var(--color-surface-alt)] p-4",children:[l.jsxs("p",{className:"text-sm text-[var(--color-text)]",children:["Reset the password for ",l.jsx("span",{className:"font-medium",children:a.email}),"? This signs the user out everywhere and replaces their password with a temporary one they must change at next login."]}),l.jsxs("div",{className:"mt-3",children:[l.jsx("input",{type:"text",value:d,onChange:v=>f(v.target.value),placeholder:"Custom temp password (optional — leave blank to generate)",className:"w-full max-w-md rounded-lg border border-[var(--color-border)] bg-[var(--color-surface)] px-3 py-1.5 text-sm text-[var(--color-text)] placeholder:text-[var(--color-text-muted)]"}),m&&l.jsx("p",{className:"mt-1 text-xs text-red-500",children:"Must be at least 8 characters"})]}),l.jsxs("div",{className:"mt-3 flex gap-2",children:[l.jsx("button",{onClick:()=>o(d||null),disabled:i||m,className:te("rounded-lg px-3 py-1.5 text-xs font-medium transition-colors",i||m?"cursor-not-allowed bg-[var(--color-surface)] text-[var(--color-text-muted)]":"bg-red-500 text-white hover:opacity-90"),children:i?l.jsxs("span",{className:"flex items-center gap-1.5",children:[l.jsx(it,{size:12,className:"animate-spin"}),"Resetting..."]}):"Reset password"}),l.jsx("button",{onClick:s,disabled:i,className:"rounded-lg px-3 py-1.5 text-xs font-medium text-[var(--color-text-muted)] hover:bg-[var(--color-surface)]",children:"Cancel"})]})]})}function e4({user:a}){const[s,o]=N.useState("idle"),[i,d]=N.useState(null),f=PE(),m=v=>{f.mutate({userId:a.id,options:v?{temp_password:v}:{}},{onSuccess:g=>{o("idle"),d(g)},onError:g=>Me.error(`Reset failed: ${g.message}`)})};return l.jsxs("div",{className:"rounded-lg border border-[var(--color-border)] bg-[var(--color-surface)] p-4",children:[l.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-3",children:[l.jsxs("div",{children:[l.jsxs("div",{className:"flex items-center gap-2",children:[l.jsx("span",{className:"font-medium text-[var(--color-text)]",children:a.email}),a.is_superuser&&l.jsxs($u,{tone:"blue",children:[l.jsx(zS,{size:10}),"Superuser"]}),!a.is_active&&l.jsxs($u,{tone:"red",children:[l.jsx(FS,{size:10}),"Deactivated"]}),a.must_change_password&&l.jsxs($u,{tone:"amber",children:[l.jsx(Fj,{size:10}),"Temp password"]})]}),l.jsxs("div",{className:"mt-1 space-y-0.5 text-xs text-[var(--color-text-muted)]",children:[l.jsxs("p",{children:[l.jsx("span",{className:"font-medium",children:"Username:"})," ",a.username]}),a.households.length>0&&l.jsxs("p",{children:[l.jsx("span",{className:"font-medium",children:"Households:"})," ",a.households.map(v=>`${v.household_name} (${v.role})`).join(", ")]}),l.jsxs("p",{children:[l.jsx("span",{className:"font-medium",children:"Created:"})," ",new Date(a.created_at).toLocaleDateString()]})]})]}),s==="idle"&&!i&&l.jsxs("button",{onClick:()=>o("confirm"),disabled:!a.is_active,title:a.is_active?void 0:"Reactivate the account first",className:te("flex items-center gap-1.5 rounded-lg px-3 py-1.5 text-xs font-medium transition-colors",a.is_active?"bg-[var(--color-surface-alt)] text-[var(--color-text)] hover:bg-[var(--color-primary)]/10 hover:text-[var(--color-primary)]":"cursor-not-allowed bg-[var(--color-surface-alt)] text-[var(--color-text-muted)]"),children:[l.jsx(lS,{size:12}),"Reset password"]})]}),s==="confirm"&&l.jsx("div",{className:"mt-3",children:l.jsx(WE,{user:a,onCancel:()=>o("idle"),onConfirm:m,isPending:f.isPending})}),i&&l.jsx("div",{className:"mt-3",children:l.jsx(IE,{result:i,email:a.email,onDismiss:()=>d(null)})})]})}function t4(){const{data:a,isLoading:s,isError:o,error:i,refetch:d,isFetching:f}=JE();return s?l.jsx("div",{className:"flex items-center justify-center py-20",children:l.jsx(it,{className:"animate-spin text-[var(--color-primary)]",size:24})}):o?l.jsxs("div",{className:"py-20 text-center",children:[l.jsx("p",{className:"mb-2 text-red-500",children:"Failed to load users"}),l.jsx("p",{className:"mb-4 text-sm text-[var(--color-text-muted)]",children:i?.message??"Unknown error"}),l.jsx("button",{onClick:()=>d(),className:"rounded-lg bg-[var(--color-primary)] px-4 py-2 text-sm text-white hover:opacity-90",children:"Retry"})]}):l.jsxs("div",{className:"mx-auto max-w-4xl space-y-6",children:[l.jsxs("div",{className:"flex items-center justify-between",children:[l.jsx("h1",{className:"text-xl font-bold text-[var(--color-text)]",children:"Users"}),l.jsx("button",{onClick:()=>d(),disabled:f,className:te("rounded-lg p-1.5 hover:bg-[var(--color-surface-alt)]",f&&"animate-spin"),title:"Refresh",children:l.jsx(it,{size:14,className:"text-[var(--color-text-muted)]"})})]}),a&&a.length===0&&l.jsx("div",{className:"py-12 text-center",children:l.jsx("p",{className:"text-sm text-[var(--color-text-muted)]",children:"No users found."})}),l.jsx("div",{className:"space-y-3",children:a?.map(m=>l.jsx(e4,{user:m},m.id))})]})}async function a4(){const{data:a}=await ge.get("/api/native-services");return a}async function n4(a){const{data:s}=await ge.post(`/api/native-services/${a}/restart`);return s}async function r4(a){const{data:s}=await ge.post(`/api/native-services/${a}/stop`);return s}async function s4(a){const{data:s}=await ge.post(`/api/native-services/${a}/uninstall`);return s}async function l4(a,s="stderr",o=200){const{data:i}=await ge.get(`/api/native-services/${a}/logs`,{params:{stream:s,lines:o}});return i}const bi=["native-services"];function o4(){return yt({queryKey:bi,queryFn:a4,staleTime:5e3,refetchInterval:5e3})}function jg(){const a=pt();return bt({mutationFn:s=>n4(s),onSuccess:()=>a.invalidateQueries({queryKey:bi})})}function i4(){const a=pt();return bt({mutationFn:s=>r4(s),onSuccess:()=>a.invalidateQueries({queryKey:bi})})}function c4(){const a=pt();return bt({mutationFn:s=>s4(s),onSuccess:()=>a.invalidateQueries({queryKey:bi})})}function u4(a,s,o){return yt({queryKey:["native-services-logs",a,s],queryFn:()=>l4(a,s,200),enabled:o,staleTime:3e3,refetchInterval:o?3e3:!1})}function d4(){const{data:a,isLoading:s,isError:o,error:i,refetch:d,isFetching:f}=o4();return s?l.jsx("div",{className:"p-6",children:l.jsx("p",{className:"text-sm text-[var(--color-text-muted)]",children:"Loading native services…"})}):o?l.jsx("div",{className:"p-6",children:l.jsx(m4,{message:i instanceof Error?i.message:String(i)})}):a?a.supported?l.jsxs("div",{className:"p-6",children:[l.jsxs("header",{className:"mb-4 flex items-start justify-between",children:[l.jsxs("div",{children:[l.jsx("h1",{className:"text-2xl font-bold text-[var(--color-text)]",children:"Native Services"}),l.jsxs("p",{className:"mt-1 text-sm text-[var(--color-text-muted)]",children:["macOS LaunchAgents — these services run outside Docker so they can use the Apple GPU (MLX / Metal / MPS). Status reflects ",l.jsx("code",{children:"launchctl print"}),"."]})]}),l.jsxs("button",{type:"button",onClick:()=>d(),disabled:f,className:te("flex items-center gap-2 rounded-lg border border-[var(--color-border)] px-3 py-1.5 text-sm","hover:bg-[var(--color-surface-alt)] transition-colors",f&&"opacity-50"),children:[l.jsx(it,{size:14,className:f?"animate-spin":""}),"Refresh"]})]}),a.services.length===0?l.jsx("div",{className:"rounded-lg border border-[var(--color-border)] bg-[var(--color-surface-alt)] p-4",children:l.jsx("p",{className:"text-sm text-[var(--color-text-muted)]",children:"No native-capable services are registered. Re-run the install wizard to add them."})}):l.jsx("div",{className:"space-y-3",children:a.services.map(m=>l.jsx(f4,{service:m},m.id))})]}):l.jsxs("div",{className:"p-6",children:[l.jsxs("header",{className:"mb-4",children:[l.jsx("h1",{className:"text-2xl font-bold text-[var(--color-text)]",children:"Native Services"}),l.jsx("p",{className:"mt-1 text-sm text-[var(--color-text-muted)]",children:"Manage Jarvis services running as macOS LaunchAgents."})]}),l.jsx("div",{className:"rounded-lg border border-[var(--color-border)] bg-[var(--color-surface-alt)] p-4",children:l.jsx("p",{className:"text-sm text-[var(--color-text-muted)]",children:"Native services are only available on macOS. On Linux all services run in Docker."})})]}):null}function f4({service:a}){const s=jg(),o=i4(),i=c4(),[d,f]=N.useState(!1),[m,v]=N.useState("stderr"),g=u4(a.id,m,d),{status:h}=a;async function y(w,E){try{await w,Me.success(E)}catch(_){Me.error(_ instanceof Error?_.message:String(_))}}async function x(){confirm(`Uninstall ${a.id}? The LaunchAgent will be removed; source files at ${h.sourceDir??"~/.jarvis/native"} stay on disk.`)&&await y(i.mutateAsync(a.id),`${a.id} uninstalled`)}const j=h.installed?h.running?`Running (pid ${h.pid??"?"})`:"Installed, stopped":"Not installed",k=h.installed?h.running?"bg-green-500":"bg-amber-500":"bg-[var(--color-text-muted)]/30";return l.jsxs("div",{className:"rounded-lg border border-[var(--color-border)] bg-[var(--color-surface)] overflow-hidden",children:[l.jsxs("div",{className:"flex items-center justify-between gap-3 px-4 py-3",children:[l.jsxs("div",{className:"min-w-0 flex-1",children:[l.jsxs("div",{className:"flex items-center gap-3",children:[l.jsx("span",{className:te("h-2.5 w-2.5 shrink-0 rounded-full",k)}),l.jsx("span",{className:"text-sm font-medium text-[var(--color-text)]",children:a.name}),l.jsxs("span",{className:"text-xs text-[var(--color-text-muted)]",children:[":",h.port??a.port]}),l.jsx("code",{className:"text-xs text-[var(--color-text-muted)]",children:h.label})]}),l.jsxs("p",{className:"ml-5 mt-0.5 text-xs text-[var(--color-text-muted)]",children:[j,h.sourceDir&&l.jsxs("span",{className:"ml-2 opacity-60",children:["· ",h.sourceDir]})]})]}),l.jsxs("div",{className:"flex shrink-0 items-center gap-2",children:[h.installed&&l.jsxs(l.Fragment,{children:[h.running?l.jsx(pl,{icon:BS,label:"Stop",onClick:()=>y(o.mutateAsync(a.id),`${a.id} stopped`),disabled:o.isPending}):l.jsx(pl,{icon:ag,label:"Start",onClick:()=>y(s.mutateAsync(a.id),`${a.id} started`),disabled:s.isPending}),h.running&&l.jsx(pl,{icon:Gd,label:"Restart",onClick:()=>y(s.mutateAsync(a.id),`${a.id} restarted`),disabled:s.isPending}),l.jsx(pl,{icon:tg,label:d?"Hide logs":"Logs",onClick:()=>f(w=>!w)}),l.jsx(pl,{icon:yi,label:"Uninstall",onClick:x,disabled:i.isPending,danger:!0})]}),!h.installed&&l.jsxs("span",{className:"flex items-center gap-1 text-xs text-[var(--color-text-muted)]",children:[l.jsx(On,{size:12})," Re-run install wizard to enable"]})]})]}),d&&h.installed&&l.jsxs("div",{className:"border-t border-[var(--color-border)] bg-[var(--color-background)] p-3",children:[l.jsxs("div",{className:"mb-2 flex items-center gap-2",children:[l.jsx(Qx,{active:m==="stderr",onClick:()=>v("stderr"),children:"stderr"}),l.jsx(Qx,{active:m==="stdout",onClick:()=>v("stdout"),children:"stdout"}),l.jsx("code",{className:"ml-2 text-xs text-[var(--color-text-muted)] opacity-60",children:g.data?.file})]}),l.jsx("pre",{className:"max-h-80 overflow-auto whitespace-pre-wrap rounded bg-[var(--color-surface-alt)] p-2 text-xs font-mono text-[var(--color-text)]",children:g.isLoading?"Loading…":g.isError?`Failed to load logs: ${g.error instanceof Error?g.error.message:String(g.error)}`:g.data?.content||"(empty)"})]})]})}function pl({icon:a,label:s,onClick:o,disabled:i,danger:d}){return l.jsxs("button",{type:"button",onClick:o,disabled:i,className:te("flex items-center gap-1.5 rounded-md border px-2.5 py-1 text-xs","transition-colors disabled:cursor-not-allowed disabled:opacity-50",d?"border-red-500/30 text-red-500 hover:bg-red-500/10":"border-[var(--color-border)] text-[var(--color-text-muted)] hover:bg-[var(--color-surface-alt)] hover:text-[var(--color-text)]"),children:[l.jsx(a,{size:12}),s]})}function Qx({active:a,onClick:s,children:o}){return l.jsx("button",{type:"button",onClick:s,className:te("rounded px-2 py-0.5 text-xs",a?"bg-[var(--color-primary)] text-white":"border border-[var(--color-border)] text-[var(--color-text-muted)] hover:text-[var(--color-text)]"),children:o})}function m4({message:a}){return l.jsxs("div",{className:"flex items-center gap-2 rounded-lg border border-red-500/30 bg-red-500/10 px-3 py-2 text-sm text-red-500",children:[l.jsx(Bd,{size:14}),a]})}async function h4(){const{data:a}=await ge.get("/api/models/installed");return a.models}async function p4(a){const{data:s}=await ge.post("/api/models/download",a);return s}async function x4(a){await ge.delete(`/api/models/${encodeURIComponent(a)}`)}async function v4(a){const{data:s}=await ge.post("/api/models/whisper-autodownload",{enabled:a});return s}function Sg(){return yt({queryKey:["models","installed"],queryFn:h4,staleTime:1e4})}function wg(){const a=pt();return bt({mutationFn:s=>p4(s),onSuccess:()=>{a.invalidateQueries({queryKey:["models","installed"]})}})}function g4(){const a=pt();return bt({mutationFn:s=>x4(s),onSuccess:()=>{a.invalidateQueries({queryKey:["models","installed"]})}})}const ss=[{id:"qwen3-4b",displayName:"Qwen 3 4B",hfRepoVllm:"Qwen/Qwen3-4B-AWQ",hfRepoGguf:"Qwen/Qwen3-4B-GGUF",ggufFilename:"Qwen3-4B-Q4_K_M.gguf",chatFormat:"chatml",contextWindow:40960,sizeVllm:"2.5GB",sizeGguf:"2.5GB",vramMb:4096,gated:!1,quantization:"awq",promptProvider:"Qwen3_8B_Compressed"},{id:"qwen3-8b",displayName:"Qwen 3 8B",hfRepoVllm:"Qwen/Qwen3-8B-AWQ",hfRepoGguf:"Qwen/Qwen3-8B-GGUF",ggufFilename:"Qwen3-8B-Q4_K_M.gguf",chatFormat:"chatml",contextWindow:40960,sizeVllm:"5.7GB",sizeGguf:"5GB",vramMb:7168,gated:!1,quantization:"awq",promptProvider:"Qwen3_8B_Compressed"},{id:"qwen3-14b",displayName:"Qwen 3 14B",hfRepoVllm:"Qwen/Qwen3-14B-AWQ",hfRepoGguf:"Qwen/Qwen3-14B-GGUF",ggufFilename:"Qwen3-14B-Q4_K_M.gguf",chatFormat:"chatml",contextWindow:40960,sizeVllm:"9.4GB",sizeGguf:"9GB",vramMb:12288,gated:!1,quantization:"awq",promptProvider:"Qwen3LargeUntrained"},{id:"qwen25-7b",displayName:"Qwen 2.5 7B Instruct",hfRepoVllm:"Qwen/Qwen2.5-7B-Instruct-AWQ",hfRepoGguf:"Qwen/Qwen2.5-7B-Instruct-GGUF",ggufFilename:"qwen2.5-7b-instruct-q4_k_m.gguf",chatFormat:"chatml",contextWindow:32768,sizeVllm:"4.7GB",sizeGguf:"4.7GB",vramMb:6144,gated:!1,quantization:"awq",promptProvider:"Qwen25MediumUntrained"},{id:"llama-3.1-8b",displayName:"Llama 3.1 8B Instruct",hfRepoVllm:"hugging-quants/Meta-Llama-3.1-8B-Instruct-AWQ-INT4",hfRepoGguf:"lmstudio-community/Meta-Llama-3.1-8B-Instruct-GGUF",ggufFilename:"Meta-Llama-3.1-8B-Instruct-Q4_K_M.gguf",chatFormat:"llama-3",contextWindow:131072,sizeVllm:"5.4GB",sizeGguf:"5GB",vramMb:7168,gated:!1,quantization:"awq",promptProvider:"Llama31MediumUntrained"},{id:"hermes-3-8b",displayName:"Hermes 3 Llama 3.1 8B",hfRepoVllm:"solidrust/Hermes-3-Llama-3.1-8B-AWQ",hfRepoGguf:"NousResearch/Hermes-3-Llama-3.1-8B-GGUF",ggufFilename:"Hermes-3-Llama-3.1-8B.Q4_K_M.gguf",chatFormat:"chatml",contextWindow:131072,sizeVllm:"5.4GB",sizeGguf:"4.9GB",vramMb:7168,gated:!1,quantization:"awq",promptProvider:"HermesMediumUntrained"}];function y4(){const[a,s]=N.useState(""),[o,i]=N.useState(""),[d,f]=N.useState(""),[m,v]=N.useState(null),{data:g,isLoading:h}=Sg(),y=wg(),x=g4();function j(E,_){const A=`${E}/${_??""}`;v(A),y.mutate({repo:E,filename:_||void 0,token:a||void 0},{onSuccess:M=>{Me.success(M.message),v(null)},onError:M=>{Me.error(M instanceof Error?M.message:"Download failed"),v(null)}})}function k(E){confirm(`Delete ${E}?`)&&x.mutate(E,{onSuccess:()=>Me.success(`Deleted ${E}`),onError:()=>Me.error("Failed to delete")})}function w(){o&&j(o,d)}return l.jsxs("div",{className:"mx-auto max-w-4xl space-y-8 p-6",children:[l.jsxs("div",{children:[l.jsx("h1",{className:"text-2xl font-bold text-[var(--color-text)]",children:"Models"}),l.jsx("p",{className:"text-sm text-[var(--color-text-muted)]",children:"Manage LLM models on the inference server"})]}),l.jsxs("section",{className:"rounded-lg border border-[var(--color-border)] bg-[var(--color-surface)] p-4",children:[l.jsxs("div",{className:"flex items-center gap-2 mb-3",children:[l.jsx(iS,{size:16,className:"text-[var(--color-text-muted)]"}),l.jsx("h2",{className:"text-sm font-semibold text-[var(--color-text)]",children:"HuggingFace Token"}),l.jsx("span",{className:"text-xs text-[var(--color-text-muted)]",children:"(optional, for gated models)"})]}),l.jsx("input",{type:"password",value:a,onChange:E=>s(E.target.value),placeholder:"hf_...",className:"w-full rounded-md border border-[var(--color-border)] bg-[var(--color-background)] px-3 py-2 text-sm text-[var(--color-text)] placeholder:text-[var(--color-text-muted)]"})]}),l.jsxs("section",{className:"rounded-lg border border-[var(--color-border)] bg-[var(--color-surface)] p-4",children:[l.jsxs("div",{className:"flex items-center gap-2 mb-4",children:[l.jsx(Hd,{size:16,className:"text-[var(--color-text-muted)]"}),l.jsx("h2",{className:"text-sm font-semibold text-[var(--color-text)]",children:"Installed Models"})]}),h?l.jsx("p",{className:"text-sm text-[var(--color-text-muted)]",children:"Loading..."}):g?.length?l.jsx("div",{className:"space-y-2",children:g.map(E=>l.jsxs("div",{className:"flex items-center justify-between rounded-md border border-[var(--color-border)] px-3 py-2",children:[l.jsxs("div",{children:[l.jsx("span",{className:"text-sm font-medium text-[var(--color-text)]",children:E.name}),l.jsx("span",{className:"ml-2 text-xs text-[var(--color-text-muted)]",children:E.sizeFormatted})]}),l.jsx("button",{onClick:()=>k(E.name),disabled:x.isPending,className:"rounded p-1 text-[var(--color-text-muted)] hover:bg-red-500/10 hover:text-red-500",children:l.jsx(yi,{size:14})})]},E.name))}):l.jsx("p",{className:"text-sm text-[var(--color-text-muted)]",children:"No models installed yet"})]}),l.jsxs("section",{className:"rounded-lg border border-[var(--color-border)] bg-[var(--color-surface)] p-4",children:[l.jsxs("div",{className:"flex items-center gap-2 mb-4",children:[l.jsx(US,{size:16,className:"text-[var(--color-text-muted)]"}),l.jsx("h2",{className:"text-sm font-semibold text-[var(--color-text)]",children:"Suggested Models"})]}),l.jsx("div",{className:"space-y-3",children:ss.map(E=>{const _=g?.some(A=>A.name===E.ggufFilename||A.name.includes(E.ggufFilename));return l.jsxs("div",{className:"flex items-center justify-between rounded-md border border-[var(--color-border)] px-4 py-3",children:[l.jsxs("div",{className:"min-w-0 flex-1",children:[l.jsxs("div",{className:"flex items-center gap-2",children:[l.jsx("span",{className:"text-sm font-medium text-[var(--color-text)]",children:E.displayName}),l.jsxs("span",{className:"rounded bg-[var(--color-surface-alt)] px-1.5 py-0.5 text-xs text-[var(--color-text-muted)]",children:["~",E.sizeGguf]}),_&&l.jsx("span",{className:"rounded bg-green-500/10 px-1.5 py-0.5 text-xs text-green-500",children:"installed"})]}),l.jsxs("p",{className:"text-xs text-[var(--color-text-muted)]",children:[E.hfRepoGguf," / ",E.ggufFilename]}),l.jsxs("p",{className:"text-xs text-[var(--color-text-muted)]",children:["Prompt provider: ",l.jsx("code",{className:"text-[var(--color-primary)]",children:E.promptProvider})]})]}),l.jsxs("button",{onClick:()=>j(E.hfRepoGguf,E.ggufFilename),disabled:m!==null,className:te("ml-4 flex items-center gap-1 rounded-md px-3 py-1.5 text-sm font-medium transition-colors",_?"border border-[var(--color-border)] text-[var(--color-text-muted)] hover:bg-[var(--color-surface-alt)]":"bg-[var(--color-primary)] text-white hover:opacity-90"),children:[l.jsx(en,{size:14}),m===`${E.hfRepoGguf}/${E.ggufFilename}`?"Downloading...":_?"Re-download":"Download"]})]},E.id)})})]}),l.jsxs("section",{className:"rounded-lg border border-[var(--color-border)] bg-[var(--color-surface)] p-4",children:[l.jsxs("div",{className:"flex items-center gap-2 mb-4",children:[l.jsx(en,{size:16,className:"text-[var(--color-text-muted)]"}),l.jsx("h2",{className:"text-sm font-semibold text-[var(--color-text)]",children:"Download from HuggingFace"})]}),l.jsxs("div",{className:"space-y-3",children:[l.jsxs("div",{children:[l.jsx("label",{className:"mb-1 block text-xs text-[var(--color-text-muted)]",children:"Repository (e.g. Qwen/Qwen3-14B-GGUF)"}),l.jsx("input",{value:o,onChange:E=>i(E.target.value),placeholder:"owner/repo-name",className:"w-full rounded-md border border-[var(--color-border)] bg-[var(--color-background)] px-3 py-2 text-sm text-[var(--color-text)] placeholder:text-[var(--color-text-muted)]"})]}),l.jsxs("div",{children:[l.jsx("label",{className:"mb-1 block text-xs text-[var(--color-text-muted)]",children:"Filename (optional — downloads specific file instead of full repo)"}),l.jsx("input",{value:d,onChange:E=>f(E.target.value),placeholder:"model-name.gguf",className:"w-full rounded-md border border-[var(--color-border)] bg-[var(--color-background)] px-3 py-2 text-sm text-[var(--color-text)] placeholder:text-[var(--color-text-muted)]"})]}),l.jsxs("button",{onClick:w,disabled:!o||m!==null,className:"flex items-center gap-2 rounded-md bg-[var(--color-primary)] px-4 py-2 text-sm font-medium text-white transition-colors hover:opacity-90 disabled:opacity-50",children:[l.jsx(en,{size:14}),m===`${o}/${d}`?"Downloading...":"Download"]})]})]})]})}async function b4(){const{data:a}=await ge.get("/api/quick-sets");return a}async function N4(a){const{data:s}=await ge.post("/api/quick-sets/apply",a);return s}async function j4(a){const{data:s}=await ge.post("/api/quick-sets/custom",a);return s}async function S4(a){const{data:s}=await ge.delete(`/api/quick-sets/custom/${a}`);return s}function w4(){return yt({queryKey:["quick-sets"],queryFn:b4,staleTime:6e4})}function E4(){const a=pt();return bt({mutationFn:s=>N4(s),onSuccess:()=>{a.invalidateQueries({queryKey:["quick-sets"]}),a.invalidateQueries({queryKey:["settings"]}),a.invalidateQueries({queryKey:["llm-status"]}),a.invalidateQueries({queryKey:["containers"]})}})}function C4(){const a=pt();return bt({mutationFn:s=>j4(s),onSuccess:()=>{a.invalidateQueries({queryKey:["quick-sets"]})}})}function T4(){const a=pt();return bt({mutationFn:s=>S4(s),onSuccess:()=>{a.invalidateQueries({queryKey:["quick-sets"]})}})}const Vx=["GGUF","MLX","VLLM","TRANSFORMERS","REST"];function _4(){const{data:a,isLoading:s,error:o}=w4(),i=E4(),d=C4(),f=T4(),{data:m}=Sg(),v=N.useMemo(()=>(m??[]).map(z=>`.models/${z.name}`),[m]),[g,h]=N.useState(null),[y,x]=N.useState(""),[j,k]=N.useState(!1),[w,E]=N.useState(""),[_,A]=N.useState(""),[M,X]=N.useState(""),[I,ne]=N.useState(""),[W,G]=N.useState(new Set(["live"])),[U,oe]=N.useState(!1),[Ne,le]=N.useState(""),[pe,Ee]=N.useState(""),[Re,ae]=N.useState(""),[C,Y]=N.useState(""),[K,xe]=N.useState("GGUF"),[ee,S]=N.useState(8192),D=a?.presets,Q=N.useMemo(()=>{if(!D)return new Map;const z=new Map;for(const Se of D){const he=Se.family||"Custom",Ut=z.get(he)??[];Ut.push(Se),z.set(he,Ut)}return z},[D]);function Z(z){if(g===z.id){h(null);return}h(z.id),x(a?.currentValues.modelName??""),k(!1),A(z.defaultBackend),X(z.chatFormat),ne(z.promptProvider);const Se=a?.currentValues.contextWindow;E(Se&&Se>0?Se:z.defaultContextWindow)}function re(z){G(Se=>{const he=new Set(Se);return he.has(z)?he.size>1&&he.delete(z):he.add(z),he})}function fe(){!g||!y.trim()||i.mutate({presetId:g,modelName:y.trim(),contextWindow:w?Number(w):void 0,backend:_,chatFormat:M,promptProvider:I,targets:Array.from(W)},{onSuccess:z=>{z.success?Me.success(z.message):Me.warning(z.message),h(null)},onError:z=>{Me.error(z.message||"Failed to apply preset")}})}function ce(){!Ne.trim()||!Re.trim()||!C.trim()||d.mutate({name:Ne.trim(),family:pe.trim()||"Custom",chatFormat:Re.trim(),promptProvider:C.trim(),defaultBackend:K,defaultContextWindow:ee?Number(ee):8192},{onSuccess:()=>{Me.success(`Created preset "${Ne.trim()}"`),oe(!1),le(""),Ee(""),ae(""),Y(""),xe("GGUF"),S(8192)},onError:z=>{Me.error(z.message||"Failed to create preset")}})}function je(z){f.mutate(z.id,{onSuccess:()=>{Me.success(`Deleted "${z.name}"`),g===z.id&&h(null)},onError:()=>Me.error("Failed to delete preset")})}const L=a?.presets.find(z=>z.id===g);return l.jsxs("div",{className:"mx-auto max-w-4xl space-y-8 p-6",children:[l.jsxs("div",{children:[l.jsx("h1",{className:"text-2xl font-bold text-[var(--color-text)]",children:"Quick Sets"}),l.jsx("p",{className:"text-sm text-[var(--color-text-muted)]",children:"Select a model preset to auto-configure chat format, prompt provider, and backend"})]}),a?.currentValues.modelName&&l.jsxs("div",{className:"flex items-center gap-3 rounded-lg border border-[var(--color-border)] bg-[var(--color-surface)] px-4 py-3",children:[l.jsx(On,{size:16,className:"text-[var(--color-primary)]"}),l.jsxs("div",{className:"min-w-0 flex-1",children:[l.jsx("span",{className:"text-xs text-[var(--color-text-muted)]",children:"Current model"}),l.jsx("p",{className:"truncate text-sm font-medium text-[var(--color-text)]",children:a.currentValues.modelName})]}),a.currentValues.contextWindow>0&&l.jsxs("span",{className:"rounded bg-[var(--color-surface-alt)] px-2 py-0.5 text-xs text-[var(--color-text-muted)]",children:[a.currentValues.contextWindow.toLocaleString()," ctx"]})]}),s&&l.jsx("div",{className:"flex items-center justify-center py-12",children:l.jsx(it,{size:20,className:"animate-spin text-[var(--color-text-muted)]"})}),o&&l.jsxs("div",{className:"flex items-center gap-2 rounded-lg border border-red-500/30 bg-red-500/5 px-4 py-3",children:[l.jsx(ra,{size:16,className:"text-red-500"}),l.jsx("span",{className:"text-sm text-red-500",children:"Failed to load presets"})]}),!s&&Array.from(Q.entries()).map(([z,Se])=>l.jsxs("section",{children:[l.jsx("h2",{className:"mb-3 text-sm font-semibold text-[var(--color-text-muted)]",children:z}),l.jsx("div",{className:"grid grid-cols-1 gap-3 sm:grid-cols-2",children:Se.map(he=>l.jsxs("div",{className:te("relative rounded-lg border px-4 py-3 transition-colors",g===he.id?"border-[var(--color-primary)] bg-[var(--color-primary)]/5":"border-[var(--color-border)] bg-[var(--color-surface)] hover:bg-[var(--color-surface-alt)]"),children:[l.jsxs("button",{onClick:()=>Z(he),className:"w-full text-left",children:[l.jsxs("div",{className:"flex items-center justify-between",children:[l.jsx("span",{className:"text-sm font-medium text-[var(--color-text)]",children:he.name}),g===he.id&&l.jsx(xi,{size:16,className:"text-[var(--color-primary)]"})]}),he.description&&l.jsx("p",{className:"mt-1 text-xs text-[var(--color-text-muted)]",children:he.description}),l.jsxs("div",{className:"mt-2 flex items-center gap-2",children:[l.jsx("span",{className:"rounded bg-[var(--color-surface-alt)] px-1.5 py-0.5 text-xs text-[var(--color-text-muted)]",children:he.chatFormat}),l.jsx("span",{className:"rounded bg-[var(--color-surface-alt)] px-1.5 py-0.5 text-xs text-[var(--color-text-muted)]",children:he.defaultBackend})]})]}),he.isCustom&&l.jsx("button",{onClick:()=>je(he),disabled:f.isPending,className:"absolute right-2 top-2 rounded p-1 text-[var(--color-text-muted)] hover:bg-red-500/10 hover:text-red-500",title:"Delete custom preset",children:l.jsx(yi,{size:14})})]},he.id))})]},z)),!s&&!U&&l.jsxs("button",{onClick:()=>oe(!0),className:"flex items-center gap-2 rounded-lg border border-dashed border-[var(--color-border)] px-4 py-3 text-sm text-[var(--color-text-muted)] transition-colors hover:border-[var(--color-primary)] hover:text-[var(--color-primary)]",children:[l.jsx(ti,{size:16}),"Create custom preset"]}),U&&l.jsxs("section",{className:"rounded-lg border border-[var(--color-border)] bg-[var(--color-surface)] p-4",children:[l.jsxs("div",{className:"mb-4 flex items-center justify-between",children:[l.jsxs("div",{className:"flex items-center gap-2",children:[l.jsx(ti,{size:16,className:"text-[var(--color-primary)]"}),l.jsx("h2",{className:"text-sm font-semibold text-[var(--color-text)]",children:"New Custom Preset"})]}),l.jsx("button",{onClick:()=>oe(!1),className:"rounded p-1 text-[var(--color-text-muted)] hover:bg-[var(--color-surface-alt)]",children:l.jsx(Vd,{size:16})})]}),l.jsxs("div",{className:"space-y-3",children:[l.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[l.jsxs("div",{children:[l.jsx("label",{className:"mb-1 block text-xs text-[var(--color-text-muted)]",children:"Name *"}),l.jsx("input",{type:"text",value:Ne,onChange:z=>le(z.target.value),placeholder:"My Custom Model",className:"w-full rounded-md border border-[var(--color-border)] bg-[var(--color-background)] px-3 py-2 text-sm text-[var(--color-text)] placeholder:text-[var(--color-text-muted)]"})]}),l.jsxs("div",{children:[l.jsx("label",{className:"mb-1 block text-xs text-[var(--color-text-muted)]",children:"Family"}),l.jsx("input",{type:"text",value:pe,onChange:z=>Ee(z.target.value),placeholder:"Custom",className:"w-full rounded-md border border-[var(--color-border)] bg-[var(--color-background)] px-3 py-2 text-sm text-[var(--color-text)] placeholder:text-[var(--color-text-muted)]"})]})]}),l.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[l.jsxs("div",{children:[l.jsx("label",{className:"mb-1 block text-xs text-[var(--color-text-muted)]",children:"Chat format *"}),l.jsx("input",{type:"text",value:Re,onChange:z=>ae(z.target.value),placeholder:"chatml",className:"w-full rounded-md border border-[var(--color-border)] bg-[var(--color-background)] px-3 py-2 text-sm text-[var(--color-text)] placeholder:text-[var(--color-text-muted)]"})]}),l.jsxs("div",{children:[l.jsx("label",{className:"mb-1 block text-xs text-[var(--color-text-muted)]",children:"Prompt provider *"}),l.jsx("input",{type:"text",value:C,onChange:z=>Y(z.target.value),placeholder:"Qwen25MediumUntrained",className:"w-full rounded-md border border-[var(--color-border)] bg-[var(--color-background)] px-3 py-2 text-sm text-[var(--color-text)] placeholder:text-[var(--color-text-muted)]"})]})]}),l.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[l.jsxs("div",{children:[l.jsx("label",{className:"mb-1 block text-xs text-[var(--color-text-muted)]",children:"Default backend"}),l.jsx("select",{value:K,onChange:z=>xe(z.target.value),className:"w-full rounded-md border border-[var(--color-border)] bg-[var(--color-background)] px-3 py-2 text-sm text-[var(--color-text)]",children:Vx.map(z=>l.jsx("option",{value:z,children:z},z))})]}),l.jsxs("div",{children:[l.jsx("label",{className:"mb-1 block text-xs text-[var(--color-text-muted)]",children:"Default context window"}),l.jsx("input",{type:"number",value:ee,onChange:z=>S(z.target.value?parseInt(z.target.value,10):""),placeholder:"8192",min:1,className:"w-full rounded-md border border-[var(--color-border)] bg-[var(--color-background)] px-3 py-2 text-sm text-[var(--color-text)] placeholder:text-[var(--color-text-muted)]"})]})]}),l.jsxs("div",{className:"flex items-center gap-3 pt-1",children:[l.jsxs("button",{onClick:ce,disabled:!Ne.trim()||!Re.trim()||!C.trim()||d.isPending,className:"flex items-center gap-2 rounded-md bg-[var(--color-primary)] px-4 py-2 text-sm font-medium text-white transition-colors hover:opacity-90 disabled:opacity-50",children:[d.isPending?l.jsx(it,{size:14,className:"animate-spin"}):l.jsx(ti,{size:14}),d.isPending?"Creating...":"Create Preset"]}),l.jsx("button",{onClick:()=>oe(!1),className:"rounded-md px-3 py-2 text-sm text-[var(--color-text-muted)] hover:bg-[var(--color-surface-alt)]",children:"Cancel"})]})]})]}),L&&l.jsxs("section",{className:"rounded-lg border border-[var(--color-primary)]/30 bg-[var(--color-surface)] p-4",children:[l.jsxs("div",{className:"mb-4 flex items-center gap-2",children:[l.jsx(oi,{size:16,className:"text-[var(--color-primary)]"}),l.jsxs("h2",{className:"text-sm font-semibold text-[var(--color-text)]",children:["Apply: ",L.name]})]}),l.jsxs("div",{className:"mb-4",children:[l.jsx("span",{className:"mb-2 block text-xs font-medium text-[var(--color-text-muted)]",children:"Apply to"}),l.jsx("div",{className:"flex items-center gap-4",children:["live","background"].map(z=>l.jsxs("label",{className:"flex items-center gap-2 text-sm text-[var(--color-text)]",children:[l.jsx("input",{type:"checkbox",checked:W.has(z),onChange:()=>re(z),className:"rounded border-[var(--color-border)] accent-[var(--color-primary)]"}),l.jsx("span",{className:"capitalize",children:z})]},z))})]}),l.jsxs("div",{className:"space-y-3",children:[l.jsxs("div",{className:"space-y-2",children:[l.jsx("label",{className:"mb-1 block text-xs text-[var(--color-text-muted)]",children:"Model file path"}),v.length>0&&l.jsxs("select",{value:j||y!==""&&!v.includes(y)?"__other__":y,onChange:z=>{z.target.value==="__other__"?k(!0):(k(!1),x(z.target.value))},className:"w-full rounded-md border border-[var(--color-border)] bg-[var(--color-background)] px-3 py-2 text-sm text-[var(--color-text)]",children:[l.jsx("option",{value:"",disabled:!0,children:"Select a model…"}),v.map(z=>l.jsx("option",{value:z,children:z.replace(/^\.models\//,"")},z)),l.jsx("option",{value:"__other__",children:"Other (custom path / HF ID)…"})]}),(v.length===0||j||y!==""&&!v.includes(y))&&l.jsx("input",{type:"text",value:y,onChange:z=>x(z.target.value),placeholder:".models/model-name.gguf",className:"w-full rounded-md border border-[var(--color-border)] bg-[var(--color-background)] px-3 py-2 text-sm text-[var(--color-text)] placeholder:text-[var(--color-text-muted)]"})]}),l.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[l.jsxs("div",{children:[l.jsx("label",{className:"mb-1 block text-xs text-[var(--color-text-muted)]",children:"Chat format"}),l.jsx("input",{type:"text",value:M,onChange:z=>X(z.target.value),placeholder:"chatml",className:"w-full rounded-md border border-[var(--color-border)] bg-[var(--color-background)] px-3 py-2 text-sm text-[var(--color-text)] placeholder:text-[var(--color-text-muted)]"})]}),l.jsxs("div",{children:[l.jsx("label",{className:"mb-1 block text-xs text-[var(--color-text-muted)]",children:"Prompt provider"}),l.jsx("input",{type:"text",value:I,onChange:z=>ne(z.target.value),placeholder:"Qwen25MediumUntrained",className:"w-full rounded-md border border-[var(--color-border)] bg-[var(--color-background)] px-3 py-2 text-sm text-[var(--color-text)] placeholder:text-[var(--color-text-muted)]"})]})]}),l.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[l.jsxs("div",{children:[l.jsx("label",{className:"mb-1 block text-xs text-[var(--color-text-muted)]",children:"Context window (tokens)"}),l.jsx("input",{type:"number",value:w,onChange:z=>E(z.target.value?parseInt(z.target.value,10):""),placeholder:String(L.defaultContextWindow),min:1,className:"w-full rounded-md border border-[var(--color-border)] bg-[var(--color-background)] px-3 py-2 text-sm text-[var(--color-text)] placeholder:text-[var(--color-text-muted)]"})]}),l.jsxs("div",{children:[l.jsx("label",{className:"mb-1 block text-xs text-[var(--color-text-muted)]",children:"Backend"}),l.jsx("select",{value:_,onChange:z=>A(z.target.value),className:"w-full rounded-md border border-[var(--color-border)] bg-[var(--color-background)] px-3 py-2 text-sm text-[var(--color-text)]",children:Vx.map(z=>l.jsx("option",{value:z,children:z},z))})]})]})]}),l.jsxs("div",{className:"mt-4 flex items-center gap-3",children:[l.jsxs("button",{onClick:fe,disabled:!y.trim()||i.isPending,className:"flex items-center gap-2 rounded-md bg-[var(--color-primary)] px-4 py-2 text-sm font-medium text-white transition-colors hover:opacity-90 disabled:opacity-50",children:[i.isPending?l.jsx(it,{size:14,className:"animate-spin"}):l.jsx(oi,{size:14}),i.isPending?"Applying...":"Apply Settings"]}),l.jsx("button",{onClick:()=>h(null),className:"rounded-md px-3 py-2 text-sm text-[var(--color-text-muted)] hover:bg-[var(--color-surface-alt)]",children:"Cancel"})]})]})]})}const Zu={preflight:"Checking prerequisites",download:"Downloading update",binary:"Updating binary",restarting:"Restarting admin server",compose:"Updating configuration",pull:"Pulling images",restart:"Restarting services",verify:"Verifying health",done:"Complete"};function R4(){const a=wa(),{data:s,isLoading:o}=Ng(),[i,d]=N.useState("idle"),[f,m]=N.useState([]),[v,g]=N.useState(null),h=N.useRef(null),y=N.useCallback(k=>{m(w=>[...w,k])},[]);N.useEffect(()=>{h.current&&(h.current.scrollTop=h.current.scrollHeight)},[f]);async function x(){d("preflight"),m([]),g(null);try{const k=localStorage.getItem("jarvis-admin:access_token")??localStorage.getItem("access_token"),w=await fetch("/api/update/apply",{method:"POST",headers:{Authorization:`Bearer ${k}`}});if(!w.ok||!w.body){const M=await w.text();throw new Error(M||`HTTP ${w.status}`)}const E=w.body.getReader(),_=new TextDecoder;let A="";for(;;){const{done:M,value:X}=await E.read();if(M)break;A+=_.decode(X,{stream:!0});const I=A.split(`
|
|
17
17
|
`);A=I.pop()??"";for(const ne of I)if(ne.startsWith("data: "))try{const W=JSON.parse(ne.slice(6));if(W.phase&&d(W.phase),W.message&&y({text:W.message,phase:W.phase}),W.stream&&W.text&&y({text:W.text.trim()}),W.restart){d("restarting"),y({text:"Admin server restarting with new version..."}),await k4(s?.latestVersion??""),d("done"),y({text:"Upgrade complete!"});return}if(W.done&&W.code!==0)throw new Error(W.error??"Upgrade failed");W.done&&W.code===0&&d("done")}catch(W){if(W instanceof SyntaxError)continue;throw W}}}catch(k){const w=k instanceof Error?k.message:String(k);g(w),d("error"),y({text:`Error: ${w}`})}}if(o)return l.jsx("div",{className:"flex min-h-[50vh] items-center justify-center",children:l.jsx(Ct,{size:24,className:"animate-spin text-[var(--color-primary)]"})});const j=Object.keys(Zu).filter(k=>{const w=Object.keys(Zu),E=w.indexOf(i);return w.indexOf(k)<E});return l.jsxs("div",{className:"mx-auto max-w-3xl space-y-6 p-6",children:[l.jsxs("div",{children:[l.jsx("h1",{className:"text-2xl font-bold text-[var(--color-text)]",children:"Update Jarvis"}),s?.updateAvailable?l.jsxs("p",{className:"text-sm text-[var(--color-text-muted)]",children:["v",s.currentVersion," → v",s.latestVersion]}):l.jsxs("p",{className:"text-sm text-[var(--color-text-muted)]",children:["You're running the latest version (v",s?.currentVersion??"?",")"]})]}),i!=="idle"&&l.jsx("div",{className:"space-y-2 rounded-lg border border-[var(--color-border)] bg-[var(--color-surface)] p-4",children:Object.entries(Zu).map(([k,w])=>{const E=k===i,_=j.includes(k),A=k===i&&i==="error";return l.jsxs("div",{className:"flex items-center gap-2",children:[_?l.jsx(ht,{size:16,className:"text-green-500"}):A?l.jsx(ra,{size:16,className:"text-red-500"}):E?l.jsx(Ct,{size:16,className:"animate-spin text-[var(--color-primary)]"}):l.jsx("div",{className:"h-4 w-4 rounded-full border border-[var(--color-border)]"}),l.jsx("span",{className:te("text-sm",E?"font-medium text-[var(--color-text)]":"text-[var(--color-text-muted)]",_&&"text-green-500"),children:w})]},k)})}),f.length>0&&l.jsx("div",{ref:h,className:"max-h-64 overflow-y-auto rounded-lg border border-[var(--color-border)] bg-[#0d1117] p-3 font-mono text-xs text-gray-300",children:f.map((k,w)=>l.jsx("div",{children:k.text},w))}),v&&l.jsxs("div",{className:"flex items-center gap-2 rounded-lg bg-red-500/10 px-3 py-2",children:[l.jsx(ra,{size:14,className:"text-red-500"}),l.jsx("span",{className:"text-sm text-red-500",children:v})]}),l.jsxs("div",{className:"flex gap-3",children:[i==="idle"&&s?.updateAvailable&&l.jsxs("button",{onClick:x,className:"flex items-center gap-2 rounded-lg bg-green-600 px-4 py-2 text-sm font-medium text-white hover:opacity-90",children:[l.jsx(eg,{size:16}),"Update to v",s.latestVersion]}),i==="done"&&l.jsxs("button",{onClick:()=>a("/dashboard"),className:"flex items-center gap-2 rounded-lg bg-[var(--color-primary)] px-4 py-2 text-sm font-medium text-white hover:opacity-90",children:[l.jsx(ht,{size:16}),"Go to Dashboard"]}),i==="error"&&l.jsxs("button",{onClick:x,className:"flex items-center gap-2 rounded-lg bg-[var(--color-primary)] px-4 py-2 text-sm font-medium text-white hover:opacity-90",children:[l.jsx(it,{size:16}),"Retry"]})]})]})}async function k4(a,s=6e4){const o=Date.now()+s;for(;Date.now()<o;){await new Promise(i=>setTimeout(i,2e3));try{const i=await fetch("/health");if(i.ok){const d=await i.json();if(d.version&&d.version!=="0.0.0-dev")return}}catch{}}throw new Error("Admin server did not restart within 60 seconds")}const Ju={regenerate:"Regenerating compose from registry",pull:"Pulling images for new release track",apply:"Applying changes (docker compose up)",done:"Complete"};function M4(){const a=wa(),s=localStorage.getItem("jarvis-admin:access_token")??localStorage.getItem("access_token"),[o,i]=N.useState("loading_options"),[d,f]=N.useState([]),[m,v]=N.useState(null),g=N.useRef(null),[h,y]=N.useState([]),[x,j]=N.useState(!1),[k,w]=N.useState("https://relay.jarvisautomation.io"),[E,_]=N.useState("/whisper-models/ggml-base.en.bin"),[A,M]=N.useState("cpu"),[X,I]=N.useState("cpu"),[ne,W]=N.useState(!1),[G,U]=N.useState("stable"),[oe,Ne]=N.useState(null),[le,pe]=N.useState(!1),Ee=N.useCallback(ee=>{f(S=>[...S,ee])},[]);N.useEffect(()=>{g.current&&(g.current.scrollTop=g.current.scrollHeight)},[d]),N.useEffect(()=>{async function ee(){try{const S=await fetch("/api/install/reconcile/options",{headers:{Authorization:`Bearer ${s}`}});if(!S.ok)throw new Error(`HTTP ${S.status}`);const D=await S.json();y(D.services),j(D.relayEnabled),w(D.relayUrl||"https://relay.jarvisautomation.io"),_(D.whisperModelPath||"/whisper-models/ggml-base.en.bin"),M(D.whisperBackend??"cpu"),I(D.ttsBackend??"cpu"),W(D.pinImages??!1),U(D.releaseTrack??"stable"),i("options")}catch(S){v(S instanceof Error?S.message:"Failed to load options"),i("error")}}ee()},[s]);function Re(ee){y(S=>S.map(D=>D.id===ee?{...D,enabled:!D.enabled}:D))}async function ae(){i("regenerate"),f([]),v(null);const ee=h.filter(S=>S.enabled).map(S=>S.id);try{const S=await fetch("/api/install/reconcile",{method:"POST",headers:{Authorization:`Bearer ${s}`,"Content-Type":"application/json"},body:JSON.stringify({enabledModules:ee,relayEnabled:x,relayUrl:k,whisperModelPath:E,whisperBackend:A,ttsBackend:X,pinImages:ne,releaseTrack:G})});if(!S.ok||!S.body){const re=await S.text();throw new Error(re||`HTTP ${S.status}`)}const D=S.body.getReader(),Q=new TextDecoder;let Z="";for(;;){const{done:re,value:fe}=await D.read();if(re)break;Z+=Q.decode(fe,{stream:!0});const ce=Z.split(`
|
|
18
|
-
`);Z=ce.pop()??"";for(const je of ce)if(je.startsWith("data: "))try{const L=JSON.parse(je.slice(6));if(L.phase&&i(L.phase),L.message&&Ee({text:L.message,phase:L.phase}),L.stream&&L.text&&Ee({text:L.text.trim()}),L.done&&L.code!==0)throw new Error(L.message??"Reconcile failed")}catch(L){if(L instanceof SyntaxError)continue;throw L}}}catch(S){const D=S instanceof Error?S.message:String(S);v(D),i("error"),Ee({text:`Error: ${D}`})}}function C(){return{enabledModules:h.filter(ee=>ee.enabled).map(ee=>ee.id),relayEnabled:x,relayUrl:k,whisperModelPath:E,whisperBackend:A,ttsBackend:X,pinImages:ne,releaseTrack:G}}async function Y(ee){pe(!0),v(null),Ne(null);try{const{latest:S,...D}=ee??{},Z=await fetch(`/api/install/regenerate-download${S?"?latest=true":""}`,{method:"POST",headers:{Authorization:`Bearer ${s}`,"Content-Type":"application/json"},body:JSON.stringify({...C(),...D})});if(!Z.ok){const fe=await Z.text();throw new Error(fe||`HTTP ${Z.status}`)}const re=await Z.json();Ne({compose:re.compose,env:re.env,initDb:re.initDb})}catch(S){v(S instanceof Error?S.message:String(S))}finally{pe(!1)}}function K(ee,S){const D=new Blob([S],{type:"text/plain;charset=utf-8"}),Q=URL.createObjectURL(D),Z=document.createElement("a");Z.href=Q,Z.download=ee,document.body.appendChild(Z),Z.click(),Z.remove(),URL.revokeObjectURL(Q)}const xe=Object.keys(Ju).filter(ee=>{const S=Object.keys(Ju),D=S.indexOf(o);return S.indexOf(ee)<D||o==="done"&&ee==="done"});return l.jsxs("div",{className:"mx-auto max-w-3xl space-y-6 p-6",children:[l.jsxs("div",{children:[l.jsx("h1",{className:"text-2xl font-bold text-[var(--color-text)]",children:"Sync Compose"}),l.jsxs("p",{className:"mt-1 text-sm text-[var(--color-text-muted)]",children:["Regenerate ",l.jsx("code",{className:"rounded bg-[var(--color-surface)] px-1.5 py-0.5 text-xs",children:"docker-compose.yml"})," from the latest service registry, preserving your secrets. ",l.jsx("strong",{className:"text-[var(--color-text)]",children:"Sync now"})," applies it to the running stack;",l.jsx("strong",{className:"text-[var(--color-text)]",children:" Download"})," hands you the files to review and apply by hand (",l.jsx("code",{className:"rounded bg-[var(--color-surface)] px-1 text-xs",children:"docker compose up -d"}),")."," ",l.jsx("strong",{className:"text-[var(--color-text)]",children:"Update stack to latest"})," downloads the same, pinned to the newest published images."]})]}),o==="loading_options"&&l.jsx("div",{className:"flex items-center justify-center py-12",children:l.jsx(Ct,{size:32,className:"animate-spin text-[var(--color-primary)]"})}),o==="options"&&l.jsxs("div",{className:"space-y-4",children:[l.jsxs("div",{className:"rounded-lg border border-[var(--color-border)] bg-[var(--color-surface)] p-4",children:[l.jsx("h2",{className:"mb-3 text-sm font-semibold text-[var(--color-text)]",children:"Services"}),l.jsx("div",{className:"space-y-2",children:h.map(ee=>l.jsxs("button",{onClick:()=>Re(ee.id),className:"flex w-full items-center gap-3 rounded-lg px-3 py-2 text-left hover:bg-[var(--color-bg-secondary)] transition-colors",children:[ee.enabled?l.jsx(ht,{size:18,className:"shrink-0 text-[var(--color-primary)]"}):l.jsx(os,{size:18,className:"shrink-0 text-[var(--color-text-muted)]"}),l.jsxs("div",{className:"min-w-0",children:[l.jsx("div",{className:"text-sm font-medium text-[var(--color-text)]",children:ee.name}),l.jsx("div",{className:"text-xs text-[var(--color-text-muted)]",children:ee.description})]})]},ee.id))})]}),l.jsxs("div",{className:"rounded-lg border border-[var(--color-border)] bg-[var(--color-surface)] p-4",children:[l.jsx("h2",{className:"mb-3 text-sm font-semibold text-[var(--color-text)]",children:"Release Track"}),l.jsxs("div",{className:"flex items-center justify-between px-3 py-2",children:[l.jsxs("div",{children:[l.jsx("div",{className:"text-sm font-medium text-[var(--color-text)]",children:G==="dev"?"Dev":"Stable"}),l.jsx("div",{className:"text-xs text-[var(--color-text-muted)]",children:G==="dev"?"Using latest main branch builds (may be unstable)":"Using tagged releases"})]}),l.jsx("button",{type:"button",role:"switch","aria-checked":G==="dev",onClick:()=>U(G==="dev"?"stable":"dev"),className:`relative h-6 w-11 shrink-0 rounded-full transition-colors ${G==="dev"?"bg-amber-500":"bg-[var(--color-surface-alt)]"}`,children:l.jsx("span",{className:`absolute left-0.5 top-0.5 h-5 w-5 rounded-full bg-white transition-transform ${G==="dev"?"translate-x-5":"translate-x-0"}`})})]}),G==="dev"&&l.jsx("div",{className:"mx-3 mt-1 rounded-lg border border-amber-300 bg-amber-500/10 px-3 py-2 text-xs text-amber-400",children:"Switching tracks will pull all images and force-recreate containers."})]}),l.jsxs("div",{className:"rounded-lg border border-[var(--color-border)] bg-[var(--color-surface)] p-4",children:[l.jsx("h2",{className:"mb-3 text-sm font-semibold text-[var(--color-text)]",children:"Integrations"}),l.jsxs("button",{onClick:()=>j(!x),className:"flex w-full items-center gap-3 rounded-lg px-3 py-2 text-left hover:bg-[var(--color-bg-secondary)] transition-colors",children:[x?l.jsx(ht,{size:18,className:"shrink-0 text-[var(--color-primary)]"}):l.jsx(os,{size:18,className:"shrink-0 text-[var(--color-text-muted)]"}),l.jsxs("div",{className:"min-w-0",children:[l.jsx("div",{className:"text-sm font-medium text-[var(--color-text)]",children:"Jarvis Relay"}),l.jsx("div",{className:"text-xs text-[var(--color-text-muted)]",children:"Routes OAuth callbacks through a cloud relay for external providers (Google, Spotify, etc.)"})]})]}),x&&l.jsxs("div",{className:"mt-2 px-3",children:[l.jsx("label",{className:"text-xs font-medium text-[var(--color-text-muted)]",children:"Relay URL"}),l.jsx("input",{type:"url",value:k,onChange:ee=>w(ee.target.value),placeholder:"https://relay.jarvisautomation.io",className:"mt-1 w-full rounded-md border border-[var(--color-border)] bg-[var(--color-bg)] px-3 py-1.5 text-sm text-[var(--color-text)] placeholder:text-[var(--color-text-muted)]"})]})]}),h.some(ee=>ee.id==="jarvis-whisper-api"&&ee.enabled)&&l.jsxs("div",{className:"rounded-lg border border-[var(--color-border)] bg-[var(--color-surface)] p-4",children:[l.jsx("h2",{className:"mb-3 text-sm font-semibold text-[var(--color-text)]",children:"Whisper"}),l.jsxs("div",{className:"px-3",children:[l.jsx("label",{className:"text-xs font-medium text-[var(--color-text-muted)]",children:"Model path"}),l.jsx("input",{type:"text",value:E,onChange:ee=>_(ee.target.value),placeholder:"/whisper-models/ggml-base.en.bin",className:"mt-1 w-full rounded-md border border-[var(--color-border)] bg-[var(--color-bg)] px-3 py-1.5 text-sm font-mono text-[var(--color-text)] placeholder:text-[var(--color-text-muted)]"}),l.jsxs("p",{className:"mt-1 text-xs text-[var(--color-text-muted)]",children:["Path inside the container. Place model files in ",l.jsx("code",{className:"rounded bg-[var(--color-bg)] px-1",children:"./whisper-models/"})," next to your compose file."]}),l.jsx("label",{className:"mt-3 block text-xs font-medium text-[var(--color-text-muted)]",children:"GPU backend"}),l.jsxs("select",{value:A,onChange:ee=>M(ee.target.value),className:"mt-1 w-full rounded-md border border-[var(--color-border)] bg-[var(--color-bg)] px-3 py-1.5 text-sm text-[var(--color-text)]",children:[l.jsx("option",{value:"cpu",children:"CPU (default)"}),l.jsx("option",{value:"cuda",children:"NVIDIA (CUDA)"}),l.jsx("option",{value:"vulkan",children:"AMD / generic (Vulkan)"}),l.jsx("option",{value:"rocm",children:"AMD (ROCm)"})]}),l.jsx("p",{className:"mt-1 text-xs text-[var(--color-text-muted)]",children:"Where speech-to-text runs. CPU leaves the GPU for the LLM; pick a GPU backend to run Whisper on the GPU."})]})]}),h.some(ee=>ee.id==="jarvis-tts"&&ee.enabled)&&l.jsxs("div",{className:"rounded-lg border border-[var(--color-border)] bg-[var(--color-surface)] p-4",children:[l.jsx("h2",{className:"mb-3 text-sm font-semibold text-[var(--color-text)]",children:"Text-to-speech"}),l.jsxs("div",{className:"px-3",children:[l.jsx("label",{className:"text-xs font-medium text-[var(--color-text-muted)]",children:"Inference device"}),l.jsxs("select",{value:X,onChange:ee=>I(ee.target.value),className:"mt-1 w-full rounded-md border border-[var(--color-border)] bg-[var(--color-bg)] px-3 py-1.5 text-sm text-[var(--color-text)]",children:[l.jsx("option",{value:"cpu",children:"CPU (default)"}),l.jsx("option",{value:"cuda",children:"NVIDIA (CUDA)"})]}),l.jsxs("p",{className:"mt-1 text-xs text-[var(--color-text-muted)]",children:["Where Kokoro synthesis runs. CPU is fine for most installs; CUDA gives the fastest first-audio. On multi-GPU hosts set ",l.jsx("code",{className:"rounded bg-[var(--color-bg)] px-1",children:"TTS_GPU_DEVICE"})," in .env to pick which GPU (default 0)."]})]})]}),l.jsx("div",{className:"rounded-lg border border-[var(--color-border)] bg-[var(--color-surface)] p-4",children:l.jsxs("label",{className:"flex items-start gap-3 text-sm",children:[l.jsx("input",{type:"checkbox",checked:ne,onChange:ee=>W(ee.target.checked),className:"mt-0.5","data-testid":"pin-images-checkbox"}),l.jsxs("span",{children:[l.jsx("span",{className:"font-medium text-[var(--color-text)]",children:"Pin images by digest"}),l.jsxs("span",{className:"mt-1 block text-xs text-[var(--color-text-muted)]",children:["Advanced supply-chain hardening: locks every image to an exact build. Leave OFF for normal use — with pinning on, ",l.jsx("code",{className:"rounded bg-[var(--color-bg)] px-1",children:"docker compose pull"})," will never update anything and services only change via this page."]})]})]})})]}),oe&&o==="options"&&l.jsxs("div",{className:"rounded-lg border border-[var(--color-primary)]/40 bg-[var(--color-surface)] p-4",children:[l.jsxs("h2",{className:"mb-1 flex items-center gap-2 text-sm font-semibold text-[var(--color-text)]",children:[l.jsx(ht,{size:16,className:"text-green-500"}),"Updated files ready"]}),l.jsxs("p",{className:"mb-3 text-xs text-[var(--color-text-muted)]",children:["Your existing secrets and settings are carried over. Download, replace the files next to your compose, then run ",l.jsx("code",{className:"rounded bg-[var(--color-bg)] px-1",children:"docker compose up -d"}),". Nothing on the server was changed."]}),l.jsxs("div",{className:"flex flex-wrap gap-2",children:[l.jsxs("button",{onClick:()=>K("docker-compose.yml",oe.compose),className:"flex items-center gap-2 rounded-lg bg-[var(--color-primary)] px-3 py-2 text-sm font-medium text-white hover:opacity-90",children:[l.jsx(en,{size:15}),"docker-compose.yml"]}),l.jsxs("button",{onClick:()=>K(".env",oe.env),className:"flex items-center gap-2 rounded-lg border border-[var(--color-border)] px-3 py-2 text-sm font-medium text-[var(--color-text)] hover:bg-[var(--color-surface-alt)]",children:[l.jsx(en,{size:15}),".env"]}),l.jsxs("button",{onClick:()=>K("init-db.sh",oe.initDb),className:"flex items-center gap-2 rounded-lg border border-[var(--color-border)] px-3 py-2 text-sm font-medium text-[var(--color-text)] hover:bg-[var(--color-surface-alt)]",children:[l.jsx(en,{size:15}),"init-db.sh"]})]}),l.jsxs("p",{className:"mt-3 text-xs text-[var(--color-text-muted)]",children:["The ",l.jsx("code",{className:"rounded bg-[var(--color-bg)] px-1",children:".env"})," merges new keys into your existing values, and ",l.jsx("code",{className:"rounded bg-[var(--color-bg)] px-1",children:"init-db.sh"})," covers any new databases — replace all three to be safe. Diff them against your current files first if you want to eyeball the changes."]})]}),o!=="loading_options"&&o!=="options"&&l.jsx("div",{className:"space-y-2 rounded-lg border border-[var(--color-border)] bg-[var(--color-surface)] p-4",children:Object.entries(Ju).map(([ee,S])=>{const D=ee===o,Q=xe.includes(ee),Z=ee===o&&o==="error";return l.jsxs("div",{className:"flex items-center gap-2",children:[Q?l.jsx(ht,{size:16,className:"text-green-500"}):Z?l.jsx(ra,{size:16,className:"text-red-500"}):D?l.jsx(Ct,{size:16,className:"animate-spin text-[var(--color-primary)]"}):l.jsx("div",{className:"h-4 w-4 rounded-full border border-[var(--color-border)]"}),l.jsx("span",{className:te("text-sm",D?"font-medium text-[var(--color-text)]":"text-[var(--color-text-muted)]",Q&&"text-green-500"),children:S})]},ee)})}),d.length>0&&l.jsx("div",{ref:g,className:"max-h-64 overflow-y-auto rounded-lg border border-[var(--color-border)] bg-[#0d1117] p-3 font-mono text-xs text-gray-300",children:d.map((ee,S)=>l.jsx("div",{children:ee.text},S))}),m&&l.jsxs("div",{className:"flex items-center gap-2 rounded-lg bg-red-500/10 px-3 py-2",children:[l.jsx(ra,{size:14,className:"text-red-500"}),l.jsx("span",{className:"text-sm text-red-500",children:m})]}),l.jsxs("div",{className:"flex gap-3",children:[o==="options"&&l.jsxs("button",{onClick:ae,className:"flex items-center gap-2 rounded-lg bg-[var(--color-primary)] px-4 py-2 text-sm font-medium text-white hover:opacity-90",children:[l.jsx(xd,{size:16}),"Sync now"]}),o==="options"&&l.jsxs("button",{onClick:()=>Y(),disabled:le,title:"Regenerate the compose and download it to apply by hand — doesn't touch the running stack",className:"flex items-center gap-2 rounded-lg border border-[var(--color-border)] px-4 py-2 text-sm font-medium text-[var(--color-text)] hover:bg-[var(--color-surface-alt)] disabled:cursor-not-allowed disabled:opacity-50",children:[le?l.jsx(Ct,{size:16,className:"animate-spin"}):l.jsx(en,{size:16}),"Download updated compose"]}),o==="options"&&l.jsxs("button",{onClick:()=>Y({latest:!0}),disabled:le,title:"Download a compose pinned to the LATEST published images (digests refreshed from the registry). Apply it yourself on the host — docker compose pull && docker compose up -d — which also updates jarvis-admin.",className:"flex items-center gap-2 rounded-lg border border-[var(--color-border)] px-4 py-2 text-sm font-medium text-[var(--color-text)] hover:bg-[var(--color-surface-alt)] disabled:cursor-not-allowed disabled:opacity-50",children:[le?l.jsx(Ct,{size:16,className:"animate-spin"}):l.jsx(it,{size:16}),"Update stack to latest"]}),o==="options"&&l.jsxs("button",{onClick:()=>Y({mqttAllowAnon:!1}),disabled:le,title:"Download a compose with the MQTT broker locked (allow_anonymous=false). Do this only after every node has authenticated, or un-migrated nodes will drop off.",className:"flex items-center gap-2 rounded-lg border border-[var(--color-border)] px-4 py-2 text-sm font-medium text-[var(--color-text)] hover:bg-[var(--color-surface-alt)] disabled:cursor-not-allowed disabled:opacity-50",children:[le?l.jsx(Ct,{size:16,className:"animate-spin"}):l.jsx(vi,{size:16}),"Download + lock broker"]}),o==="options"&&l.jsxs("button",{onClick:()=>Y({mqttAllowAnon:!0}),disabled:le,title:"Download a compose that re-opens the MQTT broker to anonymous clients (allow_anonymous=true) — the transition/rollback state.",className:"flex items-center gap-2 rounded-lg border border-[var(--color-border)] px-4 py-2 text-sm font-medium text-[var(--color-text)] hover:bg-[var(--color-surface-alt)] disabled:cursor-not-allowed disabled:opacity-50",children:[le?l.jsx(Ct,{size:16,className:"animate-spin"}):l.jsx(mS,{size:16}),"Download + unlock broker"]}),(o==="options"||o==="regenerate"||o==="apply"||o==="done")&&l.jsxs("button",{onClick:()=>a("/dashboard"),disabled:o==="regenerate"||o==="apply",className:"flex items-center gap-2 rounded-lg border border-[var(--color-border)] px-4 py-2 text-sm font-medium text-[var(--color-text)] hover:bg-[var(--color-surface-alt)] disabled:cursor-not-allowed disabled:opacity-50 disabled:hover:bg-transparent",children:[l.jsx(ht,{size:16}),"Back to dashboard"]}),o==="error"&&l.jsxs("button",{onClick:ae,className:"flex items-center gap-2 rounded-lg bg-[var(--color-primary)] px-4 py-2 text-sm font-medium text-white hover:opacity-90",children:[l.jsx(it,{size:16}),"Retry"]})]})]})}async function A4(a={}){const{data:s}=await ge.get("/api/traces",{params:a});return s}async function O4(a){const{data:s}=await ge.get(`/api/traces/${a}`);return s}function Fx(a){return a<1e3?`${Math.round(a)}ms`:`${(a/1e3).toFixed(1)}s`}function Yx(a){return new Date(a).toLocaleString(void 0,{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit",second:"2-digit"})}function z4(a){const s=new Map;for(const o of a){const i=s.get(o.conversation_id);if(!i){s.set(o.conversation_id,{conversation_id:o.conversation_id,traces:[o],newest_at:o.created_at,user_command:o.user_command,assistant_message:o.assistant_message,source:o.source,node_id:o.node_id,household_id:o.household_id,total_duration_ms:o.total_duration_ms,status:o.status});continue}i.traces.push(o),i.total_duration_ms+=o.total_duration_ms,o.created_at>i.newest_at&&(i.newest_at=o.created_at),!i.user_command&&o.user_command&&(i.user_command=o.user_command),!i.assistant_message&&o.assistant_message&&(i.assistant_message=o.assistant_message),o.status!=="ok"&&(i.status=o.status)}return Array.from(s.values()).sort((o,i)=>o.newest_at<i.newest_at?1:-1)}function D4(a){return a==="mobile"?"📱":"🔊"}function U4(){const a=wa(),[s,o]=N.useState(""),[i,d]=N.useState(""),[f,m]=N.useState(""),[v,g]=N.useState(""),[h,y]=N.useState(new Set),x=yt({queryKey:["admin","households"],queryFn:XE,staleTime:6e4}),j=yt({queryKey:["admin","nodes"],queryFn:KE,staleTime:6e4}),{data:k,isLoading:w,error:E}=yt({queryKey:["traces",s,i,f,v],queryFn:()=>A4({limit:100,...s?{status:s}:{},...i?{source:i}:{},...f?{household_id:f}:{},...v?{node_id:v}:{}}),refetchInterval:1e4}),_=N.useMemo(()=>{const G=j.data??[];return f?G.filter(U=>U.household_id===f):G},[j.data,f]),A=N.useMemo(()=>{const G=new Map;for(const U of j.data??[])G.set(U.node_id,U.name);return G},[j.data]),M=N.useMemo(()=>{const G=new Map;for(const U of x.data??[])G.set(U.id,U.name);return G},[x.data]),X=N.useMemo(()=>k?z4(k.traces):[],[k]);function I(G){y(U=>{const oe=new Set(U);return oe.has(G)?oe.delete(G):oe.add(G),oe})}function ne(G){if(m(G),G&&v){const U=(j.data??[]).find(oe=>oe.node_id===v);U&&U.household_id!==G&&g("")}}const W="rounded border border-[var(--color-border)] bg-[var(--color-surface)] px-2 py-1 text-sm text-[var(--color-text)]";return l.jsxs("div",{className:"space-y-4",children:[l.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-2",children:[l.jsx("h1",{className:"text-2xl font-bold text-[var(--color-text)]",children:"Request Traces"}),l.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[l.jsxs("select",{className:W,value:f,onChange:G=>ne(G.target.value),disabled:x.isLoading,children:[l.jsx("option",{value:"",children:"All households"}),(x.data??[]).map(G=>l.jsx("option",{value:G.id,children:G.name},G.id))]}),l.jsxs("select",{className:W,value:v,onChange:G=>g(G.target.value),disabled:j.isLoading,children:[l.jsx("option",{value:"",children:"All nodes"}),_.map(G=>l.jsx("option",{value:G.node_id,children:G.name},G.node_id))]}),l.jsxs("select",{className:W,value:s,onChange:G=>o(G.target.value),children:[l.jsx("option",{value:"",children:"All statuses"}),l.jsx("option",{value:"ok",children:"OK"}),l.jsx("option",{value:"error",children:"Error"})]}),l.jsxs("select",{className:W,value:i,onChange:G=>d(G.target.value),children:[l.jsx("option",{value:"",children:"All sources"}),l.jsx("option",{value:"node",children:"Node"}),l.jsx("option",{value:"mobile",children:"Mobile"})]})]})]}),w&&l.jsx("div",{className:"flex justify-center py-12",children:l.jsx("div",{className:"h-6 w-6 animate-spin rounded-full border-2 border-[var(--color-primary)] border-t-transparent"})}),E&&l.jsx("div",{className:"rounded-lg border border-red-300 bg-red-50 p-4 text-red-700 dark:border-red-700 dark:bg-red-900/20 dark:text-red-400",children:"Failed to load traces"}),k&&l.jsxs(l.Fragment,{children:[l.jsxs("p",{className:"text-sm text-[var(--color-text-muted)]",children:[k.total," traces in ",X.length," conversation",X.length===1?"":"s"]}),l.jsx("div",{className:"overflow-x-auto rounded-lg border border-[var(--color-border)]",children:l.jsxs("table",{className:"w-full text-sm",children:[l.jsx("thead",{children:l.jsxs("tr",{className:"border-b border-[var(--color-border)] bg-[var(--color-surface-alt)]",children:[l.jsx("th",{className:"w-8 px-2 py-2"}),l.jsx("th",{className:"px-3 py-2 text-left font-medium text-[var(--color-text-muted)]",children:"Time"}),l.jsx("th",{className:"px-3 py-2 text-left font-medium text-[var(--color-text-muted)]",children:"Source"}),l.jsx("th",{className:"px-3 py-2 text-left font-medium text-[var(--color-text-muted)]",children:"Node"}),l.jsx("th",{className:"px-3 py-2 text-left font-medium text-[var(--color-text-muted)]",children:"User said"}),l.jsx("th",{className:"px-3 py-2 text-left font-medium text-[var(--color-text-muted)]",children:"Jarvis said"}),l.jsx("th",{className:"px-3 py-2 text-right font-medium text-[var(--color-text-muted)]",children:"Duration"}),l.jsx("th",{className:"px-3 py-2 text-center font-medium text-[var(--color-text-muted)]",children:"Status"}),l.jsx("th",{className:"px-3 py-2 text-right font-medium text-[var(--color-text-muted)]",children:"Traces"})]})}),l.jsxs("tbody",{children:[X.map(G=>{const U=h.has(G.conversation_id),oe=G.traces.length,Ne=G.node_id?A.get(G.node_id)??G.node_id.slice(0,8):"-";return l.jsxs(N.Fragment,{children:[l.jsxs("tr",{className:"border-b border-[var(--color-border)] cursor-pointer transition-colors hover:bg-[var(--color-surface-alt)]",onClick:()=>I(G.conversation_id),children:[l.jsx("td",{className:"px-2 py-2 text-center text-[var(--color-text-muted)]",children:oe>1?U?"▼":"▶":""}),l.jsx("td",{className:"px-3 py-2 text-[var(--color-text)] whitespace-nowrap",children:Yx(G.newest_at)}),l.jsx("td",{className:"px-3 py-2 text-[var(--color-text-muted)]",children:l.jsxs("span",{className:"inline-flex items-center gap-1",children:[D4(G.source),G.source]})}),l.jsxs("td",{className:"px-3 py-2 text-[var(--color-text-muted)] whitespace-nowrap",children:[Ne,G.household_id&&l.jsxs("span",{className:"ml-1 text-xs opacity-60",children:["· ",M.get(G.household_id)??""]})]}),l.jsx("td",{className:"px-3 py-2 text-[var(--color-text)] max-w-xs truncate",children:G.user_command??"-"}),l.jsx("td",{className:"px-3 py-2 text-[var(--color-text-muted)] max-w-xs truncate",children:G.assistant_message??"-"}),l.jsx("td",{className:"px-3 py-2 text-right text-[var(--color-text)] tabular-nums",children:Fx(G.total_duration_ms)}),l.jsx("td",{className:"px-3 py-2 text-center",children:l.jsx("span",{className:`inline-block h-2 w-2 rounded-full ${G.status==="ok"?"bg-green-500":"bg-red-500"}`})}),l.jsx("td",{className:"px-3 py-2 text-right text-[var(--color-text-muted)] tabular-nums",children:oe})]}),U&&G.traces.slice().sort((le,pe)=>le.created_at<pe.created_at?-1:1).map(le=>l.jsxs("tr",{className:"border-b border-[var(--color-border)] cursor-pointer bg-[var(--color-surface-alt)]/40 transition-colors hover:bg-[var(--color-surface-alt)]",onClick:()=>a(`/traces/${le.id}`),children:[l.jsx("td",{className:"px-2 py-2"}),l.jsxs("td",{className:"px-3 py-2 text-[var(--color-text-muted)] whitespace-nowrap",children:[l.jsx("span",{className:"inline-block w-3"}),Yx(le.created_at)]}),l.jsx("td",{className:"px-3 py-2 text-[var(--color-text-muted)] text-xs",children:le.request_type}),l.jsx("td",{className:"px-3 py-2 text-[var(--color-text-muted)] whitespace-nowrap text-xs",children:le.node_id?A.get(le.node_id)??le.node_id.slice(0,8):"-"}),l.jsx("td",{className:"px-3 py-2 text-[var(--color-text)] max-w-xs truncate",children:le.user_command??"-"}),l.jsx("td",{className:"px-3 py-2 text-[var(--color-text-muted)] max-w-xs truncate",children:le.assistant_message??"-"}),l.jsx("td",{className:"px-3 py-2 text-right text-[var(--color-text)] tabular-nums",children:Fx(le.total_duration_ms)}),l.jsx("td",{className:"px-3 py-2 text-center",children:l.jsx("span",{className:`inline-block h-2 w-2 rounded-full ${le.status==="ok"?"bg-green-500":"bg-red-500"}`})}),l.jsx("td",{className:"px-3 py-2 text-right text-[var(--color-text-muted)] tabular-nums",children:le.span_count})]},le.id))]},G.conversation_id)}),X.length===0&&l.jsx("tr",{children:l.jsx("td",{colSpan:9,className:"px-3 py-8 text-center text-[var(--color-text-muted)]",children:"No traces yet"})})]})]})})]})]})}function ns(a){return a<1e3?`${Math.round(a)}ms`:`${(a/1e3).toFixed(1)}s`}const Xx={cc:"#9e9e9e",llm_proxy:"#42a5f5",node:"#66bb6a",tts:"#ffa726",whisper:"#ab47bc"},Kx={cc:"Command Center",llm_proxy:"LLM Proxy",node:"Node",tts:"TTS",whisper:"Whisper"};function L4(a){const s=a.filter(d=>d.duration_ms>0),o=s.filter(d=>!s.some(f=>f!==d&&d.start_ms<=f.start_ms&&d.end_ms>=f.end_ms&&f.duration_ms>0));o.sort((d,f)=>d.start_ms-f.start_ms);const i=[];for(const d of o){const f=i[i.length-1];f&&f.service===d.service?(f.duration_ms=Math.round((f.duration_ms+d.duration_ms)*10)/10,f.steps.push(d.name),d.status==="error"&&(f.status="error")):i.push({service:d.service,duration_ms:d.duration_ms,status:d.status,steps:[d.name]})}return i}function B4(){const{id:a}=k0(),s=wa(),[o,i]=N.useState(!1),[d,f]=N.useState(null),{data:m,isLoading:v,error:g}=yt({queryKey:["trace",a],queryFn:()=>O4(a),enabled:!!a}),h=N.useMemo(()=>m?L4(m.spans):[],[m]);return v?l.jsx("div",{className:"flex justify-center py-12",children:l.jsx("div",{className:"h-6 w-6 animate-spin rounded-full border-2 border-[var(--color-primary)] border-t-transparent"})}):g||!m?l.jsxs("div",{className:"space-y-4",children:[l.jsx("button",{className:"text-sm text-[var(--color-primary)] hover:underline",onClick:()=>s("/traces"),children:"Back to traces"}),l.jsx("div",{className:"rounded-lg border border-red-300 bg-red-50 p-4 text-red-700 dark:border-red-700 dark:bg-red-900/20 dark:text-red-400",children:"Trace not found"})]}):l.jsxs("div",{className:"space-y-6",children:[l.jsx("button",{className:"text-sm text-[var(--color-primary)] hover:underline",onClick:()=>s("/traces"),children:"Back to traces"}),l.jsxs("div",{className:"rounded-lg border border-[var(--color-border)] bg-[var(--color-surface)] p-4",children:[l.jsxs("div",{className:"flex items-center justify-between",children:[l.jsxs("div",{children:[l.jsx("h1",{className:"text-lg font-bold text-[var(--color-text)]",children:m.user_command??"Request Trace"}),l.jsxs("p",{className:"mt-1 text-sm text-[var(--color-text-muted)]",children:[m.source==="mobile"?"📱 Mobile":"🔊 Node",m.node_id&&` (${m.node_id})`," · ",m.request_type," · ",m.created_at?new Date(m.created_at).toLocaleString():""]})]}),l.jsxs("div",{className:"text-right",children:[l.jsx("div",{className:"text-2xl font-bold tabular-nums text-[var(--color-text)]",children:ns(m.total_duration_ms)}),l.jsxs("div",{className:"flex items-center justify-end gap-1 mt-1",children:[l.jsx("span",{className:`inline-block h-2 w-2 rounded-full ${m.status==="ok"?"bg-green-500":"bg-red-500"}`}),l.jsx("span",{className:"text-sm text-[var(--color-text-muted)]",children:m.status})]})]})]}),m.error_message&&l.jsx("div",{className:"mt-3 rounded border border-red-300 bg-red-50 p-2 text-sm text-red-700 dark:border-red-700 dark:bg-red-900/20 dark:text-red-400",children:m.error_message}),l.jsx("p",{className:"mt-2 text-xs text-[var(--color-text-muted)] font-mono",children:m.conversation_id})]}),l.jsxs("div",{className:"rounded-lg border border-[var(--color-border)] bg-[var(--color-surface)] p-4",children:[l.jsx("h2",{className:"mb-3 text-sm font-medium text-[var(--color-text-muted)]",children:"Service Flow"}),l.jsx("p",{className:"mb-4 text-xs text-[var(--color-text-muted)] opacity-60",children:h.map(y=>Kx[y.service]??y.service).join(" → ")}),l.jsx("div",{className:"space-y-2",children:h.map((y,x)=>{const j=Math.min(y.duration_ms/m.total_duration_ms*100,100),k=y.status==="error"?"#ef4444":Xx[y.service]??"#9e9e9e",w=Kx[y.service]??y.service;return l.jsxs("div",{className:"flex items-center gap-3",children:[l.jsx("span",{className:"inline-block h-2.5 w-2.5 rounded-full shrink-0",style:{backgroundColor:k}}),l.jsx("span",{className:"w-32 text-sm text-[var(--color-text)] shrink-0",children:w}),l.jsxs("div",{className:"flex-1 h-6 rounded bg-[var(--color-surface-alt)] relative",children:[l.jsx("div",{className:"absolute top-0 left-0 h-full rounded",style:{width:`${Math.max(j,1)}%`,backgroundColor:k,opacity:.7}}),l.jsx("span",{className:"absolute inset-0 flex items-center px-2 text-xs text-[var(--color-text)] opacity-70",children:y.steps.join(", ")})]}),l.jsx("span",{className:"w-16 text-sm text-[var(--color-text)] text-right tabular-nums shrink-0",children:ns(y.duration_ms)})]},`${y.service}-${x}`)})})]}),l.jsxs("div",{className:"rounded-lg border border-[var(--color-border)] bg-[var(--color-surface)] p-4",children:[l.jsxs("button",{className:"text-sm text-[var(--color-text-muted)] hover:text-[var(--color-text)]",onClick:()=>{i(y=>!y),f(null)},children:[o?"Hide":"Show"," raw spans (",m.spans.length,")"]}),o&&l.jsx("div",{className:"mt-3 space-y-1",children:m.spans.map((y,x)=>{const j=Math.min(y.duration_ms/m.total_duration_ms*100,100),k=y.start_ms/m.total_duration_ms*100,w=y.status==="error"?"#ef4444":Xx[y.service]??"#9e9e9e",E=d===y;return l.jsxs("div",{className:`flex items-center gap-2 cursor-pointer rounded px-1 py-0.5 ${E?"bg-[var(--color-surface-alt)]":""}`,onClick:()=>f(E?null:y),children:[l.jsx("span",{className:"w-36 truncate text-xs text-[var(--color-text-muted)] text-right shrink-0",children:y.name}),l.jsx("div",{className:"flex-1 relative h-4 rounded bg-[var(--color-surface-alt)]",children:l.jsx("div",{className:"absolute top-0 h-full rounded",style:{left:`${k}%`,width:`${Math.max(j,.5)}%`,backgroundColor:w,minWidth:"2px"}})}),l.jsx("span",{className:"w-14 text-xs text-[var(--color-text-muted)] text-right shrink-0 tabular-nums",children:ns(y.duration_ms)}),l.jsx("span",{className:"w-16 text-xs text-[var(--color-text-muted)] opacity-60 shrink-0",children:y.service})]},`${y.name}-${x}`)})}),d&&o&&l.jsx("div",{className:"mt-3 border-t border-[var(--color-border)] pt-3",children:l.jsxs("dl",{className:"grid grid-cols-2 gap-x-4 gap-y-1 text-sm max-w-md",children:[l.jsx("dt",{className:"text-[var(--color-text-muted)]",children:"Service"}),l.jsx("dd",{className:"text-[var(--color-text)]",children:d.service}),l.jsx("dt",{className:"text-[var(--color-text-muted)]",children:"Duration"}),l.jsx("dd",{className:"text-[var(--color-text)] tabular-nums",children:ns(d.duration_ms)}),l.jsx("dt",{className:"text-[var(--color-text-muted)]",children:"Start"}),l.jsx("dd",{className:"text-[var(--color-text)] tabular-nums",children:ns(d.start_ms)}),l.jsx("dt",{className:"text-[var(--color-text-muted)]",children:"End"}),l.jsx("dd",{className:"text-[var(--color-text)] tabular-nums",children:ns(d.end_ms)}),l.jsx("dt",{className:"text-[var(--color-text-muted)]",children:"Status"}),l.jsx("dd",{className:d.status==="ok"?"text-green-600":"text-red-600",children:d.status}),Object.entries(d.metadata||{}).map(([y,x])=>l.jsxs("div",{className:"contents",children:[l.jsx("dt",{className:"text-[var(--color-text-muted)]",children:y}),l.jsx("dd",{className:"text-[var(--color-text)] tabular-nums",children:String(x)})]},y))]})})]})]})}function q4(){return l.jsxs("div",{className:"flex min-h-[60vh] flex-col items-center justify-center",children:[l.jsx("h1",{className:"mb-2 text-4xl font-bold text-[var(--color-text)]",children:"404"}),l.jsx("p",{className:"mb-4 text-[var(--color-text-muted)]",children:"Page not found"}),l.jsx(Cd,{to:"/settings",className:"text-[var(--color-primary)] underline hover:opacity-80",children:"Go to Settings"})]})}const H4=7,G4={currentStep:0,totalSteps:H4,enabledModules:[],portOverrides:{},infraPortOverrides:{},secrets:{},dbUser:"jarvis",whisperModel:"base.en",whisperModelPath:"/whisper-models/ggml-base.en.bin",llmInterface:"Qwen25MediumUntrained",deploymentMode:"local",deploymentTarget:"standard",remoteLlmUrl:"",remoteWhisperUrl:"",platform:"linux",hardware:null,relayEnabled:!1,installRunning:!1,installComplete:!1,nativeServices:[]};function Q4(a,s,o){return Math.max(s,Math.min(o,a))}function V4(a,s){switch(s.type){case"SET_STEP":return{...a,currentStep:Q4(s.step,0,a.totalSteps-1)};case"NEXT_STEP":return{...a,currentStep:Math.min(a.currentStep+1,a.totalSteps-1)};case"PREV_STEP":return{...a,currentStep:Math.max(a.currentStep-1,0)};case"SET_ENABLED_MODULES":return{...a,enabledModules:s.modules};case"TOGGLE_MODULE":{if(s.enabled){const o=a.enabledModules.includes(s.serviceId)?a.enabledModules:[...a.enabledModules,s.serviceId];return{...a,enabledModules:o}}return{...a,enabledModules:a.enabledModules.filter(o=>o!==s.serviceId)}}case"SET_PORT_OVERRIDE":return{...a,portOverrides:{...a.portOverrides,[s.serviceId]:s.port}};case"SET_INFRA_PORT_OVERRIDE":return{...a,infraPortOverrides:{...a.infraPortOverrides,[s.infraId]:s.port}};case"SET_SECRET":return{...a,secrets:{...a.secrets,[s.name]:s.value}};case"SET_SECRETS":return{...a,secrets:s.secrets};case"SET_DB_USER":return{...a,dbUser:s.user};case"SET_WHISPER_MODEL":return{...a,whisperModel:s.model};case"SET_WHISPER_BACKEND":return{...a,whisperBackend:s.backend};case"SET_LLM_INTERFACE":return{...a,llmInterface:s.interfaceId};case"SET_DEPLOYMENT_MODE":return{...a,deploymentMode:s.mode};case"SET_DEPLOYMENT_TARGET":return{...a,deploymentTarget:s.target};case"SET_REMOTE_LLM_URL":return{...a,remoteLlmUrl:s.url};case"SET_REMOTE_WHISPER_URL":return{...a,remoteWhisperUrl:s.url};case"SET_PLATFORM":return{...a,platform:s.platform};case"SET_HARDWARE":return{...a,hardware:s.hardware,platform:s.hardware.platform};case"SET_RELAY_ENABLED":return{...a,relayEnabled:s.enabled};case"SET_INSTALL_RUNNING":return{...a,installRunning:s.running};case"SET_INSTALL_COMPLETE":return{...a,installRunning:!1,installComplete:!0};case"SET_NATIVE_SERVICES":return{...a,nativeServices:s.services};case"TOGGLE_NATIVE_SERVICE":{if(s.enabled){const o=a.nativeServices.includes(s.serviceId)?a.nativeServices:[...a.nativeServices,s.serviceId];return{...a,nativeServices:o}}return{...a,nativeServices:a.nativeServices.filter(o=>o!==s.serviceId)}}default:return a}}const Eg=N.createContext(null);function F4({children:a}){const[s,o]=N.useReducer(V4,G4);return l.jsx(Eg.Provider,{value:{state:s,dispatch:o},children:a})}function fr(){const a=N.useContext(Eg);if(!a)throw new Error("useWizard must be used within a WizardProvider");return a}function Y4(){const{state:a,dispatch:s}=fr(),[o,i]=N.useState(null),[d,f]=N.useState(!0),[m,v]=N.useState(!1);function g(){f(!0),v(!1),Yd().then(y=>{i(y);const x=y.reason==="docker_not_found";v(x),s(x?{type:"SET_INSTALL_RUNNING",running:!0}:{type:"SET_INSTALL_RUNNING",running:!1})}).catch(()=>{i({configured:!1,reason:"error"}),v(!0),s({type:"SET_INSTALL_RUNNING",running:!0})}).finally(()=>f(!1))}N.useEffect(()=>{g()},[]);const h=o&&o.reason!=="docker_not_found";return l.jsxs("div",{className:"space-y-6",children:[l.jsxs("div",{children:[l.jsx("h2",{className:"text-xl font-bold text-[var(--color-text)]",children:"Welcome to Jarvis"}),l.jsx("p",{className:"mt-1 text-sm text-[var(--color-text-muted)]",children:"Let's get your personal voice assistant up and running. This wizard will guide you through selecting services, configuring hardware, and starting everything up."})]}),l.jsx("div",{className:"rounded-lg border border-[var(--color-border)] bg-[var(--color-surface-alt)] p-4",children:l.jsxs("div",{className:"flex items-center gap-3",children:[d?l.jsx(Ct,{size:20,className:"animate-spin text-[var(--color-primary)]"}):h?l.jsx(ht,{size:20,className:"text-green-500"}):l.jsx(Bd,{size:20,className:"text-red-500"}),l.jsxs("div",{className:"flex-1",children:[l.jsx("p",{className:"text-sm font-medium text-[var(--color-text)]",children:d?"Checking Docker...":h?"Docker is running":"Docker not found"}),!d&&!h&&l.jsxs("div",{className:"mt-1 space-y-1",children:[l.jsx("p",{className:"text-xs text-red-400",children:"Docker is required to run Jarvis services."}),l.jsxs("p",{className:"text-xs text-[var(--color-text-muted)]",children:["Install"," ",l.jsx("a",{href:"https://www.docker.com/products/docker-desktop/",target:"_blank",rel:"noopener noreferrer",className:"text-[var(--color-primary)] underline hover:no-underline",children:"Docker Desktop"})," ","for your platform, start it, then click Retry."]})]})]}),m&&!d&&l.jsxs("button",{type:"button",onClick:g,className:"flex items-center gap-1 rounded-md border border-[var(--color-border)] px-2 py-1 text-xs text-[var(--color-text-muted)] hover:text-[var(--color-text)]",children:[l.jsx(gi,{size:12}),"Retry"]})]})}),l.jsxs("div",{children:[l.jsx("label",{className:"mb-2 block text-sm font-medium text-[var(--color-text)]",children:"Deployment Mode"}),l.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[l.jsxs("button",{type:"button",onClick:()=>s({type:"SET_DEPLOYMENT_MODE",mode:"local"}),className:te("flex flex-col items-center gap-2 rounded-lg border p-4 transition-colors",a.deploymentMode==="local"?"border-[var(--color-primary)] bg-[var(--color-primary)]/10":"border-[var(--color-border)] hover:border-[var(--color-primary)]/50"),children:[l.jsx(yS,{size:24,className:"text-[var(--color-primary)]"}),l.jsx("span",{className:"text-sm font-medium text-[var(--color-text)]",children:"Local"}),l.jsx("span",{className:"text-xs text-center text-[var(--color-text-muted)]",children:"Everything on this machine"})]}),l.jsxs("button",{type:"button",onClick:()=>s({type:"SET_DEPLOYMENT_MODE",mode:"remote-llm"}),className:te("flex flex-col items-center gap-2 rounded-lg border p-4 transition-colors",a.deploymentMode==="remote-llm"?"border-[var(--color-primary)] bg-[var(--color-primary)]/10":"border-[var(--color-border)] hover:border-[var(--color-primary)]/50"),children:[l.jsx(Qd,{size:24,className:"text-[var(--color-primary)]"}),l.jsx("span",{className:"text-sm font-medium text-[var(--color-text)]",children:"Remote LLM"}),l.jsx("span",{className:"text-xs text-center text-[var(--color-text-muted)]",children:"LLM on separate GPU machine"})]})]})]})]})}const $o=[{label:"None / CPU only",gpu:null,gpuType:"none",vramMb:null,backends:["gguf"],defaultBackend:"gguf"},{label:"NVIDIA RTX 4090 (24 GB)",gpu:"NVIDIA RTX 4090",gpuType:"nvidia",vramMb:24576,backends:["gguf","vllm"],defaultBackend:"gguf"},{label:"NVIDIA RTX 4080 (16 GB)",gpu:"NVIDIA RTX 4080",gpuType:"nvidia",vramMb:16384,backends:["gguf","vllm"],defaultBackend:"gguf"},{label:"NVIDIA RTX 4070 Ti (12 GB)",gpu:"NVIDIA RTX 4070 Ti",gpuType:"nvidia",vramMb:12288,backends:["gguf","vllm"],defaultBackend:"gguf"},{label:"NVIDIA RTX 3090 (24 GB)",gpu:"NVIDIA RTX 3090",gpuType:"nvidia",vramMb:24576,backends:["gguf","vllm"],defaultBackend:"gguf"},{label:"NVIDIA RTX 3080 (10 GB)",gpu:"NVIDIA RTX 3080",gpuType:"nvidia",vramMb:10240,backends:["gguf","vllm"],defaultBackend:"gguf"},{label:"NVIDIA RTX 3070 (8 GB)",gpu:"NVIDIA RTX 3070",gpuType:"nvidia",vramMb:8192,backends:["gguf","vllm"],defaultBackend:"gguf"},{label:"NVIDIA A100 (80 GB)",gpu:"NVIDIA A100",gpuType:"nvidia",vramMb:81920,backends:["gguf","vllm"],defaultBackend:"vllm"},{label:"NVIDIA A100 (40 GB)",gpu:"NVIDIA A100",gpuType:"nvidia",vramMb:40960,backends:["gguf","vllm"],defaultBackend:"vllm"},{label:"NVIDIA Tesla T4 (16 GB)",gpu:"NVIDIA Tesla T4",gpuType:"nvidia",vramMb:16384,backends:["gguf","vllm"],defaultBackend:"gguf"},{label:"AMD RX 9070 XT — Vulkan (16 GB)",gpu:"AMD RX 9070 XT",gpuType:"amd",vramMb:16384,backends:["gguf"],defaultBackend:"gguf"},{label:"AMD RX 9070 — Vulkan (12 GB)",gpu:"AMD RX 9070",gpuType:"amd",vramMb:12288,backends:["gguf"],defaultBackend:"gguf"},{label:"AMD RX 7900 XTX — Vulkan (24 GB)",gpu:"AMD RX 7900 XTX",gpuType:"amd",vramMb:24576,backends:["gguf"],defaultBackend:"gguf"},{label:"AMD RX 7900 XT — Vulkan (20 GB)",gpu:"AMD RX 7900 XT",gpuType:"amd",vramMb:20480,backends:["gguf"],defaultBackend:"gguf"},{label:"AMD RX 7800 XT — Vulkan (16 GB)",gpu:"AMD RX 7800 XT",gpuType:"amd",vramMb:16384,backends:["gguf"],defaultBackend:"gguf"},{label:"AMD RX 7600 — Vulkan (8 GB)",gpu:"AMD RX 7600",gpuType:"amd",vramMb:8192,backends:["gguf"],defaultBackend:"gguf"},{label:"AMD RX 9070 XT — ROCm (16 GB)",gpu:"AMD RX 9070 XT",gpuType:"amd-rocm",vramMb:16384,backends:["gguf"],defaultBackend:"gguf"},{label:"AMD RX 9070 — ROCm (12 GB)",gpu:"AMD RX 9070",gpuType:"amd-rocm",vramMb:12288,backends:["gguf"],defaultBackend:"gguf"},{label:"AMD RX 7900 XTX — ROCm (24 GB)",gpu:"AMD RX 7900 XTX",gpuType:"amd-rocm",vramMb:24576,backends:["gguf"],defaultBackend:"gguf"},{label:"AMD RX 7900 XT — ROCm (20 GB)",gpu:"AMD RX 7900 XT",gpuType:"amd-rocm",vramMb:20480,backends:["gguf"],defaultBackend:"gguf"},{label:"AMD RX 7800 XT — ROCm (16 GB)",gpu:"AMD RX 7800 XT",gpuType:"amd-rocm",vramMb:16384,backends:["gguf"],defaultBackend:"gguf"},{label:"Apple M4 Max (128 GB unified)",gpu:"Apple M4 Max",gpuType:"apple",vramMb:131072,backends:["gguf","mlx"],defaultBackend:"gguf"},{label:"Apple M4 Max (64 GB unified)",gpu:"Apple M4 Max",gpuType:"apple",vramMb:65536,backends:["gguf","mlx"],defaultBackend:"gguf"},{label:"Apple M4 Pro (48 GB unified)",gpu:"Apple M4 Pro",gpuType:"apple",vramMb:49152,backends:["gguf","mlx"],defaultBackend:"gguf"},{label:"Apple M4 Pro (24 GB unified)",gpu:"Apple M4 Pro",gpuType:"apple",vramMb:24576,backends:["gguf","mlx"],defaultBackend:"gguf"},{label:"Apple M2 Max (32 GB unified)",gpu:"Apple M2 Max",gpuType:"apple",vramMb:32768,backends:["gguf","mlx"],defaultBackend:"gguf"},{label:"Apple M2 Pro (16 GB unified)",gpu:"Apple M2 Pro",gpuType:"apple",vramMb:16384,backends:["gguf","mlx"],defaultBackend:"gguf"},{label:"Apple M1 (16 GB unified)",gpu:"Apple M1",gpuType:"apple",vramMb:16384,backends:["gguf","mlx"],defaultBackend:"gguf"},{label:"Apple M1 (8 GB unified)",gpu:"Apple M1",gpuType:"apple",vramMb:8192,backends:["gguf","mlx"],defaultBackend:"gguf"},{label:"Other (enter VRAM manually)",gpu:"Other",gpuType:"none",vramMb:null,backends:["gguf"],defaultBackend:"gguf"}];function X4(){const{state:a,dispatch:s}=fr(),[o,i]=N.useState(!a.hardware),[d,f]=N.useState(!1),[m,v]=N.useState(0),[g,h]=N.useState("");N.useEffect(()=>{a.hardware||ME().then(j=>{s({type:"SET_HARDWARE",hardware:j}),j.recommendedBackend==="remote"&&a.deploymentMode==="local"&&s({type:"SET_DEPLOYMENT_MODE",mode:"remote-llm"})}).catch(()=>{}).finally(()=>i(!1))},[]);function y(j,k){const w=$o[j];if(!a.hardware)return;const E=w.gpu==="Other"?(parseInt(k??g,10)||0)*1024:w.vramMb,_={...a.hardware,gpuName:w.gpu,gpuVramMb:E||null,gpuType:w.gpuType,recommendedBackends:[...w.backends],recommendedBackend:w.defaultBackend};s({type:"SET_HARDWARE",hardware:_})}const x=a.hardware;return o?l.jsxs("div",{className:"flex flex-col items-center justify-center py-12",children:[l.jsx(Ct,{size:32,className:"animate-spin text-[var(--color-primary)]"}),l.jsx("p",{className:"mt-3 text-sm text-[var(--color-text-muted)]",children:"Detecting hardware..."})]}):l.jsxs("div",{className:"space-y-6",children:[l.jsxs("div",{children:[l.jsx("h2",{className:"text-xl font-bold text-[var(--color-text)]",children:"Hardware Detection"}),l.jsx("p",{className:"mt-1 text-sm text-[var(--color-text-muted)]",children:"We detected the following hardware. This determines which LLM backend to use."})]}),x&&l.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[l.jsxs("div",{className:"rounded-lg border border-[var(--color-border)] bg-[var(--color-surface-alt)] p-4",children:[l.jsxs("div",{className:"flex items-center gap-2 text-[var(--color-text-muted)]",children:[l.jsx(On,{size:16}),l.jsx("span",{className:"text-xs font-medium uppercase",children:"Platform"})]}),l.jsxs("p",{className:"mt-1 text-sm font-medium text-[var(--color-text)]",children:[x.platform==="darwin"?"macOS":"Linux"," (",x.arch,")"]})]}),l.jsxs("div",{className:"rounded-lg border border-[var(--color-border)] bg-[var(--color-surface-alt)] p-4",children:[l.jsxs("div",{className:"flex items-center gap-2 text-[var(--color-text-muted)]",children:[l.jsx(Hd,{size:16}),l.jsx("span",{className:"text-xs font-medium uppercase",children:"Memory"})]}),l.jsxs("p",{className:"mt-1 text-sm font-medium text-[var(--color-text)]",children:[x.totalMemoryGb," GB RAM"]})]}),l.jsxs("div",{className:"col-span-2 rounded-lg border border-[var(--color-border)] bg-[var(--color-surface-alt)] p-4",children:[l.jsxs("div",{className:"flex items-center justify-between",children:[l.jsxs("div",{children:[l.jsxs("div",{className:"flex items-center gap-2 text-[var(--color-text-muted)]",children:[l.jsx(On,{size:16}),l.jsx("span",{className:"text-xs font-medium uppercase",children:"GPU"})]}),l.jsx("p",{className:"mt-1 text-sm font-medium text-[var(--color-text)]",children:x.gpuName??"No GPU detected"}),x.gpuVramMb!=null&&x.gpuVramMb>0&&l.jsxs("p",{className:"text-xs text-[var(--color-text-muted)]",children:[Math.round(x.gpuVramMb/1024)," GB VRAM"]})]}),l.jsx("button",{type:"button",onClick:()=>f(!d),className:"text-xs font-medium text-[var(--color-primary)] hover:underline",children:d?"Cancel":"Override"})]}),d&&l.jsxs("div",{className:"mt-3 space-y-3 border-t border-[var(--color-border)] pt-3",children:[l.jsxs("div",{children:[l.jsx("label",{htmlFor:"gpu-select",className:"mb-1 block text-xs text-[var(--color-text-muted)]",children:"Select GPU"}),l.jsx("select",{id:"gpu-select",value:m,onChange:j=>{const k=parseInt(j.target.value,10);v(k),$o[k].gpu!=="Other"&&(y(k),f(!1))},className:te("w-full rounded-lg border border-[var(--color-border)] bg-[var(--color-surface-alt)] px-3 py-2","text-sm text-[var(--color-text)]","outline-none focus:ring-2 focus:ring-[var(--color-primary)]"),children:$o.map((j,k)=>l.jsx("option",{value:k,children:j.label},`${j.label}-${k}`))})]}),$o[m].gpu==="Other"&&l.jsxs("div",{className:"flex items-end gap-2",children:[l.jsxs("div",{className:"flex-1",children:[l.jsx("label",{htmlFor:"custom-vram",className:"mb-1 block text-xs text-[var(--color-text-muted)]",children:"VRAM (GB)"}),l.jsx("input",{id:"custom-vram",type:"number",min:1,max:512,value:g,onChange:j=>h(j.target.value),placeholder:"e.g. 24",className:te("w-full rounded-lg border border-[var(--color-border)] bg-[var(--color-surface-alt)] px-3 py-2","text-sm text-[var(--color-text)] placeholder:text-[var(--color-text-muted)]","outline-none focus:ring-2 focus:ring-[var(--color-primary)]")})]}),l.jsx("button",{type:"button",disabled:!g||parseInt(g,10)<=0,onClick:()=>{y(m,g),f(!1)},className:te("rounded-lg px-4 py-2 text-sm font-medium","bg-[var(--color-primary)] text-white","disabled:cursor-not-allowed disabled:opacity-50"),children:"Apply"})]})]})]}),l.jsxs("div",{className:"col-span-2 rounded-lg border border-[var(--color-primary)]/30 bg-[var(--color-primary)]/5 p-4",children:[l.jsxs("p",{className:"text-sm font-medium text-[var(--color-text)]",children:["Recommended: ",l.jsx("span",{className:"text-[var(--color-primary)]",children:x.recommendedBackend.toUpperCase()})]}),x.recommendedBackends.length>1&&l.jsxs("p",{className:"mt-0.5 text-xs text-[var(--color-text-muted)]",children:["Available backends: ",x.recommendedBackends.join(", ")]})]})]}),a.deploymentMode==="remote-llm"&&l.jsxs("div",{className:"space-y-3",children:[l.jsx("h3",{className:"text-sm font-medium text-[var(--color-text)]",children:"Remote Service URLs"}),l.jsxs("div",{children:[l.jsx("label",{htmlFor:"remote-llm",className:"mb-1 block text-xs text-[var(--color-text-muted)]",children:"LLM Proxy URL"}),l.jsx("input",{id:"remote-llm",type:"url",value:a.remoteLlmUrl,onChange:j=>s({type:"SET_REMOTE_LLM_URL",url:j.target.value}),placeholder:"http://192.168.1.100:7704",className:te("w-full rounded-lg border border-[var(--color-border)] bg-[var(--color-surface-alt)] px-3 py-2","text-sm text-[var(--color-text)] placeholder:text-[var(--color-text-muted)]","outline-none focus:ring-2 focus:ring-[var(--color-primary)]")})]}),l.jsxs("div",{children:[l.jsx("label",{htmlFor:"remote-whisper",className:"mb-1 block text-xs text-[var(--color-text-muted)]",children:"Whisper URL (optional)"}),l.jsx("input",{id:"remote-whisper",type:"url",value:a.remoteWhisperUrl,onChange:j=>s({type:"SET_REMOTE_WHISPER_URL",url:j.target.value}),placeholder:"http://192.168.1.100:7706",className:te("w-full rounded-lg border border-[var(--color-border)] bg-[var(--color-surface-alt)] px-3 py-2","text-sm text-[var(--color-text)] placeholder:text-[var(--color-text-muted)]","outline-none focus:ring-2 focus:ring-[var(--color-primary)]")})]})]})]})}function K4(){const{state:a,dispatch:s}=fr(),[o,i]=N.useState(null),[d,f]=N.useState(!0);if(N.useEffect(()=>{Promise.all([bg(),AE()]).then(([h,y])=>{if(i(h),a.enabledModules.length===0&&s({type:"SET_ENABLED_MODULES",modules:y.enabledModules}),a.platform==="darwin"&&a.nativeServices.length===0){const x=h.services.filter(j=>j.nativeCapable).map(j=>j.id);x.length>0&&s({type:"SET_NATIVE_SERVICES",services:x})}}).catch(()=>{}).finally(()=>f(!1))},[]),d||!o)return l.jsx("div",{className:"flex items-center justify-center py-12",children:l.jsx(Ct,{size:32,className:"animate-spin text-[var(--color-primary)]"})});const{core:m,recommended:v,optional:g}=$4(o.services);return l.jsxs("div",{className:"space-y-6",children:[l.jsxs("div",{children:[l.jsx("h2",{className:"text-xl font-bold text-[var(--color-text)]",children:"Select Services"}),l.jsxs("p",{className:"mt-1 text-sm text-[var(--color-text-muted)]",children:["Core services are always included. Toggle recommended and optional services.",a.platform==="darwin"&&l.jsxs(l.Fragment,{children:[" Services marked ",l.jsx("em",{children:"Native"})," can run as macOS LaunchAgents to use the Apple GPU."]})]})]}),l.jsx(Pu,{title:"Core",subtitle:"Always included",services:m,enabled:m.map(h=>h.id),nativeServices:a.nativeServices,platform:a.platform,locked:!0}),l.jsx(Pu,{title:"Recommended",subtitle:"Enabled by default",services:v,enabled:a.enabledModules,nativeServices:a.nativeServices,platform:a.platform,onToggle:(h,y)=>s({type:"TOGGLE_MODULE",serviceId:h,enabled:y}),onToggleNative:(h,y)=>s({type:"TOGGLE_NATIVE_SERVICE",serviceId:h,enabled:y})}),g.length>0&&l.jsx(Pu,{title:"Optional",subtitle:"Off by default",services:g,enabled:a.enabledModules,nativeServices:a.nativeServices,platform:a.platform,onToggle:(h,y)=>s({type:"TOGGLE_MODULE",serviceId:h,enabled:y}),onToggleNative:(h,y)=>s({type:"TOGGLE_NATIVE_SERVICE",serviceId:h,enabled:y})}),l.jsxs("div",{children:[l.jsxs("div",{className:"mb-2 flex items-baseline gap-2",children:[l.jsx("h3",{className:"text-sm font-medium text-[var(--color-text)]",children:"Integrations"}),l.jsx("span",{className:"text-xs text-[var(--color-text-muted)]",children:"Cloud services"})]}),l.jsxs("button",{type:"button",onClick:()=>s({type:"SET_RELAY_ENABLED",enabled:!a.relayEnabled}),className:te("flex w-full items-center gap-3 rounded-lg border px-3 py-2.5 text-left transition-colors",a.relayEnabled?"border-[var(--color-primary)]/30 bg-[var(--color-primary)]/5":"border-[var(--color-border)] hover:border-[var(--color-primary)]/30"),children:[a.relayEnabled?l.jsx(ht,{size:16,className:"shrink-0 text-[var(--color-primary)]"}):l.jsx(os,{size:16,className:"shrink-0 text-[var(--color-text-muted)]"}),l.jsxs("div",{className:"min-w-0 flex-1",children:[l.jsxs("div",{className:"flex items-center gap-2",children:[l.jsx("span",{className:"text-sm font-medium text-[var(--color-text)]",children:"Jarvis Relay"}),l.jsx(tS,{size:12,className:"text-[var(--color-text-muted)]"})]}),l.jsx("p",{className:"text-xs text-[var(--color-text-muted)]",children:"Routes OAuth callbacks through a cloud relay for external providers (Google, Spotify, etc.)"})]})]})]})]})}function $4(a){return{core:a.filter(s=>s.category==="core"),recommended:a.filter(s=>s.category==="recommended"),optional:a.filter(s=>s.category==="optional")}}function Pu({title:a,subtitle:s,services:o,enabled:i,nativeServices:d,locked:f,onToggle:m,onToggleNative:v,platform:g}){return l.jsxs("div",{children:[l.jsxs("div",{className:"mb-2 flex items-baseline gap-2",children:[l.jsx("h3",{className:"text-sm font-medium text-[var(--color-text)]",children:a}),l.jsx("span",{className:"text-xs text-[var(--color-text-muted)]",children:s})]}),l.jsx("div",{className:"space-y-1",children:o.map(h=>{const y=i.includes(h.id),x=h.nativeCapable&&g==="darwin"&&y,j=d.includes(h.id);return l.jsxs("div",{className:te("rounded-lg border transition-colors",y?"border-[var(--color-primary)]/30 bg-[var(--color-primary)]/5":"border-[var(--color-border)]",!f&&!y&&"hover:border-[var(--color-primary)]/30"),children:[l.jsxs("button",{type:"button",disabled:f,onClick:()=>m?.(h.id,!y),className:te("flex w-full items-center gap-3 px-3 py-2.5 text-left",f&&"cursor-default"),children:[f?l.jsx(vi,{size:16,className:"shrink-0 text-[var(--color-text-muted)]"}):y?l.jsx(ht,{size:16,className:"shrink-0 text-[var(--color-primary)]"}):l.jsx(os,{size:16,className:"shrink-0 text-[var(--color-text-muted)]"}),l.jsxs("div",{className:"min-w-0 flex-1",children:[l.jsxs("div",{className:"flex items-center gap-2",children:[l.jsx("span",{className:"text-sm font-medium text-[var(--color-text)]",children:h.name}),l.jsxs("span",{className:"text-xs text-[var(--color-text-muted)]",children:[":",h.port]}),h.nativeCapable&&g==="darwin"&&l.jsx("span",{className:"rounded bg-amber-500/10 px-1.5 py-0.5 text-[10px] font-medium text-amber-500",children:"Native"})]}),l.jsx("p",{className:"truncate text-xs text-[var(--color-text-muted)]",children:h.description})]})]}),x&&l.jsxs("button",{type:"button",onClick:()=>v?.(h.id,!j),className:te("flex w-full items-center gap-2 border-t border-[var(--color-border)]/50 px-3 py-2 text-left text-xs","hover:bg-[var(--color-surface-alt)] transition-colors"),children:[l.jsx(On,{size:12,className:j?"text-amber-500":"text-[var(--color-text-muted)]"}),l.jsx("span",{className:j?"text-[var(--color-text)]":"text-[var(--color-text-muted)]",children:"Run natively via LaunchAgent"}),l.jsx("span",{className:"ml-auto text-[var(--color-text-muted)]",children:j?"On (uses Apple GPU)":"Off (runs in Docker)"})]})]},h.id)})})]})}function Z4(){const{state:a}=fr(),[s,o]=N.useState(null);if(N.useEffect(()=>{bg().then(o).catch(()=>{})},[]),!s)return l.jsx("div",{className:"flex items-center justify-center py-12",children:l.jsx(Ct,{size:32,className:"animate-spin text-[var(--color-primary)]"})});const i=s.services.filter(x=>x.category==="core"),d=s.services.filter(x=>x.category!=="core"&&a.enabledModules.includes(x.id)),f=[...i,...d],m=new Map;for(const x of f){const j=a.portOverrides[x.id]??x.port,k=m.get(j)??[];m.set(j,[...k,x.name])}const v=[...m.entries()].filter(([,x])=>x.length>1),g=f.filter(x=>x.database).length,h=f.filter(x=>a.nativeServices.includes(x.id)),y=f.filter(x=>!a.nativeServices.includes(x.id));return l.jsxs("div",{className:"space-y-6",children:[l.jsxs("div",{children:[l.jsx("h2",{className:"text-xl font-bold text-[var(--color-text)]",children:"Review Configuration"}),l.jsx("p",{className:"mt-1 text-sm text-[var(--color-text-muted)]",children:"Review your selections before installing."})]}),l.jsxs("div",{className:"grid grid-cols-3 gap-3",children:[l.jsx(Iu,{label:"Docker Services",value:y.length}),l.jsx(Iu,{label:"Native Services",value:h.length}),l.jsx(Iu,{label:"Databases",value:g})]}),l.jsxs("div",{className:"rounded-lg border border-[var(--color-border)] bg-[var(--color-surface-alt)] p-4",children:[l.jsx("p",{className:"text-xs font-medium uppercase text-[var(--color-text-muted)]",children:"Deployment Mode"}),l.jsx("p",{className:"mt-1 text-sm font-medium text-[var(--color-text)]",children:a.deploymentMode==="local"?"Local (all services on this machine)":"Remote LLM"}),a.deploymentMode==="remote-llm"&&a.remoteLlmUrl&&l.jsxs("p",{className:"mt-0.5 text-xs text-[var(--color-text-muted)]",children:["LLM: ",a.remoteLlmUrl]})]}),l.jsxs("div",{className:"rounded-lg border border-[var(--color-border)] overflow-hidden",children:[l.jsx("div",{className:"border-b border-[var(--color-border)] bg-[var(--color-surface-alt)] px-3 py-2",children:l.jsxs("span",{className:"text-xs font-medium text-[var(--color-text-muted)]",children:["Services (",f.length,")"]})}),l.jsx("div",{className:"divide-y divide-[var(--color-border)]",children:f.map(x=>l.jsxs("div",{className:"flex items-center justify-between px-3 py-2",children:[l.jsxs("div",{className:"flex items-center gap-2",children:[l.jsx(ht,{size:14,className:"text-green-500"}),l.jsx("span",{className:"text-sm text-[var(--color-text)]",children:x.name})]}),l.jsxs("span",{className:"text-xs text-[var(--color-text-muted)]",children:[":",a.portOverrides[x.id]??x.port]})]},x.id))})]}),a.relayEnabled&&l.jsxs("div",{className:"rounded-lg border border-[var(--color-border)] bg-[var(--color-surface-alt)] p-4",children:[l.jsx("p",{className:"text-xs font-medium uppercase text-[var(--color-text-muted)]",children:"Jarvis Relay"}),l.jsx("p",{className:"mt-1 text-sm font-medium text-[var(--color-text)]",children:"Enabled"}),l.jsx("p",{className:"mt-0.5 text-xs text-[var(--color-text-muted)]",children:"https://relay.jarvisautomation.io"})]}),v.length>0&&l.jsxs("div",{className:"rounded-lg border border-amber-500/30 bg-amber-500/5 p-4",children:[l.jsxs("div",{className:"flex items-center gap-2",children:[l.jsx(ra,{size:16,className:"text-amber-500"}),l.jsx("span",{className:"text-sm font-medium text-amber-500",children:"Port Conflicts"})]}),v.map(([x,j])=>l.jsxs("p",{className:"mt-1 text-xs text-[var(--color-text-muted)]",children:["Port ",x,": ",j.join(", ")]},x))]})]})}function Iu({label:a,value:s}){return l.jsxs("div",{className:"rounded-lg border border-[var(--color-border)] bg-[var(--color-surface-alt)] p-3 text-center",children:[l.jsx("p",{className:"text-2xl font-bold text-[var(--color-primary)]",children:s}),l.jsx("p",{className:"text-xs text-[var(--color-text-muted)]",children:a})]})}function Wu(){const[a,s]=N.useState({lines:[],running:!1,done:!1,exitCode:null,error:null,redirect:null}),o=N.useRef(null),i=N.useCallback((f,m)=>(o.current?.close(),s({lines:[],running:!0,done:!1,exitCode:null,error:null,redirect:null}),new Promise((v,g)=>{const h=new EventSource(f);o.current=h,h.onmessage=y=>{try{const x=JSON.parse(y.data);if(m&&m(x),"done"in x){if(s(j=>({...j,running:!1,done:!0,exitCode:x.code,redirect:x.redirect??null})),h.close(),x.code===0)v(x.code);else{const j=x.error?String(x.error):`Process exited with code ${x.code}`;g(new Error(j))}return}if("stream"in x&&"text"in x){const j={stream:x.stream,text:x.text,timestamp:Date.now()};s(k=>({...k,lines:[...k.lines,j]}))}}catch{}},h.onerror=()=>{const y=o.current===null;s(x=>({...x,running:!1,error:x.done?null:"Connection lost"})),h.close(),y||g(new Error("Connection lost"))}})),[]),d=N.useCallback(()=>{o.current?.close(),o.current=null,s(f=>({...f,running:!1}))},[]);return{...a,run:i,stop:d}}function ed({lines:a,running:s,title:o,className:i}){const d=N.useRef(null),f=N.useRef(!0);N.useEffect(()=>{const v=d.current;!v||!f.current||(v.scrollTop=v.scrollHeight)},[a]);function m(){const v=d.current;if(!v)return;const g=v.scrollHeight-v.scrollTop-v.clientHeight;f.current=g<50}return l.jsxs("div",{className:te("flex flex-col rounded-lg border border-[var(--color-border)] overflow-hidden",i),children:[o&&l.jsxs("div",{className:"flex items-center gap-2 border-b border-[var(--color-border)] bg-[var(--color-surface)] px-3 py-2",children:[l.jsx("span",{className:"text-xs font-medium text-[var(--color-text-muted)]",children:o}),s&&l.jsx("span",{className:"h-2 w-2 animate-pulse rounded-full bg-green-500"})]}),l.jsxs("div",{ref:d,onScroll:m,className:"h-64 overflow-y-auto bg-[#0d1117] p-3 font-mono text-xs leading-5",children:[a.length===0&&!s&&l.jsx("span",{className:"text-gray-500",children:"Waiting for output..."}),a.map((v,g)=>l.jsx("div",{className:te("whitespace-pre-wrap break-all",v.stream==="stderr"?"text-yellow-400":"text-gray-300"),children:v.text},g)),s&&l.jsx("span",{className:"inline-block h-4 w-1.5 animate-pulse bg-gray-400"})]})]})}function J4(){const{state:a,dispatch:s}=fr(),o=Wu(),i=Wu(),d=Wu(),[f,m]=N.useState("idle"),[v,g]=N.useState(null),[h,y]=N.useState(null),[x,j]=N.useState({}),[k,w]=N.useState({}),[E,_]=N.useState(null),[A,M]=N.useState(null),[X,I]=N.useState(null),[ne,W]=N.useState({});N.useEffect(()=>{const ae=i.redirect;if(f!=="done"||!ae||a.platform==="darwin")return;M(5);const C=setInterval(()=>{M(Y=>Y===null||Y<=1?(clearInterval(C),window.location.href=ae,0):Y-1)},1e3);return()=>clearInterval(C)},[f,i.redirect]);const G=N.useCallback(async()=>{m("preflight"),y(null),g(null);try{const ae=await kE(a.enabledModules);return y(ae),ae.canProceed?!0:(g("Pre-flight checks failed. Fix the issues above and retry."),m("error"),_("preflight"),!1)}catch(ae){return g(`Pre-flight check failed: ${ae instanceof Error?ae.message:String(ae)}`),m("error"),_("preflight"),!1}},[a.enabledModules]);async function U(){if(a.nativeServices.length!==0){m("native");for(const ae of a.nativeServices){I(ae);try{await d.run(`/api/native-services/${ae}/install`),W(C=>({...C,[ae]:{ok:!0}}))}catch(C){const Y=C instanceof Error?C.message:String(C);W(K=>({...K,[ae]:{ok:!1,error:Y}}))}}I(null)}}async function oe(){g(null),j({}),_(null),W({}),s({type:"SET_INSTALL_RUNNING",running:!0});try{if(!await G()){s({type:"SET_INSTALL_RUNNING",running:!1});return}m("generating"),await Bx(a),m("pulling"),await o.run("/api/install/pull"),m("starting"),await i.run("/api/install/start",C=>{if(C.phase==="health"&&typeof C.service=="string"&&j(Y=>({...Y,[C.service]:{healthy:C.healthy,error:C.error}})),C.serviceHealth&&typeof C.serviceHealth=="object"){const Y=C.serviceHealth;j(K=>({...K,...Y}))}}),await U(),m("done"),s({type:"SET_INSTALL_COMPLETE"})}catch(ae){g(ae instanceof Error?ae.message:String(ae)),m("error"),_(f),s({type:"SET_INSTALL_RUNNING",running:!1})}}async function Ne(){if(E==="preflight"){if(g(null),s({type:"SET_INSTALL_RUNNING",running:!0}),!await G()){s({type:"SET_INSTALL_RUNNING",running:!1});return}try{m("generating"),await Bx(a),m("pulling"),await o.run("/api/install/pull"),m("starting"),await i.run("/api/install/start",C=>{if(C.phase==="health"&&typeof C.service=="string"&&j(Y=>({...Y,[C.service]:{healthy:C.healthy,error:C.error}})),C.serviceHealth&&typeof C.serviceHealth=="object"){const Y=C.serviceHealth;j(K=>({...K,...Y}))}}),await U(),m("done"),s({type:"SET_INSTALL_COMPLETE"})}catch(C){g(C instanceof Error?C.message:String(C)),m("error"),s({type:"SET_INSTALL_RUNNING",running:!1})}}else oe()}async function le(ae){try{const C=await fetch(`/api/containers/${ae}/logs`);if(C.ok){const Y=await C.text();w(K=>({...K,[ae]:Y}))}else w(Y=>({...Y,[ae]:`Failed to fetch logs: HTTP ${C.status}`}))}catch(C){w(Y=>({...Y,[ae]:`Failed to fetch logs: ${C instanceof Error?C.message:String(C)}`}))}}const pe=[{key:"preflight",label:"Pre-flight checks"},{key:"generating",label:"Generate configuration"},{key:"pulling",label:"Pull Docker images"},{key:"starting",label:"Start services"},...a.nativeServices.length>0?[{key:"native",label:`Install ${a.nativeServices.length} native service${a.nativeServices.length===1?"":"s"}`}]:[]],Re=pe.map(ae=>ae.key).indexOf(f);return l.jsxs("div",{className:"space-y-6",children:[l.jsxs("div",{children:[l.jsx("h2",{className:"text-xl font-bold text-[var(--color-text)]",children:"Install"}),l.jsx("p",{className:"mt-1 text-sm text-[var(--color-text-muted)]",children:f==="idle"?"Ready to install. This will pull Docker images and start all services.":f==="done"?i.redirect&&a.platform!=="darwin"?`Installation complete! Redirecting to your admin dashboard in ${A??"..."}s...`:"Installation complete! Click Next to create your account and choose your models.":f==="error"?"Installation encountered an error.":"Installing..."})]}),h&&l.jsxs("div",{className:"rounded-lg border border-[var(--color-border)] overflow-hidden",children:[l.jsx("div",{className:"border-b border-[var(--color-border)] bg-[var(--color-surface-alt)] px-3 py-2",children:l.jsx("span",{className:"text-xs font-medium text-[var(--color-text-muted)]",children:"Pre-flight Checks"})}),l.jsx("div",{className:"divide-y divide-[var(--color-border)]",children:h.checks.map(ae=>l.jsx("div",{className:"flex items-center justify-between px-3 py-2",children:l.jsxs("div",{className:"flex items-center gap-2",children:[ae.status==="pass"?l.jsx(ht,{size:14,className:"text-green-500"}):ae.status==="warn"?l.jsx(ra,{size:14,className:"text-amber-500"}):l.jsx(xl,{size:14,className:"text-red-500"}),l.jsxs("div",{children:[l.jsx("span",{className:"text-sm text-[var(--color-text)]",children:ae.name}),l.jsx("p",{className:"text-xs text-[var(--color-text-muted)]",children:ae.message}),ae.details&&ae.status!=="pass"&&l.jsx("p",{className:"text-xs text-[var(--color-text-muted)] opacity-60",children:ae.details})]})]})},ae.name))})]}),l.jsx("div",{className:"space-y-2",children:pe.map((ae,C)=>{const Y=ae.key===f,K=Re>C||f==="done",xe=f==="error"&&ae.key===E;return l.jsxs("div",{className:"flex items-center gap-3",children:[K?l.jsx(ht,{size:18,className:"text-green-500"}):xe?l.jsx(xl,{size:18,className:"text-red-500"}):Y?l.jsx(Ct,{size:18,className:"animate-spin text-[var(--color-primary)]"}):l.jsx("div",{className:"h-[18px] w-[18px] rounded-full border-2 border-[var(--color-border)]"}),l.jsx("span",{className:te("text-sm",K?"text-green-500":Y?"font-medium text-[var(--color-text)]":"text-[var(--color-text-muted)]"),children:ae.label})]},ae.key)})}),(f==="starting"||f==="done"||f==="error")&&Object.keys(x).length>0&&l.jsxs("div",{className:"rounded-lg border border-[var(--color-border)] overflow-hidden",children:[l.jsx("div",{className:"border-b border-[var(--color-border)] bg-[var(--color-surface-alt)] px-3 py-2",children:l.jsx("span",{className:"text-xs font-medium text-[var(--color-text-muted)]",children:"Service Status"})}),l.jsx("div",{className:"divide-y divide-[var(--color-border)]",children:Object.entries(x).map(([ae,C])=>l.jsxs("div",{children:[l.jsxs("div",{className:"flex items-center justify-between px-3 py-2",children:[l.jsx("span",{className:"text-sm text-[var(--color-text)]",children:ae}),l.jsxs("div",{className:"flex items-center gap-2",children:[!C.healthy&&l.jsxs("button",{type:"button",onClick:()=>le(ae),className:"flex items-center gap-1 text-xs text-[var(--color-text-muted)] hover:text-[var(--color-text)]",children:[l.jsx(tg,{size:12}),"Logs"]}),C.healthy?l.jsx(ht,{size:14,className:"text-green-500"}):l.jsx(xl,{size:14,className:"text-red-500"})]})]}),C.error&&l.jsx("p",{className:"px-3 pb-2 text-xs text-red-400",children:C.error}),k[ae]&&l.jsx("div",{className:"mx-3 mb-2 max-h-32 overflow-auto rounded bg-[var(--color-background)] p-2 text-xs font-mono text-[var(--color-text-muted)]",children:l.jsx("pre",{className:"whitespace-pre-wrap",children:k[ae]})})]},ae))})]}),(o.lines.length>0||o.running)&&l.jsx(ed,{lines:o.lines,running:o.running,title:"docker compose pull"}),(i.lines.length>0||i.running)&&l.jsx(ed,{lines:i.lines,running:i.running,title:"docker compose up -d"}),(f==="native"||Object.keys(ne).length>0)&&l.jsxs("div",{className:"rounded-lg border border-[var(--color-border)] overflow-hidden",children:[l.jsx("div",{className:"border-b border-[var(--color-border)] bg-[var(--color-surface-alt)] px-3 py-2",children:l.jsx("span",{className:"text-xs font-medium text-[var(--color-text-muted)]",children:"Native Services (LaunchAgents)"})}),l.jsx("div",{className:"divide-y divide-[var(--color-border)]",children:a.nativeServices.map(ae=>{const C=ne[ae],Y=X===ae&&f==="native";return l.jsxs("div",{className:"px-3 py-2",children:[l.jsxs("div",{className:"flex items-center justify-between",children:[l.jsx("span",{className:"text-sm text-[var(--color-text)]",children:ae}),C?.ok?l.jsx(ht,{size:14,className:"text-green-500"}):C?l.jsx(xl,{size:14,className:"text-red-500"}):Y?l.jsx(Ct,{size:14,className:"animate-spin text-[var(--color-primary)]"}):l.jsx("div",{className:"h-3 w-3 rounded-full border border-[var(--color-border)]"})]}),C?.error&&l.jsx("p",{className:"mt-1 text-xs text-red-400",children:C.error})]},ae)})})]}),(d.lines.length>0||d.running)&&l.jsx(ed,{lines:d.lines,running:d.running,title:X?`deploy-launchd.sh (${X})`:"deploy-launchd.sh"}),v&&l.jsx("div",{className:"rounded-lg bg-red-500/10 px-3 py-2 text-sm text-red-500",children:v}),(f==="idle"||f==="error")&&l.jsxs("button",{type:"button",onClick:f==="error"?Ne:oe,className:te("flex w-full items-center justify-center gap-2 rounded-lg bg-[var(--color-primary)] px-4 py-3 font-medium text-white","hover:opacity-90 transition-opacity"),children:[f==="error"?l.jsx(gi,{size:18}):l.jsx(ag,{size:18}),f==="error"?"Retry Installation":"Start Installation"]})]})}const P4="jarvis-llm-proxy-api";function I4(){const{state:a,dispatch:s}=fr(),o=yg(),i=wg(),d=jg(),f=a.platform==="darwin",[m,v]=N.useState("select"),[g,h]=N.useState(null),[y,x]=N.useState("GGUF"),[j,k]=N.useState(""),[w,E]=N.useState(!0),[_,A]=N.useState(null);if(a.deploymentMode==="remote-llm")return l.jsxs("div",{className:"space-y-6",children:[l.jsxs("div",{children:[l.jsx("h2",{className:"text-xl font-bold text-[var(--color-text)]",children:"Models"}),l.jsx("p",{className:"mt-1 text-sm text-[var(--color-text-muted)]",children:"Your LLM is configured to use a remote server."})]}),l.jsxs("div",{className:"flex items-center gap-3 rounded-lg border border-green-500/30 bg-green-500/5 p-4",children:[l.jsx(ht,{size:20,className:"text-green-500"}),l.jsxs("div",{children:[l.jsx("p",{className:"text-sm font-medium text-[var(--color-text)]",children:"Remote LLM configured"}),l.jsx("p",{className:"text-xs text-[var(--color-text-muted)]",children:a.remoteLlmUrl})]})]})]});const M=U=>{h(U),A(null),U.gated&&!j.trim()?v("token"):I(U,j.trim())},X=()=>{if(!j.trim()){A("HuggingFace token is required for gated models");return}g&&I(g,j)},I=async(U,oe)=>{A(null),v("downloading");const Ne=y==="GGUF"?U.hfRepoGguf:U.hfRepoVllm,le=y==="GGUF"?U.ggufFilename:void 0;try{await i.mutateAsync({repo:Ne,filename:le,token:oe||void 0})}catch(Ee){A(`Download failed: ${Ee.message}`),v("select");return}if(await ne(U)){if(w){v("whisper");try{await v4(!0)}catch(Ee){console.warn("[models] whisper auto-download setup failed:",Ee)}}v("done")}},ne=async U=>{v("configuring");const Ne={"model.main.name":y==="GGUF"?`.models/${U.ggufFilename}`:`.models/${U.hfRepoVllm.split("/").pop()}`,"model.main.backend":y,"model.main.chat_format":U.chatFormat,"model.main.context_window":U.contextWindow,"llm.interface":U.promptProvider};y==="GGUF"&&(Ne["inference.gguf.n_gpu_layers"]=-1),y==="VLLM"&&U.quantization&&(Ne["inference.vllm.quantization"]=U.quantization);try{if(await o.mutateAsync(Ne),f)try{await d.mutateAsync(P4)}catch(le){console.warn("[models] llm-proxy restart failed (KeepAlive will retry):",le)}return s({type:"SET_LLM_INTERFACE",interfaceId:U.promptProvider}),!0}catch(le){return A(`Configuration failed: ${le.message}`),v("select"),!1}},W=a.hardware?.gpuVramMb,G=W?ss.filter(U=>U.vramMb<=W):ss;return l.jsxs("div",{className:"space-y-6",children:[l.jsxs("div",{children:[l.jsx("h2",{className:"text-xl font-bold text-[var(--color-text)]",children:"Models"}),l.jsx("p",{className:"mt-1 text-sm text-[var(--color-text-muted)]",children:m==="done"?"Models configured. Services are restarting to load them.":"Choose a language model, and optionally fetch the speech-to-text model."})]}),_&&l.jsxs("div",{className:"space-y-2",children:[l.jsxs("div",{className:"flex items-start gap-2 rounded-lg border border-red-500/30 bg-red-500/10 p-3 text-sm text-red-500",children:[l.jsx(ra,{size:16,className:"mt-0.5 shrink-0"}),_]}),g&&l.jsxs("button",{type:"button",onClick:()=>I(g,j),className:te("flex w-full items-center justify-center gap-2 rounded-lg border border-[var(--color-border)] px-4 py-2 text-sm","hover:bg-[var(--color-surface-alt)] transition-colors"),children:[l.jsx(gi,{size:14}),"Retry"]})]}),m==="select"&&l.jsxs(l.Fragment,{children:[!f&&l.jsxs("div",{className:"flex items-center justify-between",children:[l.jsx("span",{className:"text-sm font-medium text-[var(--color-text)]",children:"Backend"}),l.jsx("div",{className:"flex gap-2",children:["GGUF","VLLM"].map(U=>l.jsx("button",{type:"button",onClick:()=>x(U),className:te("rounded-md px-3 py-1 text-xs font-medium transition-colors",y===U?"bg-[var(--color-primary)] text-white":"bg-[var(--color-surface-alt)] text-[var(--color-text-muted)] hover:text-[var(--color-text)]"),children:U==="VLLM"?"vLLM":U},U))})]}),l.jsxs("label",{className:te("flex cursor-pointer items-start gap-3 rounded-lg border p-3 transition-colors",w?"border-[var(--color-primary)] bg-[var(--color-primary)]/5":"border-[var(--color-border)]"),children:[l.jsx("input",{type:"checkbox",checked:w,onChange:U=>E(U.target.checked),className:"mt-0.5"}),l.jsxs("span",{className:"flex items-center gap-2 text-sm text-[var(--color-text)]",children:[l.jsx(kx,{size:15,className:"shrink-0 text-[var(--color-primary)]"}),l.jsxs("span",{children:["Auto-download the speech-to-text model",l.jsxs("span",{className:"block text-xs text-[var(--color-text-muted)]",children:["Whisper ",l.jsx("code",{children:"base.en"})," (~150 MB, no token needed). Required for voice."]})]})]})]}),l.jsxs("div",{children:[l.jsx("label",{htmlFor:"hf-token",className:"mb-1 block text-xs text-[var(--color-text-muted)]",children:"HuggingFace Token (optional — speeds up downloads, required for gated models)"}),l.jsx("input",{id:"hf-token",type:"password",value:j,onChange:U=>k(U.target.value),placeholder:"hf_...",className:te("w-full rounded-lg border border-[var(--color-border)] bg-[var(--color-surface-alt)] px-3 py-2","text-sm text-[var(--color-text)] placeholder:text-[var(--color-text-muted)]","outline-none focus:ring-2 focus:ring-[var(--color-primary)]")})]}),l.jsxs("div",{className:"space-y-2",children:[l.jsx("span",{className:"text-sm font-medium text-[var(--color-text)]",children:"Language model"}),G.map(U=>l.jsxs("button",{type:"button",onClick:()=>M(U),className:te("flex w-full items-center justify-between rounded-lg border border-[var(--color-border)] p-3 text-left transition-colors","hover:border-[var(--color-primary)] hover:bg-[var(--color-surface-alt)]"),children:[l.jsxs("div",{children:[l.jsxs("div",{className:"flex items-center gap-2",children:[l.jsx("span",{className:"text-sm font-medium text-[var(--color-text)]",children:U.displayName}),U.gated&&l.jsxs("span",{className:"flex items-center gap-0.5 rounded bg-yellow-500/15 px-1.5 py-0.5 text-[10px] font-medium text-yellow-600 dark:text-yellow-400",children:[l.jsx(vi,{size:10}),"Gated"]})]}),l.jsxs("p",{className:"mt-0.5 text-xs text-[var(--color-text-muted)]",children:[U.promptProvider," · ",U.contextWindow.toLocaleString()," ctx"]})]}),l.jsxs("span",{className:"text-xs text-[var(--color-text-muted)]",children:["~",y==="GGUF"?U.sizeGguf:U.sizeVllm]})]},U.id)),G.length===0&&l.jsxs("p",{className:"py-4 text-center text-sm text-[var(--color-text-muted)]",children:["No models fit your available memory (",W?Math.round(W/1024)+" GB":"unknown",")."]}),W&&G.length<ss.length&&l.jsxs("p",{className:"text-xs text-[var(--color-text-muted)]",children:["Showing ",G.length," of ",ss.length," models that fit your ",Math.round(W/1024)," GB."]})]})]}),m==="token"&&g&&l.jsxs("div",{className:"space-y-4",children:[l.jsxs("p",{className:"text-sm text-[var(--color-text-muted)]",children:[l.jsx("strong",{children:g.displayName})," is a gated model. Accept the license on HuggingFace and paste your access token below."]}),l.jsx("input",{type:"password",value:j,onChange:U=>k(U.target.value),placeholder:"hf_...",className:te("w-full rounded-lg border border-[var(--color-border)] bg-[var(--color-surface-alt)] px-3 py-2","text-sm text-[var(--color-text)] placeholder:text-[var(--color-text-muted)]","outline-none focus:ring-2 focus:ring-[var(--color-primary)]")}),l.jsxs("div",{className:"flex justify-between",children:[l.jsx("button",{type:"button",onClick:()=>{v("select"),A(null)},className:"text-sm text-[var(--color-text-muted)] hover:text-[var(--color-text)]",children:"Back"}),l.jsx("button",{type:"button",onClick:X,className:"rounded-lg bg-[var(--color-primary)] px-4 py-2 text-sm text-white hover:opacity-90",children:"Download"})]})]}),m==="whisper"&&l.jsxs("div",{className:"flex flex-col items-center py-8",children:[l.jsx(kx,{className:"mb-4 animate-pulse text-[var(--color-primary)]",size:32}),l.jsx("p",{className:"text-sm font-medium text-[var(--color-text)]",children:"Enabling speech-to-text model download..."}),l.jsx("p",{className:"mt-1 text-xs text-[var(--color-text-muted)]",children:"Whisper will fetch ggml-base.en on restart"})]}),m==="downloading"&&l.jsxs("div",{className:"flex flex-col items-center py-8",children:[l.jsx(en,{className:"mb-4 animate-bounce text-[var(--color-primary)]",size:32}),l.jsxs("p",{className:"text-sm font-medium text-[var(--color-text)]",children:["Downloading ",g?.displayName,"..."]}),l.jsxs("p",{className:"mt-1 text-xs text-[var(--color-text-muted)]",children:["~",y==="GGUF"?g?.sizeGguf:g?.sizeVllm," · This may take several minutes"]})]}),m==="configuring"&&l.jsxs("div",{className:"flex flex-col items-center py-8",children:[l.jsx(Ct,{className:"mb-4 animate-spin text-[var(--color-primary)]",size:32}),l.jsx("p",{className:"text-sm font-medium text-[var(--color-text)]",children:"Configuring model and prompt provider..."})]}),m==="done"&&g&&l.jsxs("div",{className:"space-y-4",children:[l.jsxs("div",{className:"flex items-center gap-3 rounded-lg border border-green-500/30 bg-green-500/5 p-4",children:[l.jsx(ht,{size:20,className:"text-green-500"}),l.jsxs("div",{children:[l.jsxs("p",{className:"text-sm font-medium text-[var(--color-text)]",children:[g.displayName," configured"]}),l.jsxs("p",{className:"text-xs text-[var(--color-text-muted)]",children:["Backend: ",y," · Prompt provider: ",g.promptProvider,w&&" · Whisper auto-download enabled"]})]})]}),l.jsxs("p",{className:"text-xs text-[var(--color-text-muted)]",children:["The LLM proxy is restarting with the new model",w&&", and whisper is fetching its model",". This may take a few minutes to finish loading. Command Center will use the"," ",l.jsx("strong",{children:g.promptProvider})," prompt provider."]})]})]})}function W4(){const[a,s]=N.useState(""),[o,i]=N.useState(""),[d,f]=N.useState(""),[m,v]=N.useState(""),[g,h]=N.useState(!1),[y,x]=N.useState(!1),[j,k]=N.useState(null),w=o===d,E=a&&o&&d&&m&&w&&!g;async function _(){if(E){h(!0),k(null);try{const M=await Jv(a,o,m);rs(M.access_token),localStorage.setItem("access_token",M.access_token),localStorage.setItem("refresh_token",M.refresh_token),x(!0)}catch(M){const X=M?.response?.data?.error??(M instanceof Error?M.message:"Failed to create account");k(X)}finally{h(!1)}}}if(y)return l.jsxs("div",{className:"space-y-6",children:[l.jsx("div",{children:l.jsx("h2",{className:"text-xl font-bold text-[var(--color-text)]",children:"Account Created"})}),l.jsxs("div",{className:"flex items-center gap-3 rounded-lg border border-green-500/30 bg-green-500/5 p-4",children:[l.jsx(ht,{size:20,className:"text-green-500"}),l.jsxs("div",{children:[l.jsx("p",{className:"text-sm font-medium text-[var(--color-text)]",children:"Superuser account created"}),l.jsx("p",{className:"text-xs text-[var(--color-text-muted)]",children:a})]})]}),l.jsx("p",{className:"text-sm text-[var(--color-text-muted)]",children:`You're logged in. Click "Next" to configure your LLM model.`})]});const A=te("w-full rounded-lg border border-[var(--color-border)] bg-[var(--color-surface-alt)] px-3 py-2","text-sm text-[var(--color-text)] placeholder:text-[var(--color-text-muted)]","outline-none focus:ring-2 focus:ring-[var(--color-primary)]");return l.jsxs("div",{className:"space-y-6",children:[l.jsxs("div",{children:[l.jsx("h2",{className:"text-xl font-bold text-[var(--color-text)]",children:"Create Account"}),l.jsx("p",{className:"mt-1 text-sm text-[var(--color-text-muted)]",children:"Create your superuser account. This will be the admin for your Jarvis instance."})]}),l.jsxs("div",{className:"space-y-4",children:[l.jsxs("div",{children:[l.jsx("label",{htmlFor:"display-name",className:"mb-1 block text-sm text-[var(--color-text-muted)]",children:"Display Name"}),l.jsx("input",{id:"display-name",type:"text",value:m,onChange:M=>v(M.target.value),className:A,placeholder:"Alex"})]}),l.jsxs("div",{children:[l.jsx("label",{htmlFor:"email",className:"mb-1 block text-sm text-[var(--color-text-muted)]",children:"Email"}),l.jsx("input",{id:"email",type:"email",value:a,onChange:M=>s(M.target.value),className:A,placeholder:"admin@example.com"})]}),l.jsxs("div",{children:[l.jsx("label",{htmlFor:"password",className:"mb-1 block text-sm text-[var(--color-text-muted)]",children:"Password"}),l.jsx("input",{id:"password",type:"password",value:o,onChange:M=>i(M.target.value),className:A,placeholder:"Choose a strong password"})]}),l.jsxs("div",{children:[l.jsx("label",{htmlFor:"confirm-password",className:"mb-1 block text-sm text-[var(--color-text-muted)]",children:"Confirm Password"}),l.jsx("input",{id:"confirm-password",type:"password",value:d,onChange:M=>f(M.target.value),className:te(A,d&&!w&&"ring-2 ring-red-500"),placeholder:"Confirm password"}),d&&!w&&l.jsx("p",{className:"mt-1 text-xs text-red-500",children:"Passwords don't match"})]})]}),j&&l.jsxs("div",{className:"space-y-2",children:[l.jsxs("div",{className:"flex items-center gap-2 rounded-lg bg-red-500/10 px-3 py-2",children:[l.jsx(Bd,{size:14,className:"text-red-500 shrink-0"}),l.jsx("span",{className:"text-sm text-red-500",children:j})]}),l.jsxs("button",{type:"button",onClick:_,disabled:!E,className:te("flex w-full items-center justify-center gap-2 rounded-lg border border-[var(--color-border)] px-4 py-2 text-sm","hover:bg-[var(--color-surface-alt)] transition-colors","disabled:opacity-50"),children:[l.jsx(gi,{size:14}),"Retry"]})]}),!j&&l.jsx("button",{type:"button",onClick:_,disabled:!E,className:te("w-full rounded-lg bg-[var(--color-primary)] px-4 py-2 font-medium text-white","hover:opacity-90 disabled:opacity-50 transition-opacity"),children:g?"Creating...":"Create Superuser Account"})]})}const Zo=[{label:"Welcome",component:Y4},{label:"Hardware",component:X4},{label:"Services",component:K4},{label:"Review",component:Z4},{label:"Install",component:J4},{label:"Account",component:W4},{label:"Models",component:I4}],e3=5;function t3({skipToAccount:a}){const{state:s,dispatch:o}=fr();N.useEffect(()=>{a&&o({type:"SET_STEP",step:e3})},[a,o]);const i=wa(),d=Zo[s.currentStep].component,f=s.currentStep===0,m=s.currentStep===Zo.length-1,h=s.currentStep===4&&!s.installComplete,y=s.installRunning||h;function x(){m?i("/login"):o({type:"NEXT_STEP"})}function j(){o({type:"PREV_STEP"})}return l.jsx("div",{className:"flex min-h-screen items-center justify-center bg-[var(--color-background)] p-4",children:l.jsxs("div",{className:"w-full max-w-2xl",children:[l.jsx("div",{className:"mb-6 flex items-center justify-center gap-1",children:Zo.map((k,w)=>l.jsxs("button",{type:"button",onClick:()=>!y&&o({type:"SET_STEP",step:w}),disabled:y,className:te("flex items-center gap-1",y&&"cursor-not-allowed"),children:[l.jsx("div",{className:te("flex h-7 w-7 items-center justify-center rounded-full text-xs font-medium transition-colors",w===s.currentStep?"bg-[var(--color-primary)] text-white":w<s.currentStep?"bg-[var(--color-primary)]/20 text-[var(--color-primary)]":"bg-[var(--color-surface-alt)] text-[var(--color-text-muted)]"),children:w+1}),l.jsx("span",{className:te("hidden text-xs sm:inline",w===s.currentStep?"font-medium text-[var(--color-text)]":"text-[var(--color-text-muted)]"),children:k.label}),w<Zo.length-1&&l.jsx("div",{className:te("mx-1 h-px w-4 sm:w-6",w<s.currentStep?"bg-[var(--color-primary)]/30":"bg-[var(--color-border)]")})]},k.label))}),l.jsx("div",{className:"rounded-xl border border-[var(--color-border)] bg-[var(--color-surface)] p-6 shadow-lg",children:l.jsx(d,{})}),l.jsxs("div",{className:"mt-4 flex justify-between",children:[l.jsx("button",{type:"button",onClick:j,disabled:f||y,className:te("rounded-lg border border-[var(--color-border)] px-4 py-2 text-sm","hover:bg-[var(--color-surface-alt)] transition-colors","disabled:invisible"),children:"Back"}),l.jsx("button",{type:"button",onClick:x,disabled:y,className:te("rounded-lg bg-[var(--color-primary)] px-6 py-2 text-sm font-medium text-white","hover:opacity-90 transition-opacity","disabled:opacity-50 disabled:cursor-not-allowed"),children:m?"Finish":"Next"})]})]})})}function a3({skipToAccount:a}){return l.jsx(F4,{children:l.jsx(t3,{skipToAccount:a})})}function n3(){const a=wa(),s=yg(),o=RE(),[i,d]=N.useState("select"),[f,m]=N.useState(null),[v,g]=N.useState("GGUF"),[h,y]=N.useState(""),[x,j]=N.useState(null),k=M=>{m(M),M.gated?d("token"):E(M,"")},w=()=>{if(!h.trim()){j("HuggingFace token is required for gated models");return}j(null),f&&E(f,h)},E=async(M,X)=>{d("download"),j(null);const I=v==="GGUF"?M.hfRepoGguf:M.hfRepoVllm,ne=v==="GGUF"?M.ggufFilename:void 0;try{await o.mutateAsync({repo:I,filename:ne,token:X||void 0}),_(M)}catch(W){j(`Download failed: ${W.message}`),d("select")}},_=async M=>{d("configure"),j(null);const I={"model.main.name":v==="GGUF"?`.models/${M.ggufFilename}`:`.models/${M.hfRepoVllm.split("/").pop()}`,"model.main.backend":v,"model.main.chat_format":M.chatFormat,"model.main.context_window":M.contextWindow};v==="GGUF"&&(I["inference.gguf.n_gpu_layers"]=-1),v==="VLLM"&&M.quantization&&(I["inference.vllm.quantization"]=M.quantization);try{await s.mutateAsync(I),d("done"),Me.success("LLM configured successfully")}catch(ne){j(`Configuration failed: ${ne.message}`),d("select")}},A=()=>{a("/dashboard")};return l.jsx("div",{className:"flex min-h-screen items-center justify-center bg-[var(--color-bg)] p-4",children:l.jsxs("div",{className:"w-full max-w-2xl rounded-xl border border-[var(--color-border)] bg-[var(--color-surface)] p-8 shadow-lg",children:[l.jsxs("div",{className:"mb-8 text-center",children:[l.jsx(pd,{className:"mx-auto mb-3 text-[var(--color-primary)]",size:40}),l.jsx("h1",{className:"text-2xl font-bold text-[var(--color-text)]",children:"LLM Setup"}),l.jsx("p",{className:"mt-1 text-sm text-[var(--color-text-muted)]",children:"Configure a local language model for Jarvis"})]}),l.jsx("div",{className:"mb-8 flex items-center justify-center gap-2",children:["select","download","configure","done"].map((M,X)=>{const I=i==="token"?"select":i,ne=["select","download","configure","done"];return l.jsxs("div",{className:"flex items-center gap-2",children:[l.jsx("div",{className:te("h-2 w-2 rounded-full",I===M?"bg-[var(--color-primary)]":ne.indexOf(I)>X?"bg-green-500":"bg-[var(--color-border)]")}),X<3&&l.jsx("div",{className:"h-px w-8 bg-[var(--color-border)]"})]},M)})}),x&&l.jsxs("div",{className:"mb-6 flex items-start gap-2 rounded-lg border border-red-500/30 bg-red-500/10 p-3 text-sm text-red-500",children:[l.jsx(ra,{size:16,className:"mt-0.5 shrink-0"}),x]}),i==="select"&&l.jsxs("div",{className:"space-y-4",children:[l.jsxs("div",{className:"mb-4 flex items-center justify-between",children:[l.jsx("h2",{className:"text-sm font-semibold text-[var(--color-text)]",children:"Select a model"}),l.jsxs("div",{className:"flex gap-2",children:[l.jsx("button",{onClick:()=>g("GGUF"),className:te("rounded-md px-3 py-1 text-xs font-medium transition-colors",v==="GGUF"?"bg-[var(--color-primary)] text-white":"bg-[var(--color-surface-alt)] text-[var(--color-text-muted)] hover:text-[var(--color-text)]"),children:"GGUF"}),l.jsx("button",{onClick:()=>g("VLLM"),className:te("rounded-md px-3 py-1 text-xs font-medium transition-colors",v==="VLLM"?"bg-[var(--color-primary)] text-white":"bg-[var(--color-surface-alt)] text-[var(--color-text-muted)] hover:text-[var(--color-text)]"),children:"vLLM"})]})]}),l.jsx("div",{className:"grid gap-3",children:ss.map(M=>l.jsxs("button",{onClick:()=>k(M),className:te("flex items-center justify-between rounded-lg border border-[var(--color-border)] p-4 text-left transition-colors","hover:border-[var(--color-primary)] hover:bg-[var(--color-surface-alt)]"),children:[l.jsxs("div",{children:[l.jsxs("div",{className:"flex items-center gap-2",children:[l.jsx("span",{className:"font-medium text-[var(--color-text)]",children:M.displayName}),M.gated&&l.jsxs("span",{className:"flex items-center gap-1 rounded bg-yellow-500/15 px-1.5 py-0.5 text-[10px] font-medium text-yellow-600 dark:text-yellow-400",children:[l.jsx(vi,{size:10}),"Gated"]})]}),l.jsxs("p",{className:"mt-0.5 text-xs text-[var(--color-text-muted)]",children:[M.quantization?`${M.quantization.toUpperCase()} 4-bit`:M.chatFormat," · ",M.contextWindow.toLocaleString()," ctx"]})]}),l.jsxs("span",{className:"text-sm text-[var(--color-text-muted)]",children:["~",v==="GGUF"?M.sizeGguf:M.sizeVllm]})]},M.id))}),l.jsx("div",{className:"flex justify-end pt-2",children:l.jsx("button",{onClick:A,className:"text-sm text-[var(--color-text-muted)] hover:text-[var(--color-text)]",children:"Skip for now"})})]}),i==="token"&&f&&l.jsxs("div",{className:"space-y-4",children:[l.jsx("h2",{className:"text-sm font-semibold text-[var(--color-text)]",children:"HuggingFace Access Required"}),l.jsxs("p",{className:"text-sm text-[var(--color-text-muted)]",children:[l.jsx("strong",{children:f.displayName})," is a gated model. You need to:"]}),l.jsxs("ol",{className:"list-inside list-decimal space-y-1 text-sm text-[var(--color-text-muted)]",children:[l.jsx("li",{children:"Visit the model page on huggingface.co and accept the license agreement"}),l.jsx("li",{children:"Create an access token at huggingface.co/settings/tokens"}),l.jsx("li",{children:"Paste your token below"})]}),l.jsx("input",{type:"password",value:h,onChange:M=>y(M.target.value),placeholder:"hf_...",className:te("w-full rounded-lg border border-[var(--color-border)] bg-[var(--color-bg)] px-3 py-2","text-sm text-[var(--color-text)] placeholder:text-[var(--color-text-muted)]","outline-none focus:ring-2 focus:ring-[var(--color-primary)]")}),l.jsxs("div",{className:"flex justify-between",children:[l.jsx("button",{onClick:()=>{d("select"),j(null)},className:"text-sm text-[var(--color-text-muted)] hover:text-[var(--color-text)]",children:"Back"}),l.jsx("button",{onClick:w,className:"rounded-lg bg-[var(--color-primary)] px-4 py-2 text-sm text-white hover:opacity-90",children:"Continue"})]})]}),i==="download"&&l.jsxs("div",{className:"flex flex-col items-center py-8",children:[l.jsx(en,{className:"mb-4 animate-bounce text-[var(--color-primary)]",size:32}),l.jsx("h2",{className:"text-lg font-semibold text-[var(--color-text)]",children:"Downloading model..."}),l.jsxs("p",{className:"mt-1 text-sm text-[var(--color-text-muted)]",children:[f?.displayName," ","(~",v==="GGUF"?f?.sizeGguf:f?.sizeVllm,")"]}),l.jsx("p",{className:"mt-4 text-xs text-[var(--color-text-muted)]",children:"This may take several minutes depending on your connection"})]}),i==="configure"&&l.jsxs("div",{className:"flex flex-col items-center py-8",children:[l.jsx(ng,{className:"mb-4 animate-spin text-[var(--color-primary)]",size:32}),l.jsx("h2",{className:"text-lg font-semibold text-[var(--color-text)]",children:"Configuring..."}),l.jsx("p",{className:"mt-1 text-sm text-[var(--color-text-muted)]",children:"Writing settings and restarting LLM proxy"})]}),i==="done"&&l.jsxs("div",{className:"flex flex-col items-center py-8",children:[l.jsx(qj,{className:"mb-4 text-green-500",size:40}),l.jsx("h2",{className:"text-lg font-semibold text-[var(--color-text)]",children:"LLM Ready"}),l.jsxs("p",{className:"mt-1 text-sm text-[var(--color-text-muted)]",children:[f?.displayName," configured on ",v]}),l.jsx("p",{className:"mt-1 text-xs text-[var(--color-text-muted)]",children:"The model service is restarting. It may take a minute to load the model."}),l.jsx("button",{onClick:()=>a("/dashboard"),className:"mt-6 rounded-lg bg-[var(--color-primary)] px-6 py-2 text-sm text-white hover:opacity-90",children:"Go to Dashboard"})]}),(o.isPending||s.isPending)&&i!=="download"&&i!=="configure"&&l.jsx("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/40",children:l.jsx(Ct,{className:"animate-spin text-white",size:32})})]})})}const r3=new J1;function s3(){const[a,s]=N.useState(!0),[o,i]=N.useState(!1),[d,f]=N.useState(!1);return N.useEffect(()=>{Yd().then(m=>{m.state==="deployed-needs-account"?(f(!0),i(!0)):i(!m.configured)}).catch(()=>{i(!1)}).finally(()=>s(!1))},[]),a?l.jsx("div",{className:"flex min-h-screen items-center justify-center bg-[var(--color-background)]",children:l.jsx("div",{className:"h-8 w-8 animate-spin rounded-full border-4 border-[var(--color-primary)] border-t-transparent"})}):l.jsxs(X0,{children:[l.jsx(ft,{path:"/setup",element:l.jsx(a3,{skipToAccount:d})}),l.jsx(ft,{path:"/login",element:l.jsx($w,{})}),l.jsx(ft,{path:"/llm-setup",element:l.jsx(n3,{})}),l.jsxs(ft,{element:l.jsx(Kw,{}),children:[l.jsx(ft,{path:"/dashboard",element:l.jsx(UE,{})}),l.jsx(ft,{path:"/settings",element:l.jsx(oE,{})}),l.jsx(ft,{path:"/services",element:l.jsx(SE,{})}),l.jsx(ft,{path:"/models",element:l.jsx(y4,{})}),l.jsx(ft,{path:"/quick-sets",element:l.jsx(_4,{})}),l.jsx(ft,{path:"/traces",element:l.jsx(U4,{})}),l.jsx(ft,{path:"/traces/:id",element:l.jsx(B4,{})}),l.jsx(ft,{path:"/update",element:l.jsx(R4,{})}),l.jsx(ft,{path:"/reconcile",element:l.jsx(M4,{})}),l.jsx(ft,{path:"/nodes",element:l.jsx(YE,{})}),l.jsx(ft,{path:"/users",element:l.jsx(t4,{})}),l.jsx(ft,{path:"/native-services",element:l.jsx(d4,{})}),l.jsx(ft,{path:"/",element:o?l.jsx(ni,{to:"/setup",replace:!0}):l.jsx(ni,{to:"/dashboard",replace:!0})}),l.jsx(ft,{path:"*",element:l.jsx(q4,{})})]})]})}function l3(){return l.jsx(L2,{children:l.jsx(P1,{client:r3,children:l.jsxs(bj,{children:[l.jsx(x1,{children:l.jsx(s3,{})}),l.jsx(D2,{position:"bottom-right",richColors:!0})]})})})}Yb.createRoot(document.getElementById("root")).render(l.jsx(N.StrictMode,{children:l.jsx(l3,{})}));
|
|
18
|
+
`);Z=ce.pop()??"";for(const je of ce)if(je.startsWith("data: "))try{const L=JSON.parse(je.slice(6));if(L.phase&&i(L.phase),L.message&&Ee({text:L.message,phase:L.phase}),L.stream&&L.text&&Ee({text:L.text.trim()}),L.done&&L.code!==0)throw new Error(L.message??"Reconcile failed")}catch(L){if(L instanceof SyntaxError)continue;throw L}}}catch(S){const D=S instanceof Error?S.message:String(S);v(D),i("error"),Ee({text:`Error: ${D}`})}}function C(){return{enabledModules:h.filter(ee=>ee.enabled).map(ee=>ee.id),relayEnabled:x,relayUrl:k,whisperModelPath:E,whisperBackend:A,ttsBackend:X,pinImages:ne,releaseTrack:G}}async function Y(ee){pe(!0),v(null),Ne(null);try{const{latest:S,...D}=ee??{},Z=await fetch(`/api/install/regenerate-download${S?"?latest=true":""}`,{method:"POST",headers:{Authorization:`Bearer ${s}`,"Content-Type":"application/json"},body:JSON.stringify({...C(),...D})});if(!Z.ok){const fe=await Z.text();throw new Error(fe||`HTTP ${Z.status}`)}const re=await Z.json();Ne({compose:re.compose,env:re.env,initDb:re.initDb})}catch(S){v(S instanceof Error?S.message:String(S))}finally{pe(!1)}}function K(ee,S){const D=new Blob([S],{type:"text/plain;charset=utf-8"}),Q=URL.createObjectURL(D),Z=document.createElement("a");Z.href=Q,Z.download=ee,document.body.appendChild(Z),Z.click(),Z.remove(),URL.revokeObjectURL(Q)}const xe=Object.keys(Ju).filter(ee=>{const S=Object.keys(Ju),D=S.indexOf(o);return S.indexOf(ee)<D||o==="done"&&ee==="done"});return l.jsxs("div",{className:"mx-auto max-w-3xl space-y-6 p-6",children:[l.jsxs("div",{children:[l.jsx("h1",{className:"text-2xl font-bold text-[var(--color-text)]",children:"Sync Compose"}),l.jsxs("p",{className:"mt-1 text-sm text-[var(--color-text-muted)]",children:["Regenerate ",l.jsx("code",{className:"rounded bg-[var(--color-surface)] px-1.5 py-0.5 text-xs",children:"docker-compose.yml"})," from the latest service registry, preserving your secrets. ",l.jsx("strong",{className:"text-[var(--color-text)]",children:"Sync now"})," applies it to the running stack;",l.jsx("strong",{className:"text-[var(--color-text)]",children:" Download"})," hands you the files to review and apply by hand (",l.jsx("code",{className:"rounded bg-[var(--color-surface)] px-1 text-xs",children:"docker compose up -d"}),")."," ",l.jsx("strong",{className:"text-[var(--color-text)]",children:"Update stack to latest"})," downloads the same, pinned to the newest published images."]})]}),o==="loading_options"&&l.jsx("div",{className:"flex items-center justify-center py-12",children:l.jsx(Ct,{size:32,className:"animate-spin text-[var(--color-primary)]"})}),o==="options"&&l.jsxs("div",{className:"space-y-4",children:[l.jsxs("div",{className:"rounded-lg border border-[var(--color-border)] bg-[var(--color-surface)] p-4",children:[l.jsx("h2",{className:"mb-3 text-sm font-semibold text-[var(--color-text)]",children:"Services"}),l.jsx("div",{className:"space-y-2",children:h.map(ee=>l.jsxs("button",{onClick:()=>Re(ee.id),className:"flex w-full items-center gap-3 rounded-lg px-3 py-2 text-left hover:bg-[var(--color-bg-secondary)] transition-colors",children:[ee.enabled?l.jsx(ht,{size:18,className:"shrink-0 text-[var(--color-primary)]"}):l.jsx(os,{size:18,className:"shrink-0 text-[var(--color-text-muted)]"}),l.jsxs("div",{className:"min-w-0",children:[l.jsx("div",{className:"text-sm font-medium text-[var(--color-text)]",children:ee.name}),l.jsx("div",{className:"text-xs text-[var(--color-text-muted)]",children:ee.description})]})]},ee.id))})]}),l.jsxs("div",{className:"rounded-lg border border-[var(--color-border)] bg-[var(--color-surface)] p-4",children:[l.jsx("h2",{className:"mb-3 text-sm font-semibold text-[var(--color-text)]",children:"Release Track"}),l.jsxs("div",{className:"flex items-center justify-between px-3 py-2",children:[l.jsxs("div",{children:[l.jsx("div",{className:"text-sm font-medium text-[var(--color-text)]",children:G==="dev"?"Dev":"Stable"}),l.jsx("div",{className:"text-xs text-[var(--color-text-muted)]",children:G==="dev"?"Using latest main branch builds (may be unstable)":"Using tagged releases"})]}),l.jsx("button",{type:"button",role:"switch","aria-checked":G==="dev",onClick:()=>U(G==="dev"?"stable":"dev"),className:`relative h-6 w-11 shrink-0 rounded-full transition-colors ${G==="dev"?"bg-amber-500":"bg-[var(--color-surface-alt)]"}`,children:l.jsx("span",{className:`absolute left-0.5 top-0.5 h-5 w-5 rounded-full bg-white transition-transform ${G==="dev"?"translate-x-5":"translate-x-0"}`})})]}),G==="dev"&&l.jsx("div",{className:"mx-3 mt-1 rounded-lg border border-amber-300 bg-amber-500/10 px-3 py-2 text-xs text-amber-400",children:"Switching tracks will pull all images and force-recreate containers."})]}),l.jsxs("div",{className:"rounded-lg border border-[var(--color-border)] bg-[var(--color-surface)] p-4",children:[l.jsx("h2",{className:"mb-3 text-sm font-semibold text-[var(--color-text)]",children:"Integrations"}),l.jsxs("button",{onClick:()=>j(!x),className:"flex w-full items-center gap-3 rounded-lg px-3 py-2 text-left hover:bg-[var(--color-bg-secondary)] transition-colors",children:[x?l.jsx(ht,{size:18,className:"shrink-0 text-[var(--color-primary)]"}):l.jsx(os,{size:18,className:"shrink-0 text-[var(--color-text-muted)]"}),l.jsxs("div",{className:"min-w-0",children:[l.jsx("div",{className:"text-sm font-medium text-[var(--color-text)]",children:"Jarvis Relay"}),l.jsx("div",{className:"text-xs text-[var(--color-text-muted)]",children:"Routes OAuth callbacks through a cloud relay for external providers (Google, Spotify, etc.)"})]})]}),x&&l.jsxs("div",{className:"mt-2 px-3",children:[l.jsx("label",{className:"text-xs font-medium text-[var(--color-text-muted)]",children:"Relay URL"}),l.jsx("input",{type:"url",value:k,onChange:ee=>w(ee.target.value),placeholder:"https://relay.jarvisautomation.io",className:"mt-1 w-full rounded-md border border-[var(--color-border)] bg-[var(--color-bg)] px-3 py-1.5 text-sm text-[var(--color-text)] placeholder:text-[var(--color-text-muted)]"})]})]}),h.some(ee=>ee.id==="jarvis-whisper-api"&&ee.enabled)&&l.jsxs("div",{className:"rounded-lg border border-[var(--color-border)] bg-[var(--color-surface)] p-4",children:[l.jsx("h2",{className:"mb-3 text-sm font-semibold text-[var(--color-text)]",children:"Whisper"}),l.jsxs("div",{className:"px-3",children:[l.jsx("label",{className:"text-xs font-medium text-[var(--color-text-muted)]",children:"Model path"}),l.jsx("input",{type:"text",value:E,onChange:ee=>_(ee.target.value),placeholder:"/whisper-models/ggml-base.en.bin",className:"mt-1 w-full rounded-md border border-[var(--color-border)] bg-[var(--color-bg)] px-3 py-1.5 text-sm font-mono text-[var(--color-text)] placeholder:text-[var(--color-text-muted)]"}),l.jsxs("p",{className:"mt-1 text-xs text-[var(--color-text-muted)]",children:["Path inside the container. Place model files in ",l.jsx("code",{className:"rounded bg-[var(--color-bg)] px-1",children:"./whisper-models/"})," next to your compose file."]}),l.jsx("label",{className:"mt-3 block text-xs font-medium text-[var(--color-text-muted)]",children:"GPU backend"}),l.jsxs("select",{value:A,onChange:ee=>M(ee.target.value),className:"mt-1 w-full rounded-md border border-[var(--color-border)] bg-[var(--color-bg)] px-3 py-1.5 text-sm text-[var(--color-text)]",children:[l.jsx("option",{value:"cpu",children:"CPU (default)"}),l.jsx("option",{value:"cuda",children:"NVIDIA (CUDA)"}),l.jsx("option",{value:"vulkan",children:"AMD / generic (Vulkan)"}),l.jsx("option",{value:"rocm",children:"AMD (ROCm)"})]}),l.jsx("p",{className:"mt-1 text-xs text-[var(--color-text-muted)]",children:"Where speech-to-text runs. CPU leaves the GPU for the LLM; pick a GPU backend to run Whisper on the GPU."})]})]}),h.some(ee=>ee.id==="jarvis-tts"&&ee.enabled)&&l.jsxs("div",{className:"rounded-lg border border-[var(--color-border)] bg-[var(--color-surface)] p-4",children:[l.jsx("h2",{className:"mb-3 text-sm font-semibold text-[var(--color-text)]",children:"Text-to-speech"}),l.jsxs("div",{className:"px-3",children:[l.jsx("label",{className:"text-xs font-medium text-[var(--color-text-muted)]",children:"Inference device"}),l.jsxs("select",{value:X,onChange:ee=>I(ee.target.value),className:"mt-1 w-full rounded-md border border-[var(--color-border)] bg-[var(--color-bg)] px-3 py-1.5 text-sm text-[var(--color-text)]",children:[l.jsx("option",{value:"cpu",children:"CPU (default)"}),l.jsx("option",{value:"cuda",children:"NVIDIA (CUDA)"})]}),l.jsxs("p",{className:"mt-1 text-xs text-[var(--color-text-muted)]",children:["Where Kokoro synthesis runs. CPU is fine for most installs; CUDA gives the fastest first-audio. On multi-GPU hosts set ",l.jsx("code",{className:"rounded bg-[var(--color-bg)] px-1",children:"TTS_GPU_DEVICE"})," in .env to pick which GPU (default 0)."]})]})]}),l.jsx("div",{className:"rounded-lg border border-[var(--color-border)] bg-[var(--color-surface)] p-4",children:l.jsxs("label",{className:"flex items-start gap-3 text-sm",children:[l.jsx("input",{type:"checkbox",checked:ne,onChange:ee=>W(ee.target.checked),className:"mt-0.5","data-testid":"pin-images-checkbox"}),l.jsxs("span",{children:[l.jsx("span",{className:"font-medium text-[var(--color-text)]",children:"Pin images by digest"}),l.jsxs("span",{className:"mt-1 block text-xs text-[var(--color-text-muted)]",children:["Advanced supply-chain hardening: locks every image to an exact build. Leave OFF for normal use — with pinning on, ",l.jsx("code",{className:"rounded bg-[var(--color-bg)] px-1",children:"docker compose pull"})," will never update anything and services only change via this page."]})]})]})})]}),oe&&o==="options"&&l.jsxs("div",{className:"rounded-lg border border-[var(--color-primary)]/40 bg-[var(--color-surface)] p-4",children:[l.jsxs("h2",{className:"mb-1 flex items-center gap-2 text-sm font-semibold text-[var(--color-text)]",children:[l.jsx(ht,{size:16,className:"text-green-500"}),"Updated files ready"]}),l.jsxs("p",{className:"mb-3 text-xs text-[var(--color-text-muted)]",children:["Your existing secrets and settings are carried over. Download, replace the files next to your compose, then run ",l.jsx("code",{className:"rounded bg-[var(--color-bg)] px-1",children:"docker compose up -d"}),". Nothing on the server was changed."]}),l.jsxs("div",{className:"flex flex-wrap gap-2",children:[l.jsxs("button",{onClick:()=>K("docker-compose.yml",oe.compose),className:"flex items-center gap-2 rounded-lg bg-[var(--color-primary)] px-3 py-2 text-sm font-medium text-white hover:opacity-90",children:[l.jsx(en,{size:15}),"docker-compose.yml"]}),l.jsxs("button",{onClick:()=>K(".env",oe.env),className:"flex items-center gap-2 rounded-lg border border-[var(--color-border)] px-3 py-2 text-sm font-medium text-[var(--color-text)] hover:bg-[var(--color-surface-alt)]",children:[l.jsx(en,{size:15}),".env"]}),l.jsxs("button",{onClick:()=>K("init-db.sh",oe.initDb),className:"flex items-center gap-2 rounded-lg border border-[var(--color-border)] px-3 py-2 text-sm font-medium text-[var(--color-text)] hover:bg-[var(--color-surface-alt)]",children:[l.jsx(en,{size:15}),"init-db.sh"]})]}),l.jsxs("p",{className:"mt-3 text-xs text-[var(--color-text-muted)]",children:["The ",l.jsx("code",{className:"rounded bg-[var(--color-bg)] px-1",children:".env"})," merges new keys into your existing values, and ",l.jsx("code",{className:"rounded bg-[var(--color-bg)] px-1",children:"init-db.sh"})," covers any new databases — replace all three to be safe. Diff them against your current files first if you want to eyeball the changes."]})]}),o!=="loading_options"&&o!=="options"&&l.jsx("div",{className:"space-y-2 rounded-lg border border-[var(--color-border)] bg-[var(--color-surface)] p-4",children:Object.entries(Ju).map(([ee,S])=>{const D=ee===o,Q=xe.includes(ee),Z=ee===o&&o==="error";return l.jsxs("div",{className:"flex items-center gap-2",children:[Q?l.jsx(ht,{size:16,className:"text-green-500"}):Z?l.jsx(ra,{size:16,className:"text-red-500"}):D?l.jsx(Ct,{size:16,className:"animate-spin text-[var(--color-primary)]"}):l.jsx("div",{className:"h-4 w-4 rounded-full border border-[var(--color-border)]"}),l.jsx("span",{className:te("text-sm",D?"font-medium text-[var(--color-text)]":"text-[var(--color-text-muted)]",Q&&"text-green-500"),children:S})]},ee)})}),d.length>0&&l.jsx("div",{ref:g,className:"max-h-64 overflow-y-auto rounded-lg border border-[var(--color-border)] bg-[#0d1117] p-3 font-mono text-xs text-gray-300",children:d.map((ee,S)=>l.jsx("div",{children:ee.text},S))}),m&&l.jsxs("div",{className:"flex items-center gap-2 rounded-lg bg-red-500/10 px-3 py-2",children:[l.jsx(ra,{size:14,className:"text-red-500"}),l.jsx("span",{className:"text-sm text-red-500",children:m})]}),l.jsxs("div",{className:"flex gap-3",children:[o==="options"&&l.jsxs("button",{onClick:ae,className:"flex items-center gap-2 rounded-lg bg-[var(--color-primary)] px-4 py-2 text-sm font-medium text-white hover:opacity-90",children:[l.jsx(xd,{size:16}),"Sync now"]}),o==="options"&&l.jsxs("button",{onClick:()=>Y(),disabled:le,title:"Regenerate the compose and download it to apply by hand — doesn't touch the running stack",className:"flex items-center gap-2 rounded-lg border border-[var(--color-border)] px-4 py-2 text-sm font-medium text-[var(--color-text)] hover:bg-[var(--color-surface-alt)] disabled:cursor-not-allowed disabled:opacity-50",children:[le?l.jsx(Ct,{size:16,className:"animate-spin"}):l.jsx(en,{size:16}),"Download updated compose"]}),o==="options"&&l.jsxs("button",{onClick:()=>Y({latest:!0}),disabled:le,title:"Download a compose pinned to the LATEST published images (digests refreshed from the registry). Apply it yourself on the host — docker compose pull && docker compose up -d — which also updates jarvis-admin.",className:"flex items-center gap-2 rounded-lg border border-[var(--color-border)] px-4 py-2 text-sm font-medium text-[var(--color-text)] hover:bg-[var(--color-surface-alt)] disabled:cursor-not-allowed disabled:opacity-50",children:[le?l.jsx(Ct,{size:16,className:"animate-spin"}):l.jsx(it,{size:16}),"Update stack to latest"]}),o==="options"&&l.jsxs("button",{onClick:()=>Y({mqttAllowAnon:!1}),disabled:le,title:"Download a compose with the MQTT broker locked (allow_anonymous=false). Do this only after every node has authenticated, or un-migrated nodes will drop off.",className:"flex items-center gap-2 rounded-lg border border-[var(--color-border)] px-4 py-2 text-sm font-medium text-[var(--color-text)] hover:bg-[var(--color-surface-alt)] disabled:cursor-not-allowed disabled:opacity-50",children:[le?l.jsx(Ct,{size:16,className:"animate-spin"}):l.jsx(vi,{size:16}),"Download + lock broker"]}),o==="options"&&l.jsxs("button",{onClick:()=>Y({mqttAllowAnon:!0}),disabled:le,title:"Download a compose that re-opens the MQTT broker to anonymous clients (allow_anonymous=true) — the transition/rollback state.",className:"flex items-center gap-2 rounded-lg border border-[var(--color-border)] px-4 py-2 text-sm font-medium text-[var(--color-text)] hover:bg-[var(--color-surface-alt)] disabled:cursor-not-allowed disabled:opacity-50",children:[le?l.jsx(Ct,{size:16,className:"animate-spin"}):l.jsx(mS,{size:16}),"Download + unlock broker"]}),(o==="options"||o==="regenerate"||o==="apply"||o==="done")&&l.jsxs("button",{onClick:()=>a("/dashboard"),disabled:o==="regenerate"||o==="apply",className:"flex items-center gap-2 rounded-lg border border-[var(--color-border)] px-4 py-2 text-sm font-medium text-[var(--color-text)] hover:bg-[var(--color-surface-alt)] disabled:cursor-not-allowed disabled:opacity-50 disabled:hover:bg-transparent",children:[l.jsx(ht,{size:16}),"Back to dashboard"]}),o==="error"&&l.jsxs("button",{onClick:ae,className:"flex items-center gap-2 rounded-lg bg-[var(--color-primary)] px-4 py-2 text-sm font-medium text-white hover:opacity-90",children:[l.jsx(it,{size:16}),"Retry"]})]})]})}async function A4(a={}){const{data:s}=await ge.get("/api/traces",{params:a});return s}async function O4(a){const{data:s}=await ge.get(`/api/traces/${a}`);return s}function Fx(a){return a<1e3?`${Math.round(a)}ms`:`${(a/1e3).toFixed(1)}s`}function Yx(a){return new Date(a).toLocaleString(void 0,{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit",second:"2-digit"})}function z4(a){const s=new Map;for(const o of a){const i=s.get(o.conversation_id);if(!i){s.set(o.conversation_id,{conversation_id:o.conversation_id,traces:[o],newest_at:o.created_at,user_command:o.user_command,assistant_message:o.assistant_message,source:o.source,node_id:o.node_id,household_id:o.household_id,total_duration_ms:o.total_duration_ms,status:o.status});continue}i.traces.push(o),i.total_duration_ms+=o.total_duration_ms,o.created_at>i.newest_at&&(i.newest_at=o.created_at),!i.user_command&&o.user_command&&(i.user_command=o.user_command),!i.assistant_message&&o.assistant_message&&(i.assistant_message=o.assistant_message),o.status!=="ok"&&(i.status=o.status)}return Array.from(s.values()).sort((o,i)=>o.newest_at<i.newest_at?1:-1)}function D4(a){return a==="mobile"?"📱":"🔊"}function U4(){const a=wa(),[s,o]=N.useState(""),[i,d]=N.useState(""),[f,m]=N.useState(""),[v,g]=N.useState(""),[h,y]=N.useState(new Set),x=yt({queryKey:["admin","households"],queryFn:XE,staleTime:6e4}),j=yt({queryKey:["admin","nodes"],queryFn:KE,staleTime:6e4}),{data:k,isLoading:w,error:E}=yt({queryKey:["traces",s,i,f,v],queryFn:()=>A4({limit:100,...s?{status:s}:{},...i?{source:i}:{},...f?{household_id:f}:{},...v?{node_id:v}:{}}),refetchInterval:1e4}),_=N.useMemo(()=>{const G=j.data??[];return f?G.filter(U=>U.household_id===f):G},[j.data,f]),A=N.useMemo(()=>{const G=new Map;for(const U of j.data??[])G.set(U.node_id,U.name);return G},[j.data]),M=N.useMemo(()=>{const G=new Map;for(const U of x.data??[])G.set(U.id,U.name);return G},[x.data]),X=N.useMemo(()=>k?z4(k.traces):[],[k]);function I(G){y(U=>{const oe=new Set(U);return oe.has(G)?oe.delete(G):oe.add(G),oe})}function ne(G){if(m(G),G&&v){const U=(j.data??[]).find(oe=>oe.node_id===v);U&&U.household_id!==G&&g("")}}const W="rounded border border-[var(--color-border)] bg-[var(--color-surface)] px-2 py-1 text-sm text-[var(--color-text)]";return l.jsxs("div",{className:"space-y-4",children:[l.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-2",children:[l.jsx("h1",{className:"text-2xl font-bold text-[var(--color-text)]",children:"Request Traces"}),l.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[l.jsxs("select",{className:W,value:f,onChange:G=>ne(G.target.value),disabled:x.isLoading,children:[l.jsx("option",{value:"",children:"All households"}),(x.data??[]).map(G=>l.jsx("option",{value:G.id,children:G.name},G.id))]}),l.jsxs("select",{className:W,value:v,onChange:G=>g(G.target.value),disabled:j.isLoading,children:[l.jsx("option",{value:"",children:"All nodes"}),_.map(G=>l.jsx("option",{value:G.node_id,children:G.name},G.node_id))]}),l.jsxs("select",{className:W,value:s,onChange:G=>o(G.target.value),children:[l.jsx("option",{value:"",children:"All statuses"}),l.jsx("option",{value:"ok",children:"OK"}),l.jsx("option",{value:"error",children:"Error"})]}),l.jsxs("select",{className:W,value:i,onChange:G=>d(G.target.value),children:[l.jsx("option",{value:"",children:"All sources"}),l.jsx("option",{value:"node",children:"Node"}),l.jsx("option",{value:"mobile",children:"Mobile"})]})]})]}),w&&l.jsx("div",{className:"flex justify-center py-12",children:l.jsx("div",{className:"h-6 w-6 animate-spin rounded-full border-2 border-[var(--color-primary)] border-t-transparent"})}),E&&l.jsx("div",{className:"rounded-lg border border-red-300 bg-red-50 p-4 text-red-700 dark:border-red-700 dark:bg-red-900/20 dark:text-red-400",children:"Failed to load traces"}),k&&l.jsxs(l.Fragment,{children:[l.jsxs("p",{className:"text-sm text-[var(--color-text-muted)]",children:[k.total," traces in ",X.length," conversation",X.length===1?"":"s"]}),l.jsx("div",{className:"overflow-x-auto rounded-lg border border-[var(--color-border)]",children:l.jsxs("table",{className:"w-full text-sm",children:[l.jsx("thead",{children:l.jsxs("tr",{className:"border-b border-[var(--color-border)] bg-[var(--color-surface-alt)]",children:[l.jsx("th",{className:"w-8 px-2 py-2"}),l.jsx("th",{className:"px-3 py-2 text-left font-medium text-[var(--color-text-muted)]",children:"Time"}),l.jsx("th",{className:"px-3 py-2 text-left font-medium text-[var(--color-text-muted)]",children:"Source"}),l.jsx("th",{className:"px-3 py-2 text-left font-medium text-[var(--color-text-muted)]",children:"Node"}),l.jsx("th",{className:"px-3 py-2 text-left font-medium text-[var(--color-text-muted)]",children:"User said"}),l.jsx("th",{className:"px-3 py-2 text-left font-medium text-[var(--color-text-muted)]",children:"Jarvis said"}),l.jsx("th",{className:"px-3 py-2 text-right font-medium text-[var(--color-text-muted)]",children:"Duration"}),l.jsx("th",{className:"px-3 py-2 text-center font-medium text-[var(--color-text-muted)]",children:"Status"}),l.jsx("th",{className:"px-3 py-2 text-right font-medium text-[var(--color-text-muted)]",children:"Traces"})]})}),l.jsxs("tbody",{children:[X.map(G=>{const U=h.has(G.conversation_id),oe=G.traces.length,Ne=G.node_id?A.get(G.node_id)??G.node_id.slice(0,8):"-";return l.jsxs(N.Fragment,{children:[l.jsxs("tr",{className:"border-b border-[var(--color-border)] cursor-pointer transition-colors hover:bg-[var(--color-surface-alt)]",onClick:()=>I(G.conversation_id),children:[l.jsx("td",{className:"px-2 py-2 text-center text-[var(--color-text-muted)]",children:oe>1?U?"▼":"▶":""}),l.jsx("td",{className:"px-3 py-2 text-[var(--color-text)] whitespace-nowrap",children:Yx(G.newest_at)}),l.jsx("td",{className:"px-3 py-2 text-[var(--color-text-muted)]",children:l.jsxs("span",{className:"inline-flex items-center gap-1",children:[D4(G.source),G.source]})}),l.jsxs("td",{className:"px-3 py-2 text-[var(--color-text-muted)] whitespace-nowrap",children:[Ne,G.household_id&&l.jsxs("span",{className:"ml-1 text-xs opacity-60",children:["· ",M.get(G.household_id)??""]})]}),l.jsx("td",{className:"px-3 py-2 text-[var(--color-text)] max-w-xs truncate",children:G.user_command??"-"}),l.jsx("td",{className:"px-3 py-2 text-[var(--color-text-muted)] max-w-xs truncate",children:G.assistant_message??"-"}),l.jsx("td",{className:"px-3 py-2 text-right text-[var(--color-text)] tabular-nums",children:Fx(G.total_duration_ms)}),l.jsx("td",{className:"px-3 py-2 text-center",children:l.jsx("span",{className:`inline-block h-2 w-2 rounded-full ${G.status==="ok"?"bg-green-500":"bg-red-500"}`})}),l.jsx("td",{className:"px-3 py-2 text-right text-[var(--color-text-muted)] tabular-nums",children:oe})]}),U&&G.traces.slice().sort((le,pe)=>le.created_at<pe.created_at?-1:1).map(le=>l.jsxs("tr",{className:"border-b border-[var(--color-border)] cursor-pointer bg-[var(--color-surface-alt)]/40 transition-colors hover:bg-[var(--color-surface-alt)]",onClick:()=>a(`/traces/${le.id}`),children:[l.jsx("td",{className:"px-2 py-2"}),l.jsxs("td",{className:"px-3 py-2 text-[var(--color-text-muted)] whitespace-nowrap",children:[l.jsx("span",{className:"inline-block w-3"}),Yx(le.created_at)]}),l.jsx("td",{className:"px-3 py-2 text-[var(--color-text-muted)] text-xs",children:le.request_type}),l.jsx("td",{className:"px-3 py-2 text-[var(--color-text-muted)] whitespace-nowrap text-xs",children:le.node_id?A.get(le.node_id)??le.node_id.slice(0,8):"-"}),l.jsx("td",{className:"px-3 py-2 text-[var(--color-text)] max-w-xs truncate",children:le.user_command??"-"}),l.jsx("td",{className:"px-3 py-2 text-[var(--color-text-muted)] max-w-xs truncate",children:le.assistant_message??"-"}),l.jsx("td",{className:"px-3 py-2 text-right text-[var(--color-text)] tabular-nums",children:Fx(le.total_duration_ms)}),l.jsx("td",{className:"px-3 py-2 text-center",children:l.jsx("span",{className:`inline-block h-2 w-2 rounded-full ${le.status==="ok"?"bg-green-500":"bg-red-500"}`})}),l.jsx("td",{className:"px-3 py-2 text-right text-[var(--color-text-muted)] tabular-nums",children:le.span_count})]},le.id))]},G.conversation_id)}),X.length===0&&l.jsx("tr",{children:l.jsx("td",{colSpan:9,className:"px-3 py-8 text-center text-[var(--color-text-muted)]",children:"No traces yet"})})]})]})})]})]})}function ns(a){return a<1e3?`${Math.round(a)}ms`:`${(a/1e3).toFixed(1)}s`}const Xx={cc:"#9e9e9e",llm_proxy:"#42a5f5",node:"#66bb6a",tts:"#ffa726",whisper:"#ab47bc"},Kx={cc:"Command Center",llm_proxy:"LLM Proxy",node:"Node",tts:"TTS",whisper:"Whisper"};function L4(a){const s=a.filter(d=>d.duration_ms>0),o=s.filter(d=>!s.some(f=>f!==d&&d.start_ms<=f.start_ms&&d.end_ms>=f.end_ms&&f.duration_ms>0));o.sort((d,f)=>d.start_ms-f.start_ms);const i=[];for(const d of o){const f=i[i.length-1];f&&f.service===d.service?(f.duration_ms=Math.round((f.duration_ms+d.duration_ms)*10)/10,f.steps.push(d.name),d.status==="error"&&(f.status="error")):i.push({service:d.service,duration_ms:d.duration_ms,status:d.status,steps:[d.name]})}return i}function B4(){const{id:a}=k0(),s=wa(),[o,i]=N.useState(!1),[d,f]=N.useState(null),{data:m,isLoading:v,error:g}=yt({queryKey:["trace",a],queryFn:()=>O4(a),enabled:!!a}),h=N.useMemo(()=>m?L4(m.spans):[],[m]);return v?l.jsx("div",{className:"flex justify-center py-12",children:l.jsx("div",{className:"h-6 w-6 animate-spin rounded-full border-2 border-[var(--color-primary)] border-t-transparent"})}):g||!m?l.jsxs("div",{className:"space-y-4",children:[l.jsx("button",{className:"text-sm text-[var(--color-primary)] hover:underline",onClick:()=>s("/traces"),children:"Back to traces"}),l.jsx("div",{className:"rounded-lg border border-red-300 bg-red-50 p-4 text-red-700 dark:border-red-700 dark:bg-red-900/20 dark:text-red-400",children:"Trace not found"})]}):l.jsxs("div",{className:"space-y-6",children:[l.jsx("button",{className:"text-sm text-[var(--color-primary)] hover:underline",onClick:()=>s("/traces"),children:"Back to traces"}),l.jsxs("div",{className:"rounded-lg border border-[var(--color-border)] bg-[var(--color-surface)] p-4",children:[l.jsxs("div",{className:"flex items-center justify-between",children:[l.jsxs("div",{children:[l.jsx("h1",{className:"text-lg font-bold text-[var(--color-text)]",children:m.user_command??"Request Trace"}),l.jsxs("p",{className:"mt-1 text-sm text-[var(--color-text-muted)]",children:[m.source==="mobile"?"📱 Mobile":"🔊 Node",m.node_id&&` (${m.node_id})`," · ",m.request_type," · ",m.created_at?new Date(m.created_at).toLocaleString():""]})]}),l.jsxs("div",{className:"text-right",children:[l.jsx("div",{className:"text-2xl font-bold tabular-nums text-[var(--color-text)]",children:ns(m.total_duration_ms)}),l.jsxs("div",{className:"flex items-center justify-end gap-1 mt-1",children:[l.jsx("span",{className:`inline-block h-2 w-2 rounded-full ${m.status==="ok"?"bg-green-500":"bg-red-500"}`}),l.jsx("span",{className:"text-sm text-[var(--color-text-muted)]",children:m.status})]})]})]}),m.error_message&&l.jsx("div",{className:"mt-3 rounded border border-red-300 bg-red-50 p-2 text-sm text-red-700 dark:border-red-700 dark:bg-red-900/20 dark:text-red-400",children:m.error_message}),l.jsx("p",{className:"mt-2 text-xs text-[var(--color-text-muted)] font-mono",children:m.conversation_id})]}),l.jsxs("div",{className:"rounded-lg border border-[var(--color-border)] bg-[var(--color-surface)] p-4",children:[l.jsx("h2",{className:"mb-3 text-sm font-medium text-[var(--color-text-muted)]",children:"Service Flow"}),l.jsx("p",{className:"mb-4 text-xs text-[var(--color-text-muted)] opacity-60",children:h.map(y=>Kx[y.service]??y.service).join(" → ")}),l.jsx("div",{className:"space-y-2",children:h.map((y,x)=>{const j=Math.min(y.duration_ms/m.total_duration_ms*100,100),k=y.status==="error"?"#ef4444":Xx[y.service]??"#9e9e9e",w=Kx[y.service]??y.service;return l.jsxs("div",{className:"flex items-center gap-3",children:[l.jsx("span",{className:"inline-block h-2.5 w-2.5 rounded-full shrink-0",style:{backgroundColor:k}}),l.jsx("span",{className:"w-32 text-sm text-[var(--color-text)] shrink-0",children:w}),l.jsxs("div",{className:"flex-1 h-6 rounded bg-[var(--color-surface-alt)] relative",children:[l.jsx("div",{className:"absolute top-0 left-0 h-full rounded",style:{width:`${Math.max(j,1)}%`,backgroundColor:k,opacity:.7}}),l.jsx("span",{className:"absolute inset-0 flex items-center px-2 text-xs text-[var(--color-text)] opacity-70",children:y.steps.join(", ")})]}),l.jsx("span",{className:"w-16 text-sm text-[var(--color-text)] text-right tabular-nums shrink-0",children:ns(y.duration_ms)})]},`${y.service}-${x}`)})})]}),l.jsxs("div",{className:"rounded-lg border border-[var(--color-border)] bg-[var(--color-surface)] p-4",children:[l.jsxs("button",{className:"text-sm text-[var(--color-text-muted)] hover:text-[var(--color-text)]",onClick:()=>{i(y=>!y),f(null)},children:[o?"Hide":"Show"," raw spans (",m.spans.length,")"]}),o&&l.jsx("div",{className:"mt-3 space-y-1",children:m.spans.map((y,x)=>{const j=Math.min(y.duration_ms/m.total_duration_ms*100,100),k=y.start_ms/m.total_duration_ms*100,w=y.status==="error"?"#ef4444":Xx[y.service]??"#9e9e9e",E=d===y;return l.jsxs("div",{className:`flex items-center gap-2 cursor-pointer rounded px-1 py-0.5 ${E?"bg-[var(--color-surface-alt)]":""}`,onClick:()=>f(E?null:y),children:[l.jsx("span",{className:"w-36 truncate text-xs text-[var(--color-text-muted)] text-right shrink-0",children:y.name}),l.jsx("div",{className:"flex-1 relative h-4 rounded bg-[var(--color-surface-alt)]",children:l.jsx("div",{className:"absolute top-0 h-full rounded",style:{left:`${k}%`,width:`${Math.max(j,.5)}%`,backgroundColor:w,minWidth:"2px"}})}),l.jsx("span",{className:"w-14 text-xs text-[var(--color-text-muted)] text-right shrink-0 tabular-nums",children:ns(y.duration_ms)}),l.jsx("span",{className:"w-16 text-xs text-[var(--color-text-muted)] opacity-60 shrink-0",children:y.service})]},`${y.name}-${x}`)})}),d&&o&&l.jsx("div",{className:"mt-3 border-t border-[var(--color-border)] pt-3",children:l.jsxs("dl",{className:"grid grid-cols-2 gap-x-4 gap-y-1 text-sm max-w-md",children:[l.jsx("dt",{className:"text-[var(--color-text-muted)]",children:"Service"}),l.jsx("dd",{className:"text-[var(--color-text)]",children:d.service}),l.jsx("dt",{className:"text-[var(--color-text-muted)]",children:"Duration"}),l.jsx("dd",{className:"text-[var(--color-text)] tabular-nums",children:ns(d.duration_ms)}),l.jsx("dt",{className:"text-[var(--color-text-muted)]",children:"Start"}),l.jsx("dd",{className:"text-[var(--color-text)] tabular-nums",children:ns(d.start_ms)}),l.jsx("dt",{className:"text-[var(--color-text-muted)]",children:"End"}),l.jsx("dd",{className:"text-[var(--color-text)] tabular-nums",children:ns(d.end_ms)}),l.jsx("dt",{className:"text-[var(--color-text-muted)]",children:"Status"}),l.jsx("dd",{className:d.status==="ok"?"text-green-600":"text-red-600",children:d.status}),Object.entries(d.metadata||{}).map(([y,x])=>l.jsxs("div",{className:"contents",children:[l.jsx("dt",{className:"text-[var(--color-text-muted)]",children:y}),l.jsx("dd",{className:"text-[var(--color-text)] tabular-nums",children:String(x)})]},y))]})})]})]})}function q4(){return l.jsxs("div",{className:"flex min-h-[60vh] flex-col items-center justify-center",children:[l.jsx("h1",{className:"mb-2 text-4xl font-bold text-[var(--color-text)]",children:"404"}),l.jsx("p",{className:"mb-4 text-[var(--color-text-muted)]",children:"Page not found"}),l.jsx(Cd,{to:"/settings",className:"text-[var(--color-primary)] underline hover:opacity-80",children:"Go to Settings"})]})}const H4=7,G4={currentStep:0,totalSteps:H4,enabledModules:[],portOverrides:{},infraPortOverrides:{},secrets:{},dbUser:"jarvis",whisperModel:"base.en",whisperModelPath:"/whisper-models/ggml-base.en.bin",llmInterface:"Qwen25MediumUntrained",deploymentMode:"local",deploymentTarget:"standard",remoteLlmUrl:"",remoteWhisperUrl:"",platform:"linux",hardware:null,relayEnabled:!1,installRunning:!1,installComplete:!1,nativeServices:[]};function Q4(a,s,o){return Math.max(s,Math.min(o,a))}function V4(a,s){switch(s.type){case"SET_STEP":return{...a,currentStep:Q4(s.step,0,a.totalSteps-1)};case"NEXT_STEP":return{...a,currentStep:Math.min(a.currentStep+1,a.totalSteps-1)};case"PREV_STEP":return{...a,currentStep:Math.max(a.currentStep-1,0)};case"SET_ENABLED_MODULES":return{...a,enabledModules:s.modules};case"TOGGLE_MODULE":{if(s.enabled){const o=a.enabledModules.includes(s.serviceId)?a.enabledModules:[...a.enabledModules,s.serviceId];return{...a,enabledModules:o}}return{...a,enabledModules:a.enabledModules.filter(o=>o!==s.serviceId)}}case"SET_PORT_OVERRIDE":return{...a,portOverrides:{...a.portOverrides,[s.serviceId]:s.port}};case"SET_INFRA_PORT_OVERRIDE":return{...a,infraPortOverrides:{...a.infraPortOverrides,[s.infraId]:s.port}};case"SET_SECRET":return{...a,secrets:{...a.secrets,[s.name]:s.value}};case"SET_SECRETS":return{...a,secrets:s.secrets};case"SET_DB_USER":return{...a,dbUser:s.user};case"SET_WHISPER_MODEL":return{...a,whisperModel:s.model};case"SET_WHISPER_BACKEND":return{...a,whisperBackend:s.backend};case"SET_LLM_INTERFACE":return{...a,llmInterface:s.interfaceId};case"SET_DEPLOYMENT_MODE":return{...a,deploymentMode:s.mode};case"SET_DEPLOYMENT_TARGET":return{...a,deploymentTarget:s.target};case"SET_REMOTE_LLM_URL":return{...a,remoteLlmUrl:s.url};case"SET_REMOTE_WHISPER_URL":return{...a,remoteWhisperUrl:s.url};case"SET_PLATFORM":return{...a,platform:s.platform};case"SET_HARDWARE":return{...a,hardware:s.hardware,platform:s.hardware.platform};case"SET_RELAY_ENABLED":return{...a,relayEnabled:s.enabled};case"SET_INSTALL_RUNNING":return{...a,installRunning:s.running};case"SET_INSTALL_COMPLETE":return{...a,installRunning:!1,installComplete:!0};case"SET_NATIVE_SERVICES":return{...a,nativeServices:s.services};case"TOGGLE_NATIVE_SERVICE":{if(s.enabled){const o=a.nativeServices.includes(s.serviceId)?a.nativeServices:[...a.nativeServices,s.serviceId];return{...a,nativeServices:o}}return{...a,nativeServices:a.nativeServices.filter(o=>o!==s.serviceId)}}default:return a}}const Eg=N.createContext(null);function F4({children:a}){const[s,o]=N.useReducer(V4,G4);return l.jsx(Eg.Provider,{value:{state:s,dispatch:o},children:a})}function fr(){const a=N.useContext(Eg);if(!a)throw new Error("useWizard must be used within a WizardProvider");return a}function Y4(){const{state:a,dispatch:s}=fr(),[o,i]=N.useState(null),[d,f]=N.useState(!0),[m,v]=N.useState(!1);function g(){f(!0),v(!1),Yd().then(y=>{i(y);const x=y.reason==="docker_not_found";v(x),s(x?{type:"SET_INSTALL_RUNNING",running:!0}:{type:"SET_INSTALL_RUNNING",running:!1})}).catch(()=>{i({configured:!1,reason:"error"}),v(!0),s({type:"SET_INSTALL_RUNNING",running:!0})}).finally(()=>f(!1))}N.useEffect(()=>{g()},[]);const h=o&&o.reason!=="docker_not_found";return l.jsxs("div",{className:"space-y-6",children:[l.jsxs("div",{children:[l.jsx("h2",{className:"text-xl font-bold text-[var(--color-text)]",children:"Welcome to Jarvis"}),l.jsx("p",{className:"mt-1 text-sm text-[var(--color-text-muted)]",children:"Let's get your personal voice assistant up and running. This wizard will guide you through selecting services, configuring hardware, and starting everything up."})]}),l.jsx("div",{className:"rounded-lg border border-[var(--color-border)] bg-[var(--color-surface-alt)] p-4",children:l.jsxs("div",{className:"flex items-center gap-3",children:[d?l.jsx(Ct,{size:20,className:"animate-spin text-[var(--color-primary)]"}):h?l.jsx(ht,{size:20,className:"text-green-500"}):l.jsx(Bd,{size:20,className:"text-red-500"}),l.jsxs("div",{className:"flex-1",children:[l.jsx("p",{className:"text-sm font-medium text-[var(--color-text)]",children:d?"Checking Docker...":h?"Docker is running":"Docker not found"}),!d&&!h&&l.jsxs("div",{className:"mt-1 space-y-1",children:[l.jsx("p",{className:"text-xs text-red-400",children:"Docker is required to run Jarvis services."}),l.jsxs("p",{className:"text-xs text-[var(--color-text-muted)]",children:["Install"," ",l.jsx("a",{href:"https://www.docker.com/products/docker-desktop/",target:"_blank",rel:"noopener noreferrer",className:"text-[var(--color-primary)] underline hover:no-underline",children:"Docker Desktop"})," ","for your platform, start it, then click Retry."]})]})]}),m&&!d&&l.jsxs("button",{type:"button",onClick:g,className:"flex items-center gap-1 rounded-md border border-[var(--color-border)] px-2 py-1 text-xs text-[var(--color-text-muted)] hover:text-[var(--color-text)]",children:[l.jsx(gi,{size:12}),"Retry"]})]})}),l.jsxs("div",{children:[l.jsx("label",{className:"mb-2 block text-sm font-medium text-[var(--color-text)]",children:"Deployment Mode"}),l.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[l.jsxs("button",{type:"button",onClick:()=>s({type:"SET_DEPLOYMENT_MODE",mode:"local"}),className:te("flex flex-col items-center gap-2 rounded-lg border p-4 transition-colors",a.deploymentMode==="local"?"border-[var(--color-primary)] bg-[var(--color-primary)]/10":"border-[var(--color-border)] hover:border-[var(--color-primary)]/50"),children:[l.jsx(yS,{size:24,className:"text-[var(--color-primary)]"}),l.jsx("span",{className:"text-sm font-medium text-[var(--color-text)]",children:"Local"}),l.jsx("span",{className:"text-xs text-center text-[var(--color-text-muted)]",children:"Everything on this machine"})]}),l.jsxs("button",{type:"button",onClick:()=>s({type:"SET_DEPLOYMENT_MODE",mode:"remote-llm"}),className:te("flex flex-col items-center gap-2 rounded-lg border p-4 transition-colors",a.deploymentMode==="remote-llm"?"border-[var(--color-primary)] bg-[var(--color-primary)]/10":"border-[var(--color-border)] hover:border-[var(--color-primary)]/50"),children:[l.jsx(Qd,{size:24,className:"text-[var(--color-primary)]"}),l.jsx("span",{className:"text-sm font-medium text-[var(--color-text)]",children:"Remote LLM"}),l.jsx("span",{className:"text-xs text-center text-[var(--color-text-muted)]",children:"LLM on separate GPU machine"})]})]})]})]})}const $o=[{label:"None / CPU only",gpu:null,gpuType:"none",vramMb:null,backends:["gguf"],defaultBackend:"gguf"},{label:"NVIDIA RTX 4090 (24 GB)",gpu:"NVIDIA RTX 4090",gpuType:"nvidia",vramMb:24576,backends:["gguf","vllm"],defaultBackend:"gguf"},{label:"NVIDIA RTX 4080 (16 GB)",gpu:"NVIDIA RTX 4080",gpuType:"nvidia",vramMb:16384,backends:["gguf","vllm"],defaultBackend:"gguf"},{label:"NVIDIA RTX 4070 Ti (12 GB)",gpu:"NVIDIA RTX 4070 Ti",gpuType:"nvidia",vramMb:12288,backends:["gguf","vllm"],defaultBackend:"gguf"},{label:"NVIDIA RTX 3090 (24 GB)",gpu:"NVIDIA RTX 3090",gpuType:"nvidia",vramMb:24576,backends:["gguf","vllm"],defaultBackend:"gguf"},{label:"NVIDIA RTX 3080 (10 GB)",gpu:"NVIDIA RTX 3080",gpuType:"nvidia",vramMb:10240,backends:["gguf","vllm"],defaultBackend:"gguf"},{label:"NVIDIA RTX 3070 (8 GB)",gpu:"NVIDIA RTX 3070",gpuType:"nvidia",vramMb:8192,backends:["gguf","vllm"],defaultBackend:"gguf"},{label:"NVIDIA A100 (80 GB)",gpu:"NVIDIA A100",gpuType:"nvidia",vramMb:81920,backends:["gguf","vllm"],defaultBackend:"vllm"},{label:"NVIDIA A100 (40 GB)",gpu:"NVIDIA A100",gpuType:"nvidia",vramMb:40960,backends:["gguf","vllm"],defaultBackend:"vllm"},{label:"NVIDIA Tesla T4 (16 GB)",gpu:"NVIDIA Tesla T4",gpuType:"nvidia",vramMb:16384,backends:["gguf","vllm"],defaultBackend:"gguf"},{label:"AMD RX 9070 XT — Vulkan (16 GB)",gpu:"AMD RX 9070 XT",gpuType:"amd",vramMb:16384,backends:["gguf"],defaultBackend:"gguf"},{label:"AMD RX 9070 — Vulkan (12 GB)",gpu:"AMD RX 9070",gpuType:"amd",vramMb:12288,backends:["gguf"],defaultBackend:"gguf"},{label:"AMD RX 7900 XTX — Vulkan (24 GB)",gpu:"AMD RX 7900 XTX",gpuType:"amd",vramMb:24576,backends:["gguf"],defaultBackend:"gguf"},{label:"AMD RX 7900 XT — Vulkan (20 GB)",gpu:"AMD RX 7900 XT",gpuType:"amd",vramMb:20480,backends:["gguf"],defaultBackend:"gguf"},{label:"AMD RX 7800 XT — Vulkan (16 GB)",gpu:"AMD RX 7800 XT",gpuType:"amd",vramMb:16384,backends:["gguf"],defaultBackend:"gguf"},{label:"AMD RX 7600 — Vulkan (8 GB)",gpu:"AMD RX 7600",gpuType:"amd",vramMb:8192,backends:["gguf"],defaultBackend:"gguf"},{label:"AMD RX 9070 XT — ROCm (16 GB)",gpu:"AMD RX 9070 XT",gpuType:"amd-rocm",vramMb:16384,backends:["gguf"],defaultBackend:"gguf"},{label:"AMD RX 9070 — ROCm (12 GB)",gpu:"AMD RX 9070",gpuType:"amd-rocm",vramMb:12288,backends:["gguf"],defaultBackend:"gguf"},{label:"AMD RX 7900 XTX — ROCm (24 GB)",gpu:"AMD RX 7900 XTX",gpuType:"amd-rocm",vramMb:24576,backends:["gguf"],defaultBackend:"gguf"},{label:"AMD RX 7900 XT — ROCm (20 GB)",gpu:"AMD RX 7900 XT",gpuType:"amd-rocm",vramMb:20480,backends:["gguf"],defaultBackend:"gguf"},{label:"AMD RX 7800 XT — ROCm (16 GB)",gpu:"AMD RX 7800 XT",gpuType:"amd-rocm",vramMb:16384,backends:["gguf"],defaultBackend:"gguf"},{label:"Apple M4 Max (128 GB unified)",gpu:"Apple M4 Max",gpuType:"apple",vramMb:131072,backends:["gguf","mlx"],defaultBackend:"gguf"},{label:"Apple M4 Max (64 GB unified)",gpu:"Apple M4 Max",gpuType:"apple",vramMb:65536,backends:["gguf","mlx"],defaultBackend:"gguf"},{label:"Apple M4 Pro (48 GB unified)",gpu:"Apple M4 Pro",gpuType:"apple",vramMb:49152,backends:["gguf","mlx"],defaultBackend:"gguf"},{label:"Apple M4 Pro (24 GB unified)",gpu:"Apple M4 Pro",gpuType:"apple",vramMb:24576,backends:["gguf","mlx"],defaultBackend:"gguf"},{label:"Apple M2 Max (32 GB unified)",gpu:"Apple M2 Max",gpuType:"apple",vramMb:32768,backends:["gguf","mlx"],defaultBackend:"gguf"},{label:"Apple M2 Pro (16 GB unified)",gpu:"Apple M2 Pro",gpuType:"apple",vramMb:16384,backends:["gguf","mlx"],defaultBackend:"gguf"},{label:"Apple M1 (16 GB unified)",gpu:"Apple M1",gpuType:"apple",vramMb:16384,backends:["gguf","mlx"],defaultBackend:"gguf"},{label:"Apple M1 (8 GB unified)",gpu:"Apple M1",gpuType:"apple",vramMb:8192,backends:["gguf","mlx"],defaultBackend:"gguf"},{label:"Other (enter VRAM manually)",gpu:"Other",gpuType:"none",vramMb:null,backends:["gguf"],defaultBackend:"gguf"}];function X4(){const{state:a,dispatch:s}=fr(),[o,i]=N.useState(!a.hardware),[d,f]=N.useState(!1),[m,v]=N.useState(0),[g,h]=N.useState("");N.useEffect(()=>{a.hardware||ME().then(j=>{s({type:"SET_HARDWARE",hardware:j}),j.recommendedBackend==="remote"&&a.deploymentMode==="local"&&s({type:"SET_DEPLOYMENT_MODE",mode:"remote-llm"})}).catch(()=>{}).finally(()=>i(!1))},[]);function y(j,k){const w=$o[j];if(!a.hardware)return;const E=w.gpu==="Other"?(parseInt(k??g,10)||0)*1024:w.vramMb,_={...a.hardware,gpuName:w.gpu,gpuVramMb:E||null,gpuType:w.gpuType,recommendedBackends:[...w.backends],recommendedBackend:w.defaultBackend};s({type:"SET_HARDWARE",hardware:_})}const x=a.hardware;return o?l.jsxs("div",{className:"flex flex-col items-center justify-center py-12",children:[l.jsx(Ct,{size:32,className:"animate-spin text-[var(--color-primary)]"}),l.jsx("p",{className:"mt-3 text-sm text-[var(--color-text-muted)]",children:"Detecting hardware..."})]}):l.jsxs("div",{className:"space-y-6",children:[l.jsxs("div",{children:[l.jsx("h2",{className:"text-xl font-bold text-[var(--color-text)]",children:"Hardware Detection"}),l.jsx("p",{className:"mt-1 text-sm text-[var(--color-text-muted)]",children:"We detected the following hardware. This determines which LLM backend to use."})]}),x&&l.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[l.jsxs("div",{className:"rounded-lg border border-[var(--color-border)] bg-[var(--color-surface-alt)] p-4",children:[l.jsxs("div",{className:"flex items-center gap-2 text-[var(--color-text-muted)]",children:[l.jsx(On,{size:16}),l.jsx("span",{className:"text-xs font-medium uppercase",children:"Platform"})]}),l.jsxs("p",{className:"mt-1 text-sm font-medium text-[var(--color-text)]",children:[x.platform==="darwin"?"macOS":"Linux"," (",x.arch,")"]})]}),l.jsxs("div",{className:"rounded-lg border border-[var(--color-border)] bg-[var(--color-surface-alt)] p-4",children:[l.jsxs("div",{className:"flex items-center gap-2 text-[var(--color-text-muted)]",children:[l.jsx(Hd,{size:16}),l.jsx("span",{className:"text-xs font-medium uppercase",children:"Memory"})]}),l.jsxs("p",{className:"mt-1 text-sm font-medium text-[var(--color-text)]",children:[x.totalMemoryGb," GB RAM"]})]}),l.jsxs("div",{className:"col-span-2 rounded-lg border border-[var(--color-border)] bg-[var(--color-surface-alt)] p-4",children:[l.jsxs("div",{className:"flex items-center justify-between",children:[l.jsxs("div",{children:[l.jsxs("div",{className:"flex items-center gap-2 text-[var(--color-text-muted)]",children:[l.jsx(On,{size:16}),l.jsx("span",{className:"text-xs font-medium uppercase",children:"GPU"})]}),l.jsx("p",{className:"mt-1 text-sm font-medium text-[var(--color-text)]",children:x.gpuName??"No GPU detected"}),x.gpuVramMb!=null&&x.gpuVramMb>0&&l.jsxs("p",{className:"text-xs text-[var(--color-text-muted)]",children:[Math.round(x.gpuVramMb/1024)," GB VRAM"]})]}),l.jsx("button",{type:"button",onClick:()=>f(!d),className:"text-xs font-medium text-[var(--color-primary)] hover:underline",children:d?"Cancel":"Override"})]}),d&&l.jsxs("div",{className:"mt-3 space-y-3 border-t border-[var(--color-border)] pt-3",children:[l.jsxs("div",{children:[l.jsx("label",{htmlFor:"gpu-select",className:"mb-1 block text-xs text-[var(--color-text-muted)]",children:"Select GPU"}),l.jsx("select",{id:"gpu-select",value:m,onChange:j=>{const k=parseInt(j.target.value,10);v(k),$o[k].gpu!=="Other"&&(y(k),f(!1))},className:te("w-full rounded-lg border border-[var(--color-border)] bg-[var(--color-surface-alt)] px-3 py-2","text-sm text-[var(--color-text)]","outline-none focus:ring-2 focus:ring-[var(--color-primary)]"),children:$o.map((j,k)=>l.jsx("option",{value:k,children:j.label},`${j.label}-${k}`))})]}),$o[m].gpu==="Other"&&l.jsxs("div",{className:"flex items-end gap-2",children:[l.jsxs("div",{className:"flex-1",children:[l.jsx("label",{htmlFor:"custom-vram",className:"mb-1 block text-xs text-[var(--color-text-muted)]",children:"VRAM (GB)"}),l.jsx("input",{id:"custom-vram",type:"number",min:1,max:512,value:g,onChange:j=>h(j.target.value),placeholder:"e.g. 24",className:te("w-full rounded-lg border border-[var(--color-border)] bg-[var(--color-surface-alt)] px-3 py-2","text-sm text-[var(--color-text)] placeholder:text-[var(--color-text-muted)]","outline-none focus:ring-2 focus:ring-[var(--color-primary)]")})]}),l.jsx("button",{type:"button",disabled:!g||parseInt(g,10)<=0,onClick:()=>{y(m,g),f(!1)},className:te("rounded-lg px-4 py-2 text-sm font-medium","bg-[var(--color-primary)] text-white","disabled:cursor-not-allowed disabled:opacity-50"),children:"Apply"})]})]})]}),l.jsxs("div",{className:"col-span-2 rounded-lg border border-[var(--color-primary)]/30 bg-[var(--color-primary)]/5 p-4",children:[l.jsxs("p",{className:"text-sm font-medium text-[var(--color-text)]",children:["Recommended: ",l.jsx("span",{className:"text-[var(--color-primary)]",children:x.recommendedBackend.toUpperCase()})]}),x.recommendedBackends.length>1&&l.jsxs("p",{className:"mt-0.5 text-xs text-[var(--color-text-muted)]",children:["Available backends: ",x.recommendedBackends.join(", ")]})]})]}),a.deploymentMode==="remote-llm"&&l.jsxs("div",{className:"space-y-3",children:[l.jsx("h3",{className:"text-sm font-medium text-[var(--color-text)]",children:"Remote Service URLs"}),l.jsxs("div",{children:[l.jsx("label",{htmlFor:"remote-llm",className:"mb-1 block text-xs text-[var(--color-text-muted)]",children:"LLM Proxy URL"}),l.jsx("input",{id:"remote-llm",type:"url",value:a.remoteLlmUrl,onChange:j=>s({type:"SET_REMOTE_LLM_URL",url:j.target.value}),placeholder:"http://192.168.1.100:7704",className:te("w-full rounded-lg border border-[var(--color-border)] bg-[var(--color-surface-alt)] px-3 py-2","text-sm text-[var(--color-text)] placeholder:text-[var(--color-text-muted)]","outline-none focus:ring-2 focus:ring-[var(--color-primary)]")})]}),l.jsxs("div",{children:[l.jsx("label",{htmlFor:"remote-whisper",className:"mb-1 block text-xs text-[var(--color-text-muted)]",children:"Whisper URL (optional)"}),l.jsx("input",{id:"remote-whisper",type:"url",value:a.remoteWhisperUrl,onChange:j=>s({type:"SET_REMOTE_WHISPER_URL",url:j.target.value}),placeholder:"http://192.168.1.100:7706",className:te("w-full rounded-lg border border-[var(--color-border)] bg-[var(--color-surface-alt)] px-3 py-2","text-sm text-[var(--color-text)] placeholder:text-[var(--color-text-muted)]","outline-none focus:ring-2 focus:ring-[var(--color-primary)]")})]})]})]})}function K4(){const{state:a,dispatch:s}=fr(),[o,i]=N.useState(null),[d,f]=N.useState(!0);if(N.useEffect(()=>{Promise.all([bg(),AE()]).then(([h,y])=>{if(i(h),a.enabledModules.length===0&&s({type:"SET_ENABLED_MODULES",modules:y.enabledModules}),a.platform==="darwin"&&a.nativeServices.length===0){const x=h.services.filter(j=>j.nativeCapable).map(j=>j.id);x.length>0&&s({type:"SET_NATIVE_SERVICES",services:x})}}).catch(()=>{}).finally(()=>f(!1))},[]),d||!o)return l.jsx("div",{className:"flex items-center justify-center py-12",children:l.jsx(Ct,{size:32,className:"animate-spin text-[var(--color-primary)]"})});const{core:m,recommended:v,optional:g}=$4(o.services);return l.jsxs("div",{className:"space-y-6",children:[l.jsxs("div",{children:[l.jsx("h2",{className:"text-xl font-bold text-[var(--color-text)]",children:"Select Services"}),l.jsxs("p",{className:"mt-1 text-sm text-[var(--color-text-muted)]",children:["Core services are always included. Toggle recommended and optional services.",a.platform==="darwin"&&l.jsxs(l.Fragment,{children:[" Services marked ",l.jsx("em",{children:"Native"})," can run as macOS LaunchAgents to use the Apple GPU."]})]})]}),l.jsx(Pu,{title:"Core",subtitle:"Always included",services:m,enabled:m.map(h=>h.id),nativeServices:a.nativeServices,platform:a.platform,locked:!0}),l.jsx(Pu,{title:"Recommended",subtitle:"Enabled by default",services:v,enabled:a.enabledModules,nativeServices:a.nativeServices,platform:a.platform,onToggle:(h,y)=>s({type:"TOGGLE_MODULE",serviceId:h,enabled:y}),onToggleNative:(h,y)=>s({type:"TOGGLE_NATIVE_SERVICE",serviceId:h,enabled:y})}),g.length>0&&l.jsx(Pu,{title:"Optional",subtitle:"Off by default",services:g,enabled:a.enabledModules,nativeServices:a.nativeServices,platform:a.platform,onToggle:(h,y)=>s({type:"TOGGLE_MODULE",serviceId:h,enabled:y}),onToggleNative:(h,y)=>s({type:"TOGGLE_NATIVE_SERVICE",serviceId:h,enabled:y})}),l.jsxs("div",{children:[l.jsxs("div",{className:"mb-2 flex items-baseline gap-2",children:[l.jsx("h3",{className:"text-sm font-medium text-[var(--color-text)]",children:"Integrations"}),l.jsx("span",{className:"text-xs text-[var(--color-text-muted)]",children:"Cloud services"})]}),l.jsxs("button",{type:"button",onClick:()=>s({type:"SET_RELAY_ENABLED",enabled:!a.relayEnabled}),className:te("flex w-full items-center gap-3 rounded-lg border px-3 py-2.5 text-left transition-colors",a.relayEnabled?"border-[var(--color-primary)]/30 bg-[var(--color-primary)]/5":"border-[var(--color-border)] hover:border-[var(--color-primary)]/30"),children:[a.relayEnabled?l.jsx(ht,{size:16,className:"shrink-0 text-[var(--color-primary)]"}):l.jsx(os,{size:16,className:"shrink-0 text-[var(--color-text-muted)]"}),l.jsxs("div",{className:"min-w-0 flex-1",children:[l.jsxs("div",{className:"flex items-center gap-2",children:[l.jsx("span",{className:"text-sm font-medium text-[var(--color-text)]",children:"Jarvis Relay"}),l.jsx(tS,{size:12,className:"text-[var(--color-text-muted)]"})]}),l.jsx("p",{className:"text-xs text-[var(--color-text-muted)]",children:"Routes OAuth callbacks through a cloud relay for external providers (Google, Spotify, etc.)"})]})]})]})]})}function $4(a){return{core:a.filter(s=>s.category==="core"),recommended:a.filter(s=>s.category==="recommended"),optional:a.filter(s=>s.category==="optional")}}function Pu({title:a,subtitle:s,services:o,enabled:i,nativeServices:d,locked:f,onToggle:m,onToggleNative:v,platform:g}){return l.jsxs("div",{children:[l.jsxs("div",{className:"mb-2 flex items-baseline gap-2",children:[l.jsx("h3",{className:"text-sm font-medium text-[var(--color-text)]",children:a}),l.jsx("span",{className:"text-xs text-[var(--color-text-muted)]",children:s})]}),l.jsx("div",{className:"space-y-1",children:o.map(h=>{const y=i.includes(h.id),x=h.nativeCapable&&g==="darwin"&&y,j=d.includes(h.id);return l.jsxs("div",{className:te("rounded-lg border transition-colors",y?"border-[var(--color-primary)]/30 bg-[var(--color-primary)]/5":"border-[var(--color-border)]",!f&&!y&&"hover:border-[var(--color-primary)]/30"),children:[l.jsxs("button",{type:"button",disabled:f,onClick:()=>m?.(h.id,!y),className:te("flex w-full items-center gap-3 px-3 py-2.5 text-left",f&&"cursor-default"),children:[f?l.jsx(vi,{size:16,className:"shrink-0 text-[var(--color-text-muted)]"}):y?l.jsx(ht,{size:16,className:"shrink-0 text-[var(--color-primary)]"}):l.jsx(os,{size:16,className:"shrink-0 text-[var(--color-text-muted)]"}),l.jsxs("div",{className:"min-w-0 flex-1",children:[l.jsxs("div",{className:"flex items-center gap-2",children:[l.jsx("span",{className:"text-sm font-medium text-[var(--color-text)]",children:h.name}),l.jsxs("span",{className:"text-xs text-[var(--color-text-muted)]",children:[":",h.port]}),h.nativeCapable&&g==="darwin"&&l.jsx("span",{className:"rounded bg-amber-500/10 px-1.5 py-0.5 text-[10px] font-medium text-amber-500",children:"Native"})]}),l.jsx("p",{className:"truncate text-xs text-[var(--color-text-muted)]",children:h.description})]})]}),x&&l.jsxs("button",{type:"button",onClick:()=>v?.(h.id,!j),className:te("flex w-full items-center gap-2 border-t border-[var(--color-border)]/50 px-3 py-2 text-left text-xs","hover:bg-[var(--color-surface-alt)] transition-colors"),children:[l.jsx(On,{size:12,className:j?"text-amber-500":"text-[var(--color-text-muted)]"}),l.jsx("span",{className:j?"text-[var(--color-text)]":"text-[var(--color-text-muted)]",children:"Run natively via LaunchAgent"}),l.jsx("span",{className:"ml-auto text-[var(--color-text-muted)]",children:j?"On (uses Apple GPU)":"Off (runs in Docker)"})]})]},h.id)})})]})}function Z4(){const{state:a}=fr(),[s,o]=N.useState(null);if(N.useEffect(()=>{bg().then(o).catch(()=>{})},[]),!s)return l.jsx("div",{className:"flex items-center justify-center py-12",children:l.jsx(Ct,{size:32,className:"animate-spin text-[var(--color-primary)]"})});const i=s.services.filter(x=>x.category==="core"),d=s.services.filter(x=>x.category!=="core"&&a.enabledModules.includes(x.id)),f=[...i,...d],m=new Map;for(const x of f){const j=a.portOverrides[x.id]??x.port,k=m.get(j)??[];m.set(j,[...k,x.name])}const v=[...m.entries()].filter(([,x])=>x.length>1),g=f.filter(x=>x.database).length,h=f.filter(x=>a.nativeServices.includes(x.id)),y=f.filter(x=>!a.nativeServices.includes(x.id));return l.jsxs("div",{className:"space-y-6",children:[l.jsxs("div",{children:[l.jsx("h2",{className:"text-xl font-bold text-[var(--color-text)]",children:"Review Configuration"}),l.jsx("p",{className:"mt-1 text-sm text-[var(--color-text-muted)]",children:"Review your selections before installing."})]}),l.jsxs("div",{className:"grid grid-cols-3 gap-3",children:[l.jsx(Iu,{label:"Docker Services",value:y.length}),l.jsx(Iu,{label:"Native Services",value:h.length}),l.jsx(Iu,{label:"Databases",value:g})]}),l.jsxs("div",{className:"rounded-lg border border-[var(--color-border)] bg-[var(--color-surface-alt)] p-4",children:[l.jsx("p",{className:"text-xs font-medium uppercase text-[var(--color-text-muted)]",children:"Deployment Mode"}),l.jsx("p",{className:"mt-1 text-sm font-medium text-[var(--color-text)]",children:a.deploymentMode==="local"?"Local (all services on this machine)":"Remote LLM"}),a.deploymentMode==="remote-llm"&&a.remoteLlmUrl&&l.jsxs("p",{className:"mt-0.5 text-xs text-[var(--color-text-muted)]",children:["LLM: ",a.remoteLlmUrl]})]}),l.jsxs("div",{className:"rounded-lg border border-[var(--color-border)] overflow-hidden",children:[l.jsx("div",{className:"border-b border-[var(--color-border)] bg-[var(--color-surface-alt)] px-3 py-2",children:l.jsxs("span",{className:"text-xs font-medium text-[var(--color-text-muted)]",children:["Services (",f.length,")"]})}),l.jsx("div",{className:"divide-y divide-[var(--color-border)]",children:f.map(x=>l.jsxs("div",{className:"flex items-center justify-between px-3 py-2",children:[l.jsxs("div",{className:"flex items-center gap-2",children:[l.jsx(ht,{size:14,className:"text-green-500"}),l.jsx("span",{className:"text-sm text-[var(--color-text)]",children:x.name})]}),l.jsxs("span",{className:"text-xs text-[var(--color-text-muted)]",children:[":",a.portOverrides[x.id]??x.port]})]},x.id))})]}),a.relayEnabled&&l.jsxs("div",{className:"rounded-lg border border-[var(--color-border)] bg-[var(--color-surface-alt)] p-4",children:[l.jsx("p",{className:"text-xs font-medium uppercase text-[var(--color-text-muted)]",children:"Jarvis Relay"}),l.jsx("p",{className:"mt-1 text-sm font-medium text-[var(--color-text)]",children:"Enabled"}),l.jsx("p",{className:"mt-0.5 text-xs text-[var(--color-text-muted)]",children:"https://relay.jarvisautomation.io"})]}),v.length>0&&l.jsxs("div",{className:"rounded-lg border border-amber-500/30 bg-amber-500/5 p-4",children:[l.jsxs("div",{className:"flex items-center gap-2",children:[l.jsx(ra,{size:16,className:"text-amber-500"}),l.jsx("span",{className:"text-sm font-medium text-amber-500",children:"Port Conflicts"})]}),v.map(([x,j])=>l.jsxs("p",{className:"mt-1 text-xs text-[var(--color-text-muted)]",children:["Port ",x,": ",j.join(", ")]},x))]})]})}function Iu({label:a,value:s}){return l.jsxs("div",{className:"rounded-lg border border-[var(--color-border)] bg-[var(--color-surface-alt)] p-3 text-center",children:[l.jsx("p",{className:"text-2xl font-bold text-[var(--color-primary)]",children:s}),l.jsx("p",{className:"text-xs text-[var(--color-text-muted)]",children:a})]})}function Wu(){const[a,s]=N.useState({lines:[],running:!1,done:!1,exitCode:null,error:null,redirect:null}),o=N.useRef(null),i=N.useCallback((f,m)=>(o.current?.close(),s({lines:[],running:!0,done:!1,exitCode:null,error:null,redirect:null}),new Promise((v,g)=>{const h=new EventSource(f);o.current=h,h.onmessage=y=>{try{const x=JSON.parse(y.data);if(m&&m(x),"done"in x){if(s(j=>({...j,running:!1,done:!0,exitCode:x.code,redirect:x.redirect??null})),h.close(),x.code===0)v(x.code);else{const j=x.error?String(x.error):`Process exited with code ${x.code}`;g(new Error(j))}return}if("stream"in x&&"text"in x){const j={stream:x.stream,text:x.text,timestamp:Date.now()};s(k=>({...k,lines:[...k.lines,j]}))}}catch{}},h.onerror=()=>{const y=o.current===null;s(x=>({...x,running:!1,error:x.done?null:"Connection lost"})),h.close(),y||g(new Error("Connection lost"))}})),[]),d=N.useCallback(()=>{o.current?.close(),o.current=null,s(f=>({...f,running:!1}))},[]);return{...a,run:i,stop:d}}function ed({lines:a,running:s,title:o,className:i}){const d=N.useRef(null),f=N.useRef(!0);N.useEffect(()=>{const v=d.current;!v||!f.current||(v.scrollTop=v.scrollHeight)},[a]);function m(){const v=d.current;if(!v)return;const g=v.scrollHeight-v.scrollTop-v.clientHeight;f.current=g<50}return l.jsxs("div",{className:te("flex flex-col rounded-lg border border-[var(--color-border)] overflow-hidden",i),children:[o&&l.jsxs("div",{className:"flex items-center gap-2 border-b border-[var(--color-border)] bg-[var(--color-surface)] px-3 py-2",children:[l.jsx("span",{className:"text-xs font-medium text-[var(--color-text-muted)]",children:o}),s&&l.jsx("span",{className:"h-2 w-2 animate-pulse rounded-full bg-green-500"})]}),l.jsxs("div",{ref:d,onScroll:m,className:"h-64 overflow-y-auto bg-[#0d1117] p-3 font-mono text-xs leading-5",children:[a.length===0&&!s&&l.jsx("span",{className:"text-gray-500",children:"Waiting for output..."}),a.map((v,g)=>l.jsx("div",{className:te("whitespace-pre-wrap break-all",v.stream==="stderr"?"text-yellow-400":"text-gray-300"),children:v.text},g)),s&&l.jsx("span",{className:"inline-block h-4 w-1.5 animate-pulse bg-gray-400"})]})]})}function J4(){const{state:a,dispatch:s}=fr(),o=Wu(),i=Wu(),d=Wu(),[f,m]=N.useState("idle"),[v,g]=N.useState(null),[h,y]=N.useState(null),[x,j]=N.useState({}),[k,w]=N.useState({}),[E,_]=N.useState(null),[A,M]=N.useState(null),[X,I]=N.useState(null),[ne,W]=N.useState({});N.useEffect(()=>{const ae=i.redirect;if(f!=="done"||!ae||a.platform==="darwin")return;M(5);const C=setInterval(()=>{M(Y=>Y===null||Y<=1?(clearInterval(C),window.location.href=ae,0):Y-1)},1e3);return()=>clearInterval(C)},[f,i.redirect]);const G=N.useCallback(async()=>{m("preflight"),y(null),g(null);try{const ae=await kE(a.enabledModules);return y(ae),ae.canProceed?!0:(g("Pre-flight checks failed. Fix the issues above and retry."),m("error"),_("preflight"),!1)}catch(ae){return g(`Pre-flight check failed: ${ae instanceof Error?ae.message:String(ae)}`),m("error"),_("preflight"),!1}},[a.enabledModules]);async function U(){if(a.nativeServices.length!==0){m("native");for(const ae of a.nativeServices){I(ae);try{await d.run(`/api/native-services/${ae}/install`),W(C=>({...C,[ae]:{ok:!0}}))}catch(C){const Y=C instanceof Error?C.message:String(C);W(K=>({...K,[ae]:{ok:!1,error:Y}}))}}I(null)}}async function oe(){g(null),j({}),_(null),W({}),s({type:"SET_INSTALL_RUNNING",running:!0});try{if(!await G()){s({type:"SET_INSTALL_RUNNING",running:!1});return}m("generating"),await Bx(a),m("pulling"),await o.run("/api/install/pull"),m("starting"),await i.run("/api/install/start",C=>{if(C.phase==="health"&&typeof C.service=="string"&&j(Y=>({...Y,[C.service]:{healthy:C.healthy,error:C.error}})),C.serviceHealth&&typeof C.serviceHealth=="object"){const Y=C.serviceHealth;j(K=>({...K,...Y}))}}),await U(),m("done"),s({type:"SET_INSTALL_COMPLETE"})}catch(ae){g(ae instanceof Error?ae.message:String(ae)),m("error"),_(f),s({type:"SET_INSTALL_RUNNING",running:!1})}}async function Ne(){if(E==="preflight"){if(g(null),s({type:"SET_INSTALL_RUNNING",running:!0}),!await G()){s({type:"SET_INSTALL_RUNNING",running:!1});return}try{m("generating"),await Bx(a),m("pulling"),await o.run("/api/install/pull"),m("starting"),await i.run("/api/install/start",C=>{if(C.phase==="health"&&typeof C.service=="string"&&j(Y=>({...Y,[C.service]:{healthy:C.healthy,error:C.error}})),C.serviceHealth&&typeof C.serviceHealth=="object"){const Y=C.serviceHealth;j(K=>({...K,...Y}))}}),await U(),m("done"),s({type:"SET_INSTALL_COMPLETE"})}catch(C){g(C instanceof Error?C.message:String(C)),m("error"),s({type:"SET_INSTALL_RUNNING",running:!1})}}else oe()}async function le(ae){try{const C=await fetch(`/api/containers/${ae}/logs`);if(C.ok){const Y=await C.text();w(K=>({...K,[ae]:Y}))}else w(Y=>({...Y,[ae]:`Failed to fetch logs: HTTP ${C.status}`}))}catch(C){w(Y=>({...Y,[ae]:`Failed to fetch logs: ${C instanceof Error?C.message:String(C)}`}))}}const pe=[{key:"preflight",label:"Pre-flight checks"},{key:"generating",label:"Generate configuration"},{key:"pulling",label:"Pull Docker images"},{key:"starting",label:"Start services"},...a.nativeServices.length>0?[{key:"native",label:`Install ${a.nativeServices.length} native service${a.nativeServices.length===1?"":"s"}`}]:[]],Re=pe.map(ae=>ae.key).indexOf(f);return l.jsxs("div",{className:"space-y-6",children:[l.jsxs("div",{children:[l.jsx("h2",{className:"text-xl font-bold text-[var(--color-text)]",children:"Install"}),l.jsx("p",{className:"mt-1 text-sm text-[var(--color-text-muted)]",children:f==="idle"?"Ready to install. This will pull Docker images and start all services.":f==="done"?i.redirect&&a.platform!=="darwin"?`Installation complete! Redirecting to your admin dashboard in ${A??"..."}s...`:"Installation complete! Click Next to create your account and choose your models.":f==="error"?"Installation encountered an error.":"Installing..."})]}),h&&l.jsxs("div",{className:"rounded-lg border border-[var(--color-border)] overflow-hidden",children:[l.jsx("div",{className:"border-b border-[var(--color-border)] bg-[var(--color-surface-alt)] px-3 py-2",children:l.jsx("span",{className:"text-xs font-medium text-[var(--color-text-muted)]",children:"Pre-flight Checks"})}),l.jsx("div",{className:"divide-y divide-[var(--color-border)]",children:h.checks.map(ae=>l.jsx("div",{className:"flex items-center justify-between px-3 py-2",children:l.jsxs("div",{className:"flex items-center gap-2",children:[ae.status==="pass"?l.jsx(ht,{size:14,className:"text-green-500"}):ae.status==="warn"?l.jsx(ra,{size:14,className:"text-amber-500"}):l.jsx(xl,{size:14,className:"text-red-500"}),l.jsxs("div",{children:[l.jsx("span",{className:"text-sm text-[var(--color-text)]",children:ae.name}),l.jsx("p",{className:"text-xs text-[var(--color-text-muted)]",children:ae.message}),ae.details&&ae.status!=="pass"&&l.jsx("p",{className:"text-xs text-[var(--color-text-muted)] opacity-60",children:ae.details})]})]})},ae.name))})]}),l.jsx("div",{className:"space-y-2",children:pe.map((ae,C)=>{const Y=ae.key===f,K=Re>C||f==="done",xe=f==="error"&&ae.key===E;return l.jsxs("div",{className:"flex items-center gap-3",children:[K?l.jsx(ht,{size:18,className:"text-green-500"}):xe?l.jsx(xl,{size:18,className:"text-red-500"}):Y?l.jsx(Ct,{size:18,className:"animate-spin text-[var(--color-primary)]"}):l.jsx("div",{className:"h-[18px] w-[18px] rounded-full border-2 border-[var(--color-border)]"}),l.jsx("span",{className:te("text-sm",K?"text-green-500":Y?"font-medium text-[var(--color-text)]":"text-[var(--color-text-muted)]"),children:ae.label})]},ae.key)})}),(f==="starting"||f==="done"||f==="error")&&Object.keys(x).length>0&&l.jsxs("div",{className:"rounded-lg border border-[var(--color-border)] overflow-hidden",children:[l.jsx("div",{className:"border-b border-[var(--color-border)] bg-[var(--color-surface-alt)] px-3 py-2",children:l.jsx("span",{className:"text-xs font-medium text-[var(--color-text-muted)]",children:"Service Status"})}),l.jsx("div",{className:"divide-y divide-[var(--color-border)]",children:Object.entries(x).map(([ae,C])=>l.jsxs("div",{children:[l.jsxs("div",{className:"flex items-center justify-between px-3 py-2",children:[l.jsx("span",{className:"text-sm text-[var(--color-text)]",children:ae}),l.jsxs("div",{className:"flex items-center gap-2",children:[!C.healthy&&l.jsxs("button",{type:"button",onClick:()=>le(ae),className:"flex items-center gap-1 text-xs text-[var(--color-text-muted)] hover:text-[var(--color-text)]",children:[l.jsx(tg,{size:12}),"Logs"]}),C.healthy?l.jsx(ht,{size:14,className:"text-green-500"}):l.jsx(xl,{size:14,className:"text-red-500"})]})]}),C.error&&l.jsx("p",{className:"px-3 pb-2 text-xs text-red-400",children:C.error}),k[ae]&&l.jsx("div",{className:"mx-3 mb-2 max-h-32 overflow-auto rounded bg-[var(--color-background)] p-2 text-xs font-mono text-[var(--color-text-muted)]",children:l.jsx("pre",{className:"whitespace-pre-wrap",children:k[ae]})})]},ae))})]}),(o.lines.length>0||o.running)&&l.jsx(ed,{lines:o.lines,running:o.running,title:"docker compose pull"}),(i.lines.length>0||i.running)&&l.jsx(ed,{lines:i.lines,running:i.running,title:"docker compose up -d"}),(f==="native"||Object.keys(ne).length>0)&&l.jsxs("div",{className:"rounded-lg border border-[var(--color-border)] overflow-hidden",children:[l.jsx("div",{className:"border-b border-[var(--color-border)] bg-[var(--color-surface-alt)] px-3 py-2",children:l.jsx("span",{className:"text-xs font-medium text-[var(--color-text-muted)]",children:"Native Services (LaunchAgents)"})}),l.jsx("div",{className:"divide-y divide-[var(--color-border)]",children:a.nativeServices.map(ae=>{const C=ne[ae],Y=X===ae&&f==="native";return l.jsxs("div",{className:"px-3 py-2",children:[l.jsxs("div",{className:"flex items-center justify-between",children:[l.jsx("span",{className:"text-sm text-[var(--color-text)]",children:ae}),C?.ok?l.jsx(ht,{size:14,className:"text-green-500"}):C?l.jsx(xl,{size:14,className:"text-red-500"}):Y?l.jsx(Ct,{size:14,className:"animate-spin text-[var(--color-primary)]"}):l.jsx("div",{className:"h-3 w-3 rounded-full border border-[var(--color-border)]"})]}),C?.error&&l.jsx("p",{className:"mt-1 text-xs text-red-400",children:C.error})]},ae)})})]}),(d.lines.length>0||d.running)&&l.jsx(ed,{lines:d.lines,running:d.running,title:X?`deploy-launchd.sh (${X})`:"deploy-launchd.sh"}),v&&l.jsx("div",{className:"rounded-lg bg-red-500/10 px-3 py-2 text-sm text-red-500",children:v}),(f==="idle"||f==="error")&&l.jsxs("button",{type:"button",onClick:f==="error"?Ne:oe,className:te("flex w-full items-center justify-center gap-2 rounded-lg bg-[var(--color-primary)] px-4 py-3 font-medium text-white","hover:opacity-90 transition-opacity"),children:[f==="error"?l.jsx(gi,{size:18}):l.jsx(ag,{size:18}),f==="error"?"Retry Installation":"Start Installation"]})]})}const P4="jarvis-llm-proxy-api";function I4(){const{state:a,dispatch:s}=fr(),o=yg(),i=wg(),d=jg(),f=a.platform==="darwin",[m,v]=N.useState("select"),[g,h]=N.useState(null),[y,x]=N.useState("GGUF"),[j,k]=N.useState(""),[w,E]=N.useState(!0),[_,A]=N.useState(null);if(a.deploymentMode==="remote-llm")return l.jsxs("div",{className:"space-y-6",children:[l.jsxs("div",{children:[l.jsx("h2",{className:"text-xl font-bold text-[var(--color-text)]",children:"Models"}),l.jsx("p",{className:"mt-1 text-sm text-[var(--color-text-muted)]",children:"Your LLM is configured to use a remote server."})]}),l.jsxs("div",{className:"flex items-center gap-3 rounded-lg border border-green-500/30 bg-green-500/5 p-4",children:[l.jsx(ht,{size:20,className:"text-green-500"}),l.jsxs("div",{children:[l.jsx("p",{className:"text-sm font-medium text-[var(--color-text)]",children:"Remote LLM configured"}),l.jsx("p",{className:"text-xs text-[var(--color-text-muted)]",children:a.remoteLlmUrl})]})]})]});const M=U=>{h(U),A(null),U.gated&&!j.trim()?v("token"):I(U,j.trim())},X=()=>{if(!j.trim()){A("HuggingFace token is required for gated models");return}g&&I(g,j)},I=async(U,oe)=>{A(null),v("downloading");const Ne=y==="GGUF"?U.hfRepoGguf:U.hfRepoVllm,le=y==="GGUF"?U.ggufFilename:void 0;try{await i.mutateAsync({repo:Ne,filename:le,token:oe||void 0})}catch(Ee){A(`Download failed: ${Ee.message}`),v("select");return}if(await ne(U)){if(w){v("whisper");try{await v4(!0)}catch(Ee){console.warn("[models] whisper auto-download setup failed:",Ee)}}v("done")}},ne=async U=>{v("configuring");const Ne={"model.live.name":y==="GGUF"?`.models/${U.ggufFilename}`:`.models/${U.hfRepoVllm.split("/").pop()}`,"model.live.backend":y,"model.live.chat_format":U.chatFormat,"model.live.context_window":U.contextWindow,"llm.interface":U.promptProvider};y==="GGUF"&&(Ne["inference.gguf.n_gpu_layers"]=-1),y==="VLLM"&&U.quantization&&(Ne["inference.vllm.quantization"]=U.quantization);try{if(await o.mutateAsync(Ne),f)try{await d.mutateAsync(P4)}catch(le){console.warn("[models] llm-proxy restart failed (KeepAlive will retry):",le)}return s({type:"SET_LLM_INTERFACE",interfaceId:U.promptProvider}),!0}catch(le){return A(`Configuration failed: ${le.message}`),v("select"),!1}},W=a.hardware?.gpuVramMb,G=W?ss.filter(U=>U.vramMb<=W):ss;return l.jsxs("div",{className:"space-y-6",children:[l.jsxs("div",{children:[l.jsx("h2",{className:"text-xl font-bold text-[var(--color-text)]",children:"Models"}),l.jsx("p",{className:"mt-1 text-sm text-[var(--color-text-muted)]",children:m==="done"?"Models configured. Services are restarting to load them.":"Choose a language model, and optionally fetch the speech-to-text model."})]}),_&&l.jsxs("div",{className:"space-y-2",children:[l.jsxs("div",{className:"flex items-start gap-2 rounded-lg border border-red-500/30 bg-red-500/10 p-3 text-sm text-red-500",children:[l.jsx(ra,{size:16,className:"mt-0.5 shrink-0"}),_]}),g&&l.jsxs("button",{type:"button",onClick:()=>I(g,j),className:te("flex w-full items-center justify-center gap-2 rounded-lg border border-[var(--color-border)] px-4 py-2 text-sm","hover:bg-[var(--color-surface-alt)] transition-colors"),children:[l.jsx(gi,{size:14}),"Retry"]})]}),m==="select"&&l.jsxs(l.Fragment,{children:[!f&&l.jsxs("div",{className:"flex items-center justify-between",children:[l.jsx("span",{className:"text-sm font-medium text-[var(--color-text)]",children:"Backend"}),l.jsx("div",{className:"flex gap-2",children:["GGUF","VLLM"].map(U=>l.jsx("button",{type:"button",onClick:()=>x(U),className:te("rounded-md px-3 py-1 text-xs font-medium transition-colors",y===U?"bg-[var(--color-primary)] text-white":"bg-[var(--color-surface-alt)] text-[var(--color-text-muted)] hover:text-[var(--color-text)]"),children:U==="VLLM"?"vLLM":U},U))})]}),l.jsxs("label",{className:te("flex cursor-pointer items-start gap-3 rounded-lg border p-3 transition-colors",w?"border-[var(--color-primary)] bg-[var(--color-primary)]/5":"border-[var(--color-border)]"),children:[l.jsx("input",{type:"checkbox",checked:w,onChange:U=>E(U.target.checked),className:"mt-0.5"}),l.jsxs("span",{className:"flex items-center gap-2 text-sm text-[var(--color-text)]",children:[l.jsx(kx,{size:15,className:"shrink-0 text-[var(--color-primary)]"}),l.jsxs("span",{children:["Auto-download the speech-to-text model",l.jsxs("span",{className:"block text-xs text-[var(--color-text-muted)]",children:["Whisper ",l.jsx("code",{children:"base.en"})," (~150 MB, no token needed). Required for voice."]})]})]})]}),l.jsxs("div",{children:[l.jsx("label",{htmlFor:"hf-token",className:"mb-1 block text-xs text-[var(--color-text-muted)]",children:"HuggingFace Token (optional — speeds up downloads, required for gated models)"}),l.jsx("input",{id:"hf-token",type:"password",value:j,onChange:U=>k(U.target.value),placeholder:"hf_...",className:te("w-full rounded-lg border border-[var(--color-border)] bg-[var(--color-surface-alt)] px-3 py-2","text-sm text-[var(--color-text)] placeholder:text-[var(--color-text-muted)]","outline-none focus:ring-2 focus:ring-[var(--color-primary)]")})]}),l.jsxs("div",{className:"space-y-2",children:[l.jsx("span",{className:"text-sm font-medium text-[var(--color-text)]",children:"Language model"}),G.map(U=>l.jsxs("button",{type:"button",onClick:()=>M(U),className:te("flex w-full items-center justify-between rounded-lg border border-[var(--color-border)] p-3 text-left transition-colors","hover:border-[var(--color-primary)] hover:bg-[var(--color-surface-alt)]"),children:[l.jsxs("div",{children:[l.jsxs("div",{className:"flex items-center gap-2",children:[l.jsx("span",{className:"text-sm font-medium text-[var(--color-text)]",children:U.displayName}),U.gated&&l.jsxs("span",{className:"flex items-center gap-0.5 rounded bg-yellow-500/15 px-1.5 py-0.5 text-[10px] font-medium text-yellow-600 dark:text-yellow-400",children:[l.jsx(vi,{size:10}),"Gated"]})]}),l.jsxs("p",{className:"mt-0.5 text-xs text-[var(--color-text-muted)]",children:[U.promptProvider," · ",U.contextWindow.toLocaleString()," ctx"]})]}),l.jsxs("span",{className:"text-xs text-[var(--color-text-muted)]",children:["~",y==="GGUF"?U.sizeGguf:U.sizeVllm]})]},U.id)),G.length===0&&l.jsxs("p",{className:"py-4 text-center text-sm text-[var(--color-text-muted)]",children:["No models fit your available memory (",W?Math.round(W/1024)+" GB":"unknown",")."]}),W&&G.length<ss.length&&l.jsxs("p",{className:"text-xs text-[var(--color-text-muted)]",children:["Showing ",G.length," of ",ss.length," models that fit your ",Math.round(W/1024)," GB."]})]})]}),m==="token"&&g&&l.jsxs("div",{className:"space-y-4",children:[l.jsxs("p",{className:"text-sm text-[var(--color-text-muted)]",children:[l.jsx("strong",{children:g.displayName})," is a gated model. Accept the license on HuggingFace and paste your access token below."]}),l.jsx("input",{type:"password",value:j,onChange:U=>k(U.target.value),placeholder:"hf_...",className:te("w-full rounded-lg border border-[var(--color-border)] bg-[var(--color-surface-alt)] px-3 py-2","text-sm text-[var(--color-text)] placeholder:text-[var(--color-text-muted)]","outline-none focus:ring-2 focus:ring-[var(--color-primary)]")}),l.jsxs("div",{className:"flex justify-between",children:[l.jsx("button",{type:"button",onClick:()=>{v("select"),A(null)},className:"text-sm text-[var(--color-text-muted)] hover:text-[var(--color-text)]",children:"Back"}),l.jsx("button",{type:"button",onClick:X,className:"rounded-lg bg-[var(--color-primary)] px-4 py-2 text-sm text-white hover:opacity-90",children:"Download"})]})]}),m==="whisper"&&l.jsxs("div",{className:"flex flex-col items-center py-8",children:[l.jsx(kx,{className:"mb-4 animate-pulse text-[var(--color-primary)]",size:32}),l.jsx("p",{className:"text-sm font-medium text-[var(--color-text)]",children:"Enabling speech-to-text model download..."}),l.jsx("p",{className:"mt-1 text-xs text-[var(--color-text-muted)]",children:"Whisper will fetch ggml-base.en on restart"})]}),m==="downloading"&&l.jsxs("div",{className:"flex flex-col items-center py-8",children:[l.jsx(en,{className:"mb-4 animate-bounce text-[var(--color-primary)]",size:32}),l.jsxs("p",{className:"text-sm font-medium text-[var(--color-text)]",children:["Downloading ",g?.displayName,"..."]}),l.jsxs("p",{className:"mt-1 text-xs text-[var(--color-text-muted)]",children:["~",y==="GGUF"?g?.sizeGguf:g?.sizeVllm," · This may take several minutes"]})]}),m==="configuring"&&l.jsxs("div",{className:"flex flex-col items-center py-8",children:[l.jsx(Ct,{className:"mb-4 animate-spin text-[var(--color-primary)]",size:32}),l.jsx("p",{className:"text-sm font-medium text-[var(--color-text)]",children:"Configuring model and prompt provider..."})]}),m==="done"&&g&&l.jsxs("div",{className:"space-y-4",children:[l.jsxs("div",{className:"flex items-center gap-3 rounded-lg border border-green-500/30 bg-green-500/5 p-4",children:[l.jsx(ht,{size:20,className:"text-green-500"}),l.jsxs("div",{children:[l.jsxs("p",{className:"text-sm font-medium text-[var(--color-text)]",children:[g.displayName," configured"]}),l.jsxs("p",{className:"text-xs text-[var(--color-text-muted)]",children:["Backend: ",y," · Prompt provider: ",g.promptProvider,w&&" · Whisper auto-download enabled"]})]})]}),l.jsxs("p",{className:"text-xs text-[var(--color-text-muted)]",children:["The LLM proxy is restarting with the new model",w&&", and whisper is fetching its model",". This may take a few minutes to finish loading. Command Center will use the"," ",l.jsx("strong",{children:g.promptProvider})," prompt provider."]})]})]})}function W4(){const[a,s]=N.useState(""),[o,i]=N.useState(""),[d,f]=N.useState(""),[m,v]=N.useState(""),[g,h]=N.useState(!1),[y,x]=N.useState(!1),[j,k]=N.useState(null),w=o===d,E=a&&o&&d&&m&&w&&!g;async function _(){if(E){h(!0),k(null);try{const M=await Jv(a,o,m);rs(M.access_token),localStorage.setItem("access_token",M.access_token),localStorage.setItem("refresh_token",M.refresh_token),x(!0)}catch(M){const X=M?.response?.data?.error??(M instanceof Error?M.message:"Failed to create account");k(X)}finally{h(!1)}}}if(y)return l.jsxs("div",{className:"space-y-6",children:[l.jsx("div",{children:l.jsx("h2",{className:"text-xl font-bold text-[var(--color-text)]",children:"Account Created"})}),l.jsxs("div",{className:"flex items-center gap-3 rounded-lg border border-green-500/30 bg-green-500/5 p-4",children:[l.jsx(ht,{size:20,className:"text-green-500"}),l.jsxs("div",{children:[l.jsx("p",{className:"text-sm font-medium text-[var(--color-text)]",children:"Superuser account created"}),l.jsx("p",{className:"text-xs text-[var(--color-text-muted)]",children:a})]})]}),l.jsx("p",{className:"text-sm text-[var(--color-text-muted)]",children:`You're logged in. Click "Next" to configure your LLM model.`})]});const A=te("w-full rounded-lg border border-[var(--color-border)] bg-[var(--color-surface-alt)] px-3 py-2","text-sm text-[var(--color-text)] placeholder:text-[var(--color-text-muted)]","outline-none focus:ring-2 focus:ring-[var(--color-primary)]");return l.jsxs("div",{className:"space-y-6",children:[l.jsxs("div",{children:[l.jsx("h2",{className:"text-xl font-bold text-[var(--color-text)]",children:"Create Account"}),l.jsx("p",{className:"mt-1 text-sm text-[var(--color-text-muted)]",children:"Create your superuser account. This will be the admin for your Jarvis instance."})]}),l.jsxs("div",{className:"space-y-4",children:[l.jsxs("div",{children:[l.jsx("label",{htmlFor:"display-name",className:"mb-1 block text-sm text-[var(--color-text-muted)]",children:"Display Name"}),l.jsx("input",{id:"display-name",type:"text",value:m,onChange:M=>v(M.target.value),className:A,placeholder:"Alex"})]}),l.jsxs("div",{children:[l.jsx("label",{htmlFor:"email",className:"mb-1 block text-sm text-[var(--color-text-muted)]",children:"Email"}),l.jsx("input",{id:"email",type:"email",value:a,onChange:M=>s(M.target.value),className:A,placeholder:"admin@example.com"})]}),l.jsxs("div",{children:[l.jsx("label",{htmlFor:"password",className:"mb-1 block text-sm text-[var(--color-text-muted)]",children:"Password"}),l.jsx("input",{id:"password",type:"password",value:o,onChange:M=>i(M.target.value),className:A,placeholder:"Choose a strong password"})]}),l.jsxs("div",{children:[l.jsx("label",{htmlFor:"confirm-password",className:"mb-1 block text-sm text-[var(--color-text-muted)]",children:"Confirm Password"}),l.jsx("input",{id:"confirm-password",type:"password",value:d,onChange:M=>f(M.target.value),className:te(A,d&&!w&&"ring-2 ring-red-500"),placeholder:"Confirm password"}),d&&!w&&l.jsx("p",{className:"mt-1 text-xs text-red-500",children:"Passwords don't match"})]})]}),j&&l.jsxs("div",{className:"space-y-2",children:[l.jsxs("div",{className:"flex items-center gap-2 rounded-lg bg-red-500/10 px-3 py-2",children:[l.jsx(Bd,{size:14,className:"text-red-500 shrink-0"}),l.jsx("span",{className:"text-sm text-red-500",children:j})]}),l.jsxs("button",{type:"button",onClick:_,disabled:!E,className:te("flex w-full items-center justify-center gap-2 rounded-lg border border-[var(--color-border)] px-4 py-2 text-sm","hover:bg-[var(--color-surface-alt)] transition-colors","disabled:opacity-50"),children:[l.jsx(gi,{size:14}),"Retry"]})]}),!j&&l.jsx("button",{type:"button",onClick:_,disabled:!E,className:te("w-full rounded-lg bg-[var(--color-primary)] px-4 py-2 font-medium text-white","hover:opacity-90 disabled:opacity-50 transition-opacity"),children:g?"Creating...":"Create Superuser Account"})]})}const Zo=[{label:"Welcome",component:Y4},{label:"Hardware",component:X4},{label:"Services",component:K4},{label:"Review",component:Z4},{label:"Install",component:J4},{label:"Account",component:W4},{label:"Models",component:I4}],e3=5;function t3({skipToAccount:a}){const{state:s,dispatch:o}=fr();N.useEffect(()=>{a&&o({type:"SET_STEP",step:e3})},[a,o]);const i=wa(),d=Zo[s.currentStep].component,f=s.currentStep===0,m=s.currentStep===Zo.length-1,h=s.currentStep===4&&!s.installComplete,y=s.installRunning||h;function x(){m?i("/login"):o({type:"NEXT_STEP"})}function j(){o({type:"PREV_STEP"})}return l.jsx("div",{className:"flex min-h-screen items-center justify-center bg-[var(--color-background)] p-4",children:l.jsxs("div",{className:"w-full max-w-2xl",children:[l.jsx("div",{className:"mb-6 flex items-center justify-center gap-1",children:Zo.map((k,w)=>l.jsxs("button",{type:"button",onClick:()=>!y&&o({type:"SET_STEP",step:w}),disabled:y,className:te("flex items-center gap-1",y&&"cursor-not-allowed"),children:[l.jsx("div",{className:te("flex h-7 w-7 items-center justify-center rounded-full text-xs font-medium transition-colors",w===s.currentStep?"bg-[var(--color-primary)] text-white":w<s.currentStep?"bg-[var(--color-primary)]/20 text-[var(--color-primary)]":"bg-[var(--color-surface-alt)] text-[var(--color-text-muted)]"),children:w+1}),l.jsx("span",{className:te("hidden text-xs sm:inline",w===s.currentStep?"font-medium text-[var(--color-text)]":"text-[var(--color-text-muted)]"),children:k.label}),w<Zo.length-1&&l.jsx("div",{className:te("mx-1 h-px w-4 sm:w-6",w<s.currentStep?"bg-[var(--color-primary)]/30":"bg-[var(--color-border)]")})]},k.label))}),l.jsx("div",{className:"rounded-xl border border-[var(--color-border)] bg-[var(--color-surface)] p-6 shadow-lg",children:l.jsx(d,{})}),l.jsxs("div",{className:"mt-4 flex justify-between",children:[l.jsx("button",{type:"button",onClick:j,disabled:f||y,className:te("rounded-lg border border-[var(--color-border)] px-4 py-2 text-sm","hover:bg-[var(--color-surface-alt)] transition-colors","disabled:invisible"),children:"Back"}),l.jsx("button",{type:"button",onClick:x,disabled:y,className:te("rounded-lg bg-[var(--color-primary)] px-6 py-2 text-sm font-medium text-white","hover:opacity-90 transition-opacity","disabled:opacity-50 disabled:cursor-not-allowed"),children:m?"Finish":"Next"})]})]})})}function a3({skipToAccount:a}){return l.jsx(F4,{children:l.jsx(t3,{skipToAccount:a})})}function n3(){const a=wa(),s=yg(),o=RE(),[i,d]=N.useState("select"),[f,m]=N.useState(null),[v,g]=N.useState("GGUF"),[h,y]=N.useState(""),[x,j]=N.useState(null),k=M=>{m(M),M.gated?d("token"):E(M,"")},w=()=>{if(!h.trim()){j("HuggingFace token is required for gated models");return}j(null),f&&E(f,h)},E=async(M,X)=>{d("download"),j(null);const I=v==="GGUF"?M.hfRepoGguf:M.hfRepoVllm,ne=v==="GGUF"?M.ggufFilename:void 0;try{await o.mutateAsync({repo:I,filename:ne,token:X||void 0}),_(M)}catch(W){j(`Download failed: ${W.message}`),d("select")}},_=async M=>{d("configure"),j(null);const I={"model.live.name":v==="GGUF"?`.models/${M.ggufFilename}`:`.models/${M.hfRepoVllm.split("/").pop()}`,"model.live.backend":v,"model.live.chat_format":M.chatFormat,"model.live.context_window":M.contextWindow};v==="GGUF"&&(I["inference.gguf.n_gpu_layers"]=-1),v==="VLLM"&&M.quantization&&(I["inference.vllm.quantization"]=M.quantization);try{await s.mutateAsync(I),d("done"),Me.success("LLM configured successfully")}catch(ne){j(`Configuration failed: ${ne.message}`),d("select")}},A=()=>{a("/dashboard")};return l.jsx("div",{className:"flex min-h-screen items-center justify-center bg-[var(--color-bg)] p-4",children:l.jsxs("div",{className:"w-full max-w-2xl rounded-xl border border-[var(--color-border)] bg-[var(--color-surface)] p-8 shadow-lg",children:[l.jsxs("div",{className:"mb-8 text-center",children:[l.jsx(pd,{className:"mx-auto mb-3 text-[var(--color-primary)]",size:40}),l.jsx("h1",{className:"text-2xl font-bold text-[var(--color-text)]",children:"LLM Setup"}),l.jsx("p",{className:"mt-1 text-sm text-[var(--color-text-muted)]",children:"Configure a local language model for Jarvis"})]}),l.jsx("div",{className:"mb-8 flex items-center justify-center gap-2",children:["select","download","configure","done"].map((M,X)=>{const I=i==="token"?"select":i,ne=["select","download","configure","done"];return l.jsxs("div",{className:"flex items-center gap-2",children:[l.jsx("div",{className:te("h-2 w-2 rounded-full",I===M?"bg-[var(--color-primary)]":ne.indexOf(I)>X?"bg-green-500":"bg-[var(--color-border)]")}),X<3&&l.jsx("div",{className:"h-px w-8 bg-[var(--color-border)]"})]},M)})}),x&&l.jsxs("div",{className:"mb-6 flex items-start gap-2 rounded-lg border border-red-500/30 bg-red-500/10 p-3 text-sm text-red-500",children:[l.jsx(ra,{size:16,className:"mt-0.5 shrink-0"}),x]}),i==="select"&&l.jsxs("div",{className:"space-y-4",children:[l.jsxs("div",{className:"mb-4 flex items-center justify-between",children:[l.jsx("h2",{className:"text-sm font-semibold text-[var(--color-text)]",children:"Select a model"}),l.jsxs("div",{className:"flex gap-2",children:[l.jsx("button",{onClick:()=>g("GGUF"),className:te("rounded-md px-3 py-1 text-xs font-medium transition-colors",v==="GGUF"?"bg-[var(--color-primary)] text-white":"bg-[var(--color-surface-alt)] text-[var(--color-text-muted)] hover:text-[var(--color-text)]"),children:"GGUF"}),l.jsx("button",{onClick:()=>g("VLLM"),className:te("rounded-md px-3 py-1 text-xs font-medium transition-colors",v==="VLLM"?"bg-[var(--color-primary)] text-white":"bg-[var(--color-surface-alt)] text-[var(--color-text-muted)] hover:text-[var(--color-text)]"),children:"vLLM"})]})]}),l.jsx("div",{className:"grid gap-3",children:ss.map(M=>l.jsxs("button",{onClick:()=>k(M),className:te("flex items-center justify-between rounded-lg border border-[var(--color-border)] p-4 text-left transition-colors","hover:border-[var(--color-primary)] hover:bg-[var(--color-surface-alt)]"),children:[l.jsxs("div",{children:[l.jsxs("div",{className:"flex items-center gap-2",children:[l.jsx("span",{className:"font-medium text-[var(--color-text)]",children:M.displayName}),M.gated&&l.jsxs("span",{className:"flex items-center gap-1 rounded bg-yellow-500/15 px-1.5 py-0.5 text-[10px] font-medium text-yellow-600 dark:text-yellow-400",children:[l.jsx(vi,{size:10}),"Gated"]})]}),l.jsxs("p",{className:"mt-0.5 text-xs text-[var(--color-text-muted)]",children:[M.quantization?`${M.quantization.toUpperCase()} 4-bit`:M.chatFormat," · ",M.contextWindow.toLocaleString()," ctx"]})]}),l.jsxs("span",{className:"text-sm text-[var(--color-text-muted)]",children:["~",v==="GGUF"?M.sizeGguf:M.sizeVllm]})]},M.id))}),l.jsx("div",{className:"flex justify-end pt-2",children:l.jsx("button",{onClick:A,className:"text-sm text-[var(--color-text-muted)] hover:text-[var(--color-text)]",children:"Skip for now"})})]}),i==="token"&&f&&l.jsxs("div",{className:"space-y-4",children:[l.jsx("h2",{className:"text-sm font-semibold text-[var(--color-text)]",children:"HuggingFace Access Required"}),l.jsxs("p",{className:"text-sm text-[var(--color-text-muted)]",children:[l.jsx("strong",{children:f.displayName})," is a gated model. You need to:"]}),l.jsxs("ol",{className:"list-inside list-decimal space-y-1 text-sm text-[var(--color-text-muted)]",children:[l.jsx("li",{children:"Visit the model page on huggingface.co and accept the license agreement"}),l.jsx("li",{children:"Create an access token at huggingface.co/settings/tokens"}),l.jsx("li",{children:"Paste your token below"})]}),l.jsx("input",{type:"password",value:h,onChange:M=>y(M.target.value),placeholder:"hf_...",className:te("w-full rounded-lg border border-[var(--color-border)] bg-[var(--color-bg)] px-3 py-2","text-sm text-[var(--color-text)] placeholder:text-[var(--color-text-muted)]","outline-none focus:ring-2 focus:ring-[var(--color-primary)]")}),l.jsxs("div",{className:"flex justify-between",children:[l.jsx("button",{onClick:()=>{d("select"),j(null)},className:"text-sm text-[var(--color-text-muted)] hover:text-[var(--color-text)]",children:"Back"}),l.jsx("button",{onClick:w,className:"rounded-lg bg-[var(--color-primary)] px-4 py-2 text-sm text-white hover:opacity-90",children:"Continue"})]})]}),i==="download"&&l.jsxs("div",{className:"flex flex-col items-center py-8",children:[l.jsx(en,{className:"mb-4 animate-bounce text-[var(--color-primary)]",size:32}),l.jsx("h2",{className:"text-lg font-semibold text-[var(--color-text)]",children:"Downloading model..."}),l.jsxs("p",{className:"mt-1 text-sm text-[var(--color-text-muted)]",children:[f?.displayName," ","(~",v==="GGUF"?f?.sizeGguf:f?.sizeVllm,")"]}),l.jsx("p",{className:"mt-4 text-xs text-[var(--color-text-muted)]",children:"This may take several minutes depending on your connection"})]}),i==="configure"&&l.jsxs("div",{className:"flex flex-col items-center py-8",children:[l.jsx(ng,{className:"mb-4 animate-spin text-[var(--color-primary)]",size:32}),l.jsx("h2",{className:"text-lg font-semibold text-[var(--color-text)]",children:"Configuring..."}),l.jsx("p",{className:"mt-1 text-sm text-[var(--color-text-muted)]",children:"Writing settings and restarting LLM proxy"})]}),i==="done"&&l.jsxs("div",{className:"flex flex-col items-center py-8",children:[l.jsx(qj,{className:"mb-4 text-green-500",size:40}),l.jsx("h2",{className:"text-lg font-semibold text-[var(--color-text)]",children:"LLM Ready"}),l.jsxs("p",{className:"mt-1 text-sm text-[var(--color-text-muted)]",children:[f?.displayName," configured on ",v]}),l.jsx("p",{className:"mt-1 text-xs text-[var(--color-text-muted)]",children:"The model service is restarting. It may take a minute to load the model."}),l.jsx("button",{onClick:()=>a("/dashboard"),className:"mt-6 rounded-lg bg-[var(--color-primary)] px-6 py-2 text-sm text-white hover:opacity-90",children:"Go to Dashboard"})]}),(o.isPending||s.isPending)&&i!=="download"&&i!=="configure"&&l.jsx("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/40",children:l.jsx(Ct,{className:"animate-spin text-white",size:32})})]})})}const r3=new J1;function s3(){const[a,s]=N.useState(!0),[o,i]=N.useState(!1),[d,f]=N.useState(!1);return N.useEffect(()=>{Yd().then(m=>{m.state==="deployed-needs-account"?(f(!0),i(!0)):i(!m.configured)}).catch(()=>{i(!1)}).finally(()=>s(!1))},[]),a?l.jsx("div",{className:"flex min-h-screen items-center justify-center bg-[var(--color-background)]",children:l.jsx("div",{className:"h-8 w-8 animate-spin rounded-full border-4 border-[var(--color-primary)] border-t-transparent"})}):l.jsxs(X0,{children:[l.jsx(ft,{path:"/setup",element:l.jsx(a3,{skipToAccount:d})}),l.jsx(ft,{path:"/login",element:l.jsx($w,{})}),l.jsx(ft,{path:"/llm-setup",element:l.jsx(n3,{})}),l.jsxs(ft,{element:l.jsx(Kw,{}),children:[l.jsx(ft,{path:"/dashboard",element:l.jsx(UE,{})}),l.jsx(ft,{path:"/settings",element:l.jsx(oE,{})}),l.jsx(ft,{path:"/services",element:l.jsx(SE,{})}),l.jsx(ft,{path:"/models",element:l.jsx(y4,{})}),l.jsx(ft,{path:"/quick-sets",element:l.jsx(_4,{})}),l.jsx(ft,{path:"/traces",element:l.jsx(U4,{})}),l.jsx(ft,{path:"/traces/:id",element:l.jsx(B4,{})}),l.jsx(ft,{path:"/update",element:l.jsx(R4,{})}),l.jsx(ft,{path:"/reconcile",element:l.jsx(M4,{})}),l.jsx(ft,{path:"/nodes",element:l.jsx(YE,{})}),l.jsx(ft,{path:"/users",element:l.jsx(t4,{})}),l.jsx(ft,{path:"/native-services",element:l.jsx(d4,{})}),l.jsx(ft,{path:"/",element:o?l.jsx(ni,{to:"/setup",replace:!0}):l.jsx(ni,{to:"/dashboard",replace:!0})}),l.jsx(ft,{path:"*",element:l.jsx(q4,{})})]})]})}function l3(){return l.jsx(L2,{children:l.jsx(P1,{client:r3,children:l.jsxs(bj,{children:[l.jsx(x1,{children:l.jsx(s3,{})}),l.jsx(D2,{position:"bottom-right",richColors:!0})]})})})}Yb.createRoot(document.getElementById("root")).render(l.jsx(N.StrictMode,{children:l.jsx(l3,{})}));
|
package/public/index.html
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<link rel="icon" type="image/png" href="/favicon.png" />
|
|
7
7
|
<title>Jarvis Admin</title>
|
|
8
|
-
<script type="module" crossorigin src="/assets/index-
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-4y8tSbZj.js"></script>
|
|
9
9
|
<link rel="stylesheet" crossorigin href="/assets/index-CAv1RM9y.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
|
@@ -4,10 +4,10 @@ import { getHostPlatform } from '../services/host-platform.js';
|
|
|
4
4
|
import { upsertEnvVar } from '../services/env-file.js';
|
|
5
5
|
/** LLM setting key → the env-fallback var native services read at seed time. */
|
|
6
6
|
const MODEL_ENV_FALLBACK = {
|
|
7
|
-
'model.
|
|
8
|
-
'model.
|
|
9
|
-
'model.
|
|
10
|
-
'model.
|
|
7
|
+
'model.live.name': 'JARVIS_LIVE_MODEL_NAME',
|
|
8
|
+
'model.live.backend': 'JARVIS_LIVE_MODEL_BACKEND',
|
|
9
|
+
'model.live.chat_format': 'JARVIS_LIVE_MODEL_CHAT_FORMAT',
|
|
10
|
+
'model.live.context_window': 'JARVIS_LIVE_MODEL_CONTEXT_WINDOW',
|
|
11
11
|
};
|
|
12
12
|
export async function llmSetupRoutes(app) {
|
|
13
13
|
app.addHook('preHandler', requireSuperuser);
|
|
@@ -41,7 +41,7 @@ export async function llmSetupRoutes(app) {
|
|
|
41
41
|
// Try reading the setting directly
|
|
42
42
|
const settingResult = await proxyRequest({
|
|
43
43
|
method: 'GET',
|
|
44
|
-
url: `${llmUrl}/settings/model.
|
|
44
|
+
url: `${llmUrl}/settings/model.live.name`,
|
|
45
45
|
headers: { Authorization: request.headers.authorization },
|
|
46
46
|
timeout: 5_000,
|
|
47
47
|
});
|
|
@@ -72,10 +72,10 @@ export async function llmSetupRoutes(app) {
|
|
|
72
72
|
}
|
|
73
73
|
// Only allow known LLM settings keys
|
|
74
74
|
const ALLOWED_KEYS = new Set([
|
|
75
|
-
'model.
|
|
76
|
-
'model.
|
|
77
|
-
'model.
|
|
78
|
-
'model.
|
|
75
|
+
'model.live.name',
|
|
76
|
+
'model.live.backend',
|
|
77
|
+
'model.live.chat_format',
|
|
78
|
+
'model.live.context_window',
|
|
79
79
|
'inference.gguf.n_gpu_layers',
|
|
80
80
|
'inference.gguf.n_threads',
|
|
81
81
|
'inference.vllm.quantization',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"llm-setup.js","sourceRoot":"","sources":["../../src/routes/llm-setup.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAA;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AAEtD,gFAAgF;AAChF,MAAM,kBAAkB,GAA2B;IACjD,iBAAiB,EAAE,
|
|
1
|
+
{"version":3,"file":"llm-setup.js","sourceRoot":"","sources":["../../src/routes/llm-setup.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAA;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AAEtD,gFAAgF;AAChF,MAAM,kBAAkB,GAA2B;IACjD,iBAAiB,EAAE,wBAAwB;IAC3C,oBAAoB,EAAE,2BAA2B;IACjD,wBAAwB,EAAE,+BAA+B;IACzD,2BAA2B,EAAE,kCAAkC;CAChE,CAAA;AAkBD,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,GAAoB;IACvD,GAAG,CAAC,OAAO,CAAC,YAAY,EAAE,gBAAgB,CAAC,CAAA;IAE3C;;;OAGG;IACH,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QAC1C,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,WAAW,CAAA;QAErC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAA;QAC1C,CAAC;QAED,IAAI,CAAC;YACH,MAAM,YAAY,GAAG,MAAM,YAAY,CAAC;gBACtC,MAAM,EAAE,KAAK;gBACb,GAAG,EAAE,GAAG,MAAM,SAAS;gBACvB,OAAO,EAAE,KAAK;aACf,CAAC,CAAA;YAEF,IAAI,YAAY,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBAChC,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAA;YAC1C,CAAC;YAED,MAAM,MAAM,GAAG,YAAY,CAAC,IAA+B,CAAA;YAC3D,MAAM,YAAY,GAAG,MAAM,CAAC,aAAoD,CAAA;YAEhF,IAAI,YAAY,EAAE,MAAM,KAAK,IAAI,IAAI,YAAY,EAAE,YAAY,EAAE,CAAC;gBAChE,OAAO,KAAK,CAAC,IAAI,CAAC;oBAChB,UAAU,EAAE,IAAI;oBAChB,KAAK,EAAE,MAAM,CAAC,YAAY,CAAC,UAAU,IAAI,EAAE,CAAC;oBAC5C,OAAO,EAAE,MAAM,CAAC,YAAY,CAAC,YAAY,IAAI,EAAE,CAAC;iBACrB,CAAC,CAAA;YAChC,CAAC;YAED,mCAAmC;YACnC,MAAM,aAAa,GAAG,MAAM,YAAY,CAAC;gBACvC,MAAM,EAAE,KAAK;gBACb,GAAG,EAAE,GAAG,MAAM,2BAA2B;gBACzC,OAAO,EAAE,EAAE,aAAa,EAAE,OAAO,CAAC,OAAO,CAAC,aAAc,EAAE;gBAC1D,OAAO,EAAE,KAAK;aACf,CAAC,CAAA;YAEF,IAAI,aAAa,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBACjC,MAAM,OAAO,GAAG,aAAa,CAAC,IAA0B,CAAA;gBACxD,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,IAAI,EAAE,CAAA;gBACrC,MAAM,SAAS,GAAG,CAAC,SAAS,IAAI,SAAS,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,SAAS,KAAK,UAAU,CAAA;gBAC7F,OAAO,KAAK,CAAC,IAAI,CAAC;oBAChB,UAAU,EAAE,CAAC,SAAS;oBACtB,KAAK,EAAE,SAAS;oBAChB,OAAO,EAAE,EAAE;iBACgB,CAAC,CAAA;YAChC,CAAC;YAED,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAA;QAC1C,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAA;QAC1C,CAAC;IACH,CAAC,CAAC,CAAA;IAEF;;OAEG;IACH,GAAG,CAAC,IAAI,CAA0B,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QACvE,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,WAAW,CAAA;QACrC,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,IAAqB,CAAA;QAElD,IAAI,CAAC,QAAQ,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;YAC9C,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,6BAA6B,EAAE,CAAC,CAAA;QACvE,CAAC;QAED,qCAAqC;QACrC,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC;YAC3B,iBAAiB;YACjB,oBAAoB;YACpB,wBAAwB;YACxB,2BAA2B;YAC3B,6BAA6B;YAC7B,0BAA0B;YAC1B,6BAA6B;YAC7B,uCAAuC;YACvC,eAAe;SAChB,CAAC,CAAA;QACF,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;QAC7E,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC3B,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,0BAA0B,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAA;QAC5F,CAAC;QAED,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,8BAA8B,EAAE,CAAC,CAAA;QACxE,CAAC;QAED,qEAAqE;QACrE,iDAAiD;QACjD,MAAM,cAAc,GAAG,QAAQ,CAAC,eAAe,CAAuB,CAAA;QACtE,MAAM,gBAAgB,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAA;QACxC,OAAO,gBAAgB,CAAC,eAAe,CAAC,CAAA;QAExC,6EAA6E;QAC7E,0EAA0E;QAC1E,yEAAyE;QACzE,2EAA2E;QAC3E,MAAM,WAAW,GAAG,eAAe,EAAE,KAAK,QAAQ,CAAA;QAClD,IAAI,WAAW,EAAE,CAAC;YAChB,KAAK,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,kBAAkB,CAAC,EAAE,CAAC;gBAC/D,IAAI,QAAQ,CAAC,GAAG,CAAC,KAAK,SAAS;oBAAE,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;YAC9E,CAAC;QACH,CAAC;QAED,mEAAmE;QACnE,IAAI,cAAc,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,EAAa,EAAE,CAAA;QACzD,IAAI,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7C,cAAc,GAAG,MAAM,YAAY,CAAC;gBAClC,MAAM,EAAE,KAAK;gBACb,GAAG,EAAE,GAAG,MAAM,YAAY;gBAC1B,OAAO,EAAE,EAAE,aAAa,EAAE,OAAO,CAAC,OAAO,CAAC,aAAc,EAAE;gBAC1D,IAAI,EAAE,EAAE,QAAQ,EAAE,gBAAgB,EAAE;gBACpC,OAAO,EAAE,MAAM;aAChB,CAAC,CAAA;YAEF,2EAA2E;YAC3E,sEAAsE;YACtE,IAAI,cAAc,CAAC,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;gBAClD,OAAO,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAA;YACpE,CAAC;QACH,CAAC;QAED,+DAA+D;QAC/D,IAAI,oBAAwC,CAAA;QAC5C,IAAI,cAAc,IAAI,GAAG,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC;YAClD,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC;oBAClC,MAAM,EAAE,KAAK;oBACb,GAAG,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,gBAAgB,kDAAkD;oBACrF,OAAO,EAAE,EAAE,aAAa,EAAE,OAAO,CAAC,OAAO,CAAC,aAAc,EAAE;oBAC1D,IAAI,EAAE,EAAE,KAAK,EAAE,cAAc,EAAE;oBAC/B,OAAO,EAAE,MAAM;iBAChB,CAAC,CAAA;gBACF,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;oBAC5B,oBAAoB,GAAG,cAAc,CAAA;gBACvC,CAAC;YACH,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,CAAC,IAAI,CAAC,4CAA4C,EAAE,GAAG,CAAC,CAAA;YACjE,CAAC;QACH,CAAC;QAED,sDAAsD;QACtD,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAA;QACzB,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,CAAC;gBACH,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,oBAAoB,EAAE,CAAA;gBACtD,MAAM,aAAa,GAAG,UAAU,CAAC,MAAM,CACrC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CACpE,CAAA;gBAED,KAAK,MAAM,SAAS,IAAI,aAAa,EAAE,CAAC;oBACtC,MAAM,MAAM,CAAC,gBAAgB,CAAC,SAAS,CAAC,EAAE,CAAC,CAAA;gBAC7C,CAAC;YACH,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,CAAC,IAAI,CAAC,uCAAuC,EAAE,GAAG,CAAC,CAAA;YAC5D,CAAC;QACH,CAAC;QAED,OAAO,KAAK,CAAC,IAAI,CAAC;YAChB,OAAO,EAAE,IAAI;YACb,cAAc,EAAE,cAAc,CAAC,IAAI;YACnC,cAAc,EAAE,oBAAoB;YACpC,OAAO,EAAE,uCAAuC;SACjD,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF;;OAEG;IACH,GAAG,CAAC,IAAI,CAAyB,WAAW,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QACrE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC,IAAoB,CAAA;QAE9D,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,kBAAkB,EAAE,CAAC,CAAA;QAC5D,CAAC;QAED,+CAA+C;QAC/C,MAAM,YAAY,GAAG,oCAAoC,CAAA;QACzD,MAAM,gBAAgB,GAAG,mBAAmB,CAAA;QAE5C,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC7B,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,gDAAgD,EAAE,CAAC,CAAA;QAC1F,CAAC;QAED,IAAI,QAAQ,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YACjD,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,yBAAyB,EAAE,CAAC,CAAA;QACnE,CAAC;QAED,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAA;QACzB,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,yBAAyB,EAAE,CAAC,CAAA;QACnE,CAAC;QAED,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,oBAAoB,EAAE,CAAA;QACtD,MAAM,YAAY,GAAG,UAAU,CAAC,IAAI,CAClC,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;YAC9D,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;YACtB,CAAC,CAAC,KAAK,KAAK,SAAS,CACxB,IAAI,UAAU,CAAC,IAAI,CAClB,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;YAC9D,CAAC,CAAC,KAAK,KAAK,SAAS,CACxB,CAAA;QAED,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,8CAA8C,EAAE,CAAC,CAAA;QACxF,CAAC;QAED,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,yBAAyB,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;QAE3D,iFAAiF;QACjF,MAAM,GAAG,GAAG,QAAQ;YAClB,CAAC,CAAC;gBACE,QAAQ,EAAE,IAAI;gBACd,0MAA0M;gBAC1M,IAAI;gBACJ,QAAQ;aACT;YACH,CAAC,CAAC;gBACE,QAAQ,EAAE,IAAI;gBACd,wNAAwN;gBACxN,IAAI;aACL,CAAA;QAEL,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,YAAY,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;YAEtE,OAAO,KAAK,CAAC,IAAI,CAAC;gBAChB,OAAO,EAAE,IAAI;gBACb,MAAM;gBACN,OAAO,EAAE,mBAAmB;aAC7B,CAAC,CAAA;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,8BAA8B,EAAE,GAAG,CAAC,CAAA;YAClD,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;gBAC1B,KAAK,EAAE,iDAAiD;aACzD,CAAC,CAAA;QACJ,CAAC;IACH,CAAC,CAAC,CAAA;AACJ,CAAC"}
|