e02a1889b2
SQLite-basiertes Memory-System fuer persistentes Gedaechtnis ueber Sessions. Cline, OpenCode und Claude Code teilen denselben Speicher via MCP-Server. - routers/memory.py: CRUD + Export-Endpoint (GET/POST/PUT/DELETE /api/memory) - mcp_memory.py: stdio MCP-Server — Tools: get/add/search/update/delete_memory - MemoryPanel.svelte: Gedaechtnis-Tab mit Filter, Inline-Edit, Add-Formular - ConnectPanel.svelte: Gedaechtnis-MCP Setup-Guide (Cline/OpenCode/Bosgame) - Temporaere Eintraege (ephemeral) nach 7 Tagen automatisch geloescht Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
655 lines
194 KiB
JavaScript
655 lines
194 KiB
JavaScript
var rl=Object.defineProperty;var Dr=e=>{throw TypeError(e)};var sl=(e,n,a)=>n in e?rl(e,n,{enumerable:!0,configurable:!0,writable:!0,value:a}):e[n]=a;var ln=(e,n,a)=>sl(e,typeof n!="symbol"?n+"":n,a),ji=(e,n,a)=>n.has(e)||Dr("Cannot "+a);var p=(e,n,a)=>(ji(e,n,"read from private field"),a?a.call(e):n.get(e)),ye=(e,n,a)=>n.has(e)?Dr("Cannot add the same private member more than once"):n instanceof WeakSet?n.add(e):n.set(e,a),ge=(e,n,a,i)=>(ji(e,n,"write to private field"),i?i.call(e,a):n.set(e,a),a),je=(e,n,a)=>(ji(e,n,"access private method"),a);var _r=Array.isArray,ll=Array.prototype.indexOf,Ci=Array.prototype.includes,Oi=Array.from,ol=Object.defineProperty,ti=Object.getOwnPropertyDescriptor,dl=Object.getOwnPropertyDescriptors,cl=Object.prototype,ul=Array.prototype,ds=Object.getPrototypeOf,$r=Object.isExtensible;const vl=()=>{};function pl(e){for(var n=0;n<e.length;n++)e[n]()}function cs(){var e,n,a=new Promise((i,l)=>{e=i,n=l});return{promise:a,resolve:e,reject:n}}function ea(e,n){if(Array.isArray(e))return e;if(n===void 0||!(Symbol.iterator in e))return Array.from(e);const a=[];for(const i of e)if(a.push(i),a.length===n)break;return a}const Jt=2,Fa=4,Ri=8,us=1<<24,Sn=16,En=32,ia=64,rr=128,bn=512,Nt=1024,Ut=2048,Ln=4096,en=8192,_n=16384,Wa=32768,sr=1<<25,Ka=65536,Ti=1<<17,fl=1<<18,Ua=1<<19,hl=1<<20,Pn=1<<25,xa=65536,zi=1<<21,za=1<<22,aa=1<<23,Pa=Symbol("$state"),gl=Symbol(""),yi=Symbol("attributes"),lr=Symbol("class"),or=Symbol("style"),Qa=Symbol("text"),xi=Symbol("form reset"),Fi=new class extends Error{constructor(){super(...arguments);ln(this,"name","StaleReactionError");ln(this,"message","The reaction that called `getAbortSignal()` was re-run or destroyed")}};var rs;const ml=!!((rs=globalThis.document)!=null&&rs.contentType)&&globalThis.document.contentType.includes("xml");function vs(e){throw new Error("https://svelte.dev/e/lifecycle_outside_component")}function bl(){throw new Error("https://svelte.dev/e/async_derived_orphan")}function _l(e,n,a){throw new Error("https://svelte.dev/e/each_key_duplicate")}function kl(e){throw new Error("https://svelte.dev/e/effect_in_teardown")}function wl(){throw new Error("https://svelte.dev/e/effect_in_unowned_derived")}function yl(e){throw new Error("https://svelte.dev/e/effect_orphan")}function xl(){throw new Error("https://svelte.dev/e/effect_update_depth_exceeded")}function Sl(){throw new Error("https://svelte.dev/e/state_descriptors_fixed")}function Ml(){throw new Error("https://svelte.dev/e/state_prototype_fixed")}function El(){throw new Error("https://svelte.dev/e/state_unsafe_mutation")}function Al(){throw new Error("https://svelte.dev/e/svelte_boundary_reset_onerror")}const Cl=1,Tl=2,ps=4,zl=8,Pl=16,Dl=1,$l=2,Kt=Symbol("uninitialized"),fs="http://www.w3.org/1999/xhtml",Ll="http://www.w3.org/2000/svg",Il="http://www.w3.org/1998/Math/MathML";function Bl(){console.warn("https://svelte.dev/e/derived_inert")}function Ol(){console.warn("https://svelte.dev/e/select_multiple_invalid_value")}function Rl(){console.warn("https://svelte.dev/e/svelte_boundary_reset_noop")}function hs(e){return e===this.v}function Fl(e,n){return e!=e?n==n:e!==n||e!==null&&typeof e=="object"||typeof e=="function"}function gs(e){return!Fl(e,this.v)}let Ht=null;function Na(e){Ht=e}function Gn(e,n=!1,a){Ht={p:Ht,i:!1,c:null,e:null,s:e,x:null,r:Re,l:null}}function Vn(e){var n=Ht,a=n.e;if(a!==null){n.e=null;for(var i of a)Rs(i)}return n.i=!0,Ht=n.p,{}}function ms(){return!0}let da=[];function bs(){var e=da;da=[],pl(e)}function ba(e){if(da.length===0&&!ai){var n=da;queueMicrotask(()=>{n===da&&bs()})}da.push(e)}function Kl(){for(;da.length>0;)bs()}function _s(e){var n=Re;if(n===null)return Le.f|=aa,e;if((n.f&Wa)===0&&(n.f&Fa)===0)throw e;ta(e,n)}function ta(e,n){if(!(n!==null&&(n.f&_n)!==0)){for(;n!==null;){if((n.f&rr)!==0){if((n.f&Wa)===0)throw e;try{n.b.error(e);return}catch(a){e=a}}n=n.parent}throw e}}const Nl=-7169;function Ot(e,n){e.f=e.f&Nl|n}function kr(e){(e.f&bn)!==0||e.deps===null?Ot(e,Nt):Ot(e,Ln)}function ks(e){if(e!==null)for(const n of e)(n.f&Jt)===0||(n.f&xa)===0||(n.f^=xa,ks(n.deps))}function ws(e,n,a){(e.f&Ut)!==0?n.add(e):(e.f&Ln)!==0&&a.add(e),ks(e.deps),Ot(e,Nt)}function ql(e){let n=0,a=Ma(0),i;return()=>{Ar()&&(t(a),Ni(()=>(n===0&&(i=ja(()=>e(()=>ii(a)))),n+=1,()=>{ba(()=>{n-=1,n===0&&(i==null||i(),i=void 0,ii(a))})})))}}var Gl=Ka|Ua;function Vl(e,n,a,i){new Wl(e,n,a,i)}var vn,br,pn,pa,nn,fn,Yt,dn,Rn,fa,Yn,Da,ui,vi,Fn,Li,Dt,Ul,jl,Hl,dr,Si,Mi,cr,ur;class Wl{constructor(n,a,i,l){ye(this,Dt);ln(this,"parent");ln(this,"is_pending",!1);ln(this,"transform_error");ye(this,vn);ye(this,br,null);ye(this,pn);ye(this,pa);ye(this,nn);ye(this,fn,null);ye(this,Yt,null);ye(this,dn,null);ye(this,Rn,null);ye(this,fa,0);ye(this,Yn,0);ye(this,Da,!1);ye(this,ui,new Set);ye(this,vi,new Set);ye(this,Fn,null);ye(this,Li,ql(()=>(ge(this,Fn,Ma(p(this,fa))),()=>{ge(this,Fn,null)})));var o;ge(this,vn,n),ge(this,pn,a),ge(this,pa,d=>{var c=Re;c.b=this,c.f|=rr,i(d)}),this.parent=Re.b,this.transform_error=l??((o=this.parent)==null?void 0:o.transform_error)??(d=>d),ge(this,nn,Cr(()=>{je(this,Dt,dr).call(this)},Gl))}defer_effect(n){ws(n,p(this,ui),p(this,vi))}is_rendered(){return!this.is_pending&&(!this.parent||this.parent.is_rendered())}has_pending_snippet(){return!!p(this,pn).pending}update_pending_count(n,a){je(this,Dt,cr).call(this,n,a),ge(this,fa,p(this,fa)+n),!(!p(this,Fn)||p(this,Da))&&(ge(this,Da,!0),ba(()=>{ge(this,Da,!1),p(this,Fn)&&qa(p(this,Fn),p(this,fa))}))}get_effect_pending(){return p(this,Li).call(this),t(p(this,Fn))}error(n){if(!p(this,pn).onerror&&!p(this,pn).failed)throw n;ne!=null&&ne.is_fork?(p(this,fn)&&ne.skip_effect(p(this,fn)),p(this,Yt)&&ne.skip_effect(p(this,Yt)),p(this,dn)&&ne.skip_effect(p(this,dn)),ne.oncommit(()=>{je(this,Dt,ur).call(this,n)})):je(this,Dt,ur).call(this,n)}}vn=new WeakMap,br=new WeakMap,pn=new WeakMap,pa=new WeakMap,nn=new WeakMap,fn=new WeakMap,Yt=new WeakMap,dn=new WeakMap,Rn=new WeakMap,fa=new WeakMap,Yn=new WeakMap,Da=new WeakMap,ui=new WeakMap,vi=new WeakMap,Fn=new WeakMap,Li=new WeakMap,Dt=new WeakSet,Ul=function(){try{ge(this,fn,hn(()=>p(this,pa).call(this,p(this,vn))))}catch(n){this.error(n)}},jl=function(n){const a=p(this,pn).failed;a&&ge(this,dn,hn(()=>{a(p(this,vn),()=>n,()=>()=>{})}))},Hl=function(){const n=p(this,pn).pending;n&&(this.is_pending=!0,ge(this,Yt,hn(()=>n(p(this,vn)))),ba(()=>{var a=ge(this,Rn,document.createDocumentFragment()),i=qn();a.append(i),ge(this,fn,je(this,Dt,Mi).call(this,()=>hn(()=>p(this,pa).call(this,i)))),p(this,Yn)===0&&(p(this,vn).before(a),ge(this,Rn,null),ka(p(this,Yt),()=>{ge(this,Yt,null)}),je(this,Dt,Si).call(this,ne))}))},dr=function(){try{if(this.is_pending=this.has_pending_snippet(),ge(this,Yn,0),ge(this,fa,0),ge(this,fn,hn(()=>{p(this,pa).call(this,p(this,vn))})),p(this,Yn)>0){var n=ge(this,Rn,document.createDocumentFragment());zr(p(this,fn),n);const a=p(this,pn).pending;ge(this,Yt,hn(()=>a(p(this,vn))))}else je(this,Dt,Si).call(this,ne)}catch(a){this.error(a)}},Si=function(n){this.is_pending=!1,n.transfer_effects(p(this,ui),p(this,vi))},Mi=function(n){var a=Re,i=Le,l=Ht;In(p(this,nn)),kn(p(this,nn)),Na(p(this,nn).ctx);try{return Sa.ensure(),n()}catch(o){return _s(o),null}finally{In(a),kn(i),Na(l)}},cr=function(n,a){var i;if(!this.has_pending_snippet()){this.parent&&je(i=this.parent,Dt,cr).call(i,n,a);return}ge(this,Yn,p(this,Yn)+n),p(this,Yn)===0&&(je(this,Dt,Si).call(this,a),p(this,Yt)&&ka(p(this,Yt),()=>{ge(this,Yt,null)}),p(this,Rn)&&(p(this,vn).before(p(this,Rn)),ge(this,Rn,null)))},ur=function(n){p(this,fn)&&(sn(p(this,fn)),ge(this,fn,null)),p(this,Yt)&&(sn(p(this,Yt)),ge(this,Yt,null)),p(this,dn)&&(sn(p(this,dn)),ge(this,dn,null));var a=p(this,pn).onerror;let i=p(this,pn).failed;var l=!1,o=!1;const d=()=>{if(l){Rl();return}l=!0,o&&Al(),p(this,dn)!==null&&ka(p(this,dn),()=>{ge(this,dn,null)}),je(this,Dt,Mi).call(this,()=>{je(this,Dt,dr).call(this)})},c=u=>{try{o=!0,a==null||a(u,d),o=!1}catch(v){ta(v,p(this,nn)&&p(this,nn).parent)}i&&ge(this,dn,je(this,Dt,Mi).call(this,()=>{try{return hn(()=>{var v=Re;v.b=this,v.f|=rr,i(p(this,vn),()=>u,()=>d)})}catch(v){return ta(v,p(this,nn).parent),null}}))};ba(()=>{var u;try{u=this.transform_error(n)}catch(v){ta(v,p(this,nn)&&p(this,nn).parent);return}u!==null&&typeof u=="object"&&typeof u.then=="function"?u.then(c,v=>ta(v,p(this,nn)&&p(this,nn).parent)):c(u)})};function Jl(e,n,a,i){const l=wr;var o=e.filter(x=>!x.settled),d=n.map(l);if(a.length===0&&o.length===0){i(d);return}var c=Re,u=Ql(),v=o.length===1?o[0].promise:o.length>1?Promise.all(o.map(x=>x.promise)):null;function b(x){if((c.f&_n)===0){u();try{i([...d,...x])}catch(C){ta(C,c)}Pi()}}var A=ys();if(a.length===0){v.then(()=>b([])).finally(A);return}function m(){Promise.all(a.map(x=>Zl(x))).then(b).catch(x=>ta(x,c)).finally(A)}v?v.then(()=>{u(),m(),Pi()}):m()}function Ql(){var e=Re,n=Le,a=Ht,i=ne;return function(o=!0){In(e),kn(n),Na(a),o&&(e.f&_n)===0&&(i==null||i.activate(),i==null||i.apply())}}function Pi(e=!0){In(null),kn(null),Na(null),e&&(ne==null||ne.deactivate())}function ys(){var e=Re,n=e.b,a=ne,i=!!(n!=null&&n.is_rendered());return n==null||n.update_pending_count(1,a),a.increment(i,e),()=>{n==null||n.update_pending_count(-1,a),a.decrement(i,e)}}function wr(e){var n=Jt|Ut;return Re!==null&&(Re.f|=Ua),{ctx:Ht,deps:null,effects:null,equals:hs,f:n,fn:e,reactions:null,rv:0,v:Kt,wv:0,parent:Re,ac:null}}const Za=Symbol("obsolete");function Zl(e,n,a){let i=Re;i===null&&bl();var l=void 0,o=Ma(Kt),d=!Le,c=new Set;return ho(()=>{var x,C;var u=Re,v=cs();l=v.promise;try{Promise.resolve(e()).then(v.resolve,z=>{z!==Fi&&v.reject(z)}).finally(Pi)}catch(z){v.reject(z),Pi()}var b=ne;if(d){if((u.f&Wa)!==0)var A=ys();if((x=i.b)!=null&&x.is_rendered())(C=b.async_deriveds.get(u))==null||C.reject(Za);else for(const z of c.values())z.reject(Za);c.add(v),b.async_deriveds.set(u,v)}const m=(z,M=void 0)=>{A==null||A(),c.delete(v),M!==Za&&(b.activate(),M?(o.f|=aa,qa(o,M)):((o.f&aa)!==0&&(o.f^=aa),qa(o,z)),b.deactivate())};v.promise.then(m,z=>m(null,z||"unknown"))}),Os(()=>{for(const u of c)u.reject(Za)}),new Promise(u=>{function v(b){function A(){b===l?u(o):v(l)}b.then(A,A)}v(l)})}function O(e){const n=wr(e);return Ws(n),n}function Yl(e){const n=wr(e);return n.equals=gs,n}function Xl(e){var n=e.effects;if(n!==null){e.effects=null;for(var a=0;a<n.length;a+=1)sn(n[a])}}function yr(e){var n,a=Re,i=e.parent;if(!ra&&i!==null&&e.v!==Kt&&(i.f&(_n|en))!==0)return Bl(),e.v;In(i);try{e.f&=~xa,Xl(e),n=Js(e)}finally{In(a)}return n}function xs(e){var n=yr(e);if(!e.equals(n)&&(e.wv=js(),(!(ne!=null&&ne.is_fork)||e.deps===null)&&(ne!==null?(ne.capture(e,n,!0),ni==null||ni.capture(e,n,!0)):e.v=n,e.deps===null))){Ot(e,Nt);return}ra||(Wt!==null?(Ar()||ne!=null&&ne.is_fork)&&Wt.set(e,n):kr(e))}function eo(e){var n,a;if(e.effects!==null)for(const i of e.effects)(i.teardown||i.ac)&&((n=i.teardown)==null||n.call(i),(a=i.ac)==null||a.abort(Fi),i.fn!==null&&(i.teardown=vl),i.ac=null,oi(i,0),Tr(i))}function Ss(e){if(e.effects!==null)for(const n of e.effects)n.teardown&&n.fn!==null&&Ga(n)}let Hi=null,Aa=null,ne=null,ni=null,Wt=null,vr=null,ai=!1,Ji=!1,Ta=null,Ei=null;var Lr=0;let to=1;var $a,Xn,ha,La,Ia,Ba,Kn,Oa,an,pi,Nn,yn,Tn,Ra,ga,st,pr,Ya,fr,Ms,Es,Ca,no,Xa;const Ii=class Ii{constructor(){ye(this,st);ln(this,"id",to++);ye(this,$a,!1);ln(this,"linked",!0);ye(this,Xn,null);ye(this,ha,null);ln(this,"async_deriveds",new Map);ln(this,"current",new Map);ln(this,"previous",new Map);ye(this,La,new Set);ye(this,Ia,new Set);ye(this,Ba,0);ye(this,Kn,new Map);ye(this,Oa,null);ye(this,an,[]);ye(this,pi,[]);ye(this,Nn,new Set);ye(this,yn,new Set);ye(this,Tn,new Map);ye(this,Ra,new Set);ln(this,"is_fork",!1);ye(this,ga,!1);Aa===null?Hi=Aa=this:(ge(Aa,ha,this),ge(this,Xn,Aa)),Aa=this}skip_effect(n){p(this,Tn).has(n)||p(this,Tn).set(n,{d:[],m:[]}),p(this,Ra).delete(n)}unskip_effect(n,a=i=>this.schedule(i)){var i=p(this,Tn).get(n);if(i){p(this,Tn).delete(n);for(var l of i.d)Ot(l,Ut),a(l);for(l of i.m)Ot(l,Ln),a(l)}p(this,Ra).add(n)}capture(n,a,i=!1){n.v!==Kt&&!this.previous.has(n)&&this.previous.set(n,n.v),(n.f&aa)===0&&(this.current.set(n,[a,i]),Wt==null||Wt.set(n,a)),this.is_fork||(n.v=a)}activate(){ne=this}deactivate(){ne=null,Wt=null}flush(){try{Ji=!0,ne=this,je(this,st,Ya).call(this)}finally{Lr=0,vr=null,Ta=null,Ei=null,Ji=!1,ne=null,Wt=null,_a.clear()}}discard(){var n;for(const a of p(this,Ia))a(this);p(this,Ia).clear();for(const a of this.async_deriveds.values())a.reject(Za);je(this,st,Xa).call(this),(n=p(this,Oa))==null||n.resolve()}register_created_effect(n){p(this,pi).push(n)}increment(n,a){if(ge(this,Ba,p(this,Ba)+1),n){let i=p(this,Kn).get(a)??0;p(this,Kn).set(a,i+1)}}decrement(n,a){if(ge(this,Ba,p(this,Ba)-1),n){let i=p(this,Kn).get(a)??0;i===1?p(this,Kn).delete(a):p(this,Kn).set(a,i-1)}p(this,ga)||(ge(this,ga,!0),ba(()=>{ge(this,ga,!1),this.linked&&this.flush()}))}transfer_effects(n,a){for(const i of n)p(this,Nn).add(i);for(const i of a)p(this,yn).add(i);n.clear(),a.clear()}oncommit(n){p(this,La).add(n)}ondiscard(n){p(this,Ia).add(n)}settled(){return(p(this,Oa)??ge(this,Oa,cs())).promise}static ensure(){if(ne===null){const n=ne=new Ii;!Ji&&!ai&&ba(()=>{p(n,$a)||n.flush()})}return ne}apply(){{Wt=null;return}}schedule(n){var l;if(vr=n,(l=n.b)!=null&&l.is_pending&&(n.f&(Fa|Ri|us))!==0&&(n.f&Wa)===0){n.b.defer_effect(n);return}for(var a=n;a.parent!==null;){a=a.parent;var i=a.f;if(Ta!==null&&a===Re&&(Le===null||(Le.f&Jt)===0))return;if((i&(ia|En))!==0){if((i&Nt)===0)return;a.f^=Nt}}p(this,an).push(a)}};$a=new WeakMap,Xn=new WeakMap,ha=new WeakMap,La=new WeakMap,Ia=new WeakMap,Ba=new WeakMap,Kn=new WeakMap,Oa=new WeakMap,an=new WeakMap,pi=new WeakMap,Nn=new WeakMap,yn=new WeakMap,Tn=new WeakMap,Ra=new WeakMap,ga=new WeakMap,st=new WeakSet,pr=function(){if(this.is_fork)return!0;for(const i of p(this,Kn).keys()){for(var n=i,a=!1;n.parent!==null;){if(p(this,Tn).has(n)){a=!0;break}n=n.parent}if(!a)return!0}return!1},Ya=function(){var u,v,b,A;ge(this,$a,!0),Lr++>1e3&&(je(this,st,Xa).call(this),io());for(const m of p(this,Nn))p(this,yn).delete(m),Ot(m,Ut),this.schedule(m);for(const m of p(this,yn))Ot(m,Ln),this.schedule(m);const n=p(this,an);ge(this,an,[]),this.apply();var a=Ta=[],i=[],l=Ei=[];for(const m of n)try{je(this,st,fr).call(this,m,a,i)}catch(x){throw Ts(m),je(this,st,pr).call(this)||this.discard(),x}if(ne=null,l.length>0){var o=Ii.ensure();for(const m of l)o.schedule(m)}if(Ta=null,Ei=null,je(this,st,pr).call(this)){je(this,st,Ca).call(this,i),je(this,st,Ca).call(this,a);for(const[m,x]of p(this,Tn))Cs(m,x);l.length>0&&je(u=ne,st,Ya).call(u);return}const d=je(this,st,Ms).call(this);if(d){je(this,st,Ca).call(this,i),je(this,st,Ca).call(this,a),je(v=d,st,Es).call(v,this);return}p(this,Nn).clear(),p(this,yn).clear();for(const m of p(this,La))m(this);p(this,La).clear(),ni=this,Ir(i),Ir(a),ni=null,(b=p(this,Oa))==null||b.resolve();var c=ne;if(p(this,Ba)===0&&(p(this,an).length===0||c!==null)&&je(this,st,Xa).call(this),p(this,an).length>0)if(c!==null){const m=c;p(m,an).push(...p(this,an).filter(x=>!p(m,an).includes(x)))}else c=this;c!==null&&je(A=c,st,Ya).call(A)},fr=function(n,a,i){n.f^=Nt;for(var l=n.first;l!==null;){var o=l.f,d=(o&(En|ia))!==0,c=d&&(o&Nt)!==0,u=c||(o&en)!==0||p(this,Tn).has(l);if(!u&&l.fn!==null){d?l.f^=Nt:(o&Fa)!==0?a.push(l):mi(l)&&((o&Sn)!==0&&p(this,yn).add(l),Ga(l));var v=l.first;if(v!==null){l=v;continue}}for(;l!==null;){var b=l.next;if(b!==null){l=b;break}l=l.parent}}},Ms=function(){for(var n=p(this,Xn);n!==null;){if(!n.is_fork){for(const[a,[,i]]of this.current)if(n.current.has(a)&&!i)return n}n=p(n,Xn)}return null},Es=function(n){var i;for(const[l,o]of n.current)!this.previous.has(l)&&n.previous.has(l)&&this.previous.set(l,n.previous.get(l)),this.current.set(l,o);for(const[l,o]of n.async_deriveds){const d=this.async_deriveds.get(l);d&&o.promise.then(d.resolve).catch(d.reject)}n.async_deriveds.clear(),this.transfer_effects(p(n,Nn),p(n,yn));const a=l=>{var o=l.reactions;if(o!==null)for(const u of o){var d=u.f;if((d&Jt)!==0)a(u);else{var c=u;d&(za|Sn)&&!this.async_deriveds.has(c)&&(p(this,yn).delete(c),Ot(c,Ut),this.schedule(c))}}};for(const l of this.current.keys())a(l);this.oncommit(()=>n.discard()),je(i=n,st,Xa).call(i),ne=this,je(this,st,Ya).call(this)},Ca=function(n){for(var a=0;a<n.length;a+=1)ws(n[a],p(this,Nn),p(this,yn))},no=function(){var A;for(let m=Hi;m!==null;m=p(m,ha)){var n=m.id<this.id,a=[];for(const[x,[C,z]]of this.current){if(m.current.has(x)){var i=m.current.get(x)[0];if(n&&C!==i)m.current.set(x,[C,z]);else continue}a.push(x)}if(n)for(const[x,C]of this.async_deriveds){const z=m.async_deriveds.get(x);z&&C.promise.then(z.resolve).catch(z.reject)}var l=[...m.current.keys()].filter(x=>!m.current.get(x)[1]);if(!(!p(m,$a)||l.length===0)){var o=l.filter(x=>!this.current.has(x));if(o.length===0)n&&m.discard();else if(a.length>0){if(n)for(const x of p(this,Ra))m.unskip_effect(x,C=>{var z;(C.f&(Sn|za))!==0?m.schedule(C):je(z=m,st,Ca).call(z,[C])});m.activate();var d=new Set,c=new Map;for(var u of a)As(u,o,d,c);c=new Map;var v=[...m.current].filter(([x,C])=>{const z=this.current.get(x);return z?z[0]!==C[0]||z[1]!==C[1]:!0}).map(([x])=>x);if(v.length>0)for(const x of p(this,pi))(x.f&(_n|en|Ti))===0&&xr(x,v,c)&&((x.f&(za|Sn))!==0?(Ot(x,Ut),m.schedule(x)):p(m,Nn).add(x));if(p(m,an).length>0&&!p(m,ga)){m.apply();for(var b of p(m,an))je(A=m,st,fr).call(A,b,[],[]);ge(m,an,[])}m.deactivate()}}}},Xa=function(){if(this.linked){var n=p(this,Xn),a=p(this,ha);n===null?Hi=a:ge(n,ha,a),a===null?Aa=n:ge(a,Xn,n),this.linked=!1}};let Sa=Ii;function ao(e){var n=ai;ai=!0;try{for(var a;;){if(Kl(),ne===null)return a;ne.flush()}}finally{ai=n}}function io(){try{xl()}catch(e){ta(e,vr)}}let wn=null;function Ir(e){var n=e.length;if(n!==0){for(var a=0;a<n;){var i=e[a++];if((i.f&(_n|en))===0&&mi(i)&&(wn=new Set,Ga(i),i.deps===null&&i.first===null&&i.nodes===null&&i.teardown===null&&i.ac===null&&qs(i),(wn==null?void 0:wn.size)>0)){_a.clear();for(const l of wn){if((l.f&(_n|en))!==0)continue;const o=[l];let d=l.parent;for(;d!==null;)wn.has(d)&&(wn.delete(d),o.push(d)),d=d.parent;for(let c=o.length-1;c>=0;c--){const u=o[c];(u.f&(_n|en))===0&&Ga(u)}}wn.clear()}}wn=null}}function As(e,n,a,i){if(!a.has(e)&&(a.add(e),e.reactions!==null))for(const l of e.reactions){const o=l.f;(o&Jt)!==0?As(l,n,a,i):(o&(za|Sn))!==0&&(o&Ut)===0&&xr(l,n,i)&&(Ot(l,Ut),Sr(l))}}function xr(e,n,a){const i=a.get(e);if(i!==void 0)return i;if(e.deps!==null)for(const l of e.deps){if(Ci.call(n,l))return!0;if((l.f&Jt)!==0&&xr(l,n,a))return a.set(l,!0),!0}return a.set(e,!1),!1}function Sr(e){ne.schedule(e)}function Cs(e,n){if(!((e.f&En)!==0&&(e.f&Nt)!==0)){(e.f&Ut)!==0?n.d.push(e):(e.f&Ln)!==0&&n.m.push(e),Ot(e,Nt);for(var a=e.first;a!==null;)Cs(a,n),a=a.next}}function Ts(e){Ot(e,Nt);for(var n=e.first;n!==null;)Ts(n),n=n.next}let Di=new Set;const _a=new Map;let zs=!1;function Ma(e,n){var a={f:0,v:e,reactions:null,equals:hs,rv:0,wv:0};return a}function B(e,n){const a=Ma(e);return Ws(a),a}function ro(e,n=!1,a=!0){const i=Ma(e);return n||(i.equals=gs),i}function f(e,n,a=!1){Le!==null&&(!Mn||(Le.f&Ti)!==0)&&ms()&&(Le.f&(Jt|Sn|za|Ti))!==0&&(Dn===null||!Dn.has(e))&&El();let i=a?jt(n):n;return qa(e,i,Ei)}function qa(e,n,a=null){if(!e.equals(n)){_a.set(e,ra?n:e.v);var i=Sa.ensure();if(i.capture(e,n),(e.f&Jt)!==0){const l=e;(e.f&Ut)!==0&&yr(l),Wt===null&&kr(l)}e.wv=js(),Ps(e,Ut,a),Re!==null&&(Re.f&Nt)!==0&&(Re.f&(En|ia))===0&&(un===null?mo([e]):un.push(e)),!i.is_fork&&Di.size>0&&!zs&&so()}return n}function so(){zs=!1;for(const e of Di){(e.f&Nt)!==0&&Ot(e,Ln);let n;try{n=mi(e)}catch{n=!0}n&&Ga(e)}Di.clear()}function ii(e){f(e,e.v+1)}function Ps(e,n,a){var i=e.reactions;if(i!==null)for(var l=i.length,o=0;o<l;o++){var d=i[o],c=d.f,u=(c&Ut)===0;if(u&&Ot(d,n),(c&Ti)!==0)Di.add(d);else if((c&Jt)!==0){var v=d;Wt==null||Wt.delete(v),(c&xa)===0&&(c&bn&&(Re===null||(Re.f&zi)===0)&&(d.f|=xa),Ps(v,Ln,a))}else if(u){var b=d;(c&Sn)!==0&&wn!==null&&wn.add(b),a!==null?a.push(b):Sr(b)}}}function jt(e){if(typeof e!="object"||e===null||Pa in e)return e;const n=ds(e);if(n!==cl&&n!==ul)return e;var a=new Map,i=_r(e),l=B(0),o=wa,d=c=>{if(wa===o)return c();var u=Le,v=wa;kn(null),Kr(o);var b=c();return kn(u),Kr(v),b};return i&&a.set("length",B(e.length)),new Proxy(e,{defineProperty(c,u,v){(!("value"in v)||v.configurable===!1||v.enumerable===!1||v.writable===!1)&&Sl();var b=a.get(u);return b===void 0?d(()=>{var A=B(v.value);return a.set(u,A),A}):f(b,v.value,!0),!0},deleteProperty(c,u){var v=a.get(u);if(v===void 0){if(u in c){const b=d(()=>B(Kt));a.set(u,b),ii(l)}}else f(v,Kt),ii(l);return!0},get(c,u,v){var x;if(u===Pa)return e;var b=a.get(u),A=u in c;if(b===void 0&&(!A||(x=ti(c,u))!=null&&x.writable)&&(b=d(()=>{var C=jt(A?c[u]:Kt),z=B(C);return z}),a.set(u,b)),b!==void 0){var m=t(b);return m===Kt?void 0:m}return Reflect.get(c,u,v)},getOwnPropertyDescriptor(c,u){var v=Reflect.getOwnPropertyDescriptor(c,u);if(v&&"value"in v){var b=a.get(u);b&&(v.value=t(b))}else if(v===void 0){var A=a.get(u),m=A==null?void 0:A.v;if(A!==void 0&&m!==Kt)return{enumerable:!0,configurable:!0,value:m,writable:!0}}return v},has(c,u){var m;if(u===Pa)return!0;var v=a.get(u),b=v!==void 0&&v.v!==Kt||Reflect.has(c,u);if(v!==void 0||Re!==null&&(!b||(m=ti(c,u))!=null&&m.writable)){v===void 0&&(v=d(()=>{var x=b?jt(c[u]):Kt,C=B(x);return C}),a.set(u,v));var A=t(v);if(A===Kt)return!1}return b},set(c,u,v,b){var fe;var A=a.get(u),m=u in c;if(i&&u==="length")for(var x=v;x<A.v;x+=1){var C=a.get(x+"");C!==void 0?f(C,Kt):x in c&&(C=d(()=>B(Kt)),a.set(x+"",C))}if(A===void 0)(!m||(fe=ti(c,u))!=null&&fe.writable)&&(A=d(()=>B(void 0)),f(A,jt(v)),a.set(u,A));else{m=A.v!==Kt;var z=d(()=>jt(v));f(A,z)}var M=Reflect.getOwnPropertyDescriptor(c,u);if(M!=null&&M.set&&M.set.call(b,v),!m){if(i&&typeof u=="string"){var I=a.get("length"),Ie=Number(u);Number.isInteger(Ie)&&Ie>=I.v&&f(I,Ie+1)}ii(l)}return!0},ownKeys(c){t(l);var u=Reflect.ownKeys(c).filter(A=>{var m=a.get(A);return m===void 0||m.v!==Kt});for(var[v,b]of a)b.v!==Kt&&!(v in c)&&u.push(v);return u},setPrototypeOf(){Ml()}})}function Br(e){try{if(e!==null&&typeof e=="object"&&Pa in e)return e[Pa]}catch{}return e}function lo(e,n){return Object.is(Br(e),Br(n))}var Or,Ds,$s,Ls;function oo(){if(Or===void 0){Or=window,Ds=/Firefox/.test(navigator.userAgent);var e=Element.prototype,n=Node.prototype,a=Text.prototype;$s=ti(n,"firstChild").get,Ls=ti(n,"nextSibling").get,$r(e)&&(e[lr]=void 0,e[yi]=null,e[or]=void 0,e.__e=void 0),$r(a)&&(a[Qa]=void 0)}}function qn(e=""){return document.createTextNode(e)}function na(e){return $s.call(e)}function gi(e){return Ls.call(e)}function s(e,n){return na(e)}function Ze(e,n=!1){{var a=na(e);return a instanceof Comment&&a.data===""?gi(a):a}}function r(e,n=1,a=!1){let i=e;for(;n--;)i=gi(i);return i}function co(e){e.textContent=""}function Is(){return!1}function Bs(e,n,a){return n==null||n===fs?a?document.createElement(e,{is:a}):document.createElement(e):a?document.createElementNS(n,e,{is:a}):document.createElementNS(n,e)}let Rr=!1;function uo(){Rr||(Rr=!0,document.addEventListener("reset",e=>{Promise.resolve().then(()=>{var n;if(!e.defaultPrevented)for(const a of e.target.elements)(n=a[xi])==null||n.call(a)})},{capture:!0}))}function Mr(e){var n=Le,a=Re;kn(null),In(null);try{return e()}finally{kn(n),In(a)}}function Er(e,n,a,i=a){e.addEventListener(n,()=>Mr(a));const l=e[xi];l?e[xi]=()=>{l(),i(!0)}:e[xi]=()=>i(!0),uo()}function vo(e){Re===null&&(Le===null&&yl(),wl()),ra&&kl()}function po(e,n){var a=n.last;a===null?n.last=n.first=e:(a.next=e,e.prev=a,n.last=e)}function Wn(e,n){var a=Re;a!==null&&(a.f&en)!==0&&(e|=en);var i={ctx:Ht,deps:null,nodes:null,f:e|Ut|bn,first:null,fn:n,last:null,next:null,parent:a,b:a&&a.b,prev:null,teardown:null,wv:0,ac:null};ne==null||ne.register_created_effect(i);var l=i;if((e&Fa)!==0)Ta!==null?Ta.push(i):Sa.ensure().schedule(i);else if(n!==null){try{Ga(i)}catch(d){throw sn(i),d}l.deps===null&&l.teardown===null&&l.nodes===null&&l.first===l.last&&(l.f&Ua)===0&&(l=l.first,(e&Sn)!==0&&(e&Ka)!==0&&l!==null&&(l.f|=Ka))}if(l!==null&&(l.parent=a,a!==null&&po(l,a),Le!==null&&(Le.f&Jt)!==0&&(e&ia)===0)){var o=Le;(o.effects??(o.effects=[])).push(l)}return i}function Ar(){return Le!==null&&!Mn}function Os(e){const n=Wn(Ri,null);return Ot(n,Nt),n.teardown=e,n}function Ki(e){vo();var n=Re.f,a=!Le&&(n&En)!==0&&Ht!==null&&!Ht.i;if(a){var i=Ht;(i.e??(i.e=[])).push(e)}else return Rs(e)}function Rs(e){return Wn(Fa|hl,e)}function fo(e){Sa.ensure();const n=Wn(ia|Ua,e);return(a={})=>new Promise(i=>{a.outro?ka(n,()=>{sn(n),i(void 0)}):(sn(n),i(void 0))})}function Fs(e){return Wn(Fa,e)}function ho(e){return Wn(za|Ua,e)}function Ni(e,n=0){return Wn(Ri|n,e)}function $(e,n=[],a=[],i=[]){Jl(i,n,a,l=>{Wn(Ri,()=>{e(...l.map(t))})})}function Cr(e,n=0){var a=Wn(Sn|n,e);return a}function hn(e){return Wn(En|Ua,e)}function Ks(e){var n=e.teardown;if(n!==null){const a=ra,i=Le;Fr(!0),kn(null);try{n.call(null)}finally{Fr(a),kn(i)}}}function Tr(e,n=!1){var a=e.first;for(e.first=e.last=null;a!==null;){const l=a.ac;l!==null&&Mr(()=>{l.abort(Fi)});var i=a.next;(a.f&ia)!==0?a.parent=null:sn(a,n),a=i}}function go(e){for(var n=e.first;n!==null;){var a=n.next;(n.f&En)===0&&sn(n),n=a}}function sn(e,n=!0){var a=!1;(n||(e.f&fl)!==0)&&e.nodes!==null&&e.nodes.end!==null&&(Ns(e.nodes.start,e.nodes.end),a=!0),e.f|=sr,Tr(e,n&&!a),oi(e,0);var i=e.nodes&&e.nodes.t;if(i!==null)for(const o of i)o.stop();Ks(e),e.f^=sr,e.f|=_n;var l=e.parent;l!==null&&l.first!==null&&qs(e),e.next=e.prev=e.teardown=e.ctx=e.deps=e.fn=e.nodes=e.ac=e.b=null}function Ns(e,n){for(;e!==null;){var a=e===n?null:gi(e);e.remove(),e=a}}function qs(e){var n=e.parent,a=e.prev,i=e.next;a!==null&&(a.next=i),i!==null&&(i.prev=a),n!==null&&(n.first===e&&(n.first=i),n.last===e&&(n.last=a))}function ka(e,n,a=!0){var i=[];Gs(e,i,!0);var l=()=>{a&&sn(e),n&&n()},o=i.length;if(o>0){var d=()=>--o||l();for(var c of i)c.out(d)}else l()}function Gs(e,n,a){if((e.f&en)===0){e.f^=en;var i=e.nodes&&e.nodes.t;if(i!==null)for(const c of i)(c.is_global||a)&&n.push(c);for(var l=e.first;l!==null;){var o=l.next;if((l.f&ia)===0){var d=(l.f&Ka)!==0||(l.f&En)!==0&&(e.f&Sn)!==0;Gs(l,n,d?a:!1)}l=o}}}function $i(e){Vs(e,!0)}function Vs(e,n){if((e.f&en)!==0){e.f^=en,(e.f&Nt)===0&&(Ot(e,Ut),Sa.ensure().schedule(e));for(var a=e.first;a!==null;){var i=a.next,l=(a.f&Ka)!==0||(a.f&En)!==0;Vs(a,l?n:!1),a=i}var o=e.nodes&&e.nodes.t;if(o!==null)for(const d of o)(d.is_global||n)&&d.in()}}function zr(e,n){if(e.nodes)for(var a=e.nodes.start,i=e.nodes.end;a!==null;){var l=a===i?null:gi(a);n.append(a),a=l}}let Ai=!1,ra=!1;function Fr(e){ra=e}let Le=null,Mn=!1;function kn(e){Le=e}let Re=null;function In(e){Re=e}let Dn=null;function Ws(e){Le!==null&&(Dn??(Dn=new Set)).add(e)}let rn=null,on=0,un=null;function mo(e){un=e}let Us=1,ca=0,wa=ca;function Kr(e){wa=e}function js(){return++Us}function mi(e){var n=e.f;if((n&Ut)!==0)return!0;if(n&Jt&&(e.f&=~xa),(n&Ln)!==0){for(var a=e.deps,i=a.length,l=0;l<i;l++){var o=a[l];if(mi(o)&&xs(o),o.wv>e.wv)return!0}(n&bn)!==0&&Wt===null&&Ot(e,Nt)}return!1}function Hs(e,n,a=!0){var i=e.reactions;if(i!==null&&!(Dn!==null&&Dn.has(e)))for(var l=0;l<i.length;l++){var o=i[l];(o.f&Jt)!==0?Hs(o,n,!1):n===o&&(a?Ot(o,Ut):(o.f&Nt)!==0&&Ot(o,Ln),Sr(o))}}function Js(e){var z;var n=rn,a=on,i=un,l=Le,o=Dn,d=Ht,c=Mn,u=wa,v=e.f;rn=null,on=0,un=null,Le=(v&(En|ia))===0?e:null,Dn=null,Na(e.ctx),Mn=!1,wa=++ca,e.ac!==null&&(Mr(()=>{e.ac.abort(Fi)}),e.ac=null);try{e.f|=zi;var b=e.fn,A=b();e.f|=Wa;var m=e.deps,x=ne==null?void 0:ne.is_fork;if(rn!==null){var C;if(x||oi(e,on),m!==null&&on>0)for(m.length=on+rn.length,C=0;C<rn.length;C++)m[on+C]=rn[C];else e.deps=m=rn;if(Ar()&&(e.f&bn)!==0)for(C=on;C<m.length;C++)((z=m[C]).reactions??(z.reactions=[])).push(e)}else!x&&m!==null&&on<m.length&&(oi(e,on),m.length=on);if(ms()&&un!==null&&!Mn&&m!==null&&(e.f&(Jt|Ln|Ut))===0)for(C=0;C<un.length;C++)Hs(un[C],e);if(l!==null&&l!==e){if(ca++,l.deps!==null)for(let M=0;M<a;M+=1)l.deps[M].rv=ca;if(n!==null)for(const M of n)M.rv=ca;un!==null&&(i===null?i=un:i.push(...un))}return(e.f&aa)!==0&&(e.f^=aa),A}catch(M){return _s(M)}finally{e.f^=zi,rn=n,on=a,un=i,Le=l,Dn=o,Na(d),Mn=c,wa=u}}function bo(e,n){let a=n.reactions;if(a!==null){var i=ll.call(a,e);if(i!==-1){var l=a.length-1;l===0?a=n.reactions=null:(a[i]=a[l],a.pop())}}if(a===null&&(n.f&Jt)!==0&&(rn===null||!Ci.call(rn,n))){var o=n;(o.f&bn)!==0&&(o.f^=bn,o.f&=~xa),o.v!==Kt&&kr(o),eo(o),oi(o,0)}}function oi(e,n){var a=e.deps;if(a!==null)for(var i=n;i<a.length;i++)bo(e,a[i])}function Ga(e){var n=e.f;if((n&_n)===0){Ot(e,Nt);var a=Re,i=Ai;Re=e,Ai=!0;try{(n&(Sn|us))!==0?go(e):Tr(e),Ks(e);var l=Js(e);e.teardown=typeof l=="function"?l:null,e.wv=Us;var o}finally{Ai=i,Re=a}}}async function _o(){await Promise.resolve(),ao()}function t(e){var n=e.f,a=(n&Jt)!==0;if(Le!==null&&!Mn){var i=Re!==null&&(Re.f&_n)!==0;if(!i&&(Dn===null||!Dn.has(e))){var l=Le.deps;if((Le.f&zi)!==0)e.rv<ca&&(e.rv=ca,rn===null&&l!==null&&l[on]===e?on++:rn===null?rn=[e]:rn.push(e));else{Le.deps??(Le.deps=[]),Ci.call(Le.deps,e)||Le.deps.push(e);var o=e.reactions;o===null?e.reactions=[Le]:Ci.call(o,Le)||o.push(Le)}}}if(ra&&_a.has(e))return _a.get(e);if(a){var d=e;if(ra){var c=d.v;return((d.f&Nt)===0&&d.reactions!==null||Zs(d))&&(c=yr(d)),_a.set(d,c),c}var u=(d.f&bn)===0&&!Mn&&Le!==null&&(Ai||(Le.f&bn)!==0),v=(d.f&Wa)===0;mi(d)&&(u&&(d.f|=bn),xs(d)),u&&!v&&(Ss(d),Qs(d))}if(Wt!=null&&Wt.has(e))return Wt.get(e);if((e.f&aa)!==0)throw e.v;return e.v}function Qs(e){if(e.f|=bn,e.deps!==null)for(const n of e.deps)(n.reactions??(n.reactions=[])).push(e),(n.f&Jt)!==0&&(n.f&bn)===0&&(Ss(n),Qs(n))}function Zs(e){if(e.v===Kt)return!0;if(e.deps===null)return!1;for(const n of e.deps)if(_a.has(n)||(n.f&Jt)!==0&&Zs(n))return!0;return!1}function ja(e){var n=Mn;try{return Mn=!0,e()}finally{Mn=n}}const ko=["touchstart","touchmove"];function wo(e){return ko.includes(e)}const ua=Symbol("events"),Ys=new Set,hr=new Set;function S(e,n,a){(n[ua]??(n[ua]={}))[e]=a}function sa(e){for(var n=0;n<e.length;n++)Ys.add(e[n]);for(var a of hr)a(e)}let Nr=null;function qr(e){var z,M;var n=this,a=n.ownerDocument,i=e.type,l=((z=e.composedPath)==null?void 0:z.call(e))||[],o=l[0]||e.target;Nr=e;var d=0,c=Nr===e&&e[ua];if(c){var u=l.indexOf(c);if(u!==-1&&(n===document||n===window)){e[ua]=n;return}var v=l.indexOf(n);if(v===-1)return;u<=v&&(d=u)}if(o=l[d]||e.target,o!==n){ol(e,"currentTarget",{configurable:!0,get(){return o||a}});var b=Le,A=Re;kn(null),In(null);try{for(var m,x=[];o!==null&&o!==n;){try{var C=(M=o[ua])==null?void 0:M[i];C!=null&&(!o.disabled||e.target===o)&&C.call(o,e)}catch(I){m?x.push(I):m=I}if(e.cancelBubble)break;d++,o=d<l.length?l[d]:null}if(m){for(let I of x)queueMicrotask(()=>{throw I});throw m}}finally{e[ua]=n,delete e.currentTarget,kn(b),In(A)}}}var ss;const Qi=((ss=globalThis==null?void 0:globalThis.window)==null?void 0:ss.trustedTypes)&&globalThis.window.trustedTypes.createPolicy("svelte-trusted-html",{createHTML:e=>e});function yo(e){return(Qi==null?void 0:Qi.createHTML(e))??e}function xo(e){var n=Bs("template");return n.innerHTML=yo(e.replaceAll("<!>","<!---->")),n.content}function Va(e,n){var a=Re;a.nodes===null&&(a.nodes={start:e,end:n,a:null,t:null})}function _(e,n){var a=(n&Dl)!==0,i=(n&$l)!==0,l,o=!e.startsWith("<!>");return()=>{l===void 0&&(l=xo(o?e:"<!>"+e),a||(l=na(l)));var d=i||Ds?document.importNode(l,!0):l.cloneNode(!0);if(a){var c=na(d),u=d.lastChild;Va(c,u)}else Va(d,d);return d}}function ri(e=""){{var n=qn(e+"");return Va(n,n),n}}function di(){var e=document.createDocumentFragment(),n=document.createComment(""),a=qn();return e.append(n,a),Va(n,a),e}function h(e,n){e!==null&&e.before(n)}function g(e,n){var a=n==null?"":typeof n=="object"?`${n}`:n;a!==(e[Qa]??(e[Qa]=e.nodeValue))&&(e[Qa]=a,e.nodeValue=`${a}`)}function So(e,n){return Mo(e,n)}const wi=new Map;function Mo(e,{target:n,anchor:a,props:i={},events:l,context:o,intro:d=!0,transformError:c}){oo();var u=void 0,v=fo(()=>{var b=a??n.appendChild(qn());Vl(b,{pending:()=>{}},x=>{Gn({});var C=Ht;o&&(C.c=o),l&&(i.$$events=l),u=e(x,i)||{},Vn()},c);var A=new Set,m=x=>{for(var C=0;C<x.length;C++){var z=x[C];if(!A.has(z)){A.add(z);var M=wo(z);for(const fe of[n,document]){var I=wi.get(fe);I===void 0&&(I=new Map,wi.set(fe,I));var Ie=I.get(z);Ie===void 0?(fe.addEventListener(z,qr,{passive:M}),I.set(z,1)):I.set(z,Ie+1)}}}};return m(Oi(Ys)),hr.add(m),()=>{var M;for(var x of A)for(const I of[n,document]){var C=wi.get(I),z=C.get(x);--z==0?(I.removeEventListener(x,qr),C.delete(x),C.size===0&&wi.delete(I)):C.set(x,z)}hr.delete(m),b!==a&&((M=b.parentNode)==null||M.removeChild(b))}});return Eo.set(u,v),u}let Eo=new WeakMap;var xn,zn,cn,ma,fi,hi,Bi;class Ao{constructor(n,a=!0){ln(this,"anchor");ye(this,xn,new Map);ye(this,zn,new Map);ye(this,cn,new Map);ye(this,ma,new Set);ye(this,fi,!0);ye(this,hi,n=>{if(p(this,xn).has(n)){var a=p(this,xn).get(n),i=p(this,zn).get(a);if(i)$i(i),p(this,ma).delete(a);else{var l=p(this,cn).get(a);l&&($i(l.effect),p(this,zn).set(a,l.effect),p(this,cn).delete(a),l.fragment.lastChild.remove(),this.anchor.before(l.fragment),i=l.effect)}for(const[o,d]of p(this,xn)){if(p(this,xn).delete(o),o===n)break;const c=p(this,cn).get(d);c&&(sn(c.effect),p(this,cn).delete(d))}for(const[o,d]of p(this,zn)){if(o===a||p(this,ma).has(o))continue;const c=()=>{if(Array.from(p(this,xn).values()).includes(o)){var v=document.createDocumentFragment();zr(d,v),v.append(qn()),p(this,cn).set(o,{effect:d,fragment:v})}else sn(d);p(this,ma).delete(o),p(this,zn).delete(o)};p(this,fi)||!i?(p(this,ma).add(o),ka(d,c,!1)):c()}}});ye(this,Bi,n=>{p(this,xn).delete(n);const a=Array.from(p(this,xn).values());for(const[i,l]of p(this,cn))a.includes(i)||(sn(l.effect),p(this,cn).delete(i))});this.anchor=n,ge(this,fi,a)}ensure(n,a){var i=ne,l=Is();if(a&&!p(this,zn).has(n)&&!p(this,cn).has(n))if(l){var o=document.createDocumentFragment(),d=qn();o.append(d),p(this,cn).set(n,{effect:hn(()=>a(d)),fragment:o})}else p(this,zn).set(n,hn(()=>a(this.anchor)));if(p(this,xn).set(i,n),l){for(const[c,u]of p(this,zn))c===n?i.unskip_effect(u):i.skip_effect(u);for(const[c,u]of p(this,cn))c===n?i.unskip_effect(u.effect):i.skip_effect(u.effect);i.oncommit(p(this,hi)),i.ondiscard(p(this,Bi))}else p(this,hi).call(this,i)}}xn=new WeakMap,zn=new WeakMap,cn=new WeakMap,ma=new WeakMap,fi=new WeakMap,hi=new WeakMap,Bi=new WeakMap;function q(e,n,a=!1){var i=new Ao(e),l=a?Ka:0;function o(d,c){i.ensure(d,c)}Cr(()=>{var d=!1;n((c,u=0)=>{d=!0,o(u,c)}),d||o(-1,null)},l)}function rt(e,n){return n}function Co(e,n,a){for(var i=[],l=n.length,o,d=n.length,c=0;c<l;c++){let A=n[c];ka(A,()=>{if(o){if(o.pending.delete(A),o.done.add(A),o.pending.size===0){var m=e.outrogroups;gr(e,Oi(o.done)),m.delete(o),m.size===0&&(e.outrogroups=null)}}else d-=1},!1)}if(d===0){var u=i.length===0&&a!==null;if(u){var v=a,b=v.parentNode;co(b),b.append(v),e.items.clear()}gr(e,n,!u)}else o={pending:new Set(n),done:new Set},(e.outrogroups??(e.outrogroups=new Set)).add(o)}function gr(e,n,a=!0){var i;if(e.pending.size>0){i=new Set;for(const d of e.pending.values())for(const c of d)i.add(e.items.get(c).e)}for(var l=0;l<n.length;l++){var o=n[l];if(i!=null&&i.has(o)){o.f|=Pn;const d=document.createDocumentFragment();zr(o,d)}else sn(n[l],a)}}var Gr;function nt(e,n,a,i,l,o=null){var d=e,c=new Map,u=(n&ps)!==0;if(u){var v=e;d=v.appendChild(qn())}var b=null,A=Yl(()=>{var fe=a();return _r(fe)?fe:fe==null?[]:Oi(fe)}),m,x=new Map,C=!0;function z(fe){(Ie.effect.f&_n)===0&&(Ie.pending.delete(fe),Ie.fallback=b,To(Ie,m,d,n,i),b!==null&&(m.length===0?(b.f&Pn)===0?$i(b):(b.f^=Pn,ei(b,null,d)):ka(b,()=>{b=null})))}function M(fe){Ie.pending.delete(fe)}var I=Cr(()=>{m=t(A);for(var fe=m.length,me=new Set,ke=ne,K=Is(),Y=0;Y<fe;Y+=1){var he=m[Y],xe=i(he,Y),Te=C?null:c.get(xe);Te?(Te.v&&qa(Te.v,he),Te.i&&qa(Te.i,Y),K&&ke.unskip_effect(Te.e)):(Te=zo(c,C?d:Gr??(Gr=qn()),he,xe,Y,l,n,a),C||(Te.e.f|=Pn),c.set(xe,Te)),me.add(xe)}if(fe===0&&o&&!b&&(C?b=hn(()=>o(d)):(b=hn(()=>o(Gr??(Gr=qn()))),b.f|=Pn)),fe>me.size&&_l(),!C)if(x.set(ke,me),K){for(const[Ve,yt]of c)me.has(Ve)||ke.skip_effect(yt.e);ke.oncommit(z),ke.ondiscard(M)}else z(ke);t(A)}),Ie={effect:I,items:c,pending:x,outrogroups:null,fallback:b};C=!1}function Ja(e){for(;e!==null&&(e.f&En)===0;)e=e.next;return e}function To(e,n,a,i,l){var Te,Ve,yt,T,X,ve,Ye,ae,Be;var o=(i&zl)!==0,d=n.length,c=e.items,u=Ja(e.effect.first),v,b=null,A,m=[],x=[],C,z,M,I;if(o)for(I=0;I<d;I+=1)C=n[I],z=l(C,I),M=c.get(z).e,(M.f&Pn)===0&&((Ve=(Te=M.nodes)==null?void 0:Te.a)==null||Ve.measure(),(A??(A=new Set)).add(M));for(I=0;I<d;I+=1){if(C=n[I],z=l(C,I),M=c.get(z).e,e.outrogroups!==null)for(const re of e.outrogroups)re.pending.delete(M),re.done.delete(M);if((M.f&en)!==0&&($i(M),o&&((T=(yt=M.nodes)==null?void 0:yt.a)==null||T.unfix(),(A??(A=new Set)).delete(M))),(M.f&Pn)!==0)if(M.f^=Pn,M===u)ei(M,null,a);else{var Ie=b?b.next:u;M===e.effect.last&&(e.effect.last=M.prev),M.prev&&(M.prev.next=M.next),M.next&&(M.next.prev=M.prev),Jn(e,b,M),Jn(e,M,Ie),ei(M,Ie,a),b=M,m=[],x=[],u=Ja(b.next);continue}if(M!==u){if(v!==void 0&&v.has(M)){if(m.length<x.length){var fe=x[0],me;b=fe.prev;var ke=m[0],K=m[m.length-1];for(me=0;me<m.length;me+=1)ei(m[me],fe,a);for(me=0;me<x.length;me+=1)v.delete(x[me]);Jn(e,ke.prev,K.next),Jn(e,b,ke),Jn(e,K,fe),u=fe,b=K,I-=1,m=[],x=[]}else v.delete(M),ei(M,u,a),Jn(e,M.prev,M.next),Jn(e,M,b===null?e.effect.first:b.next),Jn(e,b,M),b=M;continue}for(m=[],x=[];u!==null&&u!==M;)(v??(v=new Set)).add(u),x.push(u),u=Ja(u.next);if(u===null)continue}(M.f&Pn)===0&&m.push(M),b=M,u=Ja(M.next)}if(e.outrogroups!==null){for(const re of e.outrogroups)re.pending.size===0&&(gr(e,Oi(re.done)),(X=e.outrogroups)==null||X.delete(re));e.outrogroups.size===0&&(e.outrogroups=null)}if(u!==null||v!==void 0){var Y=[];if(v!==void 0)for(M of v)(M.f&en)===0&&Y.push(M);for(;u!==null;)(u.f&en)===0&&u!==e.fallback&&Y.push(u),u=Ja(u.next);var he=Y.length;if(he>0){var xe=(i&ps)!==0&&d===0?a:null;if(o){for(I=0;I<he;I+=1)(Ye=(ve=Y[I].nodes)==null?void 0:ve.a)==null||Ye.measure();for(I=0;I<he;I+=1)(Be=(ae=Y[I].nodes)==null?void 0:ae.a)==null||Be.fix()}Co(e,Y,xe)}}o&&ba(()=>{var re,F;if(A!==void 0)for(M of A)(F=(re=M.nodes)==null?void 0:re.a)==null||F.apply()})}function zo(e,n,a,i,l,o,d,c){var u=(d&Cl)!==0?(d&Pl)===0?ro(a,!1,!1):Ma(a):null,v=(d&Tl)!==0?Ma(l):null;return{v:u,i:v,e:hn(()=>(o(n,u??a,v??l,c),()=>{e.delete(i)}))}}function ei(e,n,a){if(e.nodes)for(var i=e.nodes.start,l=e.nodes.end,o=n&&(n.f&Pn)===0?n.nodes.start:a;i!==null;){var d=gi(i);if(o.before(i),i===l)return;i=d}}function Jn(e,n,a){n===null?e.effect.first=a:n.next=a,a===null?e.effect.last=n:a.prev=n}function qe(e,n,a=!1,i=!1,l=!1,o=!1){var d=e,c="";if(a)var u=e;$(()=>{var v=Re;if(c!==(c=n()??"")){if(a){v.nodes=null,u.innerHTML=c,c!==""&&Va(na(u),u.lastChild);return}if(v.nodes!==null&&(Ns(v.nodes.start,v.nodes.end),v.nodes=null),c!==""){var b=i?Ll:l?Il:void 0,A=Bs(i?"svg":l?"math":"template",b);A.innerHTML=c;var m=i||l?A:A.content;if(Va(na(m),m.lastChild),i||l)for(;na(m);)d.before(na(m));else d.before(m)}}})}function Po(e,n,a){var i=e==null?"":""+e;return i===""?null:i}function Do(e,n){return e==null?null:String(e)}function Ct(e,n,a,i,l,o){var d=e[lr];if(d!==a||d===void 0){var c=Po(a);c==null?e.removeAttribute("class"):e.className=c,e[lr]=a}return o}function Xt(e,n,a,i){var l=e[or];if(l!==n){var o=Do(n);o==null?e.removeAttribute("style"):e.style.cssText=o,e[or]=n}return i}function Xs(e,n,a=!1){if(e.multiple){if(n==null)return;if(!_r(n))return Ol();for(var i of e.options)i.selected=n.includes(si(i));return}for(i of e.options){var l=si(i);if(lo(l,n)){i.selected=!0;return}}(!a||n!==void 0)&&(e.selectedIndex=-1)}function $o(e){var n=new MutationObserver(()=>{Xs(e,e.__value)});n.observe(e,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["value"]}),Os(()=>{n.disconnect()})}function ya(e,n,a=n){var i=new WeakSet,l=!0;Er(e,"change",o=>{var d=o?"[selected]":":checked",c;if(e.multiple)c=[].map.call(e.querySelectorAll(d),si);else{var u=e.querySelector(d)??e.querySelector("option:not([disabled])");c=u&&si(u)}a(c),e.__value=c,ne!==null&&i.add(ne)}),Fs(()=>{var o=n();if(e===document.activeElement){var d=ne;if(i.has(d))return}if(Xs(e,o,l),l&&o===void 0){var c=e.querySelector(":checked");c!==null&&(o=si(c),a(o))}e.__value=o,l=!1}),$o(e)}function si(e){return"__value"in e?e.__value:e.value}const Lo=Symbol("is custom element"),Io=Symbol("is html"),Bo=ml?"progress":"PROGRESS";function Qn(e,n){var a=el(e);a.value===(a.value=n??void 0)||e.value===n&&(n!==0||e.nodeName!==Bo)||(e.value=n??"")}function qi(e,n,a,i){var l=el(e);l[n]!==(l[n]=a)&&(n==="loading"&&(e[gl]=a),a==null?e.removeAttribute(n):typeof a!="string"&&Oo(e).includes(n)?e[n]=a:e.setAttribute(n,a))}function el(e){return e[yi]??(e[yi]={[Lo]:e.nodeName.includes("-"),[Io]:e.namespaceURI===fs})}var Vr=new Map;function Oo(e){var n=e.getAttribute("is")||e.nodeName,a=Vr.get(n);if(a)return a;Vr.set(n,a=[]);for(var i,l=e,o=Element.prototype;o!==l;){i=dl(l);for(var d in i)i[d].set&&d!=="innerHTML"&&d!=="textContent"&&d!=="innerText"&&a.push(d);l=ds(l)}return a}function gn(e,n,a=n){var i=new WeakSet;Er(e,"input",async l=>{var o=l?e.defaultValue:e.value;if(o=Zi(e)?Yi(o):o,a(o),ne!==null&&i.add(ne),await _o(),o!==(o=n())){var d=e.selectionStart,c=e.selectionEnd,u=e.value.length;if(e.value=o??"",c!==null){var v=e.value.length;d===c&&c===u&&v>u?(e.selectionStart=v,e.selectionEnd=v):(e.selectionStart=d,e.selectionEnd=Math.min(c,v))}}}),ja(n)==null&&e.value&&(a(Zi(e)?Yi(e.value):e.value),ne!==null&&i.add(ne)),Ni(()=>{var l=n();if(e===document.activeElement){var o=ne;if(i.has(o))return}Zi(e)&&l===Yi(e.value)||e.type==="date"&&!l&&!e.value||l!==e.value&&(e.value=l??"")})}function Ro(e,n,a=n){Er(e,"change",i=>{var l=i?e.defaultChecked:e.checked;a(l)}),ja(n)==null&&a(e.checked),Ni(()=>{var i=n();e.checked=!!i})}function Zi(e){var n=e.type;return n==="number"||n==="range"}function Yi(e){return e===""?null:+e}function Xi(e,n){return e===n||(e==null?void 0:e[Pa])===n}function Fo(e={},n,a,i){var l=Ht.r,o=Re;return Fs(()=>{var d,c;return Ni(()=>{d=c,c=[],ja(()=>{Xi(a(...c),e)||(n(e,...c),d&&Xi(a(...d),e)&&n(null,...d))})}),()=>{let u=o;for(;u!==l&&u.parent!==null&&u.parent.f&sr;)u=u.parent;const v=()=>{c&&Xi(a(...c),e)&&n(null,...c)},b=u.teardown;u.teardown=()=>{v(),b==null||b()}}}),e}function bi(e){Ht===null&&vs(),Ki(()=>{const n=ja(e);if(typeof n=="function")return n})}function Ko(e){Ht===null&&vs(),bi(()=>()=>ja(e))}let ci=localStorage.getItem("mc_token")||"";function tl(){return ci}function No(e){ci=(e||"").trim(),localStorage.setItem("mc_token",ci)}function qo(){const e={"Content-Type":"application/json"};return ci&&(e["X-MC-Token"]=ci),e}function li(){return localStorage.getItem("mc_hf_token")||""}function Go(e){localStorage.setItem("mc_hf_token",(e||"").trim())}async function Se(e,n={}){const a=await fetch(e,{headers:qo(),...n}),i=await a.json().catch(()=>({}));if(!a.ok)throw new Error(i.error||"HTTP "+a.status);return i}const Vo=(e,n=document)=>n.querySelector(e),Wr=(e,n=document)=>[...n.querySelectorAll(e)];function $n(e){return String(e??"").replace(/[&<>]/g,n=>({"&":"&","<":"<",">":">"})[n])}let Ur;function ee(e,n=!1){const a=Vo("#toast");a&&(a.textContent=e,a.className="toast show"+(n?" err":""),clearTimeout(Ur),Ur=setTimeout(()=>a.className="toast",3200))}function Wo(e,n){return e==="running"||e==="ready"?'<span class="badge b-run">geladen</span>':e==="loading"||e==="starting"?'<span class="badge b-load">lädt…</span>':e==="downloading"?`<span class="badge b-load">↓ Download${n!=null?` ${Math.round(n)}%`:""}</span>`:'<span class="badge b-run">bereit</span>'}const it=e=>`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round">${e}</svg>`,Gi={logo:it('<circle cx="12" cy="12" r="3.2"/><path d="M12 2v3M12 19v3M2 12h3M19 12h3M5 5l2 2M17 17l2 2M19 5l-2 2M7 17l-2 2"/>'),grid:it('<rect x="3" y="3" width="7" height="7" rx="1.5"/><rect x="14" y="3" width="7" height="7" rx="1.5"/><rect x="3" y="14" width="7" height="7" rx="1.5"/><rect x="14" y="14" width="7" height="7" rx="1.5"/>'),cpu:it('<rect x="6" y="6" width="12" height="12" rx="2"/><path d="M9 1v3M15 1v3M9 20v3M15 20v3M1 9h3M1 15h3M20 9h3M20 15h3"/>'),pulse:it('<path d="M3 12h4l2 6 4-14 2 8h6"/>'),server:it('<rect x="3" y="4" width="18" height="7" rx="2"/><rect x="3" y="13" width="18" height="7" rx="2"/><path d="M7 7.5h.01M7 16.5h.01"/>'),book:it('<path d="M4 5a2 2 0 0 1 2-2h13v16H6a2 2 0 0 0-2 2z"/><path d="M19 19H6a2 2 0 0 0-2 2"/>'),help:it('<circle cx="12" cy="12" r="9"/><path d="M9.5 9.2a2.5 2.5 0 0 1 4.8 1c0 1.7-2.3 2-2.3 3.4"/><path d="M12 17h.01"/>'),settings:it('<circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.6 1.6 0 0 0 .3 1.8l.1.1a2 2 0 1 1-2.8 2.8l-.1-.1a1.6 1.6 0 0 0-2.7 1.1V21a2 2 0 1 1-4 0v-.1A1.6 1.6 0 0 0 6.6 19l-.1.1a2 2 0 1 1-2.8-2.8l.1-.1a1.6 1.6 0 0 0-1.1-2.7H2a2 2 0 1 1 0-4h.1A1.6 1.6 0 0 0 4 6.6l-.1-.1a2 2 0 1 1 2.8-2.8l.1.1A1.6 1.6 0 0 0 9 4.6V4a2 2 0 1 1 4 0v.1A1.6 1.6 0 0 0 17.4 6l.1-.1a2 2 0 1 1 2.8 2.8l-.1.1a1.6 1.6 0 0 0 1.1 2.7H21a2 2 0 1 1 0 4h-.1a1.6 1.6 0 0 0-1.5 1z"/>'),swap:it('<path d="M7 4 3 8l4 4"/><path d="M3 8h12a4 4 0 0 1 0 8h-1"/><path d="m17 20 4-4-4-4"/>'),monitor:it('<rect x="3" y="4" width="18" height="12" rx="2"/><path d="M8 20h8M12 16v4"/>'),layers:it('<path d="m12 2 9 5-9 5-9-5z"/><path d="m3 12 9 5 9-5M3 17l9 5 9-5"/>'),alert:it('<path d="M10.3 3.9 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0z"/><path d="M12 9v4M12 17h.01"/>'),gauge:it('<path d="M12 14 16 9"/><circle cx="12" cy="13" r="9"/><path d="M12 4v2M21 13h-2M5 13H3"/>'),search:it('<circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/>'),compass:it('<circle cx="12" cy="12" r="10"/><polygon points="16.24 7.76 14.12 14.12 7.76 16.24 9.88 9.88 16.24 7.76"/>'),code:it('<polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/>'),eye:it('<path d="M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z"/><circle cx="12" cy="12" r="3"/>'),refresh:it('<path d="M3 12a9 9 0 0 1 15-6.7L21 8"/><path d="M21 3v5h-5"/><path d="M21 12a9 9 0 0 1-15 6.7L3 16"/><path d="M3 21v-5h5"/>'),file:it('<path d="M14 3H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><path d="M14 3v5h5"/><path d="M9 13h6M9 17h5"/>'),database:it('<ellipse cx="12" cy="5" rx="8" ry="3"/><path d="M4 5v6c0 1.7 3.6 3 8 3s8-1.3 8-3V5"/><path d="M4 11v6c0 1.7 3.6 3 8 3s8-1.3 8-3v-6"/>'),thermo:it('<path d="M14 14.76V5a2 2 0 0 0-4 0v9.76a4 4 0 1 0 4 0z"/>'),shield:it('<path d="M12 3l8 4v5c0 5-3.5 8-8 9-4.5-1-8-4-8-9V7z"/><path d="m9 12 2 2 4-4"/>'),info:it('<circle cx="12" cy="12" r="9"/><path d="M12 16v-4M12 8h.01"/>'),chevron:it('<path d="m9 6 6 6-6 6"/>'),bolt:it('<path d="M13 2 3 14h7l-1 8 10-12h-7z"/>'),x:it('<path d="M18 6 6 18M6 6l12 12"/>'),check:it('<path d="M20 6 9 17l-5-5"/>'),download:it('<path d="M12 3v12M7 10l5 5 5-5"/><path d="M5 21h14"/>'),clock:it('<circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/>')};function Ft(e){return Gi[e]||""}function mr(e){return`<span class="info-dot" tabindex="0" title="${$n(e)}" aria-label="${$n(e)}">${Gi.info}</span>`}function oa(e){if(!e&&e!==0)return"–";const n=e/1024/1024/1024;return n>=1?n.toFixed(1)+" GB":Math.round(e/1024/1024)+" MB"}function mn({title:e,body:n,confirmLabel:a="Bestätigen",cancelLabel:i="Abbrechen",danger:l=!1}){return new Promise(o=>{const d=document.createElement("div");d.className="modal-overlay",d.innerHTML=`<div class="modal-card" role="dialog" aria-modal="true">
|
||
<h3>${$n(e)}</h3>
|
||
<p>${n}</p>
|
||
<div class="modal-actions">
|
||
<button data-x="0">${$n(i)}</button>
|
||
<button class="${l?"danger":"primary"}" data-x="1">${$n(a)}</button>
|
||
</div></div>`;const c=u=>{d.remove(),o(u)};d.addEventListener("click",u=>{if(u.target===d)return c(!1);const v=u.target.closest("[data-x]");v&&c(v.getAttribute("data-x")==="1")}),document.body.appendChild(d),d.querySelector('[data-x="1"]').focus()})}function jr({title:e,body:n="",placeholder:a="",password:i=!1,confirmLabel:l="Weiter",danger:o=!1}){return new Promise(d=>{const c=document.createElement("div");c.className="modal-overlay",c.innerHTML=`<div class="modal-card" role="dialog" aria-modal="true">
|
||
<h3>${$n(e)}</h3>
|
||
${n?`<p>${n}</p>`:""}
|
||
<input type="${i?"password":"text"}" placeholder="${$n(a)}" autocomplete="off" style="margin-bottom:18px">
|
||
<div class="modal-actions">
|
||
<button data-x="0">Abbrechen</button>
|
||
<button class="${o?"danger":"primary"}" data-x="1">${$n(l)}</button>
|
||
</div></div>`;const u=c.querySelector("input"),v=b=>{c.remove(),d(b)};c.addEventListener("click",b=>{if(b.target===c)return v(null);const A=b.target.closest("[data-x]");A&&v(A.getAttribute("data-x")==="1"?u.value||"":null)}),u.addEventListener("keydown",b=>{b.key==="Enter"&&v(u.value||""),b.key==="Escape"&&v(null)}),document.body.appendChild(c),u.focus()})}function Uo(e="overview"){const n=Wr(".nav-item[data-view]:not(.disabled)"),a=Wr(".view[data-view]"),i=new Set(a.map(o=>o.dataset.view));function l(o){i.has(o)||(o=e),a.forEach(d=>d.hidden=d.dataset.view!==o),n.forEach(d=>d.classList.toggle("active",d.dataset.view===o)),location.hash!=="#/"+o&&(location.hash="#/"+o)}return n.forEach(o=>o.addEventListener("click",d=>{d.preventDefault(),l(o.dataset.view)})),window.addEventListener("hashchange",()=>l(location.hash.replace("#/",""))),l(location.hash.replace("#/","")||e),{show:l}}let Hr=B(null);const _i={get value(){return t(Hr)},set(e){f(Hr,e,!0)}};let Jr=B(jt([])),Zn=B(jt([]));const va={get value(){return t(Jr)},set(e){f(Jr,e||[],!0)},get tracked(){return t(Zn)},track(e){t(Zn).includes(e)||f(Zn,[...t(Zn),e],!0)},toggle(e){f(Zn,t(Zn).includes(e)?t(Zn).filter(n=>n!==e):[...t(Zn),e],!0)}};let Qr=B(null);const Pr={get value(){return t(Qr)},set(e){f(Qr,e,!0)}},jo="5";var ls;typeof window<"u"&&((ls=window.__svelte??(window.__svelte={})).v??(ls.v=new Set)).add(jo);var Ho=_('<span style="font-size:13px;font-weight:400;color:var(--mut)">— bereit für Anfragen</span>'),Jo=_('<div><div class="k-h"><span class="k-t">Temperatur (GPU)</span><span class="k-ic"></span></div> <div class="k-v"> </div> <div class="k-s"> </div></div> <div><div class="k-h"><span class="k-t">Freier Speicher</span><span class="k-ic"></span></div> <div class="k-v"> <small>GB</small></div> <div class="k-s"> </div></div>',1),Qo=_('<div class="kpi muted"><div class="k-h"><span class="k-t">Temperatur</span></div><div class="k-v">–</div><div class="k-s">messe…</div></div> <div class="kpi muted"><div class="k-h"><span class="k-t">Freier Speicher</span></div><div class="k-v">–</div><div class="k-s">messe…</div></div>',1),Zo=_('<div class="meter"><div class="meter-h"><span class="mk"> </span><span class="mv"> </span></div> <div><i></i></div></div>'),Yo=_('<div class="empty">Warte auf Messwerte…</div>'),Xo=_('<div class="card-sub">Noch kein Modell eingerichtet — starte hier:</div> <button class="qa"><span class="qa-ic teal"></span> <span class="qa-main"><span class="qa-t">Schritt 1 · Modell holen</span><span class="qa-s">Cookbook → passendes Setup installieren</span></span> <span class="qa-arrow"></span></button> <button class="qa" style="opacity:.55;pointer-events:none"><span class="qa-ic teal"></span> <span class="qa-main"><span class="qa-t">Schritt 2 · Tools verbinden</span><span class="qa-s">Erst nach dem Download verfügbar</span></span> <span class="qa-arrow"></span></button> <button class="qa"><span class="qa-ic blue"></span> <span class="qa-main"><span class="qa-t">Einsteiger-Guide lesen</span><span class="qa-s">Alle Begriffe erklärt, ohne Vorwissen</span></span> <span class="qa-arrow"></span></button>',1),ed=_('<div class="card-sub">Die häufigsten Aufgaben — ein Klick.</div> <button class="qa"><span class="qa-ic teal"></span> <span class="qa-main"><span class="qa-t">Modell finden</span><span class="qa-s">Passend zu deiner Hardware</span></span> <span class="qa-arrow"></span></button> <button class="qa"><span class="qa-ic amber"></span> <span class="qa-main"><span class="qa-t">Speicher freigeben</span><span class="qa-s">Alle Modelle entladen</span></span> <span class="qa-arrow"></span></button> <button class="qa"><span class="qa-ic blue"></span> <span class="qa-main"><span class="qa-t">Logs ansehen</span><span class="qa-s">Live mitlesen, was läuft</span></span> <span class="qa-arrow"></span></button> <button class="qa"><span class="qa-ic teal"></span> <span class="qa-main"><span class="qa-t">Tools verbinden</span><span class="qa-s">Zed, OpenCode, Cline einrichten</span></span> <span class="qa-arrow"></span></button>',1),td=_('<span class="tag img">Bild</span>'),nd=_('<span class="tag code">Code</span>'),ad=_('<span class="tag text">Text</span>'),id=_('<span class="chip" style="padding:2px 7px;font-size:11px">∞ aktiv</span>'),rd=_('<button class="ghost"> </button>'),sd=_('<div class="li" style="padding:10px 4px"><span></span> <div class="li-main"><div class="flex items-center gap-2" style="flex-wrap:wrap"><span class="li-id"> </span> <!> <!></div> <div class="li-sub mono-sm"> </div></div> <div class="flex items-center gap-2"><span class="li-meta"> </span> <!></div></div>'),Zr=_('<div class="list"></div>'),ld=_('<div class="empty-c"><div class="e-t">Noch keine Modelle</div> <div class="e-s">Hol dir unter „Cookbook" ein Modell, das auf deine Hardware passt.</div> <button class="primary" style="margin-top:12px">Zum Cookbook →</button></div>'),od=_('<a class="li" target="_blank" rel="noopener" style="text-decoration:none;color:inherit"><div class="li-main"><div style="font-size:13px;line-height:1.4"> </div> <div class="li-sub"> </div></div></a>'),dd=_('<div class="empty">News gerade nicht ladbar.</div>'),cd=_('<div class="pagehead" style="margin-bottom:10px"><div><h1 style="display:flex;align-items:center;gap:10px"> <!></h1> <div class="sub"> </div></div></div> <div class="tiles"><div><div class="k-h"><span class="k-t">LLM-Engine</span> <span class="k-ic"></span></div> <div class="k-v"> </div> <div class="k-s"> </div></div> <div><div class="k-h"><span class="k-t">Aktives Modell</span> <span class="k-ic"></span></div> <div class="k-v" style="font-size:16px;word-break:break-word"> </div> <div class="k-s"><!></div></div> <!></div> <div class="split"><div class="card"><div class="card-h"><h3>System-Gesundheit</h3></div> <div class="card-sub">Auslastung in Echtzeit.</div> <!></div> <div class="card"><div class="card-h"><h3>Schnellstart</h3></div> <!></div></div> <div class="grid grid-2"><div class="card"><div class="card-h"><h3>Dein Stack</h3> <span class="meta"> </span></div> <!></div> <div class="card"><div class="card-h"><h3>Top-News</h3> <span class="meta" style="cursor:pointer" role="button" tabindex="0">Alle →</span></div> <!></div></div>',1);function ud(e,n){Gn(n,!0);const a=O(()=>_i.value),i=O(()=>Pr.value),l=O(()=>{var E;return((E=t(a))==null?void 0:E.models)||[]}),o=O(()=>{var E;return((E=t(a))==null?void 0:E.swap_ok)??!1}),d=["running","ready","loading","starting"],c=O(()=>t(l).find(E=>d.includes(E.state))),u=O(()=>t(l).filter(E=>!E.incomplete)),v=O(()=>t(a)?t(o)?t(i)&&t(i).ram.percent>=90?"Achtung: Speicher wird knapp.":"Alles läuft rund.":"LLM-Engine offline":"Verbinde…"),b=O(()=>t(a)?t(o)?t(i)&&t(i).ram.percent>=90?`Arbeitsspeicher bei ${Math.round(t(i).ram.percent)} % — eventuell Speicher freigeben.`:`${t(u).length} ${t(u).length===1?"Modell":"Modelle"} konfiguriert · ${t(c)?`„${t(c).name}" geladen`:"keines geladen"} · keine Warnungen.`:"Der llama-swap-Dienst antwortet gerade nicht.":""),A=O(()=>()=>{var H;const E=(H=t(i))==null?void 0:H.gpu;return E&&E.vram.total+E.gtt.total>0?(E.vram.used+E.gtt.used)/(E.vram.total+E.gtt.total)*100:0});let m=B(jt([])),x=B(null);bi(async()=>{try{f(m,((await Se("/api/news")).items||[]).slice(0,4),!0)}catch{}});async function C(){await mn({title:"Speicher freigeben?",body:"Alle aktuell geladenen Modelle werden aus dem Grafikspeicher geworfen. Sie laden beim nächsten Aufruf automatisch neu.",confirmLabel:"Speicher freigeben"})&&(await Se("/api/unload",{method:"POST"}),M())}async function z(E){f(x,E,!0);try{await Se("/api/preload?model="+encodeURIComponent(E),{method:"POST"})}catch(H){ee("Laden fehlgeschlagen: "+(H.message||"Engine nicht erreichbar?"),!0)}f(x,null),M()}function M(){document.dispatchEvent(new Event("mc:refresh"))}function I(E){var H;(H=document.querySelector(`.nav-item[data-view="${E}"]`))==null||H.dispatchEvent(new MouseEvent("click"))}function Ie(E){return E>=90?"red":E>=75?"":"green"}function fe(E){return E==null?"":E>=75?"red":E>=55?"":"green"}function me(E){return E>=90?"red":E>=70?"":"green"}var ke=cd(),K=Ze(ke),Y=s(K),he=s(Y),xe=s(he),Te=r(xe);{var Ve=E=>{var H=Ho();h(E,H)};q(Te,E=>{t(o)&&!t(c)&&E(Ve)})}var yt=r(he,2),T=s(yt),X=r(K,2),ve=s(X),Ye=s(ve),ae=r(s(Ye),2);qe(ae,()=>Ft("server"),!0);var Be=r(Ye,2),re=s(Be),F=r(Be,2),Z=s(F),oe=r(ve,2),se=s(oe),Oe=r(s(se),2);qe(Oe,()=>Ft("cpu"),!0);var He=r(se,2),mt=s(He),ut=r(He,2),vt=s(ut);{var Je=E=>{var H=ri();$(Ne=>g(H,`${Ne??""} · ${t(c).state??""}`),[()=>{var Ne;return(Ne=t(c).meta)!=null&&Ne.ctx?Math.round(t(c).meta.ctx/1024)+"k ctx":""}]),h(E,H)},ze=E=>{var H=ri("lädt bei erster Anfrage");h(E,H)};q(vt,E=>{t(c)?E(Je):E(ze,-1)})}var Et=r(oe,2);{var Tt=E=>{const H=O(()=>{var jn;return t(i).gpu_temp??((jn=t(i).cpu)==null?void 0:jn.temp)??null}),Ne=O(()=>fe(t(H))),ce=O(()=>t(i).ram.total-t(i).ram.used),G=O(()=>100-t(i).ram.percent);var j=Jo(),W=Ze(j),R=s(W),J=r(s(R));qe(J,()=>Ft("thermo"),!0);var Q=r(R,2),le=s(Q),Ae=r(Q,2),be=s(Ae),pt=r(W,2),xt=s(pt),_e=r(s(xt));qe(_e,()=>Ft("database"),!0);var bt=r(xt,2),Bn=s(bt),Un=r(bt,2),la=s(Un);$((jn,Ha,y,w)=>{Ct(W,1,`kpi ${t(Ne)??""}`),g(le,jn),g(be,t(H)==null?"messe…":t(H)<55?"kühl":t(H)<75?"normal":"⚠ heiß"),Ct(pt,1,`kpi ${t(G)<15?"red":t(G)<30?"":"green"}`),g(Bn,Ha),g(la,`von ${y??""} GB · ${w??""} % frei`)},[()=>t(H)!=null?`${Math.round(t(H))}°C`:"–",()=>Math.round(t(ce)/1073741824),()=>Math.round(t(i).ram.total/1073741824),()=>Math.round(t(G))]),h(E,j)},$t=E=>{var H=Qo();h(E,H)};q(Et,E=>{t(i)?E(Tt):E($t,-1)})}var D=r(X,2),N=s(D),Me=r(s(N),4);{var Qe=E=>{const H=O(()=>t(A)());var Ne=di(),ce=Ze(Ne);nt(ce,17,()=>{var G;return[["Prozessor (CPU)",((G=t(i).cpu)==null?void 0:G.percent)??0,""],["Arbeitsspeicher (RAM)",t(i).ram.percent,Ie(t(i).ram.percent)],["Grafikspeicher (VRAM)",t(H),me(t(H))]]},rt,(G,j)=>{var W=O(()=>ea(t(j),3));let R=()=>t(W)[0],J=()=>t(W)[1];const Q=O(()=>Math.max(0,Math.min(100,J()||0)));var le=Zo(),Ae=s(le),be=s(Ae),pt=s(be),xt=r(be),_e=s(xt),bt=r(Ae,2),Bn=s(bt);$((Un,la)=>{g(pt,R()),g(_e,`${Un??""} %`),Ct(bt,1,`bar ${t(Q)>=90?"bad":t(Q)>=75?"warn":""}`),Xt(Bn,`width:${la??""}%`)},[()=>Math.round(t(Q)),()=>Math.max(2,t(Q))]),h(G,le)}),h(E,Ne)},k=E=>{var H=Yo();h(E,H)};q(Me,E=>{t(i)?E(Qe):E(k,-1)})}var L=r(N,2),te=r(s(L),2);{var Pe=E=>{var H=Xo(),Ne=r(Ze(H),2),ce=s(Ne);qe(ce,()=>Ft("search"),!0);var G=r(ce,4);qe(G,()=>Ft("chevron"),!0);var j=r(Ne,2),W=s(j);qe(W,()=>Ft("swap"),!0);var R=r(W,4);qe(R,()=>Ft("chevron"),!0);var J=r(j,2),Q=s(J);qe(Q,()=>Ft("file"),!0);var le=r(Q,4);qe(le,()=>Ft("chevron"),!0),S("click",Ne,()=>I("cookbook")),S("click",j,()=>I("connect")),S("click",J,()=>I("guides")),h(E,H)},de=E=>{var H=ed(),Ne=r(Ze(H),2),ce=s(Ne);qe(ce,()=>Ft("search"),!0);var G=r(ce,4);qe(G,()=>Ft("chevron"),!0);var j=r(Ne,2),W=s(j);qe(W,()=>Ft("refresh"),!0);var R=r(W,4);qe(R,()=>Ft("chevron"),!0);var J=r(j,2),Q=s(J);qe(Q,()=>Ft("file"),!0);var le=r(Q,4);qe(le,()=>Ft("chevron"),!0);var Ae=r(J,2),be=s(Ae);qe(be,()=>Ft("swap"),!0);var pt=r(be,4);qe(pt,()=>Ft("chevron"),!0),S("click",Ne,()=>I("cookbook")),S("click",j,C),S("click",J,()=>I("server")),S("click",Ae,()=>I("connect")),h(E,H)};q(te,E=>{t(u).length?E(de,-1):E(Pe)})}var Fe=r(D,2),Ee=s(Fe),$e=s(Ee),Xe=r(s($e),2),Ke=s(Xe),lt=r($e,2);{var P=E=>{var H=Zr();nt(H,21,()=>t(u),rt,(Ne,ce)=>{const G=O(()=>d.includes(t(ce).state)),j=O(()=>t(ce).state==="downloading"),W=O(()=>t(ce).state==="loading"||t(ce).state==="starting"||t(j)?"load":t(G)?"on":""),R=O(()=>t(j)?`↓ ${t(ce).download_progress!=null?Math.round(t(ce).download_progress)+"%":"..."}`:t(ce).state==="loading"||t(ce).state==="starting"?"lädt…":t(G)?"geladen ✓":"bereit");var J=sd(),Q=s(J),le=r(Q,2),Ae=s(le),be=s(Ae),pt=s(be),xt=r(be,2);{var _e=ue=>{var De=td();h(ue,De)},bt=O(()=>{var ue,De;return(De=(ue=t(ce).meta)==null?void 0:ue.caps)==null?void 0:De.includes("Bild")}),Bn=ue=>{var De=nd();h(ue,De)},Un=O(()=>{var ue,De;return(De=(ue=t(ce).meta)==null?void 0:ue.caps)==null?void 0:De.includes("Code")}),la=ue=>{var De=ad();h(ue,De)};q(xt,ue=>{t(bt)?ue(_e):t(Un)?ue(Bn,1):ue(la,-1)})}var jn=r(xt,2);{var Ha=ue=>{var De=id();h(ue,De)};q(jn,ue=>{t(ce).ttl>=99999&&ue(Ha)})}var y=r(Ae,2),w=s(y),U=r(le,2),V=s(U),pe=s(V),ft=r(V,2);{var _t=ue=>{var De=rd(),Ge=s(De);$(()=>{Xt(De,`padding:3px 9px;font-size:12px;opacity:${t(x)===t(ce).name?".5":"1"}`),De.disabled=t(x)===t(ce).name,g(Ge,t(x)===t(ce).name?"…":"Laden")}),S("click",De,()=>z(t(ce).name)),h(ue,De)};q(ft,ue=>{!t(G)&&!t(j)&&t(o)&&ue(_t)})}$((ue,De)=>{var Ge;Ct(Q,1,`li-dot ${t(W)??""}`),Xt(be,t(G)?"color:var(--accent)":""),g(pt,t(ce).name),g(w,`${ue??""}
|
||
${(Ge=t(ce).meta)!=null&&Ge.quant?" · "+t(ce).meta.quant:""}
|
||
${De??""}`),Xt(V,`white-space:nowrap;color:${t(G)?"var(--on)":"var(--mut)"}`),g(pe,t(R))},[()=>{var ue;return(ue=t(ce).meta)!=null&&ue.ctx?Math.round(t(ce).meta.ctx/1024)+"k ctx":""},()=>{var ue;return(ue=t(ce).meta)!=null&&ue.size_bytes?" · "+(t(ce).meta.size_bytes/1073741824).toFixed(1)+" GB":""}]),h(Ne,J)}),h(E,H)},ie=E=>{var H=ld(),Ne=r(s(H),4);S("click",Ne,()=>I("cookbook")),h(E,H)};q(lt,E=>{t(u).length?E(P):E(ie,-1)})}var we=r(Ee,2),ot=s(we),et=r(s(ot),2),Qt=r(ot,2);{var Zt=E=>{var H=Zr();nt(H,21,()=>t(m),rt,(Ne,ce)=>{var G=od(),j=s(G),W=s(j),R=s(W),J=r(W,2),Q=s(J);$(()=>{qi(G,"href",t(ce).link),g(R,t(ce).title),g(Q,`${t(ce).source??""}${t(ce).relevant?" · für dich":""}`)}),h(Ne,G)}),h(E,H)},qt=E=>{var H=dd();h(E,H)};q(Qt,E=>{t(m).length?E(Zt):E(qt,-1)})}$(E=>{g(xe,`${t(v)??""} `),g(T,t(b)),Ct(ve,1,`kpi ${t(o)?"green":"red"}`),g(re,t(o)?"Online":"Offline"),g(Z,E),Ct(oe,1,`kpi ${t(c)?"blue":"muted"}`),g(mt,t(c)?t(c).name:"Keins"),g(Ke,t(u).length?t(u).length+" konfiguriert":"")},[()=>{var E,H;return((H=(E=t(a))==null?void 0:E.swap_url)==null?void 0:H.replace(/^https?:\/\//,""))??"—"}]),S("click",et,()=>I("news")),S("keydown",et,E=>E.key==="Enter"&&I("news")),h(e,ke),Vn()}sa(["click","keydown"]);var vd=_("<option> </option>"),pd=_('<div class="reply" style="margin-top:12px"> </div>'),fd=_('<div class="empty-c"><div class="e-t">Noch keine Modelle konfiguriert</div> <div class="e-s">Hol dir unter „Cookbook" ein passendes Modell.</div></div>'),hd=_('<tr style="opacity:.9"><td class="mid" style="font-weight:500"> <div class="li-sub mono-sm" style="color:var(--warn)">kein Modell hinterlegt</div></td><td>—</td><td><span class="mono-sm text-mut">leere Rolle</span></td><td><span class="badge">leer</span></td><td class="port">—</td><td style="text-align:right;white-space:nowrap"><button class="ghost">Modell zuweisen</button> <button class="ghost del">Löschen</button></td></tr>'),gd=_('<span class="tag" style="background:rgba(45,212,191,.14);color:var(--accent);border-color:rgba(45,212,191,.3)"> </span>'),md=_('<div class="li-sub mono-sm"> </div>'),bd=_('<code style="cursor:pointer" title="Klicken zum Kopieren"> </code>'),_d=_('<tr><td class="mid"><div style="font-weight:500;display:flex;align-items:center;gap:7px;flex-wrap:wrap"> <!></div> <!> <div class="li-sub mono-sm" style="margin-top:3px;display:flex;align-items:center;gap:6px;flex-wrap:wrap"><span class="text-mut">API-Name:</span> <!></div></td><td></td><td></td><td></td><td class="port"> </td><td style="text-align:right;white-space:nowrap"><button class="ghost">Rolle</button> <button class="ghost">Konfigurieren</button> <button class="ghost">Entladen</button> <button class="ghost del">Löschen</button></td></tr>'),kd=_('<table><thead><tr><th>Modell</th><th>Kann</th><th>Details</th><th>Status</th><th>Port</th><th style="text-align:right">Aktionen</th></tr></thead><tbody></tbody></table>'),wd=_('<div class="tile" style="display:flex;justify-content:space-between;align-items:center;margin:8px 0 10px"><div style="flex:1"><div style="font-size:13px">Empfohlen für deine Hardware</div> <div class="hint" style="margin:4px 0 0"> <br/> </div></div> <button class="ghost">Optimal übernehmen</button></div>'),yd=_('<div class="modal-overlay" role="dialog"><div class="modal-card"><button class="ghost" style="position:absolute;top:14px;right:14px">Schließen</button> <h3>Modell konfigurieren</h3> <p class="mono-sm" style="margin:-4px 0 16px"> </p> <label>Kontext-Größe (Tokens) <!></label> <input type="number"/> <!> <div class="hint" style="margin-bottom:14px">Es läuft immer nur <b>ein</b> Modell gleichzeitig — ein größerer Kontext hier beeinflusst deine anderen Modelle nicht.</div> <div class="tile" style="display:flex;justify-content:space-between;align-items:center;margin:0 0 14px"><div style="flex:1"><div style="font-size:13px;font-weight:500">Immer aktiv halten</div> <div class="hint" style="margin:3px 0 0">Modell bleibt dauerhaft im RAM — nie automatisch entladen. Ideal für den kleinen Scout (~5 GB), der immer schnell antworten soll.</div></div> <label style="display:flex;align-items:center;gap:8px;margin:0;cursor:pointer;flex:0 0 auto"><input type="checkbox" style="width:18px;height:18px;accent-color:var(--accent);cursor:pointer"/> <span class="mono-sm"> </span></label></div> <button class="primary" style="width:100%;margin-top:6px">Speichern</button></div></div>'),xd=_('<button style="border-radius:999px"> </button>'),Sd=_('<div class="modal-overlay" role="dialog"><div class="modal-card"><button class="ghost" style="position:absolute;top:14px;right:14px">Schließen</button> <h3>Rolle festlegen <!></h3> <p class="mono-sm" style="margin:-4px 0 16px"> </p> <div class="hint" style="margin-bottom:10px">Wähle eine Rolle als zweiten, sprechenden Namen. In deinen Tools funktionieren danach <b>beide</b>: der echte Modellname und die Rolle.</div> <div class="flex gap-2" style="flex-wrap:wrap;margin-bottom:12px"></div> <label>Eigene Rolle (optional)</label> <input placeholder="z.B. uebersetzer"/> <div class="btn-row" style="margin-top:14px;display:flex;gap:8px"><button class="ghost" style="flex:1">Rolle entfernen</button> <button class="primary" style="flex:2">Speichern</button></div></div></div>'),Md=_('<div id="m-head"><div class="pagehead"><div><h1>Modelle</h1> <div class="sub">Deine konfigurierten Modelle — testen, Kontext anpassen oder aus dem Speicher werfen.</div></div></div></div> <div class="card"><div class="card-h"><h3>Schnelltest</h3></div> <div class="card-sub">Schreib eine Nachricht — das gewählte Modell wird automatisch geweckt.</div> <label>Modell</label> <select></select> <label>Nachricht</label> <textarea placeholder="z.B. „Erklär mir kurz, was du kannst.""></textarea> <button class="primary"> </button> <!></div> <div class="card"><div class="card-h"><h3>Modelle & Ports</h3><span class="meta"> </span></div> <div class="card-sub">Modelle laden automatisch, sobald eine Anfrage kommt — du musst nichts manuell starten.</div> <!></div> <!> <!>',1);function Ed(e,n){Gn(n,!0);const a="Kontext = das Kurzzeitgedächtnis des Modells. Größer = merkt sich mehr (längere Dateien/Chats), braucht aber mehr Speicher und wird etwas langsamer.",i="Die Rolle ist ein zusätzlicher, sprechender Name (z.B. coder). Du kannst in deinen Tools entweder den echten Modellnamen ODER die Rolle angeben — beides führt zum selben Modell.",l=[{id:"coder",label:"Coder",desc:"Programmieren & Code"},{id:"vision",label:"Vision",desc:"Bilder verstehen"},{id:"scout",label:"Scout",desc:"Schneller Allrounder"},{id:"reviewer",label:"Reviewer",desc:"Code/Texte prüfen"},{id:"manager",label:"Manager",desc:"Planen & koordinieren"}],o=O(()=>{var D;return((D=_i.value)==null?void 0:D.models)||[]});function d(){document.dispatchEvent(new Event("mc:refresh"))}let c=B(""),u=B(""),v=B(""),b=B(!1);const A=O(()=>t(o).filter(D=>!D.incomplete));async function m(){var N;const D=t(c)||((N=t(A)[0])==null?void 0:N.name);if(!(!D||!t(u).trim())){f(b,!0),f(v,"(wecke Modell, kann beim Laden kurz dauern…)");try{const Me=await Se("/api/chat",{method:"POST",body:JSON.stringify({model:D,message:t(u)})});f(v,Me.reply,!0)}catch(Me){f(v,"Fehler: "+Me.message)}f(b,!1),d()}}const x=300;let C=B(!1),z=B(null),M=B(8192),I=B(!1);function Ie(D){var N;f(z,t(o).find(Me=>Me.name===D),!0),t(z)&&(f(M,((N=t(z).meta)==null?void 0:N.ctx)||8192,!0),f(I,(t(z).ttl??x)>=99999),f(C,!0))}async function fe(){const D=t(I)?99999:x;try{await Se("/api/update_model",{method:"POST",body:JSON.stringify({alias:t(z).name,ctx:t(M),ttl:D})}),ee("Gespeichert — aktiv beim nächsten Modell-Start."),f(C,!1),d()}catch(N){ee(N.message,!0)}}let me=B(!1),ke=B(""),K=B(""),Y=B("");function he(D){const N=t(o).find(Me=>Me.name===D);f(ke,D,!0),f(Y,(N==null?void 0:N.role)||"",!0),f(K,""),f(me,!0)}async function xe(D){try{await Se("/api/set_role",{method:"POST",body:JSON.stringify({alias:t(ke),role:D})}),ee(D?`Rolle gesetzt: ${D}`:"Rolle entfernt."),f(me,!1),d()}catch(N){ee(N.message,!0)}}async function Te(D){if(await mn({title:`„${D}" entladen?`,body:"Das Modell wird aus dem Grafikspeicher geworfen und lädt beim nächsten Aufruf automatisch neu.",confirmLabel:"Entladen"}))try{await Se("/api/unload?model="+encodeURIComponent(D),{method:"POST"}),ee("Entladen: "+D),setTimeout(d,600)}catch(N){ee(N.message,!0)}}async function Ve(D){if(await mn({title:`„${D}" wirklich löschen?`,body:"Das Modell wird aus der Konfiguration ausgetragen und seine Dateien werden von der Festplatte gelöscht, um Speicher freizugeben. <b>Das lässt sich nicht rückgängig machen</b> — später brauchst du dafür einen neuen Download.",confirmLabel:"Endgültig löschen",danger:!0}))try{const N=await Se("/api/delete_model",{method:"POST",body:JSON.stringify({alias:D})});ee(N.note||"Gelöscht: "+D),setTimeout(d,600)}catch(N){ee(N.message,!0)}}function yt(D){return D!=null&&D.length?D.map(N=>N==="Code"?'<span class="tag code">Code</span>':N==="Bild"?'<span class="tag img">Bild</span>':'<span class="tag text">Text</span>').join(" "):"–"}function T(D){if(!D)return"–";const N=D.quant||"?",Me=D.ctx?Math.round(D.ctx/1024)+"K":"?",Qe=D.size_bytes?(D.size_bytes/1024**3).toFixed(1)+" GB":"?";return`<span class="mono-sm">${N} · ${Me} · ${Qe}</span>`}function X(D){var N;(N=navigator.clipboard)==null||N.writeText(D),ee("Kopiert: "+D)}var ve=Md(),Ye=r(Ze(ve),2),ae=r(s(Ye),6);nt(ae,21,()=>t(A),rt,(D,N)=>{var Me=vd(),Qe=s(Me),k={};$(()=>{g(Qe,t(N).name),k!==(k=t(N).name)&&(Me.value=(Me.__value=t(N).name)??"")}),h(D,Me)});var Be=r(ae,4),re=r(Be,2),F=s(re),Z=r(re,2);{var oe=D=>{var N=pd(),Me=s(N);$(()=>g(Me,t(v))),h(D,N)};q(Z,D=>{t(v)&&D(oe)})}var se=r(Ye,2),Oe=s(se),He=r(s(Oe)),mt=s(He),ut=r(Oe,4);{var vt=D=>{var N=fd();h(D,N)},Je=D=>{var N=kd(),Me=r(s(N));nt(Me,21,()=>t(o),rt,(Qe,k)=>{var L=di(),te=Ze(L);{var Pe=Fe=>{var Ee=hd(),$e=s(Ee),Xe=s($e),Ke=r($e,5),lt=s(Ke),P=r(lt,2);$(()=>g(Xe,t(k).name)),S("click",lt,()=>{var ie;ee("Lade im Cookbook ein Modell und setze den Alias auf: "+t(k).name),(ie=document.querySelector(".nav-item[data-view='cookbook']"))==null||ie.dispatchEvent(new MouseEvent("click"))}),S("click",P,()=>Ve(t(k).name)),h(Fe,Ee)},de=Fe=>{var Ee=_d(),$e=s(Ee),Xe=s($e),Ke=s(Xe),lt=r(Ke);{var P=R=>{var J=gd(),Q=s(J);$(()=>g(Q,t(k).role)),h(R,J)};q(lt,R=>{t(k).role&&R(P)})}var ie=r(Xe,2);{var we=R=>{var J=md(),Q=s(J);$(()=>g(Q,t(k).meta.filename)),h(R,J)};q(ie,R=>{var J;(J=t(k).meta)!=null&&J.filename&&R(we)})}var ot=r(ie,2),et=r(s(ot),2);nt(et,17,()=>{var R;return(R=t(k).api_ids)!=null&&R.length?t(k).api_ids:[t(k).name]},rt,(R,J)=>{var Q=bd(),le=s(Q);$(()=>g(le,t(J))),S("click",Q,()=>X(t(J))),h(R,Q)});var Qt=r($e);qe(Qt,()=>{var R;return yt((R=t(k).meta)==null?void 0:R.caps)},!0);var Zt=r(Qt);qe(Zt,()=>T(t(k).meta),!0);var qt=r(Zt);qe(qt,()=>Wo(t(k).state,t(k).download_progress),!0);var E=r(qt),H=s(E),Ne=r(E),ce=s(Ne),G=r(ce,2),j=r(G,2),W=r(j,2);$(()=>{g(Ke,`${t(k).name??""} `),g(H,t(k).port??"auto")}),S("click",ce,()=>he(t(k).name)),S("click",G,()=>Ie(t(k).name)),S("click",j,()=>Te(t(k).name)),S("click",W,()=>Ve(t(k).name)),h(Fe,Ee)};q(te,Fe=>{t(k).incomplete?Fe(Pe):Fe(de,-1)})}h(Qe,L)}),h(D,N)};q(ut,D=>{t(o).length?D(Je,-1):D(vt)})}var ze=r(se,2);{var Et=D=>{var N=yd(),Me=s(N),Qe=s(Me),k=r(Qe,4),L=s(k),te=r(k,2),Pe=r(s(te));qe(Pe,()=>mr(a));var de=r(te,2),Fe=r(de,2);{var Ee=we=>{var ot=wd(),et=s(ot),Qt=r(s(et),2),Zt=s(Qt),qt=r(Zt,2),E=r(et,2);$((H,Ne)=>{g(Zt,`Optimal ~${H??""}k → ~${t(z).meta.peak_ram_optimal_gb??""} GB Spitzenbedarf.`),g(qt,` Aktuell ~${Ne??""}k → ~${t(z).meta.peak_ram_gb??""} GB.`)},[()=>Math.round(t(z).meta.optimal_ctx/1024),()=>Math.round((t(z).meta.ctx||0)/1024)]),S("click",E,()=>f(M,t(z).meta.optimal_ctx,!0)),h(we,ot)};q(Fe,we=>{var ot;(ot=t(z).meta)!=null&&ot.optimal_ctx&&we(Ee)})}var $e=r(Fe,4),Xe=r(s($e),2),Ke=s(Xe),lt=r(Ke,2),P=s(lt),ie=r($e,2);$(()=>{g(L,t(z).name),Xt(lt,`color:${t(I)?"var(--accent)":"var(--mut)"}`),g(P,t(I)?"An (TTL = ∞)":"Aus (TTL = 5 min)")}),S("click",N,we=>{we.target.classList.contains("modal-overlay")&&f(C,!1)}),S("click",Qe,()=>f(C,!1)),gn(de,()=>t(M),we=>f(M,we)),Ro(Ke,()=>t(I),we=>f(I,we)),S("click",ie,fe),h(D,N)};q(ze,D=>{t(C)&&t(z)&&D(Et)})}var Tt=r(ze,2);{var $t=D=>{var N=Sd(),Me=s(N),Qe=s(Me),k=r(Qe,2),L=r(s(k));qe(L,()=>mr(i));var te=r(k,2),Pe=s(te),de=r(te,4);nt(de,21,()=>l,rt,(Ke,lt)=>{var P=xd(),ie=s(P);$(()=>{Ct(P,1,t(Y)===t(lt).id?"primary":"ghost"),qi(P,"title",t(lt).desc),g(ie,t(lt).label)}),S("click",P,()=>xe(t(lt).id)),h(Ke,P)});var Fe=r(de,4),Ee=r(Fe,2),$e=s(Ee),Xe=r($e,2);$(()=>g(Pe,t(ke))),S("click",N,Ke=>{Ke.target.classList.contains("modal-overlay")&&f(me,!1)}),S("click",Qe,()=>f(me,!1)),gn(Fe,()=>t(K),Ke=>f(K,Ke)),S("click",$e,()=>xe("")),S("click",Xe,()=>xe(t(K).trim().toLowerCase())),h(D,N)};q(Tt,D=>{t(me)&&D($t)})}$(()=>{re.disabled=t(b),g(F,t(b)?"…":"Senden"),g(mt,t(o).length?t(o).length+" konfiguriert":"")}),ya(ae,()=>t(c),D=>f(c,D)),gn(Be,()=>t(u),D=>f(u,D)),S("click",re,m),h(e,ve),Vn()}sa(["click"]);var Ad=_('<div class="tiles"><div class="tile"><div class="t-l">Prozessor (CPU)</div> <div class="t-v"> <small>%</small></div> <div class="t-s"> </div></div> <div class="tile"><div class="t-l">Arbeitsspeicher</div> <div class="t-v"> <small>%</small></div> <div class="t-s"> </div></div> <div class="tile"><div class="t-l">Grafikspeicher</div> <div class="t-v"> <small>%</small></div> <div class="t-s"> </div></div></div> <div class="card"><div class="card-h"><h3>System-Metriken (Bosgame)</h3></div> <div class="card-sub">Live-Auslastung deines Mini-PCs, alle 0,5 Sekunden.</div> <div class="kv" style="margin-bottom:6px"><div class="kv-row"><span class="kv-k">Arbeitsspeicher (RAM)</span><span class="kv-v"> </span></div> <div class="kv-row"><span class="kv-k">Grafikspeicher (VRAM + GTT)</span> <span class="kv-v"> </span></div> <div class="kv-row"><span class="kv-k">Speicherplatz (Disk)</span><span class="kv-v"> </span></div> <div class="kv-row"><span class="kv-k">Temperatur (GPU / CPU)</span> <span class="kv-v"> </span></div></div> <div class="grid grid-3" style="margin-top:14px"><div><div class="meta text-xs">CPU-Verlauf</div><div style="display:flex;align-items:flex-end;gap:2px;height:38px;margin-top:10px"></div></div> <div><div class="meta text-xs">RAM-Verlauf</div><div style="display:flex;align-items:flex-end;gap:2px;height:38px;margin-top:10px"></div></div> <div><div class="meta text-xs">VRAM-Verlauf</div><div style="display:flex;align-items:flex-end;gap:2px;height:38px;margin-top:10px"></div></div></div></div>',1),Cd=_('<button class="ghost" style="margin-left:auto;padding:4px 11px;font-size:12px">Verlauf leeren</button>'),Td=_('<div class="empty-c"><div class="e-t">Gerade nichts los.</div> <div class="e-s">Alles ruhig — keine laufenden Aufgaben.</div></div>'),zd=_('<span class="mono-sm" style="margin-left:auto"> </span>'),Pd=_('<button class="ghost">Abbrechen</button>'),Dd=_('<button class="ghost" title="Aus Verlauf entfernen" style="margin-left:auto;margin-right:2px;padding:2px 9px;font-size:14px;line-height:1">×</button>'),$d=_('<div class="bar" style="margin-top:8px"><i></i></div>'),Ld=_('<div class="log"> </div>'),Id=_('<div class="job"><div class="job-h" role="button" tabindex="0"><span></span> <span class="mid"> </span> <!> <!> <!></div> <!> <!></div>'),Bd=_('<div class="pagehead"><div><h1>Aktivität</h1> <div class="sub">Live-Auslastung und laufende Aufgaben (Downloads, Updates) mit Protokoll.</div></div></div> <!> <div class="card"><div class="card-h"><h3>Hintergrund-Aufgaben</h3> <span class="meta"> </span> <!></div> <div class="card-sub">Downloads & Updates erscheinen hier mit Live-Protokoll — zum Aufklappen klicken.</div> <!></div>',1);function Od(e,n){Gn(n,!0);const a=O(()=>va.value),i=O(()=>va.tracked),l=O(()=>Pr.value);let o=jt({cpu:[],ram:[],gpu:[]});Ki(()=>{var ve;if(!t(l))return;const T=t(l).gpu,X=T&&T.vram.total+T.gtt.total>0?(T.vram.used+T.gtt.used)/(T.vram.total+T.gtt.total)*100:0;o.cpu=[...o.cpu,((ve=t(l).cpu)==null?void 0:ve.percent)??0].slice(-60),o.ram=[...o.ram,t(l).ram.percent].slice(-60),o.gpu=[...o.gpu,X].slice(-60)});const d=O(()=>()=>{var X;const T=(X=t(l))==null?void 0:X.gpu;return T&&T.vram.total+T.gtt.total>0?(T.vram.used+T.gtt.used)/(T.vram.total+T.gtt.total)*100:0}),c=O(()=>t(a).filter(T=>T.state!=="running"&&T.state!=="queued").length),u=O(()=>t(a).filter(T=>T.state==="failed").length);function v(T){if(T.state!=="running")return null;if(typeof T.progress=="number")return Math.min(100,T.progress);const ve=((T.log||[]).at(-1)||"").match(/(\d+(?:\.\d+)?)\s*%/);return ve?Math.min(100,parseFloat(ve[1])):null}function b(T){return T==null||T<0?"":T>=90?`noch ~${Math.round(T/60)} min`:`noch ~${Math.max(1,Math.round(T))} s`}function A(T){return T==="done"?'<span class="badge b-run">fertig</span>':T==="failed"?'<span class="badge b-err">fehler</span>':T==="canceled"?'<span class="badge">abgebrochen</span>':'<span class="badge b-load">läuft…</span>'}function m(T){return T==="done"?"on":T==="failed"||T==="canceled"?"":"load"}async function x(T){try{await Se(`/api/jobs/${T}/cancel`,{method:"POST"}),ee("Abbruch angefordert…")}catch(X){ee(X.message,!0)}}async function C(T){try{await Se(`/api/jobs/${T}`,{method:"DELETE"})}catch(X){ee(X.message,!0)}}async function z(){try{const T=await Se("/api/jobs/clear",{method:"POST"});ee(`${T.removed} Einträge entfernt.`)}catch(T){ee(T.message,!0)}}function M(T,X){return T.map(ve=>`<div style="width:4px;background:var(${X});opacity:.55;height:${Math.max(2,ve)}%;border-radius:2px"></div>`).join("")}var I=Bd(),Ie=r(Ze(I),2);{var fe=T=>{const X=O(()=>t(d)());var ve=Ad(),Ye=Ze(ve),ae=s(Ye),Be=r(s(ae),2),re=s(Be),F=r(Be,2),Z=s(F),oe=r(ae,2),se=r(s(oe),2),Oe=s(se),He=r(se,2),mt=s(He),ut=r(oe,2),vt=r(s(ut),2),Je=s(vt),ze=r(vt,2),Et=s(ze),Tt=r(Ye,2),$t=r(s(Tt),4),D=s($t),N=r(s(D)),Me=s(N),Qe=r(D,2),k=r(s(Qe),2),L=s(k),te=r(Qe,2),Pe=r(s(te)),de=s(Pe),Fe=r(te,2),Ee=r(s(Fe),2),$e=s(Ee),Xe=r($t,2),Ke=s(Xe),lt=r(s(Ke));qe(lt,()=>M(o.cpu,"--accent"),!0);var P=r(Ke,2),ie=r(s(P));qe(ie,()=>M(o.ram,"--purple"),!0);var we=r(P,2),ot=r(s(we));qe(ot,()=>M(o.gpu,"--on"),!0),$((et,Qt,Zt,qt,E,H,Ne,ce,G,j,W,R,J)=>{g(re,et),g(Z,Qt),g(Oe,Zt),g(mt,`${qt??""} / ${E??""}`),g(Je,H),g(Et,Ne),g(Me,`${ce??""} / ${G??""}`),g(L,j),g(de,`${W??""} % belegt`),g($e,`${R??""} / ${J??""}`)},[()=>{var et;return Math.round(((et=t(l).cpu)==null?void 0:et.percent)??0)},()=>{var et;return((et=t(l).cpu)==null?void 0:et.temp)!=null?`${Math.round(t(l).cpu.temp)}° CPU-Temp`:"Auslastung"},()=>Math.round(t(l).ram.percent),()=>oa(t(l).ram.used),()=>oa(t(l).ram.total),()=>Math.round(t(X)),()=>t(l).gpu_temp!=null?`${Math.round(t(l).gpu_temp)}° GPU-Temp`:"VRAM + GTT",()=>oa(t(l).ram.used),()=>oa(t(l).ram.total),()=>t(l).gpu?`${oa(t(l).gpu.vram.used+t(l).gpu.gtt.used)} / ${oa(t(l).gpu.vram.total+t(l).gpu.gtt.total)}`:"–",()=>{var et;return Math.round(((et=t(l).disk)==null?void 0:et.percent)??0)},()=>t(l).gpu_temp!=null?Math.round(t(l).gpu_temp)+"°":"–",()=>{var et;return((et=t(l).cpu)==null?void 0:et.temp)!=null?Math.round(t(l).cpu.temp)+"°":"–"}]),h(T,ve)};q(Ie,T=>{t(l)&&T(fe)})}var me=r(Ie,2),ke=s(me),K=r(s(ke),2),Y=s(K),he=r(K,2);{var xe=T=>{var X=Cd();S("click",X,z),h(T,X)};q(he,T=>{t(c)&&T(xe)})}var Te=r(ke,4);{var Ve=T=>{var X=Td();h(T,X)},yt=T=>{var X=di(),ve=Ze(X);nt(ve,17,()=>t(a),rt,(Ye,ae)=>{const Be=O(()=>v(t(ae))),re=O(()=>t(ae).state==="running"?b(t(ae).eta_s):""),F=O(()=>t(ae).state==="running"&&t(ae).rate_bps?oa(t(ae).rate_bps)+"/s":""),Z=O(()=>[t(re),t(F)].filter(Boolean).join(" · ")),oe=O(()=>t(i).includes(t(ae).id));var se=Id(),Oe=s(se),He=s(Oe),mt=r(He,2),ut=s(mt),vt=r(mt,2);{var Je=k=>{var L=zd(),te=s(L);$(Pe=>g(te,`${Pe??""} %${t(Z)?` · ${t(Z)}`:""}`),[()=>Math.round(t(Be))]),h(k,L)};q(vt,k=>{t(Be)!=null&&k(Je)})}var ze=r(vt,2);{var Et=k=>{var L=Pd();$(()=>Xt(L,`${t(Be)==null?"margin-left:auto;":""}margin-right:2px;padding:2px 9px;font-size:12px`)),S("click",L,te=>{te.stopPropagation(),x(t(ae).id)}),h(k,L)},Tt=k=>{var L=Dd();S("click",L,te=>{te.stopPropagation(),C(t(ae).id)}),h(k,L)};q(ze,k=>{t(ae).state==="running"?k(Et):k(Tt,-1)})}var $t=r(ze,2);qe($t,()=>A(t(ae).state));var D=r(Oe,2);{var N=k=>{var L=$d(),te=s(L);$(()=>Xt(te,`width:${t(Be)??""}%`)),h(k,L)};q(D,k=>{t(Be)!=null&&t(ae).state==="running"&&k(N)})}var Me=r(D,2);{var Qe=k=>{var L=Ld(),te=s(L);$(Pe=>g(te,Pe),[()=>(t(ae).log||[]).join(`
|
||
`)]),h(k,L)};q(Me,k=>{t(oe)&&k(Qe)})}$(k=>{Ct(He,1,`li-dot ${k??""}`),g(ut,t(ae).label)},[()=>m(t(ae).state)]),S("click",Oe,()=>va.toggle(t(ae).id)),S("keydown",Oe,k=>k.key==="Enter"&&va.toggle(t(ae).id)),h(Ye,se)}),h(T,X)};q(Te,T=>{t(a).length?T(yt,-1):T(Ve)})}$(()=>g(Y,t(a).length?t(u)?t(u)+" Fehler":t(a).length+" gesamt":"")),h(e,I),Vn()}sa(["click","keydown"]);var Rd=_('<span class="mono-sm"> </span>'),Fd=_('<button class="ghost" style="margin-left:auto;padding:3px 12px">Abbrechen</button>'),Kd=_('<span class="badge b-run">✓ fertig</span>'),Nd=_('<span class="badge b-err">✗ fehlgeschlagen</span>'),qd=_('<span class="badge">abgebrochen</span>'),Gd=_('<span class="badge b-load">läuft…</span>'),Vd=_('<div class="bar" style="margin-bottom:10px"><i></i></div>'),Wd=_('<div class="card"><div class="card-h"><h3>Aktueller Vorgang</h3> <!> <span style="margin-left:10px"><!></span></div> <div class="card-sub"> </div> <!> <div class="log" style="max-height:280px"> </div></div>'),Ud=_('<div class="pagehead"><div><h1>Server & Wartung</h1> <div class="sub">Dienste steuern, Updates einspielen und live mitlesen — ganz ohne SSH oder Terminal.</div></div></div> <div class="card"><div class="card-h"><h3>LLM-Engine (llama-swap)</h3> <span class="chip"> </span></div> <div class="card-sub">Das Herzstück: lädt bei jeder Anfrage automatisch das passende Modell.</div> <div class="kv" style="margin-bottom:6px"><div class="kv-row"><span class="kv-k">Adresse (für deine Tools)</span><span class="kv-v mono-sm"> </span></div> <div class="kv-row"><span class="kv-k">Aktuell geladen</span> <span class="kv-v"> </span></div> <div class="kv-row"><span class="kv-k">Konfigurierte Modelle</span> <span class="kv-v"> </span></div></div> <div class="btn-row" style="display:flex;align-items:center;gap:10px"><button class="ghost">Verbindung prüfen</button> <!></div></div> <div class="card"><div class="card-h"><h3>Dienste & Applikation</h3></div> <div class="card-sub">Diese Aktionen sind harmlos und passwortlos — es geht nichts dabei verloren.</div> <button class="qa"><span class="qa-ic teal">↻</span> <span class="qa-main"><span class="qa-t">LLM-Engine neustarten</span><span class="qa-s">Startet llama-swap neu. Geladene Modelle laden danach automatisch wieder.</span></span> <span class="qa-arrow">›</span></button> <button class="qa"><span class="qa-ic blue">↻</span> <span class="qa-main"><span class="qa-t">Dashboard neustarten</span><span class="qa-s">Startet diese Oberfläche neu (~5 Sek).</span></span> <span class="qa-arrow">›</span></button> <button class="qa"><span class="qa-ic teal">⬇</span> <span class="qa-main"><span class="qa-t">Mission Control aktualisieren</span><span class="qa-s">Holt die neueste Version aus Gitea und startet automatisch neu (~10 Sek).</span></span> <span class="qa-arrow">›</span></button> <button class="qa"><span class="qa-ic blue">⚡</span> <span class="qa-main"><span class="qa-t">LLM-Engine aktualisieren</span><span class="qa-s">Lädt die neueste llama.cpp-Version (ROCm) für deine GPU.</span></span> <span class="qa-arrow">›</span></button> <button class="qa"><span class="qa-ic amber">🗄</span> <span class="qa-main"><span class="qa-t">Grafikspeicher leeren</span><span class="qa-s">Wirft alle aktuell geladenen Modelle aus dem VRAM. Fragt vorher nach.</span></span> <span class="qa-arrow">›</span></button></div> <div class="card"><div class="card-h"><h3>Betriebssystem (Bosgame)</h3></div> <div class="card-sub">Tiefe Eingriffe — das Dashboard fragt einmalig nach deinem sudo-Passwort.</div> <button class="qa"><span class="qa-ic amber">↻</span> <span class="qa-main"><span class="qa-t">OS-Updates installieren</span><span class="qa-s">Führt apt update & upgrade aus. Kann ein paar Minuten dauern.</span></span> <span class="qa-arrow">›</span></button> <button class="qa qa-danger"><span class="qa-ic red">⚡</span> <span class="qa-main"><span class="qa-t">Server neustarten (Reboot)</span><span class="qa-s">Bootet den ganzen Bosgame neu. Alles ist für ~1 Minute offline.</span></span> <span class="qa-arrow">›</span></button></div> <!> <div class="card"><div class="card-h"><h3>Live-Konsole</h3> <select style="margin:0 0 0 auto;width:240px"><option>LLM-Engine (llama-swap)</option><option>Dashboard (mission-control)</option><option>System (ganzer Server)</option></select></div> <div class="card-sub">Live mitlesen, was der Dienst gerade tut.</div> <div class="console"> </div></div>',1);function jd(e,n){Gn(n,!0);const a=O(()=>_i.value),i=O(()=>va.value);let l=null,o=B(`Verbinde…
|
||
`),d=B("llama-swap"),c,u=B(null),v=B("");const b=new Set,A=O(()=>t(u)?t(i).find(P=>P.id===t(u)):null);Ki(()=>{if(!t(A))return;const P=t(A),ie=P.state==="done",we=P.state==="failed",ot=P.state==="canceled";(ie||we||ot)&&!b.has(P.id)&&(b.add(P.id),ee(ie?`✓ ${t(v)} abgeschlossen.`:ot?`${t(v)} abgebrochen.`:`✗ ${t(v)} fehlgeschlagen.`,we),ie&&setTimeout(()=>document.dispatchEvent(new Event("mc:refresh")),800))});function m(P,ie){f(u,P,!0),f(v,ie,!0),va.track(P)}bi(()=>{x()}),Ko(()=>{l==null||l.close()});function x(){l==null||l.close();const P=t(d);f(o,`Verbinde mit ${P}…
|
||
`);const ie=location.protocol==="https:"?"wss:":"ws:";l=new WebSocket(`${ie}//${location.host}/api/logs/${P}?token=${encodeURIComponent(tl())}`),l.onmessage=we=>{f(o,t(o)+we.data),c&&(c.scrollTop=c.scrollHeight)},l.onclose=()=>{f(o,t(o)+`
|
||
— Verbindung getrennt —`)},l.onerror=()=>l==null?void 0:l.close()}async function C(P,ie,we){if(await mn({title:ie,body:we,confirmLabel:"Neustarten"}))try{await Se(`/api/service/${P}/restart`,{method:"POST"}),ee("Neustart ausgelöst: "+P),setTimeout(()=>document.dispatchEvent(new Event("mc:refresh")),2e3)}catch(ot){ee(ot.message,!0)}}async function z(){if(await mn({title:"Mission Control aktualisieren?",body:"Holt die neueste Dashboard-Version aus Gitea und startet automatisch neu. Die Seite trennt kurz und verbindet von selbst wieder (~10 Sek)."}))try{const P=await Se("/api/self-update",{method:"POST"});ee("Update läuft — Dashboard startet gleich neu."),m(P.job_id,"Mission Control Update")}catch(P){ee(P.message,!0)}}async function M(){if(await mn({title:"LLM-Engine aktualisieren?",body:"Lädt die neueste llama.cpp-ROCm-Version und installiert sie. Die Engine ist während des Updates kurz nicht erreichbar."}))try{const P=await Se("/api/update",{method:"POST"});ee("LLM-Engine-Update läuft."),m(P.job_id,"LLM-Engine-Update")}catch(P){ee(P.message,!0)}}async function I(){if(await mn({title:"Grafikspeicher leeren?",body:"Alle geladenen Modelle werden entladen. Sie laden beim nächsten Aufruf automatisch neu — es geht nichts verloren.",confirmLabel:"Leeren"}))try{await Se("/api/unload",{method:"POST"}),ee("Grafikspeicher geleert."),setTimeout(()=>document.dispatchEvent(new Event("mc:refresh")),600)}catch(P){ee(P.message,!0)}}async function Ie(){if(!await mn({title:"OS-Updates installieren?",body:"Führt <code>apt update & upgrade</code> aus. Das kann ein paar Minuten dauern; der Fortschritt erscheint in der Aktivität."}))return;const P=await jr({title:"sudo-Passwort",body:"Für die System-Updates wird einmalig dein sudo-Passwort gebraucht.",placeholder:"sudo-Passwort",password:!0,confirmLabel:"Installieren"});if(P)try{const ie=await Se("/api/os-update",{method:"POST",body:JSON.stringify({password:P})});ee("OS-Update gestartet."),m(ie.job_id,"OS-Update")}catch(ie){ee(ie.message,!0)}}async function fe(){if(!await mn({title:"Server wirklich neu starten?",body:"Der ganze Bosgame startet physisch neu. Alles ist für ~1 Minute offline — auch dieses Dashboard.",confirmLabel:"Reboot",danger:!0}))return;const P=await jr({title:"sudo-Passwort",body:"Für den Reboot wird einmalig dein sudo-Passwort gebraucht.",placeholder:"sudo-Passwort",password:!0,confirmLabel:"Jetzt neustarten",danger:!0});if(P)try{await Se("/api/reboot",{method:"POST",body:JSON.stringify({password:P})}),ee("Reboot ausgelöst — bis gleich.")}catch(ie){ee(ie.message,!0)}}async function me(){f(ke,"prüfe…");try{const P=await Se("/api/integration/test");f(ke,P.ok?`✓ Engine antwortet — ${P.models.length} Modell(e): ${P.models.join(", ")}`:`✗ keine Verbindung: ${P.error}`,!0),f(K,P.ok,!0)}catch(P){f(ke,"✗ "+P.message),f(K,!1)}}let ke=B(""),K=B(!1);const Y=O(()=>{var P;return((P=t(a))==null?void 0:P.models)||[]}),he=["running","ready","loading","starting"],xe=O(()=>t(Y).find(P=>he.includes(P.state)));function Te(P){if(!P||P.state!=="running")return null;if(typeof P.progress=="number")return Math.min(100,P.progress);const we=((P.log||[]).at(-1)||"").match(/(\d+(?:\.\d+)?)\s*%/);return we?Math.min(100,parseFloat(we[1])):null}var Ve=Ud(),yt=r(Ze(Ve),2),T=s(yt),X=r(s(T),2),ve=s(X),Ye=r(T,4),ae=s(Ye),Be=r(s(ae)),re=s(Be),F=r(ae,2),Z=r(s(F),2),oe=s(Z),se=r(F,2),Oe=r(s(se),2),He=s(Oe),mt=r(Ye,2),ut=s(mt),vt=r(ut,2);{var Je=P=>{var ie=Rd(),we=s(ie);$(()=>{Xt(ie,`color:${t(K)?"#7ee29a":"#ff9b95"}`),g(we,t(ke))}),h(P,ie)};q(vt,P=>{t(ke)&&P(Je)})}var ze=r(yt,2),Et=r(s(ze),4),Tt=r(Et,2),$t=r(Tt,2),D=r($t,2),N=r(D,2),Me=r(ze,2),Qe=r(s(Me),4),k=r(Qe,2),L=r(Me,2);{var te=P=>{const ie=O(()=>t(A)),we=O(()=>t(ie).state==="done"),ot=O(()=>t(ie).state==="failed"),et=O(()=>t(ie).state==="canceled"),Qt=O(()=>t(we)||t(ot)||t(et)),Zt=O(()=>Te(t(ie)));var qt=Wd(),E=s(qt),H=r(s(E),2);{var Ne=_e=>{var bt=Fd();S("click",bt,async()=>{await mn({title:t(v)+" abbrechen?",body:"Der laufende Vorgang wird gestoppt.",confirmLabel:"Abbrechen",danger:!0})&&Se(`/api/jobs/${t(ie).id}/cancel`,{method:"POST"})}),h(_e,bt)};q(H,_e=>{t(Qt)||_e(Ne)})}var ce=r(H,2),G=s(ce);{var j=_e=>{var bt=Kd();h(_e,bt)},W=_e=>{var bt=Nd();h(_e,bt)},R=_e=>{var bt=qd();h(_e,bt)},J=_e=>{var bt=Gd();h(_e,bt)};q(G,_e=>{t(we)?_e(j):t(ot)?_e(W,1):t(et)?_e(R,2):_e(J,-1)})}var Q=r(E,2),le=s(Q),Ae=r(Q,2);{var be=_e=>{var bt=Vd(),Bn=s(bt);$(()=>Xt(Bn,`width:${t(Zt)??""}%`)),h(_e,bt)};q(Ae,_e=>{t(Zt)!=null&&!t(Qt)&&_e(be)})}var pt=r(Ae,2),xt=s(pt);$(_e=>{g(le,`${t(v)??""}${t(Qt)?t(we)?" — erfolgreich.":t(et)?" — abgebrochen.":" — fehlgeschlagen.":" läuft…"}`),g(xt,_e)},[()=>(t(ie).log||[]).join(`
|
||
`)]),h(P,qt)};q(L,P=>{t(A)&&P(te)})}var Pe=r(L,2),de=s(Pe),Fe=r(s(de),2),Ee=s(Fe);Ee.value=Ee.__value="llama-swap";var $e=r(Ee);$e.value=$e.__value="mission-control";var Xe=r($e);Xe.value=Xe.__value="system";var Ke=r(de,4),lt=s(Ke);Fo(Ke,P=>c=P,()=>c),$(P=>{var ie,we,ot;Xt(X,`margin-left:auto;${(ie=t(a))!=null&&ie.swap_ok?"background:rgba(63,185,80,.12);border-color:rgba(63,185,80,.25);color:#7ee29a":"background:rgba(248,81,73,.12);border-color:rgba(248,81,73,.3);color:#ff9b95"}`),g(ve,(we=t(a))!=null&&we.swap_ok?"● erreichbar":"● offline"),g(re,(((ot=t(a))==null?void 0:ot.swap_url)||"—")+"/v1"),g(oe,t(xe)?t(xe).name+` (${t(xe).state})`:"nichts geladen — lädt bei der nächsten Anfrage"),g(He,P),g(lt,t(o))},[()=>t(Y).filter(P=>!P.incomplete).length||"keine"]),S("click",ut,me),S("click",Et,()=>C("llama-swap","LLM-Engine neustarten?","Die Engine startet neu. Geladene Modelle werden kurz entladen (~5 Sekunden), laden danach automatisch wieder.")),S("click",Tt,()=>C("mission-control","Dashboard neustarten?","Diese Oberfläche trennt sich kurz und verbindet automatisch wieder.")),S("click",$t,z),S("click",D,M),S("click",N,I),S("click",Qe,Ie),S("click",k,fe),S("change",Fe,x),ya(Fe,()=>t(d),P=>f(d,P)),h(e,Ve),Vn()}sa(["click","change"]);var Hd=_('<div class="empty" style="text-align:center;padding:30px">Lade Setups…</div>'),Jd=_('<span title="Setup bearbeiten" style="position:absolute;top:10px;right:36px;color:var(--accent);cursor:pointer;font-size:14px;line-height:1" role="button" tabindex="0">✎</span> <span title="Setup löschen" style="position:absolute;top:9px;right:12px;color:var(--err);cursor:pointer;font-size:18px;line-height:1" role="button" tabindex="0">×</span>',1),er=_('<div class="cb-best-tag">★ Beste Wahl für dein System</div>'),Qd=_('<div class="cb-best-tag" style="background:var(--act);color:#fff">Dein Setup</div>'),Zd=_('<button style="text-align:left;position:relative"><!> <!> <div class="flex justify-between items-center"><span class="flex items-center gap-2"><h3 style="margin:0;font-size:15px"> </h3></span> <span> </span></div> <p> </p> <div class="text-xs text-mut"> </div></button>'),Yd=_('<div id="cb-recipes" class="grid grid-3" style="gap:10px;margin-top:6px"></div>'),Xd=_('<span style="color:var(--warn)">· ⚠ Cache veraltet</span>'),ec=_("<!> <!>",1),tc=_('<div class="empty" style="text-align:center;padding:30px">Frage Quellen ab…</div>'),nc=_('<div class="li-sub" style="color:var(--warn);margin-top:3px"> </div>'),ac=_('<span class="fit-badge ok">✓ installiert</span>'),ic=_('<button class="primary" style="padding:6px 12px;font-size:12.5px">Installieren</button>'),rc=_('<div style="display:flex;flex-direction:column;position:relative"><!> <div class="flex justify-between" style="align-items:flex-start;gap:8px"><div style="min-width:0"><h3 style="margin:0;font-size:14px;font-weight:500;word-break:break-word"> </h3> <div class="text-xs text-mut" style="margin-top:3px"> </div></div> <span> </span></div> <div class="flex gap-2" style="flex-wrap:wrap;margin-top:7px"><!> <!></div> <div class="mono-sm text-mut" style="margin-top:8px;font-size:11.5px"> </div> <!> <div style="flex:1;min-height:8px"></div> <div class="flex justify-end" style="margin-top:10px"><!></div></div>'),sc=_('<div style="margin-bottom:8px"><div class="flex items-center gap-2" style="margin:6px 0 8px"><h4 style="margin:0;font-size:13.5px;font-weight:600"> </h4></div> <div class="grid grid-3"></div></div>'),lc=_('<button style="padding:4px 10px;border-radius:999px;font-size:12px"> </button>'),oc=_('<div style="display:flex;flex-direction:column;cursor:pointer"><!> <div class="flex justify-between" style="align-items:flex-start;gap:8px"><div style="min-width:0"><h3 style="margin:0;font-size:14.5px;font-weight:500;word-break:break-word"> </h3> <div class="text-xs text-mut" style="margin-top:3px"> </div></div> <span> </span></div> <div class="flex gap-2" style="flex-wrap:wrap;margin-top:7px"><!> <!></div> <div style="flex:1;margin-top:12px"></div> <div class="flex justify-between items-center text-xs text-mut" style="border-top:1px solid var(--line);padding-top:11px"><span class="mono-sm"> </span> <span class="mono-sm"> </span></div></div>'),dc=_('<div class="grid grid-3" id="cb-grid"></div>'),cc=_('<div class="li-sub"> </div>'),uc=_('<div class="li-sub mono-sm"> </div>'),vc=_("<span> </span>"),pc=_('<div class="li" style="align-items:flex-start"><div class="li-main"><div class="flex items-center gap-2" style="flex-wrap:wrap"><span class="li-id"> </span> <span class="tag text"> </span> <!></div> <!> <!></div> <!></div>'),fc=_('<div class="hint" style="margin:12px 0">Größter Spitzenbedarf: <b> </b>. Es läuft immer nur <b>ein</b> Modell gleichzeitig — das größte bestimmt, ob das Setup passt.</div>'),hc=_('Alternative: <a href="#" style="color:var(--accent)"> </a> — passt auf dein System.',1),gc=_('<div class="hint" style="color:var(--warn);margin-bottom:10px;border-left:2px solid var(--warn);padding-left:10px">⚠ Dieses Setup übersteigt deinen verfügbaren Speicher. <!></div>'),mc=_('<div class="modal-overlay" role="dialog"><div class="modal-card" style="max-width:560px"><button class="ghost" style="position:absolute;top:14px;right:14px">Schließen</button> <h3> </h3> <p class="text-mut text-sm" style="margin:-4px 0 16px"> </p> <div class="list"></div> <!> <!> <button id="cb-r-install-btn" style="width:100%"> </button></div></div>'),bc=_('<div class="hint">Lade Dateien von HuggingFace…</div>'),Yr=_("<option> </option>"),_c=_('<div class="hint" style="margin:-6px 0 14px">Empfohlener Kontext für deine Hardware: <b> </b> — <a href="#">übernehmen</a></div>'),kc=_('<div class="tile" style="display:flex;justify-content:space-between;align-items:center;margin:8px 0 18px"><div><div style="font-size:13px">Ressourcen-Check</div> <div class="hint" style="margin:4px 0 0"> </div></div> <span> </span></div>'),wc=_('<div class="hint" style="color:var(--warn);margin:-8px 0 14px;border-left:2px solid var(--warn);padding-left:10px">⚠ Diese Datei ist zu groß für deinen Speicher. Kleinere Alternative: <a href="#" style="color:var(--accent)"> </a> — einfach auswählen.</div>'),yc=_('<div class="hint" style="color:var(--warn);margin:-8px 0 14px;border-left:2px solid var(--warn);padding-left:10px">⚠ Alle Varianten dieses Modells sind zu groß für deinen Speicher. Ein kleineres Modell aus den Empfehlungen wäre die bessere Wahl.</div>'),xc=_('<label>Quantisierung (GGUF-Datei) wählen</label> <select></select> <div class="row" style="margin-top:4px"><div><label>Rolle (optional)</label> <input placeholder="z.B. coder, vision, scout"/></div> <div><label>Kontext-Größe <!></label> <input type="number"/></div></div> <!> <!> <!> <button style="width:100%"> </button>',1),Sc=_('<div class="hint">Keine GGUF-Dateien im Repo gefunden.</div>'),Mc=_('<div class="modal-overlay" role="dialog"><div class="modal-card" style="max-width:560px"><button class="ghost" style="position:absolute;top:14px;right:14px">Schließen</button> <h3> </h3> <p class="mono-sm" style="margin:-4px 0 16px"> </p> <!></div></div>'),Ec=_('<div class="flex gap-2" style="margin-bottom:8px;align-items:center"><input placeholder="Repo, z.B. unsloth/Qwen3-8B-GGUF" style="flex:2;margin:0"/> <input placeholder="Rolle (z.B. coder)" style="flex:1;margin:0"/> <select style="width:auto;margin:0"></select> <button class="ghost del" style="margin:0;padding:6px 10px">×</button></div>'),Ac=_('<div class="modal-overlay" role="dialog"><div class="modal-card" style="max-width:640px"><button class="ghost" style="position:absolute;top:14px;right:14px">Schließen</button> <h3> </h3> <p class="text-mut text-sm" style="margin:-4px 0 16px">Stell dir aus beliebigen Modellen ein eigenes Setup zusammen.</p> <label>Titel</label> <input placeholder="z.B. Mein Schreib-Stack"/> <label>Kurzbeschreibung (optional)</label> <input placeholder="Wofür ist dieses Setup gut?"/> <label style="margin-top:10px">Modelle</label> <!> <button class="ghost" style="margin-top:8px">+ Modell hinzufügen</button> <div class="hint" style="margin-top:10px">Die <b>Repo-ID</b> findest du über die <b>Profi-Suche</b> weiter unten (z.B. <code>unsloth/Qwen3-8B-GGUF</code>).</div> <button class="primary" style="width:100%;margin-top:14px"> </button></div></div>'),Cc=_('<div class="pagehead"><div><h1>Cookbook</h1><div class="sub">Modelle finden, installieren und eigene Setups zusammenstellen.</div></div></div> <div class="card"><div class="card-h"><h3>1 · Anwendungsfall wählen & installieren</h3> <button class="ghost" style="margin-left:auto">+ Eigenes Setup</button></div> <div class="card-sub">Hier starten: Fertige Modell-Bundles für deinen Anwendungsfall — ein Klick installiert alles. Die Hardware-Ampel zeigt vorab, ob das Setup auf deinen PC passt.</div> <!></div> <div class="card"><div class="card-h"><h3>Aktuell die besten Modelle für dein System</h3> <span class="meta" style="margin-left:auto"><!></span> <button class="ghost" style="margin-left:8px"> </button></div> <div class="card-sub">Top-Modelle je Kategorie von HuggingFace — Hardware-Fit wird live für dein System berechnet.</div> <!></div> <div class="card"><div class="card-h"><h3>Profi-Suche (HuggingFace)</h3></div> <div class="card-sub">Direkt HuggingFace durchsuchen — oder eine Modell-URL einfügen für den direkten Sprung.</div> <div class="flex gap-2" style="align-items:stretch;margin-bottom:10px"><input placeholder="Suchbegriff oder HuggingFace-URL…" style="flex:1;margin:0"/> <select style="width:auto;margin:0"><option>Downloads</option><option>Trending</option><option>Neu</option></select> <button class="primary"> </button></div> <div class="flex gap-2" style="flex-wrap:wrap;margin-bottom:12px"></div> <!></div> <!> <!> <!>',1);function Tc(e,n){Gn(n,!0);const a="Kontext = das Kurzzeitgedächtnis des Modells. Größer = merkt sich mehr, braucht aber mehr Speicher und wird etwas langsamer.",i="MoE (Mixture of Experts): viele Parameter fürs Wissen, aber pro Wort ist nur ein kleiner Teil aktiv → fast große-Modell-Qualität bei hohem Tempo. Ideal für deine APU.",l={perfect:0,marginal:1,too_tight:2},o={vision:"Bilder",coder:"Coden",reasoning:"Logik",agent:"Agenten & Tools",scout:"Allrounder",reviewer:"Review",manager:"Manager"},d=[{label:"Bilder",kw:["-vl-","-vl","vision","llava","multimodal","-mm-","pixtral"]},{label:"Coden",kw:["coder","-code-","code-","codestral","starcoder"]},{label:"Logik",kw:["-r1","deepseek-r1","reasoning","qwq","magistral","-think","thinking","-o1"]},{label:"Agenten & Tools",kw:["hermes","-tool","command-r","watt","-fc-","function"]}];function c(y){const w=(y||"").toLowerCase();for(const U of d)if(U.kw.some(V=>w.includes(V)))return U.label;return"Allrounder"}function u(y=""){const w=y.toLowerCase();return/\d+x\d+(\.\d+)?b/.test(w)||new RegExp("(?<![a-z])a\\d+(\\.\\d+)?b\\b").test(w)||w.includes("mixtral")||/\bmoe\b/.test(w)}function v(y=""){const w=y.toLowerCase().match(new RegExp("(?<![a-z])a(\\d+(?:\\.\\d+)?)b\\b"));return w?w[1]:null}function b(y){return y==="perfect"?"ok":y==="marginal"?"warn":"bad"}function A(y){return y==="perfect"?"Passt":y==="marginal"?"Knapp":"Zu groß"}function m(y){return`~${(y.req_gb??0).toFixed(1)} GB · ~${Math.round(y.tps??0)} Tok/s`}let x=B(jt([])),C=B(null),z=B(!0),M=B(null),I=B(!1),Ie=B(!1),fe=B(""),me=B(jt([])),ke=B(!1),K=B(""),Y=B("downloads"),he=B(jt([])),xe=B(-1),Te=B(null),Ve=B(!1),yt=B(""),T=B(""),X=B(null),ve=B(""),Ye=B(""),ae=B(8192),Be=B(!1),re=B(null),F=B(!1),Z=B(""),oe=B(""),se=B(jt([{repo:"",role:"",quant:"Q4_K_M"}])),Oe=B(null);function He(y){var w;(w=document.querySelector(`.nav-item[data-view="${y}"]`))==null||w.dispatchEvent(new MouseEvent("click"))}bi(()=>{mt(),ut()});async function mt(){f(z,!0);try{const y=await Se("/api/cookbook/recipes");f(x,y.recipes||[],!0),f(C,y.recommended_id||null,!0)}catch(y){ee(y.message,!0)}f(z,!1)}async function ut(y=!1){f(I,!0);try{const w=await Se("/api/cookbook/discover"+(y?"?force=true":""));f(M,w,!0),f(Ie,w.stale,!0)}catch(w){ee("Empfehlungen nicht ladbar: "+w.message,!0)}f(I,!1)}function vt(y){y=y.trim();const w=y.match(/huggingface\.co\/([^\s/]+\/[^\s/?#]+)/i);return w?w[1]:/^[\w.-]+\/[\w.-]+$/.test(y)?y:null}async function Je(){const y=t(fe).trim(),w=vt(y);let U=y;if(t(K)&&!w&&(U=U?U+" "+t(K):t(K)),!U&&!w){f(me,[],!0);return}f(ke,!0),f(he,[],!0),f(xe,-1);try{if(w)f(me,[{id:w,author:w.split("/")[0],downloads:0}],!0);else{const V=`https://huggingface.co/api/models?search=${encodeURIComponent(U)}&filter=gguf&sort=${encodeURIComponent(t(Y))}&direction=-1&limit=40`,pe=await fetch(V);f(me,await pe.json(),!0)}t(me).forEach((V,pe)=>ze(pe,V.id))}catch(V){ee(V.message,!0),f(me,[],!0)}f(ke,!1)}async function ze(y,w){var U;try{const V=await Se("/api/cookbook/analyze",{method:"POST",body:JSON.stringify({repo_id:w,ctx:8192})});if(!((U=V.files)!=null&&U.length)){t(he)[y]=null,Et();return}const pe=V.files.find(ft=>{var _t;return(_t=ft.quant)==null?void 0:_t.includes("Q4_K_M")})||V.files[0];t(he)[y]=pe.fit.level,Et()}catch{t(he)[y]=null,Et()}}function Et(){let y=-1,w=99;t(he).forEach((U,V)=>{if(U==null)return;const pe=l[U]??99;pe<w&&(w=pe,y=V)}),f(xe,y>=0&&w<=1?y:-1,!0)}function Tt(y){f(Te,t(x).find(w=>w.id===y),!0)}async function $t(y){const w=document.getElementById("cb-r-install-btn");w&&(w.disabled=!0,w.textContent="Starte…");try{const U=await Se("/api/cookbook/install-recipe",{method:"POST",body:JSON.stringify({recipe_id:y,hf_token:li()})});ee(`${U.count} Download${U.count!==1?"s":""} läuft — Modelle erscheinen danach automatisch im Modelle-Tab.`),f(Te,null),He("activity")}catch(U){ee(U.message,!0),w&&(w.disabled=!1,w.textContent="Installieren")}}async function D(y,w){var U,V;f(Ve,!0),f(yt,w,!0),f(T,y,!0),f(Ye,""),f(ae,8192),f(X,null),f(re,null),f(ve,""),f(Be,!0);try{if(f(X,await Se("/api/cookbook/analyze",{method:"POST",body:JSON.stringify({repo_id:y,ctx:8192})}),!0),(V=(U=t(X))==null?void 0:U.files)!=null&&V.length){const pe=t(X).files.find(ft=>{var _t;return(_t=ft.quant)==null?void 0:_t.includes("Q4_K_M")})||t(X).files[0];f(ve,pe.filename,!0),pe.optimal_ctx&&t(ae)===8192&&f(ae,pe.optimal_ctx,!0),N()}}catch(pe){ee(pe.message,!0)}f(Be,!1)}function N(){var y,w,U;!((w=(y=t(X))==null?void 0:y.files)!=null&&w.length)||!t(ve)||(f(re,t(X).files.find(V=>V.filename===t(ve))||null,!0),(U=t(re))!=null&&U.optimal_ctx&&t(ae)===8192&&f(ae,t(re).optimal_ctx,!0))}async function Me(){var y,w;if(!t(T)||!t(ve))return ee("Bitte eine GGUF-Datei wählen.",!0);f(Be,!0);try{const U=((y=t(X))==null?void 0:y.params_b)??7,V=((w=t(re))==null?void 0:w.quant)??"Q4_K_M";await Se("/api/cookbook/install-model",{method:"POST",body:JSON.stringify({repo:t(T),role:t(Ye),params_b:U,quant:V,file:t(ve),ctx:t(ae),hf_token:li()})}),ee("Download läuft — Modell erscheint danach automatisch im Modelle-Tab."),f(Ve,!1),He("activity")}catch(U){ee("Fehler: "+U.message,!0)}f(Be,!1)}async function Qe(y,w,U,V){V.disabled=!0,V.textContent="Starte…";try{await Se("/api/cookbook/install-model",{method:"POST",body:JSON.stringify({repo:y,role:w,params_b:U,quant:"Q4_K_M",hf_token:li()})}),ee("Download läuft — Modell erscheint danach automatisch im Modelle-Tab."),He("activity")}catch(pe){ee(pe.message,!0),V.disabled=!1,V.textContent="Installieren"}}function k(){f(Oe,null),f(Z,""),f(oe,""),f(se,[{repo:"",role:"",quant:"Q4_K_M"}],!0),f(F,!0)}function L(y){const w=t(x).find(U=>U.id===y);w&&(f(Oe,y,!0),f(Z,w.title,!0),f(oe,w.desc||"",!0),f(se,w.models.map(U=>({repo:U.repo,role:U.role,quant:U.quant||"Q4_K_M"})),!0),f(F,!0))}async function te(){if(!t(Z).trim())return ee("Bitte einen Titel angeben.",!0);const y=t(se).filter(w=>w.repo.trim());if(!y.length)return ee("Mindestens ein Modell (Repo) angeben.",!0);try{t(Oe)?(await Se("/api/cookbook/user-recipe/"+encodeURIComponent(t(Oe)),{method:"PUT",body:JSON.stringify({title:t(Z),desc:t(oe),models:y})}),ee("Setup aktualisiert.")):(await Se("/api/cookbook/user-recipe",{method:"POST",body:JSON.stringify({title:t(Z),desc:t(oe),models:y})}),ee("Setup gespeichert.")),f(F,!1),mt()}catch(w){ee(w.message,!0)}}async function Pe(y){const w=t(x).find(U=>U.id===y);if(await mn({title:`„${(w==null?void 0:w.title)||y}" löschen?`,body:"Dein eigenes Setup wird aus dem Cookbook entfernt. Bereits installierte Modelle bleiben unangetastet.",confirmLabel:"Löschen",danger:!0}))try{await Se("/api/cookbook/user-recipe/"+encodeURIComponent(y),{method:"DELETE"}),ee("Setup gelöscht."),mt()}catch(U){ee(U.message,!0)}}function de(y){if(!u(y))return"";const w=v(y);return`<span class="chip" title="${$n(i)}">MoE${w?` · ~${w}B aktiv`:""}</span>`}function Fe(y){return y?`<span class="chip">${$n(y)}</span>`:""}var Ee=Cc(),$e=r(Ze(Ee),2),Xe=s($e),Ke=r(s(Xe),2),lt=r(Xe,4);{var P=y=>{var w=Hd();h(y,w)},ie=y=>{var w=Yd();nt(w,21,()=>t(x),rt,(U,V)=>{const pe=O(()=>t(V).id===t(C));var ft=Zd(),_t=s(ft);{var ue=Ce=>{var dt=Jd(),Vt=Ze(dt),Bt=r(Vt,2);S("click",Vt,zt=>{zt.stopPropagation(),L(t(V).id)}),S("keydown",Vt,zt=>{zt.key==="Enter"&&(zt.stopPropagation(),L(t(V).id))}),S("click",Bt,zt=>{zt.stopPropagation(),Pe(t(V).id)}),S("keydown",Bt,zt=>{zt.key==="Enter"&&(zt.stopPropagation(),Pe(t(V).id))}),h(Ce,dt)};q(_t,Ce=>{t(V).user&&Ce(ue)})}var De=r(_t,2);{var Ge=Ce=>{var dt=er();h(Ce,dt)},St=Ce=>{var dt=Qd();h(Ce,dt)};q(De,Ce=>{t(pe)?Ce(Ge):t(V).user&&Ce(St,1)})}var We=r(De,2),tt=s(We),kt=s(tt),Lt=s(kt),tn=r(tt,2),Mt=s(tn),Ue=r(We,2),It=s(Ue),Gt=r(Ue,2),At=s(Gt);$((Ce,dt)=>{Ct(ft,1,`card-btn${t(pe)?" cb-best":""}`),g(Lt,t(V).title),Ct(tn,1,`fit-badge ${Ce??""}`),g(Mt,dt),g(It,t(V).desc),g(At,`${t(V).models.length??""} Modell${t(V).models.length>1?"e":""} im Setup`)},[()=>b(t(V).fit_level),()=>A(t(V).fit_level)]),S("click",ft,()=>Tt(t(V).id)),h(U,ft)}),h(y,w)};q(lt,y=>{t(z)?y(P):y(ie,-1)})}var we=r($e,2),ot=s(we),et=r(s(ot),2),Qt=s(et);{var Zt=y=>{const w=O(()=>Math.round((Date.now()/1e3-t(M).updated)/60));var U=ec(),V=Ze(U);{var pe=Ge=>{var St=ri();$(()=>g(St,`Quellen befragt vor ${t(w)??""} min`)),h(Ge,St)},ft=Ge=>{var St=ri();$(We=>g(St,`Quellen befragt vor ${We??""} h`),[()=>Math.round(t(w)/60)]),h(Ge,St)},_t=Ge=>{var St=ri();$(We=>g(St,`Quellen befragt vor ${We??""} Tg.`),[()=>Math.round(t(w)/1440)]),h(Ge,St)};q(V,Ge=>{t(w)<60?Ge(pe):t(w)<1440?Ge(ft,1):Ge(_t,-1)})}var ue=r(V,2);{var De=Ge=>{var St=Xd();h(Ge,St)};q(ue,Ge=>{t(Ie)&&Ge(De)})}h(y,U)};q(Qt,y=>{var w;(w=t(M))!=null&&w.updated&&y(Zt)})}var qt=r(et,2),E=s(qt),H=r(ot,4);{var Ne=y=>{var w=tc();h(y,w)},ce=y=>{var w=di(),U=Ze(w);nt(U,17,()=>t(M).categories,rt,(V,pe)=>{var ft=sc(),_t=s(ft),ue=s(_t),De=s(ue),Ge=r(_t,2);nt(Ge,21,()=>t(pe).models,rt,(St,We)=>{const tt=O(()=>t(pe).recommended&&t(We).repo===t(pe).recommended);var kt=rc(),Lt=s(kt);{var tn=ct=>{var gt=er();h(ct,gt)};q(Lt,ct=>{t(tt)&&ct(tn)})}var Mt=r(Lt,2),Ue=s(Mt),It=s(Ue),Gt=s(It),At=r(It,2),Ce=s(At),dt=r(Ue,2),Vt=s(dt),Bt=r(Mt,2),zt=s(Bt);qe(zt,()=>Fe(o[t(We).role]||c(t(We).repo)));var On=r(zt,2);qe(On,()=>de(t(We).repo));var Hn=r(Bt,2),An=s(Hn),Ea=r(Hn,2);nt(Ea,17,()=>t(We).requirements||[],rt,(ct,gt)=>{var Rt=nc(),Cn=s(Rt);$(()=>g(Cn,`⚠ ${t(gt)??""}`)),h(ct,Rt)});var wt=r(Ea,4),at=s(wt);{var ht=ct=>{var gt=ac();$(()=>qi(gt,"title",`bereits eingerichtet als ${t(We).installed??""}`)),h(ct,gt)},Pt=ct=>{var gt=ic();S("click",gt,Rt=>Qe(t(We).repo,t(We).role,t(We).params_b,Rt.currentTarget)),h(ct,gt)};q(at,ct=>{t(We).installed?ct(ht):ct(Pt,-1)})}$((ct,gt,Rt)=>{Ct(kt,1,`card${t(tt)?" res-best":""}`),g(Gt,t(We).name),g(Ce,`${t(We).author??""} · ${t(We).params_b??""}B`),Ct(dt,1,`fit-badge ${ct??""}`),g(Vt,t(We).fit.text),g(An,`${gt??""} · ⬇ ${Rt??""}`)},[()=>b(t(We).fit.level),()=>m(t(We).fit),()=>(t(We).downloads||0).toLocaleString()]),h(St,kt)}),$(()=>g(De,t(pe).title)),h(V,ft)}),h(y,w)};q(H,y=>{var w;t(I)&&!t(M)?y(Ne):(w=t(M))!=null&&w.categories&&y(ce,1)})}var G=r(we,2),j=r(s(G),4),W=s(j),R=r(W,2),J=s(R);J.value=J.__value="downloads";var Q=r(J);Q.value=Q.__value="trending";var le=r(Q);le.value=le.__value="created_at";var Ae=r(R,2),be=s(Ae),pt=r(j,2);nt(pt,20,()=>["","coder","vision","reasoning","chat","agent"],rt,(y,w)=>{var U=lc(),V=s(U);$(()=>{Ct(U,1,t(K)===w?"primary":"ghost"),g(V,w||"Alle")}),S("click",U,()=>{f(K,w,!0),Je()}),h(y,U)});var xt=r(pt,2);{var _e=y=>{var w=dc();nt(w,21,()=>t(me),rt,(U,V,pe)=>{var ft=oc(),_t=s(ft);{var ue=Bt=>{var zt=er();h(Bt,zt)};q(_t,Bt=>{pe===t(xe)&&Bt(ue)})}var De=r(_t,2),Ge=s(De),St=s(Ge),We=s(St),tt=r(St,2),kt=s(tt),Lt=r(Ge,2),tn=s(Lt),Mt=r(De,2),Ue=s(Mt);qe(Ue,()=>Fe(c(t(V).id)));var It=r(Ue,2);qe(It,()=>de(t(V).id));var Gt=r(Mt,4),At=s(Gt),Ce=s(At),dt=r(At,2),Vt=s(dt);$((Bt,zt,On,Hn,An)=>{Ct(ft,1,`card${pe===t(xe)?" res-best":""}`),g(We,Bt),g(kt,t(V).author||""),Ct(Lt,1,`fit-badge ${zt??""}`),g(tn,On),g(Ce,Hn),g(Vt,`⬇ ${An??""}`)},[()=>t(V).id.split("/").pop(),()=>t(he)[pe]?b(t(he)[pe]):"warn",()=>t(he)[pe]?A(t(he)[pe]):"prüfe…",()=>t(he)[pe]?m({req_gb:0,tps:0}):"Hardware-Fit…",()=>(t(V).downloads||0).toLocaleString()]),S("click",ft,()=>D(t(V).id,t(V).id.split("/").pop())),h(U,ft)}),h(y,w)};q(xt,y=>{t(me).length&&y(_e)})}var bt=r(G,2);{var Bn=y=>{const w=O(()=>t(Te));var U=mc(),V=s(U),pe=s(V),ft=r(pe,2),_t=s(ft),ue=r(ft,2),De=s(ue),Ge=r(ue,2);nt(Ge,21,()=>t(w).models,rt,(Mt,Ue)=>{var It=pc(),Gt=s(It),At=s(Gt),Ce=s(At),dt=s(Ce),Vt=r(Ce,2),Bt=s(Vt),zt=r(Vt,2);qe(zt,()=>de(t(Ue).repo));var On=r(At,2);{var Hn=ht=>{var Pt=cc(),ct=s(Pt);$(()=>g(ct,t(Ue).why)),h(ht,Pt)};q(On,ht=>{t(Ue).why&&ht(Hn)})}var An=r(On,2);{var Ea=ht=>{var Pt=uc(),ct=s(Pt);$((gt,Rt,Cn)=>g(ct,`~${gt??""} GB · ~${Rt??""} Tok/s · optimal ~${Cn??""}k Kontext`),[()=>(t(Ue).fit.req_gb??0).toFixed(1),()=>Math.round(t(Ue).fit.tps??0),()=>Math.round((t(Ue).optimal_ctx||8192)/1024)]),h(ht,Pt)};q(An,ht=>{t(Ue).fit&&ht(Ea)})}var wt=r(Gt,2);{var at=ht=>{var Pt=vc(),ct=s(Pt);$(gt=>{Ct(Pt,1,`fit-badge ${gt??""}`),g(ct,t(Ue).fit.text)},[()=>b(t(Ue).fit.level)]),h(ht,Pt)};q(wt,ht=>{t(Ue).fit&&ht(at)})}$(()=>{g(dt,t(Ue).name),g(Bt,t(Ue).role)}),h(Mt,It)});var St=r(Ge,2);{var We=Mt=>{const Ue=O(()=>Math.max(...t(w).models.map(Ce=>{var dt;return((dt=Ce.fit)==null?void 0:dt.req_gb)??0})));var It=fc(),Gt=r(s(It)),At=s(Gt);$(Ce=>g(At,`~${Ce??""} GB`),[()=>t(Ue).toFixed(1)]),h(Mt,It)};q(St,Mt=>{t(w).models.length&&t(w).models[0].fit&&Mt(We)})}var tt=r(St,2);{var kt=Mt=>{const Ue=O(()=>t(x).find(Ce=>!Ce.user&&Ce.fit_level!=="too_tight"&&Ce.id!==t(w).id));var It=gc(),Gt=r(s(It));{var At=Ce=>{var dt=hc(),Vt=r(Ze(dt)),Bt=s(Vt);$(()=>g(Bt,`„${t(Ue).title??""}" ansehen`)),S("click",Vt,zt=>{zt.preventDefault(),f(Te,null),setTimeout(()=>Tt(t(Ue).id),50)}),h(Ce,dt)};q(Gt,Ce=>{t(Ue)&&Ce(At)})}h(Mt,It)};q(tt,Mt=>{t(w).fit_level==="too_tight"&&Mt(kt)})}var Lt=r(tt,2),tn=s(Lt);$(()=>{g(_t,t(w).title),g(De,t(w).desc),Ct(Lt,1,`primary${t(w).fit_level==="too_tight"?" warn":""}`),g(tn,t(w).fit_level==="too_tight"?"Trotzdem installieren (nicht empfohlen)":"Komplettes Setup installieren")}),S("click",U,Mt=>{Mt.target.classList.contains("modal-overlay")&&f(Te,null)}),S("click",pe,()=>f(Te,null)),S("click",Lt,()=>$t(t(w).id)),h(y,U)};q(bt,y=>{t(Te)&&y(Bn)})}var Un=r(bt,2);{var la=y=>{var w=Mc(),U=s(w),V=s(U),pe=r(V,2),ft=s(pe),_t=r(pe,2),ue=s(_t),De=r(_t,2);{var Ge=tt=>{var kt=bc();h(tt,kt)},St=tt=>{var kt=xc(),Lt=r(Ze(kt),2);nt(Lt,21,()=>t(X).files,rt,(wt,at)=>{const ht=O(()=>t(at).fit.level==="perfect"?"●":t(at).fit.level==="marginal"?"◐":"○");var Pt=Yr(),ct=s(Pt),gt={};$(()=>{g(ct,`${t(ht)??""} ${t(at).filename??""}`),gt!==(gt=t(at).filename)&&(Pt.value=(Pt.__value=t(at).filename)??"")}),h(wt,Pt)});var tn=r(Lt,2),Mt=s(tn),Ue=r(s(Mt),2),It=r(Mt,2),Gt=s(It),At=r(s(Gt));qe(At,()=>mr(a));var Ce=r(Gt,2),dt=r(tn,2);{var Vt=wt=>{var at=_c(),ht=r(s(at)),Pt=s(ht),ct=r(ht,2);$(gt=>g(Pt,`~${gt??""}k`),[()=>Math.round(t(re).optimal_ctx/1024)]),S("click",ct,gt=>{gt.preventDefault(),f(ae,t(re).optimal_ctx,!0)}),h(wt,at)};q(dt,wt=>{var at;(at=t(re))!=null&&at.optimal_ctx&&wt(Vt)})}var Bt=r(dt,2);{var zt=wt=>{var at=kc(),ht=s(at),Pt=r(s(ht),2),ct=s(Pt),gt=r(ht,2),Rt=s(gt);$((Cn,ki,Wi)=>{g(ct,`~${Cn??""} GB · ~${ki??""} Tok/s · ${(t(re).quant||"GGUF")??""}`),Ct(gt,1,`fit-badge ${Wi??""}`),g(Rt,t(re).fit.text)},[()=>(t(re).fit.req_gb??0).toFixed(1),()=>Math.round(t(re).fit.tps??0),()=>b(t(re).fit.level)]),h(wt,at)};q(Bt,wt=>{t(re)&&wt(zt)})}var On=r(Bt,2);{var Hn=wt=>{const at=O(()=>t(X).files.find(Rt=>Rt.fit.level!=="too_tight"&&Rt.filename!==t(ve)));var ht=di(),Pt=Ze(ht);{var ct=Rt=>{var Cn=wc(),ki=r(s(Cn)),Wi=s(ki);$(Ui=>g(Wi,`${t(at).filename??""} (${Ui??""})`),[()=>A(t(at).fit.level)]),S("click",ki,Ui=>{Ui.preventDefault(),f(ve,t(at).filename,!0),N()}),h(Rt,Cn)},gt=Rt=>{var Cn=yc();h(Rt,Cn)};q(Pt,Rt=>{t(at)?Rt(ct):Rt(gt,-1)})}h(wt,ht)};q(On,wt=>{var at,ht;((at=t(re))==null?void 0:at.fit.level)==="too_tight"&&((ht=t(X))!=null&&ht.files)&&wt(Hn)})}var An=r(On,2),Ea=s(An);$(()=>{var wt,at;Ct(An,1,`primary${((wt=t(re))==null?void 0:wt.fit.level)==="too_tight"?" warn":""}`),An.disabled=t(Be),g(Ea,t(Be)?"Starte…":((at=t(re))==null?void 0:at.fit.level)==="too_tight"?"Trotzdem holen (zu groß — nicht empfohlen)":"Herunterladen & Einpflegen")}),S("change",Lt,N),ya(Lt,()=>t(ve),wt=>f(ve,wt)),gn(Ue,()=>t(Ye),wt=>f(Ye,wt)),gn(Ce,()=>t(ae),wt=>f(ae,wt)),S("click",An,Me),h(tt,kt)},We=tt=>{var kt=Sc();h(tt,kt)};q(De,tt=>{var kt,Lt;t(Be)&&!t(X)?tt(Ge):(Lt=(kt=t(X))==null?void 0:kt.files)!=null&&Lt.length?tt(St,1):t(Be)||tt(We,2)})}$(()=>{g(ft,t(yt)),g(ue,t(T))}),S("click",w,tt=>{tt.target.classList.contains("modal-overlay")&&f(Ve,!1)}),S("click",V,()=>f(Ve,!1)),h(y,w)};q(Un,y=>{t(Ve)&&y(la)})}var jn=r(Un,2);{var Ha=y=>{var w=Ac(),U=s(w),V=s(U),pe=r(V,2),ft=s(pe),_t=r(pe,6),ue=r(_t,4),De=r(ue,4);nt(De,17,()=>t(se),rt,(tt,kt,Lt)=>{var tn=Ec(),Mt=s(tn),Ue=r(Mt,2),It=r(Ue,2);nt(It,20,()=>["Q4_K_M","Q5_K_M","Q6_K","Q8_0","Q3_K_M"],rt,(At,Ce)=>{var dt=Yr(),Vt=s(dt),Bt={};$(()=>{g(Vt,Ce),Bt!==(Bt=Ce)&&(dt.__value=Ce)}),h(At,dt)});var Gt=r(It,2);gn(Mt,()=>t(kt).repo,At=>t(kt).repo=At),gn(Ue,()=>t(kt).role,At=>t(kt).role=At),ya(It,()=>t(kt).quant,At=>t(kt).quant=At),S("click",Gt,()=>f(se,t(se).filter((At,Ce)=>Ce!==Lt),!0)),h(tt,tn)});var Ge=r(De,2),St=r(Ge,4),We=s(St);$(()=>{g(ft,t(Oe)?"Setup bearbeiten":"Eigenes Setup erstellen"),g(We,t(Oe)?"Änderungen speichern":"Setup speichern")}),S("click",w,tt=>{tt.target.classList.contains("modal-overlay")&&f(F,!1)}),S("click",V,()=>f(F,!1)),gn(_t,()=>t(Z),tt=>f(Z,tt)),gn(ue,()=>t(oe),tt=>f(oe,tt)),S("click",Ge,()=>f(se,[...t(se),{repo:"",role:"",quant:"Q4_K_M"}],!0)),S("click",St,te),h(y,w)};q(jn,y=>{t(F)&&y(Ha)})}$(()=>{qt.disabled=t(I),g(E,t(I)?"Suche…":"Aktualisieren"),Ae.disabled=t(ke),g(be,t(ke)?"Lade…":"Suchen")}),S("click",Ke,k),S("click",qt,()=>ut(!0)),S("keydown",W,y=>y.key==="Enter"&&Je()),gn(W,()=>t(fe),y=>f(fe,y)),ya(R,()=>t(Y),y=>f(Y,y)),S("click",Ae,Je),h(e,Ee),Vn()}sa(["click","keydown","change"]);var zc=_(`<div class="alert warn" style="margin:0 0 12px"><span class="a-dot"></span> <span>Du öffnest Mission Control über einen <b>Proxy/Namen</b>. Die Engine läuft auf <b>Port 8080 ohne HTTPS</b> direkt am Bosgame.
|
||
Trag in deinen Tools die <b>LAN-IP</b> ein: <code>http://192.168.178.151:8080/v1</code> — nicht den Proxy-Namen.</span></div>`),Pc=_('<span class="mono-sm"> </span>'),Dc=_('<div class="tile" style="display:flex;gap:12px;align-items:flex-start"><span style="font-size:20px;line-height:1;flex:0 0 auto"> </span> <div><div style="font-weight:500;font-size:13.5px"> </div> <div class="card-sub" style="margin:4px 0 0"> </div></div></div>'),$c=_('<span class="chip" role="button" tabindex="0"> </span>'),Lc=_('<div style="margin-top:10px"><a href="#" style="color:var(--mut);font-size:12.5px">Auswahl aufheben (alle)</a></div>'),Xr=_('<button style="text-align:left;padding:12px 16px"><div style="font-weight:500;font-size:13.5px"> </div> <div class="card-sub" style="margin:3px 0 0"> </div></button>'),Ic=_('<p><b>Jan AI</b> ist eine Desktop-App — kein Browser, kein Server, kein Admin-Panel. Einfach installieren und loslegen.</p> <p>Jan AI öffnen → linke Leiste → <b>Remote-Modelle</b> → <b>+ Modell hinzufügen</b>:</p> <label>Basis-URL (kopieren und in Jan AI einfügen)</label> <div class="flex gap-2" style="align-items:stretch;margin-bottom:12px"><input class="mono-sm" readonly="" style="flex:1;margin:0"/> <button class="ghost">Kopieren</button></div> <label>Modell-ID (in Jan AI als „Model name" eintragen)</label> <div class="flex gap-2" style="align-items:stretch;margin-bottom:12px"><input class="mono-sm" readonly="" style="flex:1;margin:0"/> <button class="ghost">Kopieren</button></div> <div class="hint">API-Key: ein beliebiger Wert (z.B. <code>local</code>). Jan AI fragt danach beim Einrichten.</div> <div class="hint" style="margin-top:8px">Jan AI herunterladen: <a href="https://jan.ai" target="_blank" rel="noopener">jan.ai</a> — kostenlos, open source, Windows/macOS/Linux.</div>',1),Bc=_('<p>Datei anlegen oder öffnen: <code>~/.continue/config.json</code></p> <div class="alert warn" style="margin:8px 0 12px;padding:10px 14px"><span class="a-dot"></span><span>Falls bereits eine <code>config.json</code> vorhanden: nur den <code>"models"</code>-Eintrag ergänzen, nicht die ganze Datei ersetzen.</span></div> <div style="position:relative"><button class="ghost" style="position:absolute;top:8px;right:8px;z-index:1">Kopieren</button> <div class="log" style="max-height:none"><code> </code></div></div> <p style="margin-top:12px">Danach Continue in VS Code neu starten → im Chat-Panel das Modell <b> </b> wählen.</p> <div class="hint">Continue: <a href="https://continue.dev" target="_blank" rel="noopener">continue.dev</a> — kostenlose VS Code / JetBrains Extension. Hinweis: 2026 von Cursor akquiriert — aktuell weiter aktiv und kostenlos.</div>',1),Oc=_('<p><b>Antigravity</b> (Googles agentic IDE, VS Code-basiert) unterstützt OpenAI-kompatible Endpoints direkt:</p> <p>Settings → Models → <b>Custom Endpoint</b> → <b>+ hinzufügen</b>:</p> <label>Basis-URL</label> <div class="flex gap-2" style="align-items:stretch;margin-bottom:12px"><input class="mono-sm" readonly="" style="flex:1;margin:0"/> <button class="ghost">Kopieren</button></div> <label>Modell-ID</label> <div class="flex gap-2" style="align-items:stretch;margin-bottom:12px"><input class="mono-sm" readonly="" style="flex:1;margin:0"/> <button class="ghost">Kopieren</button></div> <div class="hint">API-Key: ein beliebiger Wert (z.B. <code>local</code>). Danach das Modell <b> </b> in der Model-Liste auswählen.</div> <div class="hint" style="margin-top:8px">Antigravity herunterladen: <a href="https://antigravityide.net" target="_blank" rel="noopener">antigravityide.net</a> — kostenlose Einzelperson-Tier, VS Code-basiert.</div>',1),Rc=_('<p>Öffne die Zed-Settings mit <code>Cmd/Strg + ,</code> und <b>füge diesen Block</b> in deine bestehende <code>settings.json</code> ein. Falls bereits ein <code>"bosgame"</code>-Eintrag existiert: vorher löschen.</p> <div class="alert warn" style="margin-bottom:12px;padding:10px 14px"><span class="a-dot"></span><span>Nur diesen Block einfügen, <b>nicht die ganze Datei ersetzen</b> — sonst gehen andere Einstellungen verloren.</span></div> <div style="position:relative"><button class="ghost" style="position:absolute;top:8px;right:8px;z-index:1">Kopieren</button> <div class="log" style="max-height:none"><code> </code></div></div> <p style="margin-top:12px"><b>API-Key:</b> Öffne den Agent-Panel → Anbieter <b>bosgame</b> → trag irgendeinen Wert ein (z.B. <code>local</code>).</p> <div class="hint">Danach im Agent-Panel das Modell <b> </b> auswählen.</div>',1),Fc=_('<p>Datei anlegen oder öffnen:</p> <p class="mono-sm" style="line-height:1.6">Windows: <code>%USERPROFILE%\\.config\\opencode\\opencode.json</code></p> <div class="alert warn" style="margin:8px 0 12px;padding:10px 14px"><span class="a-dot"></span><span>Nur den <code>"provider"</code>-Block einfügen. Falls bereits ein <code>"llama-swap"</code>-Eintrag vorhanden: <b>vorher löschen</b>, sonst erscheinen Modelle doppelt.</span></div> <div style="position:relative"><button class="ghost" style="position:absolute;top:8px;right:8px;z-index:1">Kopieren</button> <div class="log" style="max-height:none"><code> </code></div></div> <p style="margin-top:12px">Danach in OpenCode <code>/models</code> → <b> </b> wählen.</p>',1),Kc=_('<p>In Cline/Cursor den Provider <b>„OpenAI Compatible"</b> wählen:</p> <label>Basis-URL</label> <div class="flex gap-2" style="align-items:stretch;margin-bottom:12px"><input class="mono-sm" readonly="" style="flex:1;margin:0"/> <button class="ghost">Kopieren</button></div> <label>Modell-ID</label> <div class="flex gap-2" style="align-items:stretch;margin-bottom:12px"><input class="mono-sm" readonly="" style="flex:1;margin:0"/> <button class="ghost">Kopieren</button></div> <div class="hint">API-Key: ein beliebiger Wert (z.B. <code>local</code>).</div>',1),Nc=_('<p>Settings → Admin Panel → Connections → neue OpenAI-Verbindung:</p> <label>Basis-URL</label> <div class="flex gap-2" style="align-items:stretch;margin-bottom:12px"><input class="mono-sm" readonly="" style="flex:1;margin:0"/> <button class="ghost">Kopieren</button></div> <label>API-Key</label> <div class="flex gap-2" style="align-items:stretch"><input class="mono-sm" readonly="" value="dummy-key" style="flex:1;margin:0"/> <button class="ghost">Kopieren</button></div>',1),qc=_('<div class="card"><div class="card-h"><h3>Bilder einbinden (Vision)</h3> <span class="chip" style="background:rgba(63,185,80,.12);border-color:rgba(63,185,80,.25);color:#7ee29a"><!> </span></div> <div class="card-sub">Mit Vision-Modellen kannst du Screenshots oder Fehlerbilder direkt mitschicken.</div> <div style="position:relative;margin-top:8px"><button class="ghost" style="position:absolute;top:8px;right:8px;z-index:1">Kopieren</button> <div class="log" style="max-height:none"><code> </code></div></div></div>'),Gc=_('<div class="card"><div class="card-h"><h3>2 · Modelle auswählen</h3> <span class="meta"> </span></div> <div class="card-sub">Wähle, welche Modelle im Config-Snippet erscheinen sollen.</div> <div class="flex gap-2" style="flex-wrap:wrap"></div> <!></div> <div class="card"><div class="card-h"><h3>3 · Tool wählen</h3></div> <div class="card-sub" style="margin-bottom:8px">Für welches Werkzeug brauchst du die Konfiguration?</div> <div style="font-size:10.5px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--accent);margin-bottom:6px">Chat</div> <div class="grid grid-3" style="gap:8px;margin-bottom:14px"></div> <div style="font-size:10.5px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--accent);margin-bottom:6px">Coding-Assistenten</div> <div class="grid grid-3" style="gap:8px"></div></div> <div class="card"><div class="card-h"><h3>4 · Config-Snippet</h3></div> <!></div> <!>',1),Vc=_('<div class="card"><div class="card-h"><h3>2 · Erst ein Modell installieren</h3></div> <div class="empty-c" style="padding:8px 0 4px"><div class="e-t">Noch kein Modell eingerichtet</div> <div class="e-s">Bevor du ein Tool verbinden kannst, braucht die Engine mindestens ein Modell. Das Config-Snippet wird dann automatisch mit deinen echten Modellnamen befüllt.</div> <button class="primary" style="margin-top:14px">→ Zum Cookbook (Modell holen)</button></div></div>'),Wc=_('<button style="text-align:left;padding:10px 14px"><div style="font-weight:500;font-size:13px"> </div> <div class="card-sub" style="margin:2px 0 0;font-size:11.5px"> </div></button>'),Uc=_('<p style="margin-top:12px">In <b>Cline</b>: MCP-Einstellungen öffnen (Stecker-Icon in der Cline-Sidebar) → „Add MCP Server" → diesen Block einfügen.</p> <p>In <b>Claude Code</b>: Block in <code>~/.claude/settings.json</code> unter <code>"mcpServers"</code> einfügen.</p> <div class="alert warn" style="margin-top:8px;padding:10px 14px"><span class="a-dot"></span> <span>Einmalig auf dem Windows-PC: <code>pip install mcp httpx</code> ausführen — danach <code>mcp_memory.py</code> aus dem Repo-Ordner erreichbar machen (Pfad im Snippet anpassen).</span></div>',1),jc=_('<p style="margin-top:12px">Block in <code>~/.config/opencode/opencode.json</code> unter <code>"mcpServers"</code> einfügen.</p> <div class="alert warn" style="margin-top:8px;padding:10px 14px"><span class="a-dot"></span> <span>Einmalig: <code>pip install mcp httpx</code> — und Pfad zu <code>mcp_memory.py</code> im Snippet anpassen.</span></div>',1),Hc=_('<p style="margin-top:12px">Block in die MCP-Config des jeweiligen Tools einfügen. Der Bosgame-Pfad <code>/opt/mission-control/mcp_memory.py</code> ist bereits korrekt — kein weiteres Setup nötig.</p>'),Jc=_(`<div class="pagehead"><div><h1>Verbinden</h1> <div class="sub">Schritt für Schritt: KI-Modelle in deine Tools einbinden — getestet, erklärt, mit Copy-Paste-Config.</div></div></div> <div class="card"><div class="card-h"><h3>1 · Verbindung prüfen</h3></div> <div class="card-sub">Stelle sicher, dass die LLM-Engine erreichbar ist, bevor du Tools konfigurierst.</div> <label>Engine-Adresse (für alle Tools)</label> <div class="flex gap-2" style="align-items:stretch;margin-bottom:12px"><input class="mono-sm" readonly="" style="flex:1;margin:0"/> <button class="ghost">Kopieren</button></div> <!> <div class="btn-row" style="display:flex;align-items:center;gap:10px"><button class="primary">Verbindung testen</button> <!></div></div> <div class="card"><div class="card-h"><h3>Wie funktioniert das Auto-Swap?</h3></div> <div style="display:flex;flex-direction:column;gap:10px"></div></div> <!> <div class="card"><div class="card-h"><h3>Gedächtnis-MCP</h3> <span class="chip" style="background:rgba(45,212,191,.1);border-color:rgba(45,212,191,.3);color:var(--accent)">Neu in v7</span></div> <div class="card-sub" style="margin-bottom:14px">Damit Cline, OpenCode und Claude Code sich Projektfakten, Entscheidungen und Präferenzen
|
||
über Sessions hinweg merken — geteilt über alle Tools, verwaltet im <a href="#" style="color:var(--accent)">Gedächtnis-Tab</a>.</div> <div class="flex gap-2" style="margin-bottom:14px;flex-wrap:wrap"></div> <div style="position:relative"><button class="ghost" style="position:absolute;top:8px;right:8px;z-index:1">Kopieren</button> <div class="log" style="max-height:none"><code> </code></div></div> <!></div>`,1);function Qc(e,n){Gn(n,!0);const a=O(()=>_i.value),i=O(()=>{var k;return(((k=t(a))==null?void 0:k.models)||[]).filter(L=>!L.incomplete)}),l=O(A);let o=B("zed"),d=B(jt([])),c=B(""),u=B(!1),v=B("cline");const b=O(()=>Y(t(v)));function A(){return`http://${location.hostname}:8080/v1`}function m(k){return/^\d{1,3}(\.\d{1,3}){3}$/.test(k)}function x(){return location.protocol==="https:"||!m(location.hostname)}const C=O(()=>t(d).length?t(d):t(i).map(k=>k.name)),z=O(()=>t(C)[0]||"coder"),M=O(()=>{var k;return(k=t(i).find(L=>{var te,Pe;return(Pe=(te=L.meta)==null?void 0:te.caps)==null?void 0:Pe.includes("Bild")}))==null?void 0:k.name});function I(k,L){const Pe=(L.length?t(i).filter(de=>L.includes(de.name)):t(i).length?t(i):[{name:"coder",meta:{}}]).map(de=>{var $e,Xe;const Fe=((($e=de.meta)==null?void 0:$e.caps)||[]).some(Ke=>/Bild|Vision/i.test(Ke)),Ee=((Xe=de.meta)==null?void 0:Xe.ctx)||131072;return` { "name": "${de.name}", "display_name": "${de.name}", "max_tokens": ${Ee}${Fe?', "capabilities": { "tools": true, "images": true }':""} }`}).join(`,
|
||
`);return`"language_models": {
|
||
"openai_compatible": {
|
||
"bosgame": {
|
||
"api_url": "${k}",
|
||
"available_models": [
|
||
${Pe}
|
||
]
|
||
}
|
||
}
|
||
}`}function Ie(k,L){const Pe=(L.length?t(i).filter(de=>L.includes(de.name)):t(i).length?t(i):[{name:"coder",meta:{}}]).map(de=>{var Ee;const Fe=((Ee=de.meta)==null?void 0:Ee.ctx)||131072;return` "${de.name}": { "name": "${de.name}", "contextWindowSize": ${Fe} }`}).join(`,
|
||
`);return`"provider": {
|
||
"llama-swap": {
|
||
"npm": "@ai-sdk/openai-compatible",
|
||
"name": "Bosgame (llama-swap)",
|
||
"options": {
|
||
"baseURL": "${k}",
|
||
"apiKey": "local"
|
||
},
|
||
"models": {
|
||
${Pe}
|
||
}
|
||
}
|
||
}`}function fe(k,L){return`{
|
||
"models": [
|
||
${(L.length?t(i).filter(de=>L.includes(de.name)):t(i).length?t(i):[{name:"coder",meta:{}}]).map(de=>` {
|
||
"title": "llama-swap / ${de.name}",
|
||
"provider": "openai",
|
||
"model": "${de.name}",
|
||
"apiBase": "${k}",
|
||
"apiKey": "local"
|
||
}`).join(`,
|
||
`)}
|
||
]
|
||
}`}async function me(){f(c,"Teste…");try{const k=await Se("/api/integration/test");f(u,k.ok,!0),f(c,k.ok?`✓ Verbunden — ${k.models.length} Modell(e): ${k.models.join(", ")}`:`✗ Keine Verbindung: ${k.error}`,!0)}catch(k){f(u,!1),f(c,"✗ "+k.message)}}function ke(k){var te;const L=k.querySelector("code");L&&((te=navigator.clipboard)==null||te.writeText(L.textContent||""))}function K(k){var L;(L=navigator.clipboard)==null||L.writeText(k.value)}function Y(k){return`{
|
||
"mcpServers": {
|
||
"mission-control-memory": {
|
||
"command": "${k==="bosgame"?"/opt/mission-control/.venv/bin/python":"python"}",
|
||
"args": ["${k==="bosgame"?"/opt/mission-control/mcp_memory.py":"C:\\\\Users\\\\TobisPC\\\\mission-control\\\\mcp_memory.py"}"],
|
||
"env": {
|
||
"MC_URL": "http://192.168.178.151:9000"
|
||
}
|
||
}
|
||
}
|
||
}`}var he=Jc(),xe=r(Ze(he),2),Te=r(s(xe),6),Ve=s(Te),yt=r(Ve,2),T=r(Te,2);{var X=k=>{var L=zc();h(k,L)},ve=O(()=>x());q(T,k=>{t(ve)&&k(X)})}var Ye=r(T,2),ae=s(Ye),Be=r(ae,2);{var re=k=>{var L=Pc(),te=s(L);$(()=>{Xt(L,`color:${t(u)?"#7ee29a":"#ff9b95"}`),g(te,t(c))}),h(k,L)};q(Be,k=>{t(c)&&k(re)})}var F=r(xe,2),Z=r(s(F),2);nt(Z,20,()=>[["⚡","Kein manuelles Starten nötig",'Wenn du in Zed oder OpenCode „coder" auswählst und eine Anfrage sendest, lädt llama-swap das Modell automatisch — in ca. 2–5 Sekunden.'],["🔄","Modelle wechseln sich automatisch ab","Rufst du ein anderes Modell auf, entlädt llama-swap das aktuelle (nach TTL-Ablauf) und lädt das neue. Es läuft immer nur eines gleichzeitig."],["🧠","Zwei Modelle gleichzeitig aktiv halten","Du hast 124 GB RAM — genug für z.B. Scout 8B (~5 GB) dauerhaft geladen + ein größeres Modell das swappt. Dafür beim Scout im Modelle-Tab → Konfigurieren die TTL auf 99999 setzen."]],rt,(k,L)=>{var te=O(()=>ea(L,3));let Pe=()=>t(te)[0],de=()=>t(te)[1],Fe=()=>t(te)[2];var Ee=Dc(),$e=s(Ee),Xe=s($e),Ke=r($e,2),lt=s(Ke),P=s(lt),ie=r(lt,2),we=s(ie);$(()=>{g(Xe,Pe()),g(P,de()),g(we,Fe())}),h(k,Ee)});var oe=r(F,2);{var se=k=>{var L=Gc(),te=Ze(L),Pe=s(te),de=r(s(Pe),2),Fe=s(de),Ee=r(Pe,4);nt(Ee,21,()=>t(i),rt,(G,j)=>{const W=O(()=>t(d).includes(t(j).name));var R=$c(),J=s(R);$(()=>{Xt(R,`cursor:pointer;${t(W)?"background:rgba(45,212,191,.2);border-color:var(--accent);color:var(--accent)":""}`),g(J,t(j).name)}),S("click",R,()=>f(d,t(W)?t(d).filter(Q=>Q!==t(j).name):[...t(d),t(j).name],!0)),S("keydown",R,Q=>Q.key==="Enter"&&f(d,t(W)?t(d).filter(le=>le!==t(j).name):[...t(d),t(j).name],!0)),h(G,R)});var $e=r(Ee,2);{var Xe=G=>{var j=Lc(),W=s(j);S("click",W,R=>{R.preventDefault(),f(d,[],!0)}),h(G,j)};q($e,G=>{t(d).length&&G(Xe)})}var Ke=r(te,2),lt=r(s(Ke),6);nt(lt,20,()=>[["janai","Jan AI","Einfachstes Chat-Interface — Desktop-App, kein Setup"],["openwebui","OpenWebUI","Browser-Chat für Teams — mehr Features, mehr Setup"]],rt,(G,j)=>{var W=O(()=>ea(j,3));let R=()=>t(W)[0],J=()=>t(W)[1],Q=()=>t(W)[2];var le=Xr(),Ae=s(le),be=s(Ae),pt=r(Ae,2),xt=s(pt);$(()=>{Ct(le,1,`card-btn${t(o)===R()?" cb-best":""}`),g(be,J()),g(xt,Q())}),S("click",le,()=>f(o,R(),!0)),h(G,le)});var P=r(lt,4);nt(P,20,()=>[["continue","Continue","VS Code/JetBrains — Hilfe ohne Agent-Overhead"],["cline","Cline","VS Code/JetBrains/Zed — voller Coding-Agent"],["antigravity","Antigravity","Googles agentic IDE — VS Code-basiert"],["opencode","OpenCode","Terminal-Agent — autonom, mächtig"],["zed","Zed","Schneller nativer Editor mit KI-Panel"]],rt,(G,j)=>{var W=O(()=>ea(j,3));let R=()=>t(W)[0],J=()=>t(W)[1],Q=()=>t(W)[2];var le=Xr(),Ae=s(le),be=s(Ae),pt=r(Ae,2),xt=s(pt);$(()=>{Ct(le,1,`card-btn${t(o)===R()?" cb-best":""}`),g(be,J()),g(xt,Q())}),S("click",le,()=>f(o,R(),!0)),h(G,le)});var ie=r(Ke,2),we=r(s(ie),2);{var ot=G=>{var j=Ic(),W=r(Ze(j),6),R=s(W),J=r(R,2),Q=r(W,4),le=s(Q),Ae=r(le,2);$(()=>{Qn(R,t(l)),Qn(le,t(z))}),S("click",J,be=>K(be.currentTarget.previousElementSibling)),S("click",Ae,be=>K(be.currentTarget.previousElementSibling)),h(G,j)},et=G=>{const j=O(()=>fe(t(l),t(C)));var W=Bc(),R=r(Ze(W),4),J=s(R),Q=r(J,2),le=s(Q),Ae=s(le),be=r(R,2),pt=r(s(be)),xt=s(pt);$(()=>{g(Ae,t(j)),g(xt,`llama-swap / ${t(z)??""}`)}),S("click",J,_e=>ke(_e.currentTarget.parentElement)),h(G,W)},Qt=G=>{var j=Oc(),W=r(Ze(j),6),R=s(W),J=r(R,2),Q=r(W,4),le=s(Q),Ae=r(le,2),be=r(Q,2),pt=r(s(be),3),xt=s(pt);$(()=>{Qn(R,t(l)),Qn(le,t(z)),g(xt,t(z))}),S("click",J,_e=>K(_e.currentTarget.previousElementSibling)),S("click",Ae,_e=>K(_e.currentTarget.previousElementSibling)),h(G,j)},Zt=G=>{const j=O(()=>I(t(l),t(C)));var W=Rc(),R=r(Ze(W),4),J=s(R),Q=r(J,2),le=s(Q),Ae=s(le),be=r(R,4),pt=r(s(be)),xt=s(pt);$(()=>{g(Ae,t(j)),g(xt,`bosgame / ${t(z)??""}`)}),S("click",J,_e=>ke(_e.currentTarget.parentElement)),h(G,W)},qt=G=>{const j=O(()=>Ie(t(l),t(C)));var W=Fc(),R=r(Ze(W),6),J=s(R),Q=r(J,2),le=s(Q),Ae=s(le),be=r(R,2),pt=r(s(be),3),xt=s(pt);$(()=>{g(Ae,t(j)),g(xt,`llama-swap/${t(z)??""}`)}),S("click",J,_e=>ke(_e.currentTarget.parentElement)),h(G,W)},E=G=>{var j=Kc(),W=r(Ze(j),4),R=s(W),J=r(R,2),Q=r(W,4),le=s(Q),Ae=r(le,2);$(()=>{Qn(R,t(l)),Qn(le,t(z))}),S("click",J,be=>K(be.currentTarget.previousElementSibling)),S("click",Ae,be=>K(be.currentTarget.previousElementSibling)),h(G,j)},H=G=>{var j=Nc(),W=r(Ze(j),4),R=s(W),J=r(R,2),Q=r(W,4),le=s(Q),Ae=r(le,2);$(()=>Qn(R,t(l))),S("click",J,be=>K(be.currentTarget.previousElementSibling)),S("click",Ae,be=>K(be.currentTarget.previousElementSibling)),h(G,j)};q(we,G=>{t(o)==="janai"?G(ot):t(o)==="continue"?G(et,1):t(o)==="antigravity"?G(Qt,2):t(o)==="zed"?G(Zt,3):t(o)==="opencode"?G(qt,4):t(o)==="cline"?G(E,5):t(o)==="openwebui"&&G(H,6)})}var Ne=r(ie,2);{var ce=G=>{const j=O(()=>`curl ${t(l)}/chat/completions \\
|
||
-H "Content-Type: application/json" \\
|
||
-d '{
|
||
"model": "${t(M)}",
|
||
"messages": [{"role":"user","content":[{"type":"text","text":"Was ist auf dem Bild falsch?"},{"type":"image_url","image_url":{"url":"data:image/png;base64,<DEIN_BILD>"}}]}]
|
||
}'`);var W=qc(),R=s(W),J=r(s(R),2),Q=s(J);qe(Q,()=>Ft("check"));var le=r(Q),Ae=r(R,4),be=s(Ae),pt=r(be,2),xt=s(pt),_e=s(xt);$(()=>{g(le,` „${t(M)??""}" bereit`),g(_e,t(j))}),S("click",be,bt=>ke(bt.currentTarget.parentElement)),h(G,W)};q(Ne,G=>{t(M)&&G(ce)})}$(()=>g(Fe,t(d).length?`${t(d).length} von ${t(i).length} ausgewählt`:"alle werden eingeschlossen")),h(k,L)},Oe=k=>{var L=Vc(),te=r(s(L),2),Pe=r(s(te),4);S("click",Pe,()=>{var de;return(de=document.querySelector(".nav-item[data-view='cookbook']"))==null?void 0:de.dispatchEvent(new MouseEvent("click"))}),h(k,L)};q(oe,k=>{t(i).length?k(se):k(Oe,-1)})}var He=r(oe,2),mt=r(s(He),2),ut=r(s(mt)),vt=r(mt,2);nt(vt,20,()=>[["cline","Cline / Claude Code","Windows — Tools auf dem Entwicklungs-PC"],["opencode","OpenCode","Windows — Terminal-Agent"],["bosgame","Direkt am Bosgame","Wenn das Tool am Server läuft"]],rt,(k,L)=>{var te=O(()=>ea(L,3));let Pe=()=>t(te)[0],de=()=>t(te)[1],Fe=()=>t(te)[2];var Ee=Wc(),$e=s(Ee),Xe=s($e),Ke=r($e,2),lt=s(Ke);$(()=>{Ct(Ee,1,`card-btn${t(v)===Pe()?" cb-best":""}`),g(Xe,de()),g(lt,Fe())}),S("click",Ee,()=>f(v,Pe(),!0)),h(k,Ee)});var Je=r(vt,2),ze=s(Je),Et=r(ze,2),Tt=s(Et),$t=s(Tt),D=r(Je,2);{var N=k=>{var L=Uc();h(k,L)},Me=k=>{var L=jc();h(k,L)},Qe=k=>{var L=Hc();h(k,L)};q(D,k=>{t(v)==="cline"?k(N):t(v)==="opencode"?k(Me,1):k(Qe,-1)})}$(()=>{Qn(Ve,t(l)),g($t,t(b))}),S("click",yt,k=>{const L=k.currentTarget.previousElementSibling;K(L)}),S("click",ae,me),S("click",ut,k=>{var L;k.preventDefault(),(L=document.querySelector(".nav-item[data-view='memory']"))==null||L.click()}),S("click",ze,k=>ke(k.currentTarget.parentElement)),h(e,he),Vn()}sa(["click","keydown"]);var Zc=_('<div class="li" style="align-items:flex-start"><div class="li-main"><div class="flex items-center gap-2" style="flex-wrap:wrap"><span class="li-id" style="font-family:var(--sans);font-weight:500"> </span> <span> </span></div> <div class="li-sub"> </div></div> <button class="primary">Installieren</button></div>'),Yc=_('<div class="card" style="margin-bottom:18px;border-color:rgba(45,212,191,.25)"><div class="card-h"><h3>Für dich: Upgrades</h3> <span class="meta"> </span></div> <div class="card-sub">Neuere Modelle, die ein installiertes ersetzen können.</div> <div class="list"></div></div>'),Xc=_('<div class="empty" style="text-align:center;padding:40px">Lade News… (erstes Laden kann kurz dauern)</div>'),eu=_('<div class="alert err" style="margin:0"> </div>'),tu=_('<div class="empty-c"><div class="e-t">Keine News geladen</div> <div class="e-s">Die Quellen sind gerade nicht erreichbar — später nochmal probieren.</div></div>'),nu=_('<span class="news-rel">für dich</span>'),au=_('<a target="_blank" rel="noopener"><div class="news-meta"><span class="news-src"> </span> <!> <span class="news-date"> </span></div> <div class="news-title"> </div></a>'),iu=_('<div class="news-grid"></div>'),ru=_('<div class="pagehead"><div><h1>News</h1> <div class="sub">Aktuelles aus der Local-LLM-Welt — aus kuratierten Quellen.</div></div> <button class="ghost">Aktualisieren</button></div> <!> <!>',1);function su(e,n){Gn(n,!0);let a=B(jt([])),i=B(jt([])),l=B(!0),o=B("");const d=K=>K==="perfect"?"ok":K==="marginal"?"warn":"bad";function c(K){const Y=Math.max(0,Date.now()/1e3-K);return Y<60?Y+"s":Y<3600?Math.floor(Y/60)+"m":Y<86400?Math.floor(Y/3600)+"h":Math.floor(Y/86400)+"d"}async function u(){f(l,!0),f(o,"");try{f(a,(await Se("/api/news")).items||[],!0)}catch(K){f(o,K.message||"Fehler beim Laden",!0)}finally{f(l,!1)}}async function v(){try{f(i,(await Se("/api/cookbook/upgrades")).upgrades||[],!0)}catch{f(i,[],!0)}}async function b(K,Y){var he;Y.disabled=!0,Y.textContent="Starte…";try{await Se("/api/cookbook/install-model",{method:"POST",body:JSON.stringify({repo:K.repo,role:K.role,params_b:K.params_b,quant:K.quant,hf_token:li()})}),(he=document.querySelector(".nav-item[data-view='activity']"))==null||he.dispatchEvent(new MouseEvent("click"))}catch(xe){Y.disabled=!1,Y.textContent="Installieren",alert("Fehler: "+xe.message)}}function A(){u(),v()}bi(()=>{u(),v()});var m=ru(),x=Ze(m),C=r(s(x),2),z=r(x,2);{var M=K=>{var Y=Yc(),he=s(Y),xe=r(s(he),2),Te=s(xe),Ve=r(he,4);nt(Ve,21,()=>t(i),rt,(yt,T)=>{var X=Zc(),ve=s(X),Ye=s(ve),ae=s(Ye),Be=s(ae),re=r(ae,2),F=s(re),Z=r(Ye,2),oe=s(Z),se=r(ve,2);$(Oe=>{g(Be,t(T).name),Ct(re,1,`fit-badge ${Oe??""}`),g(F,t(T).fit.text),g(oe,`Ersetzt dein „${t(T).old??""}". ${t(T).why??""}`)},[()=>d(t(T).fit.level)]),S("click",se,Oe=>b(t(T),Oe.currentTarget)),h(yt,X)}),$(()=>g(Te,t(i).length)),h(K,Y)};q(z,K=>{t(i).length&&K(M)})}var I=r(z,2);{var Ie=K=>{var Y=Xc();h(K,Y)},fe=K=>{var Y=eu(),he=s(Y);$(()=>g(he,t(o))),h(K,Y)},me=K=>{var Y=tu();h(K,Y)},ke=K=>{var Y=iu();nt(Y,21,()=>t(a),rt,(he,xe,Te)=>{var Ve=au();Ct(Ve,1,`news-card${Te===0?" featured":""}`);var yt=s(Ve),T=s(yt),X=s(T),ve=r(T,2);{var Ye=Z=>{var oe=nu();h(Z,oe)};q(ve,Z=>{t(xe).relevant&&Z(Ye)})}var ae=r(ve,2),Be=s(ae),re=r(yt,2),F=s(re);$(Z=>{qi(Ve,"href",t(xe).link),g(X,t(xe).source),g(Be,Z),g(F,t(xe).title)},[()=>t(xe).ts?c(t(xe).ts):""]),h(he,Ve)}),h(K,Y)};q(I,K=>{t(l)?K(Ie):t(o)?K(fe,1):t(a).length?K(ke,-1):K(me,2)})}S("click",C,A),h(e,m),Vn()}sa(["click"]);const lu=[{label:"Einstieg",tutorials:[["Dein erster Workflow — in 3 Schritten",`
|
||
<ol class="tut-steps">
|
||
<li><b>Modell holen:</b> Tab <b>Cookbook</b> → Anwendungsfall wählen (z.B. „Coden & Programmieren") →
|
||
<b>Komplettes Setup installieren</b>. Der Download läuft im Tab <b>Aktivität</b> — einfach warten bis der Job grün wird.</li>
|
||
<li><b>Verbinden:</b> Tab <b>Verbinden</b> → Tool wählen → Config-Snippet kopieren und einfügen.
|
||
<b>Verbindung testen</b> bestätigt, dass alles klappt.</li>
|
||
<li><b>Arbeiten:</b> Im Tool das gewünschte Modell auswählen und loslegen.
|
||
Das Modell wird <b>automatisch geladen</b> — du musst nichts manuell starten.</li>
|
||
</ol>
|
||
<p style="margin-top:10px"><b>Nicht sicher welches Tool du nehmen sollst?</b>
|
||
Lies den Abschnitt „Welches Tool ist das richtige für mich?" weiter unten.</p>`],["Kontext — das Kurzzeitgedächtnis des Modells",`
|
||
<p>Der Kontext ist wie ein Blatt Papier: alles was du mit dem Modell besprochen hast,
|
||
steht darauf. Wird es voll, fallen die ältesten Nachrichten raus.</p>
|
||
<p><b>Was du meist nicht tun musst:</b> Tools wie OpenCode, Cline und OpenWebUI
|
||
verwalten das Kontextfenster automatisch. Ein neuer Chat = leeres Blatt.</p>
|
||
<p><b>Wenn der Kontext volläuft</b> (Fehler „context length exceeded" oder das Modell vergisst den Anfang):</p>
|
||
<ol class="tut-steps">
|
||
<li><b>Neuen Chat starten</b> — der einfachste Reset.</li>
|
||
<li>Vorher: <em>„Fasse kurz zusammen was wir bisher erreicht haben"</em> — dann diesen Stand in den neuen Chat einfügen.</li>
|
||
<li><b>Kontext vergrößern:</b> Tab <b>Modelle</b> → <b>Konfigurieren</b> → Empfehlung für deine Hardware übernehmen.</li>
|
||
</ol>
|
||
<p><b>Wichtig:</b> „Grafikspeicher leeren" (Tab <b>Server</b>) ist etwas anderes —
|
||
das wirft das <em>Modell</em> aus dem Speicher, nicht den Gesprächsverlauf.</p>`],["Auto-Swap — Modelle laden sich von selbst",`
|
||
<p>llama-swap lädt automatisch das Modell, das gerade angefragt wird —
|
||
und entlädt es nach einer Leerlaufzeit wieder. <b>Es läuft immer nur eines gleichzeitig.</b></p>
|
||
<p>Du richtest beliebig viele Modelle ein und wählst im Tool das passende.
|
||
Das Laden und Entladen passiert unsichtbar im Hintergrund.</p>
|
||
<p><b>Warum dauert die erste Antwort manchmal 5–15 Sekunden?</b><br>
|
||
Das Modell wird gerade geladen — danach geht es normal weiter.
|
||
Die Topbar zeigt <em>„[Modellname] lädt…"</em> während das passiert.</p>
|
||
<p><b>Scout immer sofort verfügbar halten:</b> Tab <b>Modelle</b> → Konfigurieren →
|
||
<em>Immer aktiv halten</em> aktivieren (TTL = ∞). Das Modell bleibt dann dauerhaft im RAM
|
||
und antwortet ohne Wartezeit — ideal für den kleinen, schnellen Allrounder.</p>`]]},{label:"Tools einrichten",tutorials:[["Welches Tool ist das richtige für mich?",`
|
||
<p><b>Chat — ich will einfach reden, schreiben, fragen:</b></p>
|
||
<div class="tut-table">
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">Einfachster Einstieg</div>
|
||
<div class="tut-cell-bd">→ <b>Jan AI</b> — Desktop-App, Doppelklick-Installer, sofort loslegen.
|
||
Vertraut wie ChatGPT, läuft komplett lokal. Kein Admin-Panel, kein Docker.</div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">Teams / Power-User</div>
|
||
<div class="tut-cell-bd">→ <b>OpenWebUI</b> — viele Features (RAG, Bilder, Plugins, Mehrbenutzer).
|
||
Mehr Setup-Aufwand, aber der mächtigste Chat-Client.</div>
|
||
</div>
|
||
</div>
|
||
<p style="margin-top:12px"><b>Coding — ich will KI beim Programmieren:</b></p>
|
||
<div class="tut-table">
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">Simpler Einstieg in VS Code</div>
|
||
<div class="tut-cell-bd">→ <b>Continue</b> — Chat + Autocomplete direkt im Editor, kein Agent-Overhead.
|
||
Macht keinen Schritt ohne dich.</div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">Voller Coding-Agent im Editor</div>
|
||
<div class="tut-cell-bd">→ <b>Cline</b> — liest Dateien, schreibt Code, fragt vor jeder Änderung.
|
||
VS Code, JetBrains, Zed u.a.</div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">Agent-IDE mit VS Code-Feeling</div>
|
||
<div class="tut-cell-bd">→ <b>Antigravity</b> — Googles agentic IDE (VS Code-Fork), kostenlos.
|
||
Multi-Agent, planen + coden + testen in einem.</div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">Autonomer Terminal-Agent</div>
|
||
<div class="tut-cell-bd">→ <b>OpenCode</b> — mächtigster lokaler Agent, lebt im Terminal.
|
||
Ideal für „bau mir Feature X komplett fertig".</div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">Schneller Editor, minimalistisch</div>
|
||
<div class="tut-cell-bd">→ <b>Zed</b> — nativer Editor (Rust), eingebautes KI-Panel.
|
||
Für Leute die Performance über Features stellen.</div>
|
||
</div>
|
||
</div>
|
||
<p style="margin-top:10px"><b>Faustregel:</b> Fang mit <b>Jan AI</b> zum Chatten an.
|
||
Für Coding: <b>Continue</b> als sanfter Einstieg oder gleich <b>Cline/Antigravity</b>
|
||
wenn du bereit bist, dem Agenten mehr Kontrolle zu geben.</p>`],["OpenCode verbinden und die ersten Schritte",`
|
||
<p>OpenCode ist installiert? Dann in vier Schritten verbinden:</p>
|
||
<ol class="tut-steps">
|
||
<li><b>Config-Snippet holen:</b> Tab <b>Verbinden</b> → <em>OpenCode</em> auswählen →
|
||
Snippet kopieren und in <code>~/.config/opencode/opencode.json</code> einfügen.</li>
|
||
<li><b>OpenCode starten:</b> Terminal öffnen, <code>opencode</code> eintippen —
|
||
immer im Projektordner starten, damit der Agent deine Dateien sieht.</li>
|
||
<li><b>Modell wählen:</b> <code>/models</code> eintippen → <em>llama-swap/coder</em> auswählen.</li>
|
||
<li><b>Erste Aufgabe geben</b> — z.B.:
|
||
<em>„Lies die Datei README.md und erkläre mir kurz was dieses Projekt macht."</em></li>
|
||
</ol>
|
||
<p><b>Die wichtigsten Slash-Commands:</b></p>
|
||
<div class="tut-table">
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd"><code>/model</code></div>
|
||
<div class="tut-cell-bd">Modell wechseln — z.B. mitten im Gespräch auf <em>scout</em> für kurze Fragen</div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd"><code>/compact</code> · <code>/summarize</code></div>
|
||
<div class="tut-cell-bd">Kontext komprimieren wenn er voll wird — fasst die Session zusammen und setzt fort</div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd"><code>/clear</code> · <code>/new</code></div>
|
||
<div class="tut-cell-bd">Neue Session starten — komplett leerer Kontext</div>
|
||
</div>
|
||
</div>
|
||
<p>Bevor OpenCode eine Datei ändert, fragt es nach — mit <b>y</b> bestätigen oder <b>n</b> ablehnen.</p>
|
||
<p><b>Terminal oder Desktop-App?</b> Die Anleitung gilt für beide —
|
||
der Config-Snippet landet in derselben Datei (<code>~/.config/opencode/opencode.json</code>),
|
||
und alle Slash-Commands funktionieren in beiden Versionen gleich.
|
||
Unterschied: Im Terminal startest du mit <code>cd ~/mein-projekt && opencode</code>;
|
||
in der Desktop-App öffnest du einfach die App und wählst den Projektordner über die GUI.</p>
|
||
<p><b>Multi-Agenten (2026):</b> Du kannst in OpenCode mehrere spezialisierte Agenten definieren
|
||
— z.B. einen <em>review</em>-Agent und einen <em>coder</em>-Agent.
|
||
Mit <b>Tab</b> wechselst du zwischen primären Agenten; mit <b>@review</b> rufst du einen Subagenten direkt im Chat auf.
|
||
Agenten werden als Markdown-Dateien angelegt: eine Datei <code>review.md</code> im
|
||
<code>~/.config/opencode/</code>-Ordner erstellt automatisch den Agenten <em>review</em>.</p>
|
||
<p class="tut-sources">Weitere Infos: <a href="https://opencode.ai/docs" target="_blank" rel="noopener">opencode.ai/docs</a> · <a href="https://opencode.ai/docs/agents/" target="_blank" rel="noopener">Agenten-Docs</a></p>`],["Cline verbinden und nutzen",`
|
||
<p>Cline (v3.81, Stand Juni 2026) läuft in: <b>VS Code, JetBrains, Cursor, Windsurf, Zed, Neovim</b>
|
||
und als CLI auf macOS/Linux. Verbinden funktioniert überall gleich:</p>
|
||
<ol class="tut-steps">
|
||
<li>Das Cline-Panel öffnen (Roboter-Icon in der Seitenleiste).</li>
|
||
<li>Provider <b>„OpenAI Compatible"</b> wählen.</li>
|
||
<li>Tab <b>Verbinden</b> → <em>Cline / Cursor</em> → Basis-URL und Modell-ID kopieren und eintragen.</li>
|
||
<li>API-Key: irgendeinen beliebigen Text eingeben (z.B. <code>local</code>) — wird nicht geprüft.</li>
|
||
</ol>
|
||
<p><b>Plan-Modus vs. Act-Modus:</b></p>
|
||
<div class="tut-table">
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">Plan</div>
|
||
<div class="tut-cell-bd">Cline liest und denkt nach — erklärt den Plan bevor es handelt.
|
||
Billiger (weniger Tokens) und ideal für Anfänger.</div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">Act</div>
|
||
<div class="tut-cell-bd">Cline handelt sofort, fragt aber vor jeder Dateiänderung um Erlaubnis.
|
||
Schneller für klare Aufgaben.</div>
|
||
</div>
|
||
</div>
|
||
<p><b>Memory Bank (empfohlen):</b> Lege eine Datei <code>projectbrief.md</code> im Projektordner an —
|
||
Cline liest sie zu Beginn jeder Aufgabe automatisch. Sie ist das Fundament: Projektziel, Tech-Stack,
|
||
wichtigste Regeln. Ergänzend: <code>activeContext.md</code> für den aktuellen Fokus,
|
||
<code>progress.md</code> für den Stand.</p>
|
||
<p><b>.clinerules:</b> Für größere Projekte kannst du statt einer einzelnen Datei ein ganzes
|
||
Verzeichnis <code>.clinerules/</code> anlegen — jede Datei darin gilt als separate Regel.
|
||
Achtung: Jedes Zeichen in .clinerules verbraucht Kontext — kurze, präzise Regeln schlagen lange Listen.</p>
|
||
<p><b>Ausgaben-Limit (seit April 2026):</b> In Settings → Spending Limits kannst du ein
|
||
Tages- oder Monats-Budget setzen — verhindert dass ein laufender Agent unbemerkt viel Token verbraucht.</p>
|
||
<p class="tut-sources">Weitere Infos: <a href="https://cline.bot" target="_blank" rel="noopener">cline.bot</a> · <a href="https://docs.cline.bot/best-practices/memory-bank" target="_blank" rel="noopener">Memory Bank Docs</a></p>`],["Jan AI — einfachstes Chat-Interface",`
|
||
<p><b>Jan AI</b> ist die einfachste Art, lokal mit KI zu chatten —
|
||
Desktop-App, kein Terminal, kein Docker, kein Admin-Panel.</p>
|
||
<ol class="tut-steps">
|
||
<li><b>Jan AI installieren:</b> <a href="https://jan.ai" target="_blank" rel="noopener">jan.ai</a>
|
||
→ Download → Doppelklick-Installer (Windows/macOS/Linux).</li>
|
||
<li><b>Remote-Modell hinzufügen:</b> In der linken Leiste auf das Hub-Icon →
|
||
oben rechts <b>+ Remote-Modell</b>.</li>
|
||
<li><b>Verbindung eintragen:</b> Tab <b>Verbinden</b> → <em>Jan AI</em> auswählen →
|
||
Basis-URL und Modell-ID kopieren und in Jan einfügen.</li>
|
||
<li>API-Key: irgendeinen Text (z.B. <code>local</code>). Speichern.</li>
|
||
</ol>
|
||
<p>Danach erscheint das Modell in der Modell-Liste — auswählen und loslegen.</p>
|
||
<p><b>Gut für:</b> Chatten, Texte schreiben, übersetzen, Fragen stellen —
|
||
genauso wie ChatGPT, aber 100% lokal und privat. Bilder mitschicken klappt auch
|
||
sobald ein Vision-Modell eingetragen ist.</p>
|
||
<p class="tut-sources">Download & Docs: <a href="https://jan.ai" target="_blank" rel="noopener">jan.ai</a> · <a href="https://www.jan.ai/docs" target="_blank" rel="noopener">jan.ai/docs</a></p>`],["Continue — Coding-Hilfe in VS Code ohne Agent-Overhead",`
|
||
<p><b>Continue</b> ist die einfachste Coding-Erweiterung für VS Code und JetBrains —
|
||
kein autonomer Agent, sondern ein KI-Assistent der nur auf Anfrage handelt.</p>
|
||
<ol class="tut-steps">
|
||
<li><b>Extension installieren:</b> VS Code → Extensions → „Continue" suchen → Installieren.<br>
|
||
Oder: <a href="https://continue.dev" target="_blank" rel="noopener">continue.dev</a></li>
|
||
<li><b>Config holen:</b> Tab <b>Verbinden</b> → <em>Continue</em> auswählen →
|
||
Snippet kopieren und in <code>~/.continue/config.json</code> einfügen.</li>
|
||
<li>Continue in VS Code neu starten → im Chat-Panel Modell wählen → loslegen.</li>
|
||
</ol>
|
||
<p><b>Was Continue kann:</b></p>
|
||
<ul class="tut-steps" style="list-style:disc">
|
||
<li><b>Chat:</b> Frage direkt im Editor — markiere Code und drücke <code>Strg+L</code></li>
|
||
<li><b>Autocomplete:</b> Ergänzt Code während du tippst (wie Copilot)</li>
|
||
<li><b>Inline-Edit:</b> Markieren → <code>Strg+I</code> → „Refactore das zu TypeScript"</li>
|
||
</ul>
|
||
<p><b>Unterschied zu Cline:</b> Continue macht nichts von alleine — du steuerst jeden Schritt.
|
||
Ideal als erster Einstieg bevor man mit vollen Agenten arbeitet.</p>
|
||
<p class="tut-sources">Weitere Infos: <a href="https://continue.dev" target="_blank" rel="noopener">continue.dev</a>
|
||
— Hinweis: 2026 von Cursor akquiriert, weiterhin kostenlos & open source.</p>`],["Antigravity — Googles agentic IDE",`
|
||
<p><b>Antigravity</b> ist Googles agent-first IDE — ein Fork von VS Code, der Planung,
|
||
Coding, Testing und Deployment in einem Workflow zusammenführt. Kostenlos für Einzelpersonen.</p>
|
||
<ol class="tut-steps">
|
||
<li><b>Antigravity installieren:</b>
|
||
<a href="https://antigravityide.net" target="_blank" rel="noopener">antigravityide.net</a>
|
||
→ Download → läuft wie VS Code.</li>
|
||
<li><b>Eigenen Endpoint einrichten:</b> Settings → Models → <b>Custom Endpoint</b> → + hinzufügen.</li>
|
||
<li><b>Verbindung eintragen:</b> Tab <b>Verbinden</b> → <em>Antigravity</em> auswählen →
|
||
Basis-URL und Modell-ID kopieren und eintragen.</li>
|
||
<li>API-Key: beliebiger Text (z.B. <code>local</code>). Danach das Modell aus der Liste wählen.</li>
|
||
</ol>
|
||
<p><b>Was Antigravity besonders macht:</b></p>
|
||
<ul class="tut-steps" style="list-style:disc">
|
||
<li><b>Agent-First:</b> Statt Code-Completion steht der Agent im Mittelpunkt —
|
||
du beschreibst, er plant und setzt um</li>
|
||
<li><b>Multi-Agent:</b> Mehrere Agenten arbeiten parallel an verschiedenen Teilen</li>
|
||
<li><b>Manager-Oberfläche:</b> Übersicht über alle laufenden Agenten-Sessions</li>
|
||
<li><b>VS Code-kompatibel:</b> Extensions und Keybindings funktionieren wie gewohnt</li>
|
||
</ul>
|
||
<p><b>Wann Antigravity statt OpenCode?</b> Wenn du lieber eine grafische IDE als ein Terminal magst
|
||
und trotzdem volle Agenten-Kontrolle willst. OpenCode ist mächtiger im Terminal-Flow;
|
||
Antigravity ist komfortabler für Umsteiger aus VS Code.</p>
|
||
<p class="tut-sources">Weitere Infos: <a href="https://antigravityide.net" target="_blank" rel="noopener">antigravityide.net</a> ·
|
||
<a href="https://developers.googleblog.com/build-with-google-antigravity-our-new-agentic-development-platform/" target="_blank" rel="noopener">Google Dev Blog</a></p>`],["OpenWebUI — für Teams und Power-User",`
|
||
<p>OpenWebUI ist der mächtigste lokale Chat-Client — aber auch der komplexeste.
|
||
Empfohlen wenn du mehr als ein einfaches Chat-Interface brauchst.</p>
|
||
<p><b>Was OpenWebUI besonders kann (gegenüber Jan AI):</b></p>
|
||
<ul class="tut-steps" style="list-style:disc">
|
||
<li>RAG: eigene Dokumente hochladen, KI liest und beantwortet Fragen dazu</li>
|
||
<li>Mehrbenutzer: eigene Accounts für verschiedene Personen im Heimnetz</li>
|
||
<li>Plugins und Agenten: erweiterbar mit Tools und Custom-Pipelines</li>
|
||
<li>Bilder generieren (mit Stable Diffusion), Sprachausgabe, Web-Suche</li>
|
||
</ul>
|
||
<p><b>Verbinden</b> (braucht Docker oder eine lokale Installation):</p>
|
||
<ol class="tut-steps">
|
||
<li>OpenWebUI im Browser öffnen → <b>Admin Panel</b> → <b>Connections</b>.</li>
|
||
<li><b>+ OpenAI-Verbindung</b> → Tab <b>Verbinden</b> → <em>OpenWebUI</em> → Basis-URL kopieren.</li>
|
||
<li>API-Key: <code>dummy-key</code>. Speichern.</li>
|
||
</ol>
|
||
<p>Danach Modell auswählen und loslegen. Für einfaches Chatten: <b>Jan AI</b> ist einfacher.
|
||
OpenWebUI lohnt sich ab dem Moment, wo du mehr als nur Chat willst.</p>
|
||
<p class="tut-sources">Weitere Infos: <a href="https://openwebui.com" target="_blank" rel="noopener">openwebui.com</a></p>`]]},{label:"Agenten meistern",tutorials:[["Was ein Agent tut — und was er nicht kann",`
|
||
<p>Ein nacktes Modell antwortet auf Text — das war's.
|
||
Ein <b>Agent</b> ist das Programm drumherum, das das Modell in eine <b>Handlungsschleife</b> bringt:</p>
|
||
<p style="text-align:center;padding:8px 0;font-family:monospace;font-size:12.5px;color:var(--accent)">
|
||
Planen → Werkzeug nutzen → Ergebnis prüfen → nächsten Schritt planen → …
|
||
</p>
|
||
<p>Konkret: Datei lesen → Code verstehen → Änderung schreiben → Test ausführen → Fehler beheben —
|
||
ohne dass du jeden Schritt anstoßen musst.</p>
|
||
<p><b>Was Agenten gut können:</b></p>
|
||
<ul class="tut-steps" style="list-style:disc">
|
||
<li>Features über mehrere Dateien implementieren</li>
|
||
<li>Bugs finden und in ihrem Kontext beheben</li>
|
||
<li>Code refactoren, Dokumentation schreiben, Tests ergänzen</li>
|
||
<li>Recherchieren und das Ergebnis direkt umsetzen (mit MCP)</li>
|
||
<li>Parallele Teilaufgaben an Subagenten delegieren (OpenCode 2026)</li>
|
||
</ul>
|
||
<p><b>Was Agenten schlecht können:</b></p>
|
||
<ul class="tut-steps" style="list-style:disc">
|
||
<li>Kreative Richtungsentscheidungen ohne klare Vorgabe treffen</li>
|
||
<li>Sehr komplexe, undokumentierte Systeme ohne Kontext verstehen</li>
|
||
<li>Fehler in externer Hardware oder fremden APIs beheben</li>
|
||
</ul>
|
||
<p><b>Faustregel:</b> Je klarer die Aufgabe, desto besser das Ergebnis. Unklarer Auftrag → unklares Ergebnis.</p>`],["Einen Agenten richtig briefen",`
|
||
<p>Der Unterschied zwischen „es passiert nichts Sinnvolles" und „es funktioniert auf Anhieb"
|
||
ist meistens die Qualität des Auftrags.</p>
|
||
<p><b>Schlecht → Gut:</b></p>
|
||
<div class="tut-table">
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd bad">„Mach meine App besser."</div>
|
||
<div class="tut-cell-bd">→ <em>„Die Login-Seite in <code>src/pages/Login.tsx</code> zeigt
|
||
bei falschem Passwort gar keinen Fehler an. Füge unter dem Passwortfeld eine rote Fehlermeldung
|
||
ein wenn die API 401 zurückgibt."</em></div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd bad">„Erkläre mir Python."</div>
|
||
<div class="tut-cell-bd">→ <em>„Ich bin Anfänger. Erkläre mir in 5 Schritten wie ich eine CSV-Datei
|
||
in Python einlese und die Summe einer Spalte berechne — mit echtem Code-Beispiel."</em></div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd bad">„Mach das schneller."</div>
|
||
<div class="tut-cell-bd">→ <em>„Die Funktion <code>loadUsers()</code> in <code>src/api/users.ts</code>
|
||
braucht 3 Sekunden. Die Daten kommen vom Backend. Prüfe ob Caching helfen würde und schlage eine
|
||
konkrete Lösung vor."</em></div>
|
||
</div>
|
||
</div>
|
||
<p style="margin-top:12px"><b>Die 3 Zutaten für einen guten Auftrag:</b></p>
|
||
<ol class="tut-steps">
|
||
<li><b>WO:</b> Welche Datei / welcher Ordner / welches Feature</li>
|
||
<li><b>WAS:</b> Was ist das genaue Problem oder Ziel</li>
|
||
<li><b>WIE:</b> Welches Ergebnis erwartest du</li>
|
||
</ol>
|
||
<p><b>Trick:</b> Wenn du nicht sicher bist ob der Auftrag klar genug ist, frag den Agenten:
|
||
<em>„Hast du alles was du brauchst, oder fehlt dir etwas?"</em></p>`],["MCP — deinem Agenten echte Werkzeuge geben",`
|
||
<p><b>MCP</b> (Model Context Protocol) ist ein einheitlicher „Stecker", über den ein Agent
|
||
zusätzliche <b>Werkzeuge</b> bekommt. Ohne MCP kann er nur Text lesen und schreiben.
|
||
Mit MCP kann er z.B.:</p>
|
||
<ul class="tut-steps" style="list-style:disc">
|
||
<li>Im Web suchen (Brave Search, Tavily)</li>
|
||
<li>GitHub Issues lesen und kommentieren</li>
|
||
<li>Deine Datenbank abfragen</li>
|
||
<li>Screenshots machen, E-Mails lesen, Kalender verwalten</li>
|
||
</ul>
|
||
<p><b>Wie MCPs eingebunden werden</b> (Beispiel für OpenCode):</p>
|
||
<p>In der Konfigurationsdatei (<code>~/.config/opencode/opencode.json</code>) einen
|
||
<code>"mcp"</code>-Block hinzufügen:</p>
|
||
<pre class="tut-code">{
|
||
"mcp": {
|
||
"brave-search": {
|
||
"command": "npx",
|
||
"args": ["-y", "@modelcontextprotocol/server-brave-search"],
|
||
"env": { "BRAVE_API_KEY": "dein-key" }
|
||
}
|
||
}
|
||
}</pre>
|
||
<p>Danach OpenCode neu starten — der Agent nutzt das Werkzeug automatisch wenn er es braucht.</p>
|
||
<p><b>Empfohlene MCPs 2026 — nach Anwendungsfall:</b></p>
|
||
<div class="tut-table">
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">Web-Suche</div>
|
||
<div class="tut-cell-bd"><b>brave-search</b> oder <b>tavily</b> — recherchieren, aktuelle Infos holen</div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">GitHub</div>
|
||
<div class="tut-cell-bd"><b>github</b> — meistinstallierter MCP überhaupt. Issues, PRs, Commits, Repos direkt im Chat verwalten</div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">Lokale Dateien</div>
|
||
<div class="tut-cell-bd"><b>filesystem</b> — meistgenutzter MCP überhaupt. Sichere Dateizugriffe auf beliebige Ordner</div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">Browser</div>
|
||
<div class="tut-cell-bd"><b>playwright</b> — Browser-Automatisierung und UI-Tests. Agent öffnet Seiten, klickt, prüft</div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">Gedächtnis</div>
|
||
<div class="tut-cell-bd"><b>memory / mem0</b> — persistentes Gedächtnis über Sessions hinweg. Agent erinnert sich an deine Präferenzen und Projekt-Kontext auch in neuen Chats</div>
|
||
</div>
|
||
</div>
|
||
<p style="margin-top:8px">Über <b>36.000 MCPs</b> sind mittlerweile verfügbar (Stand Juni 2026).
|
||
Fang mit filesystem + github an — die decken 80% der täglichen Arbeit ab.</p>
|
||
<p class="tut-sources"><b>Wo MCPs finden:</b>
|
||
<a href="https://mcp.run" target="_blank" rel="noopener">mcp.run</a> ·
|
||
<a href="https://smithery.ai" target="_blank" rel="noopener">smithery.ai</a> ·
|
||
<a href="https://modelcontextprotocol.io/servers" target="_blank" rel="noopener">modelcontextprotocol.io/servers</a>
|
||
— oder fragen: <em>„Welche MCPs gibt es für [dein Werkzeug]?"</em></p>
|
||
<p><b>Merksatz:</b> Fehlt dem Agenten eine <em>Fähigkeit</em> → MCP.
|
||
Soll er etwas nur <em>besser machen</em> → Skill (nächster Abschnitt).</p>`],["Skills & Rules — Agenten Gewohnheiten beibringen",`
|
||
<p><b>Skills</b> (auch <em>Rules</em>, <em>AGENTS.md</em> oder <em>Instructions</em> genannt)
|
||
sind kurze Texte, die dem Agenten beibringen wie er in deinem Projekt arbeiten soll —
|
||
immer, ohne dass du es jedes Mal neu sagen musst.</p>
|
||
<p><b>Beispiel</b> — eine einfache AGENTS.md:</p>
|
||
<pre class="tut-code">Schreib alle Variablen in camelCase.
|
||
Kommentare immer auf Deutsch.
|
||
Tests immer mit describe/it-Blöcken (Jest).
|
||
Importiere nichts was nicht schon in package.json steht.
|
||
Bevor du Dateien änderst: erkläre kurz was du vorhast.</pre>
|
||
<p>Der Agent liest das vor jeder Aufgabe und hält sich daran.</p>
|
||
<p><b>Wo die Datei ablegen:</b></p>
|
||
<div class="tut-table">
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">OpenCode</div>
|
||
<div class="tut-cell-bd"><code>AGENTS.md</code> im Projektordner (pro Projekt)<br>
|
||
<code>~/.config/opencode/AGENTS.md</code> (global, gilt überall)</div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">Cline</div>
|
||
<div class="tut-cell-bd"><code>.clinerules</code> im Projektordner<br>
|
||
<code>~/.clinerules</code> (global)</div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">Zed</div>
|
||
<div class="tut-cell-bd">Zed Settings → Assistant → System Prompt</div>
|
||
</div>
|
||
</div>
|
||
<p style="margin-top:10px"><b>Fertige Skills finden:</b></p>
|
||
<div class="tut-table">
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd"><a href="https://skills.sh" target="_blank" rel="noopener">skills.sh</a></div>
|
||
<div class="tut-cell-bd">Von Vercel gestartet (Jan 2026) — das npm für Agent-Skills. Funktioniert mit Claude Code, OpenCode, Cursor u.v.m. One-Command-Installer.
|
||
<b>Hinweis:</b> Community-Inhalte ohne formale Prüfung — Skill vor dem Einsatz kurz lesen.</div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd"><a href="https://skillhub.ai" target="_blank" rel="noopener">SkillHub</a></div>
|
||
<div class="tut-cell-bd">KI-bewertete Skills (S/A/B-Ranking nach Qualität, Klarheit, Wirkung). Kleinerer Katalog, höhere Signal-Qualität.</div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd"><a href="https://cursor.directory" target="_blank" rel="noopener">cursor.directory</a></div>
|
||
<div class="tut-cell-bd">Vorgefertigte Rules für React, Vue, Python, Go etc. — direkt als .clinerules oder AGENTS.md nutzbar.</div>
|
||
</div>
|
||
</div>
|
||
<p style="margin-top:8px"><b>Sicherheitshinweis:</b> Ein Snyk-Audit (2026) fand in 13,4% der Community-Skills
|
||
kritische Probleme (Prompt Injection, exponierte Secrets). Regel: Skill-Datei kurz lesen bevor du sie einsetzt.</p>
|
||
<p style="margin-top:8px">Oder einfach fragen: <em>„Schreib mir eine AGENTS.md für ein React + TypeScript Projekt mit Tailwind."</em></p>`],["Die Persona — Rolle, Beziehung & Onboarding",`
|
||
<p>Eine Persona hat <b>zwei Dimensionen</b> — beide sind wichtig:</p>
|
||
<div class="tut-table">
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">Was der Agent tut</div>
|
||
<div class="tut-cell-bd">Fokus, Fachgebiet, Grenzen — die klassische Rollenbeschreibung.</div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">Wie er mit dir umgeht</div>
|
||
<div class="tut-cell-bd">Ton, Proaktivität, Feedback-Stil — antwortet er kurz oder ausführlich?
|
||
Hakt er nach oder liefert er einfach? Spricht er Fehler direkt an oder verpackt er sie?</div>
|
||
</div>
|
||
</div>
|
||
<p style="margin-top:10px">Ein Agent der technisch gleich konfiguriert ist, verhält sich komplett anders
|
||
wenn er weiß: <em>Du willst kurze Antworten ohne Erklärung.</em> Oder: <em>Du lernst noch —
|
||
ermutige mich und erkläre immer warum.</em></p>
|
||
|
||
<p><b>Das vollständige Persona-Template:</b></p>
|
||
<pre class="tut-code">Du bist [Name], [Rolle].
|
||
|
||
Fokus: [Was du hauptsächlich tust]
|
||
Wie du kommunizierst: [Stil — direkt/erklärend/ermutigend, kurze oder ausführliche Antworten]
|
||
Wie du mit mir umgehst: [Proaktivität, Rückfragen, Feedback-Stil, Fehlerkultur]
|
||
Sprache: Immer auf Deutsch. Code-Kommentare auf Englisch.
|
||
Grenzen: [Was du nicht tust, was du nachfragst statt zu raten]</pre>
|
||
|
||
<p><b>Beispiel 1 — Coding-Assistent (direkt, erfahren):</b></p>
|
||
<pre class="tut-code">Du bist Alex, ein erfahrener Senior-Entwickler spezialisiert auf TypeScript und React.
|
||
|
||
Fokus: Code schreiben, reviewen, erklären — immer mit konkreten Beispielen.
|
||
Wie du kommunizierst: direkt, pragmatisch. Keine Erklärung wenn der Code für sich spricht.
|
||
Wie du mit mir umgehst: Du fragst nach bevor du loslegst wenn die Aufgabe unklar ist.
|
||
Fehler sprichst du klar an — aber ohne Schuldzuweisungen. Du machst Gegenvorschläge
|
||
wenn du eine bessere Lösung siehst, aber respektierst meine Entscheidung.
|
||
Sprache: Deutsch. Code-Kommentare auf Englisch.
|
||
Grenzen: Kein Code ohne Datei-Kontext. Keine neuen Dependencies ohne Rückfrage.</pre>
|
||
|
||
<p><b>Beispiel 2 — Lernbegleiter (geduldig, ermutigend):</b></p>
|
||
<pre class="tut-code">Du bist Sam, eine geduldige Lernbegleiterin für Programmier-Anfänger.
|
||
|
||
Fokus: Konzepte erklären, Fehler korrigieren, Schritt für Schritt führen.
|
||
Wie du kommunizierst: freundlich, mit Analogien aus dem Alltag. Fachbegriffe sofort erklären.
|
||
Wie du mit mir umgehst: Du lobst Fortschritte, auch kleine. Fehler sind Lernchancen —
|
||
du zeigst was falsch war und warum, ohne zu urteilen. Du fragst ob ich es verstanden
|
||
habe bevor du weitermachst.
|
||
Sprache: Immer auf Deutsch. Niemals Englisch ohne Übersetzung.</pre>
|
||
|
||
<hr style="border:none;border-top:1px solid var(--line);margin:18px 0">
|
||
<p><b>Der schnellste Weg: Onboarding-Interview</b></p>
|
||
<p>Statt die Persona selbst auszufüllen — lass den Agenten <em>dich</em> befragen.
|
||
Starte einen frischen Chat und gib ihm diesen Prompt:</p>
|
||
<pre class="tut-code">Ich möchte dich in mein Projekt und meinen Arbeitsstil einarbeiten.
|
||
Führe mit mir ein kurzes Interview durch — stelle mir 6–8 Fragen,
|
||
eine nach der anderen — um zu verstehen:
|
||
|
||
1. Wer ich bin und wie ich am liebsten kommuniziere
|
||
2. Was unser Projekt ist und welches Ziel es hat
|
||
3. Was ich gut kann und wobei ich Unterstützung brauche
|
||
4. Meine Arbeitsgewohnheiten und Präferenzen
|
||
5. Was mir wichtig ist und was mich stört
|
||
|
||
Wenn du alle Antworten hast, erstelle daraus:
|
||
- Eine vollständige AGENTS.md als dauerhaftes Fundament
|
||
- Einen Satz der zusammenfasst wer ich für dich bin</pre>
|
||
<p>Das Ergebnis: eine maßgeschneiderte Persona die <em>wirklich</em> zu dir passt —
|
||
weil du sie nicht selbst formulieren musstest, sondern im Gespräch entstanden ist.</p>
|
||
|
||
<p><b>Wo eintragen:</b></p>
|
||
<div class="tut-table">
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">Für ein Projekt</div>
|
||
<div class="tut-cell-bd">Erste Zeilen der <code>AGENTS.md</code> im Projektordner.</div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">Global (überall)</div>
|
||
<div class="tut-cell-bd"><code>~/.config/opencode/AGENTS.md</code> (OpenCode) ·
|
||
Settings → System Prompt (OpenWebUI)</div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">Nur dieser Chat</div>
|
||
<div class="tut-cell-bd"><em>„Ab jetzt bist du …"</em> direkt eintippen.</div>
|
||
</div>
|
||
</div>
|
||
<p class="tut-sources" style="margin-top:10px">Fertige Personas: <a href="https://skills.sh" target="_blank" rel="noopener">skills.sh</a> · <a href="https://cursor.directory" target="_blank" rel="noopener">cursor.directory</a></p>`],["AGENTS.MD & SAVEPOINT.MD — Gedächtnis für den Agenten",`
|
||
<p>Jedes Mal wenn du einen neuen Chat startest, weiß der Agent <b>nichts</b> über dein Projekt.
|
||
Diese zwei Dateien lösen das Problem.</p>
|
||
<p><b>AGENTS.md ist 2026 der plattformübergreifende Standard</b> — nativ gelesen von:
|
||
OpenCode, Claude Code, Codex CLI, Cursor, Aider, Devin, GitHub Copilot, Gemini CLI, Windsurf, Amazon Q.
|
||
Eine Datei, alle Tools.</p>
|
||
<div class="tut-table">
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">AGENTS.md</div>
|
||
<div class="tut-cell-bd"><b>Was das Projekt ist</b> — Tech-Stack, Konventionen,
|
||
Struktur. Wird vor jeder Aufgabe gelesen. Einmal schreiben, immer wirksam.</div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">SAVEPOINT.md</div>
|
||
<div class="tut-cell-bd"><b>Wo wir gerade stehen</b> — aktueller Stand, offene Punkte,
|
||
nächste Schritte. Wird am Ende einer Session aktualisiert und zu Beginn der nächsten gelesen.</div>
|
||
</div>
|
||
</div>
|
||
|
||
<p style="margin-top:14px"><b>AGENTS.MD — Vorlage:</b></p>
|
||
<pre class="tut-code"># Projekt: [Name]
|
||
|
||
## Persona
|
||
Du bist [Name], [Rolle]. [Stil, Sprache, Grenzen]
|
||
|
||
## Tech-Stack
|
||
- Frontend: [z.B. React 18, TypeScript, Tailwind CSS]
|
||
- Backend: [z.B. FastAPI, Python 3.12]
|
||
- Datenbank:[z.B. PostgreSQL via Prisma]
|
||
|
||
## Konventionen
|
||
- Variablen: camelCase (JS) / snake_case (Python)
|
||
- Kommentare: auf Deutsch
|
||
- Commits: konventionell (feat/fix/chore/docs)
|
||
- Tests: immer mit describe/it-Blöcken
|
||
|
||
## Projektstruktur
|
||
src/
|
||
components/ → UI-Komponenten (eine Datei = eine Komponente)
|
||
pages/ → Seiten / Routes
|
||
api/ → Backend-Calls und Typen
|
||
|
||
## Regeln
|
||
- Vor jeder Dateiänderung kurz erklären was geplant ist
|
||
- Keine neuen Dependencies ohne Rückfrage hinzufügen
|
||
- Bei Unklarheiten fragen, nicht raten
|
||
|
||
<!-- Ziel: 200–500 Zeilen. AGENTS.md wird in jeden Kontext geladen —
|
||
kürzer = mehr Platz für Code und Gespräch. --></pre>
|
||
<p style="color:var(--mut);font-size:12px;margin:4px 0 8px">
|
||
<b>Größe:</b> 200–500 Zeilen sind der empfohlene Sweet Spot (Stand 2026).
|
||
AGENTS.md wird in jeden Kontext geladen — je kürzer, desto mehr Platz bleibt für Code und Gespräch.</p>
|
||
|
||
<p><b>SAVEPOINT.MD — Vorlage:</b></p>
|
||
<pre class="tut-code"># Savepoint — [Datum / Uhrzeit]
|
||
|
||
## Aktueller Stand
|
||
[1–2 Sätze: wo steht das Projekt gerade?]
|
||
|
||
## Zuletzt erledigt
|
||
- [Aufgabe] ✓
|
||
- [Aufgabe] ✓
|
||
|
||
## In Arbeit / halbfertig
|
||
- [Was noch offen ist — welche Datei, welcher Schritt fehlt noch]
|
||
|
||
## Als nächstes
|
||
1. [Konkrete nächste Aufgabe]
|
||
2. [Übernächste Aufgabe]
|
||
|
||
## Wichtige Entscheidungen
|
||
- [Was entschieden wurde]: [Warum]
|
||
|
||
## Bekannte Probleme
|
||
- [Problem]: [Was bekannt ist, noch nicht gelöst]</pre>
|
||
|
||
<p><b>Workflow:</b></p>
|
||
<ol class="tut-steps">
|
||
<li><b>Session starten:</b> <em>„Lies AGENTS.md und SAVEPOINT.md und mach weiter."</em></li>
|
||
<li><b>Session beenden:</b> <em>„Aktualisiere SAVEPOINT.md mit dem aktuellen Stand."</em></li>
|
||
</ol>
|
||
<p><b>Tipp:</b> Lass den Agenten die SAVEPOINT.md selbst schreiben — er sieht was er getan hat.
|
||
Du prüfst nur ob der Stand stimmt und ergänzt bei Bedarf.</p>
|
||
<p class="tut-sources">Vorlagen & Inspiration: <a href="https://skills.sh" target="_blank" rel="noopener">skills.sh</a> · <a href="https://opencode.ai/docs" target="_blank" rel="noopener">opencode.ai/docs</a></p>`]]},{label:"Wenn etwas nicht klappt",tutorials:[["Häufige Probleme & Lösungen",`
|
||
<div class="tut-table">
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">🔴 Engine offline, rotes Licht in der Topbar</div>
|
||
<div class="tut-cell-bd">Tab <b>Server</b> → LLM-Engine-Karte → <b>Neustart</b>.
|
||
Warte 10–15 Sekunden — danach sollte die Verbindung wieder grün sein.</div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">⏳ Modell lädt länger als 5 Minuten</div>
|
||
<div class="tut-cell-bd">Tab <b>Aktivität</b> prüfen: läuft ein Download-Job?
|
||
Der muss erst abgeschlossen sein bevor das Modell ladbar ist.
|
||
Bei Fehler → Job-Zeile aufklappen, Log lesen.</div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">💬 „context length exceeded" Fehler im Tool</div>
|
||
<div class="tut-cell-bd">Neuen Chat starten. Vorher: <em>„Fasse kurz zusammen was wir
|
||
erreicht haben"</em> eingeben und diesen Text in den neuen Chat mitnehmen.</div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">🌐 Modell antwortet immer auf Englisch</div>
|
||
<div class="tut-cell-bd">Am Anfang der Unterhaltung schreiben: <em>„Antworte immer auf Deutsch."</em>
|
||
Für dauerhaft: eine <code>AGENTS.md</code> / <code>.clinerules</code> mit dieser Anweisung anlegen
|
||
(siehe Abschnitt Skills & Rules).</div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">🔌 Tool findet keine Modelle / Verbindung schlägt fehl</div>
|
||
<div class="tut-cell-bd">Tab <b>Verbinden</b> → <b>Verbindung testen</b>. Wenn Fehler:
|
||
läuft llama-swap? (Tab Server). URL korrekt? Muss <code>http://</code> (nicht https) sein,
|
||
Port <b>8080</b>. Über Proxy? → LAN-IP direkt nutzen: <code>http://192.168.178.151:8080/v1</code></div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">⬇ Download schlägt fehl / bricht ab</div>
|
||
<div class="tut-cell-bd">Tab <b>Aktivität</b> → Job-Zeile aufklappen → Log lesen.
|
||
Häufigste Ursache: HuggingFace braucht einen Token für dieses Modell (gated model).
|
||
→ Einstellungen (Zahnrad-Icon oben) → <b>HuggingFace-Token</b> eintragen.</div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">🔄 Seite lädt / Dashboard hängt komplett</div>
|
||
<div class="tut-cell-bd">Strg+Shift+R (Hard Reload). Wenn das nicht hilft:
|
||
Tab <b>Server</b> → Mission Control → <b>Neu starten</b>.</div>
|
||
</div>
|
||
</div>`]]}],ou=[["LLM / Modell","Die KI selbst — versteht und schreibt Text (wie ChatGPT, nur lokal auf deinem PC). Ein Modell ist eine konkrete Datei, oft auf etwas spezialisiert (Code, Bilder, Chat)."],["GGUF","Das lokal lauffähige Dateiformat. llama-swap lädt nur GGUF — Repos ohne GGUF kann die Engine nicht nutzen."],["Quantisierung (Q4_K_M)","Verkleinert ein Modell (16-Bit → 4-Bit), damit es in den Speicher passt — bei kaum Qualitätsverlust. Q4_K_M ist der bewährte Sweetspot. Für Coding/Reasoning: Q8_0 (nahezu verlustfrei). Wenn Q4_K_M 1 GB zu groß ist: IQ4_XS als Alternative (ähnliche Qualität, etwas kleiner)."],["Kontextfenster","Das Kurzzeitgedächtnis: wie viel Text sich das Modell gleichzeitig merken kann. Größer = mehr Überblick, mehr Speicher, etwas langsamer."],["Token","Die kleinste Einheit die ein Modell verarbeitet — meist 3–4 Zeichen oder ein kurzes Wort. 1 000 Tokens ≈ 750 Wörter. Kontextfenster, Geschwindigkeit und Kosten werden in Tokens gemessen."],["Auto-Swap","llama-swap lädt/entlädt Modelle automatisch — immer nur eins gleichzeitig. Du managst nichts."],["TTL (Time to Live)","Wie lange ein Modell nach der letzten Anfrage im RAM bleibt bevor es entladen wird. Standard: 5 Minuten. ∞ = bleibt dauerhaft geladen (sinnvoll für den Scout)."],["Agent","Ein Programm (OpenCode, Cline, Continue), das das Modell in einer Handlungsschleife laufen lässt — Dateien lesen/ändern, Befehle ausführen, planen, bis die Aufgabe erledigt ist."],["MCP","Model Context Protocol — der Stecker, über den ein Agent zusätzliche Werkzeuge bekommt (Web, Datenbank, GitHub …). MCP = neue Fähigkeiten."],["Skills / Rules","Kurze Textdatei (AGENTS.md, .clinerules …) mit Anweisungen wie der Agent in deinem Projekt arbeiten soll — einmal geschrieben, immer befolgt. Seit 2026 plattformübergreifender Standard: AGENTS.md wird von über 10 Tools nativ gelesen."],["Memory Bank","Clines Konzept für dauerhaften Projekt-Kontext: projectbrief.md (Ziel & Scope), activeContext.md (aktueller Fokus), progress.md (Stand). Wird zu Beginn jeder Aufgabe automatisch gelesen — ähnlich wie AGENTS.md, aber aufgeteilt nach Zweck."],["System-Prompt","Eine unsichtbare Anweisung die vor deiner Nachricht steht und das Verhalten des Modells grundlegend prägt (Sprache, Ton, Rolle). Skills nutzen oft den System-Prompt."],["Vision","Modelle mit Vision-Fähigkeit können Bilder verstehen — Screenshots, Diagramme, Fehlerfotos. Erkennbar am mmproj-Projektor der mitgeladen wird."]];var du=_('<details class="guide-acc"><summary> </summary> <div class="acc-body"></div></details>'),cu=_('<div class="card guide-card svelte-112sh7i"><div class="guide-group-hd svelte-112sh7i"> </div> <!></div>'),uu=_('<div class="concept"><h4> </h4> <p> </p></div>'),vu=_('<div class="pagehead"><div><h1>Guide</h1> <div class="sub">Schritt für Schritt erklärt — von der ersten Einrichtung bis zu echten Agenten-Workflows.</div></div></div> <!> <div class="card-h" style="margin-top:8px"><h3>Begriffe kurz erklärt</h3></div> <div class="concept-grid"></div>',1);function pu(e){var n=vu(),a=r(Ze(n),2);nt(a,17,()=>lu,rt,(l,o,d)=>{var c=cu(),u=s(c),v=s(u),b=r(u,2);nt(b,17,()=>t(o).tutorials,rt,(A,m,x)=>{var C=O(()=>ea(t(m),2));let z=()=>t(C)[0],M=()=>t(C)[1];var I=du();I.open=d===0&&x===0;var Ie=s(I),fe=s(Ie),me=r(Ie,2);qe(me,M,!0),$(()=>g(fe,z())),h(A,I)}),$(()=>g(v,t(o).label)),h(l,c)});var i=r(a,4);nt(i,21,()=>ou,rt,(l,o)=>{var d=O(()=>ea(t(o),2));let c=()=>t(d)[0],u=()=>t(d)[1];var v=uu(),b=s(v),A=s(b),m=r(b,2),x=s(m);$(()=>{g(A,c()),g(x,u())}),h(l,v)}),h(e,n)}var fu=_('<div class="card"><div class="card-h"><h3>Neuer Eintrag</h3></div> <label>Inhalt</label> <textarea rows="3" placeholder="z.B.: Mission Control läuft auf Port 9000 — oder: Wir nutzen SQLite statt Qdrant" style="width:100%;box-sizing:border-box;resize:vertical;margin-bottom:10px"></textarea> <label>Kategorie</label> <select style="margin-bottom:14px"><option>Stabil — Projektfakten, die sich selten ändern</option><option>Versioniert — Tech-Versionen (bei Updates überschreiben)</option><option>Temporär — Aktuelle Aufgabe (nach 7 Tagen gelöscht)</option></select> <div class="btn-row"><button class="primary">Speichern</button> <button class="ghost">Abbrechen</button> <span class="card-sub" style="font-size:11.5px;margin-left:4px">Strg+Enter zum Speichern</span></div></div>'),hu=_('<span class="chip" role="button" tabindex="0"> <span style="color:var(--mut);margin-left:2px"> </span></span>'),gu=_('<div class="card"><div class="card-sub">Lade…</div></div>'),mu=_('<button class="primary" style="margin-top:14px">+ Ersten Eintrag anlegen</button>'),bu=_('<div class="card"><div class="empty-c" style="padding:8px 0 4px"><div class="e-t"> </div> <div class="e-s"> </div> <!></div></div>'),_u=_('<textarea rows="3" style="width:100%;box-sizing:border-box;resize:vertical;margin-bottom:8px"></textarea> <select style="margin-bottom:10px"><option>Stabil</option><option>Versioniert</option><option>Temporär</option></select> <div class="btn-row"><button class="primary">Speichern</button> <button class="ghost">Abbrechen</button></div>',1),ku=_('<div style="display:flex;gap:10px;align-items:flex-start"><div style="flex:1;min-width:0"><div style="font-size:13.5px;line-height:1.55;word-break:break-word"> </div> <div class="flex gap-2" style="margin-top:8px;flex-wrap:wrap;align-items:center"><span class="chip"> </span> <span class="chip"> </span> <span style="font-size:11px;color:var(--mut)"> </span></div></div> <div class="flex gap-2" style="flex-shrink:0;margin-top:2px"><button class="ghost" style="padding:4px 10px;font-size:12px">Bearbeiten</button> <button class="ghost" style="padding:4px 10px;font-size:12px;color:var(--err)">Löschen</button></div></div>'),wu=_("<div><!></div>"),yu=_('<div class="card" style="padding:0;overflow:hidden"></div>'),xu=_(`<div class="pagehead" style="display:flex;justify-content:space-between;align-items:flex-start"><div><h1>Gedächtnis</h1> <div class="sub">Fakten, Entscheidungen und Kontext — geteilt von allen KI-Tools via MCP.</div></div> <button class="primary" style="flex-shrink:0;margin-top:4px"> </button></div> <!> <div class="card" style="padding:10px 16px"><div class="flex gap-2" style="flex-wrap:wrap;align-items:center"><span style="font-size:11.5px;color:var(--mut);margin-right:4px">Filter:</span> <!></div></div> <!> <div class="card" style="background:rgba(45,212,191,.04);border-color:rgba(45,212,191,.2)"><div class="card-h"><h3 style="font-size:13px;font-weight:500">Wie KI-Tools dieses Gedächtnis nutzen</h3></div> <div class="card-sub" style="line-height:1.6">Cline, OpenCode und Claude Code greifen über den <b>Memory MCP-Server</b> auf diese Einträge zu.
|
||
Beim Start einer Session lädt der Agent automatisch alle Einträge — er kennt dann deinen Stack,
|
||
deine Präferenzen und frühere Entscheidungen. Den Setup-Guide findest du unter <a href="#" style="color:var(--accent)">Verbinden → Gedächtnis-MCP</a>.</div> <div class="card-sub" style="margin-top:8px;font-size:11.5px">Kategorien: <b style="color:var(--accent)">Stabil</b> = Projektfakten die sich selten ändern · <b style="color:#f59e0b">Versioniert</b> = Tech-Versionen (bei Updates überschreiben) · <b style="color:var(--mut)">Temporär</b> = aktuelle Aufgaben, nach 7 Tagen automatisch gelöscht</div></div>`,1);function Su(e,n){Gn(n,!0);let a=B(jt([])),i=B(!0),l=B("all"),o=B(!1),d=B(""),c=B("stable"),u=B(null),v=B(""),b=B("stable");const A=O(()=>t(l)==="all"?t(a):t(a).filter(F=>F.category===t(l))),m={stable:{label:"Stabil",color:"var(--accent)"},versioned:{label:"Versioniert",color:"#f59e0b"},ephemeral:{label:"Temporär",color:"var(--mut)"}};function x(F){const Z=Math.floor((Date.now()-new Date(F).getTime())/1e3);return Z<60?"gerade eben":Z<3600?`vor ${Math.floor(Z/60)} Min`:Z<86400?`vor ${Math.floor(Z/3600)} Std`:`vor ${Math.floor(Z/86400)} Tagen`}function C(F){return t(a).filter(Z=>Z.category===F).length}async function z(){try{f(a,await Se("/api/memory"),!0)}catch(F){ee("Laden fehlgeschlagen: "+F.message,!0)}finally{f(i,!1)}}async function M(){if(t(d).trim())try{const F=await Se("/api/memory",{method:"POST",body:JSON.stringify({content:t(d).trim(),category:t(c),source:"manual"})});f(a,[F,...t(a)],!0),f(d,""),f(c,"stable"),f(o,!1),ee("Gespeichert")}catch(F){ee("Fehler: "+F.message,!0)}}async function I(F){try{const Z=await Se(`/api/memory/${F.id}`,{method:"PUT",body:JSON.stringify({content:t(v),category:t(b)})});f(a,t(a).map(oe=>oe.id===F.id?Z:oe),!0),f(u,null),ee("Aktualisiert")}catch(Z){ee("Fehler: "+Z.message,!0)}}async function Ie(F){if(await mn({title:"Eintrag löschen?",body:`„${F.content.length>80?F.content.slice(0,80)+"…":F.content}" wird dauerhaft entfernt.`,danger:!0}))try{await Se(`/api/memory/${F.id}`,{method:"DELETE"}),f(a,t(a).filter(oe=>oe.id!==F.id),!0),ee("Gelöscht")}catch(oe){ee("Fehler: "+oe.message,!0)}}function fe(F){f(u,F.id,!0),f(v,F.content,!0),f(b,F.category,!0)}Ki(()=>{z()});var me=xu(),ke=Ze(me),K=r(s(ke),2),Y=s(K),he=r(ke,2);{var xe=F=>{var Z=fu(),oe=r(s(Z),4),se=r(oe,4),Oe=s(se);Oe.value=Oe.__value="stable";var He=r(Oe);He.value=He.__value="versioned";var mt=r(He);mt.value=mt.__value="ephemeral";var ut=r(se,2),vt=s(ut),Je=r(vt,2);$(ze=>vt.disabled=ze,[()=>!t(d).trim()]),S("keydown",oe,ze=>{ze.key==="Enter"&&(ze.ctrlKey||ze.metaKey)&&M()}),gn(oe,()=>t(d),ze=>f(d,ze)),ya(se,()=>t(c),ze=>f(c,ze)),S("click",vt,M),S("click",Je,()=>{f(o,!1),f(d,"")}),h(F,Z)};q(he,F=>{t(o)&&F(xe)})}var Te=r(he,2),Ve=s(Te),yt=r(s(Ve),2);nt(yt,17,()=>[["all","Alle","",t(a).length],["stable","Stabil","var(--accent)",C("stable")],["versioned","Versioniert","#f59e0b",C("versioned")],["ephemeral","Temporär","var(--mut)",C("ephemeral")]],rt,(F,Z)=>{var oe=O(()=>ea(t(Z),4));let se=()=>t(oe)[0],Oe=()=>t(oe)[1],He=()=>t(oe)[2],mt=()=>t(oe)[3];var ut=hu(),vt=s(ut),Je=r(vt),ze=s(Je);$(()=>{Xt(ut,`cursor:pointer;${t(l)===se()?`background:rgba(45,212,191,.12);border-color:${He()||"var(--accent)"};color:${He()||"var(--accent)"}`:""}`),g(vt,`${Oe()??""} `),g(ze,mt())}),S("click",ut,()=>f(l,se(),!0)),S("keydown",ut,Et=>Et.key==="Enter"&&f(l,se(),!0)),h(F,ut)});var T=r(Te,2);{var X=F=>{var Z=gu();h(F,Z)},ve=F=>{var Z=bu(),oe=s(Z),se=s(oe),Oe=s(se),He=r(se,2),mt=s(He),ut=r(He,2);{var vt=Je=>{var ze=mu();S("click",ze,()=>f(o,!0)),h(Je,ze)};q(ut,Je=>{t(a).length===0&&Je(vt)})}$(()=>{g(Oe,t(a).length===0?"Noch keine Einträge":"Keine Treffer"),g(mt,t(a).length===0?'Klicke „+ Eintrag" um manuell etwas zu speichern, oder verbinde ein KI-Tool via MCP.':"Andere Kategorie wählen oder Eintrag anlegen.")}),h(F,Z)},Ye=F=>{var Z=yu();nt(Z,23,()=>t(A),oe=>oe.id,(oe,se,Oe)=>{var He=wu(),mt=s(He);{var ut=Je=>{var ze=_u(),Et=Ze(ze),Tt=r(Et,2),$t=s(Tt);$t.value=$t.__value="stable";var D=r($t);D.value=D.__value="versioned";var N=r(D);N.value=N.__value="ephemeral";var Me=r(Tt,2),Qe=s(Me),k=r(Qe,2);gn(Et,()=>t(v),L=>f(v,L)),ya(Tt,()=>t(b),L=>f(b,L)),S("click",Qe,()=>I(t(se))),S("click",k,()=>f(u,null)),h(Je,ze)},vt=Je=>{var ze=ku(),Et=s(ze),Tt=s(Et),$t=s(Tt),D=r(Tt,2),N=s(D),Me=s(N),Qe=r(N,2),k=s(Qe),L=r(Qe,2),te=s(L),Pe=r(Et,2),de=s(Pe),Fe=r(de,2);$(Ee=>{var $e,Xe,Ke;g($t,t(se).content),Xt(N,`border-color:${((($e=m[t(se).category])==null?void 0:$e.color)||"var(--mut)")??""};color:${(((Xe=m[t(se).category])==null?void 0:Xe.color)||"var(--mut)")??""}`),g(Me,((Ke=m[t(se).category])==null?void 0:Ke.label)||t(se).category),g(k,t(se).source),g(te,Ee)},[()=>x(t(se).updated_at)]),S("click",de,()=>fe(t(se))),S("click",Fe,()=>Ie(t(se))),h(Je,ze)};q(mt,Je=>{t(u)===t(se).id?Je(ut):Je(vt,-1)})}$(()=>Xt(He,`padding:14px 16px;${t(Oe)<t(A).length-1?"border-bottom:1px solid var(--brd, rgba(255,255,255,.07))":""}`)),h(oe,He)}),h(F,Z)};q(T,F=>{t(i)?F(X):t(A).length===0?F(ve,1):F(Ye,-1)})}var ae=r(T,2),Be=r(s(ae),2),re=r(s(Be),3);$(()=>g(Y,t(o)?"Abbrechen":"+ Eintrag")),S("click",K,()=>{f(o,!t(o)),f(d,"")}),S("click",re,F=>{var Z;F.preventDefault(),(Z=document.querySelector(".nav-item[data-view='connect']"))==null||Z.click()}),h(e,me),Vn()}sa(["click","keydown"]);let es={};function Mu(){const e=document.getElementById("top-active-text");e&&(e.classList.add("swap-flash"),setTimeout(()=>e.classList.remove("swap-flash"),900))}function ts(e){var l;const n=document.getElementById("swdot"),a=document.getElementById("swlabel"),i=document.getElementById("top-active-text");if(!e)n&&(n.className="dot off"),a&&(a.textContent="Backend nicht erreichbar"),i&&(i.textContent="Backend offline"),ns("Backend nicht erreichbar – läuft uvicorn?",!1);else{const o=(e.swap_url||"").replace(/^https?:\/\//,"");n&&(n.className="dot "+(e.swap_ok?"on":"off")),a&&(a.textContent=(e.swap_ok?"LLM-Engine: Online – ":"LLM-Engine: Offline – ")+o);const d=["running","ready","loading","starting"],c=(e.models||[]).find(v=>d.includes(v.state));if(i)if(c){const v=(l=c.meta)!=null&&l.ctx?` <span style="color:var(--mut);font-size:11.5px">· ${Math.round(c.meta.ctx/1024)}k ctx</span>`:"",b=c.state==="loading"||c.state==="starting"?' <span style="color:var(--warn);font-size:11.5px">lädt…</span>':"";i.innerHTML=`<b style="color:var(--accent)">${c.name}</b>${v}${b}`}else i.innerHTML='<span style="color:var(--mut)">Kein Modell im VRAM</span>';e.swap_ok?Tu():ns(`LLM-Engine nicht erreichbar unter <b>${o}</b> – läuft der llama-swap Dienst?`,!0);const u={};for(const v of e.models||[])u[v.name]=v.state;for(const[v,b]of Object.entries(u)){const A=es[v];if(A&&A!==b&&(b==="running"||b==="loading")){Mu();break}}es=u}Eu(e),_i.set(e)}function Eu(e){const n=document.getElementById("sec-chip"),a=document.getElementById("sec-chip-tx");!n||!a||(n.classList.toggle("ok",!!(e!=null&&e.secured)),a.textContent=e!=null&&e.secured?"Geschützt · Heimnetz":"Nur im Heimnetz (offen)")}function Au(e){va.set(e||[])}function Cu(e){Pr.set(e)}function ns(e,n){const a=document.getElementById("alert");a.className="alert"+(n?" warn":""),a.innerHTML=`<span class="a-dot"></span><span>${e}</span>`,a.style.display="flex"}function Tu(){const e=document.getElementById("alert");e&&(e.style.display="none")}const zu=e=>{var n;return(n=document.querySelector(`.nav-item[data-view="${e}"]`))==null?void 0:n.click()};function tr(e,n,a,i){const l=document.createElement("span");return l.className="upd-badge"+(n?" "+n:""),l.textContent=e,i&&(l.title=i),l.onclick=()=>zu(a),l}async function nl(){try{const e=await Se("/api/updates"),n=document.getElementById("update-badges");if(!n)return;const a=e.apt_cache_age_h,i=a!=null&&a>24,l=a!=null?` · apt-Cache: vor ${a}h`:"";n.innerHTML="",n.appendChild(tr(e.os>0?`OS: ${e.os} Updates`:i?"OS: ?":"OS: aktuell",e.os>0||i?"warn":"ok","server",e.os>0?`${e.os} Pakete${l}`:i?`apt-Cache veraltet (${a}h)`:`Keine Updates${l}`)),n.appendChild(tr(e.engine>0?"Engine: Update":"Engine: aktuell",e.engine>0?"warn":"ok","server")),n.appendChild(tr(e.models>0?`Modelle: ${e.models}`:"Modelle: aktuell",e.models>0?"warn":"ok","news"))}catch{}}async function Vi(){try{ts(await Se("/api/status"))}catch{ts(null)}}async function al(){try{Au(await Se("/api/jobs"))}catch{}}function il(){const e=window.location.protocol==="https:"?"wss:":"ws:",n=new WebSocket(`${e}//${window.location.host}/api/system/stream`);n.onmessage=a=>{try{Cu(JSON.parse(a.data))}catch{}},n.onclose=()=>{setTimeout(il,3e3)},n.onerror=()=>n.close()}var os;((os=document.getElementById("logo"))==null?void 0:os.innerHTML)!==void 0&&(document.getElementById("logo").innerHTML=Gi.logo);document.querySelectorAll("[data-ic]").forEach(e=>{e.innerHTML=Gi[e.dataset.ic||""]||""});const Pu=[["overview",ud],["models",Ed],["activity",Od],["server",jd],["cookbook",Tc],["connect",Qc],["news",su],["guides",pu],["memory",Su]];for(const[e,n]of Pu){const a=document.querySelector(`.view[data-view="${e}"]`);a&&So(n,{target:a})}Uo("overview");const nr=document.getElementById("token");nr&&(nr.value=tl(),nr.addEventListener("change",e=>{No(e.target.value),Vi()}));const ar=document.getElementById("hf-token");ar&&(ar.value=li(),ar.addEventListener("change",e=>Go(e.target.value)));const as=document.getElementById("nav-settings"),ir=document.getElementById("settings-modal"),is=document.getElementById("sm-close");as&&ir&&is&&(as.addEventListener("click",()=>ir.style.display="flex"),is.addEventListener("click",()=>ir.style.display="none"));function Du(){const e=document.getElementById("clock");e&&(e.textContent=new Date().toTimeString().slice(0,5))}document.addEventListener("mc:refresh",Vi);Vi();al();il();setInterval(Du,1e3);setInterval(Vi,3e3);setInterval(al,1500);nl();setInterval(nl,6e4);
|