701476179e
- Profi-Suche: HF-Suche mit &full=true (liefert Tags); Multi-Capability-Chips (Code/Bild/Logik/MoE·aktiv/Tools(yes|likely)/Chat) aus Name + HF-Tags. - Facetten-Filter (Mehrfachauswahl: Tools/MoE/Logik/Bild/Code) statt Einzel-Kategorie — clientseitig auf den Treffern (Index für Fit/Best bleibt). - Discover: dieselben Chips; Backend liefert HF-Tags je Modell mit. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
666 lines
218 KiB
JavaScript
666 lines
218 KiB
JavaScript
var pl=Object.defineProperty;var Fr=e=>{throw TypeError(e)};var fl=(e,n,a)=>n in e?pl(e,n,{enumerable:!0,configurable:!0,writable:!0,value:a}):e[n]=a;var vn=(e,n,a)=>fl(e,typeof n!="symbol"?n+"":n,a),Xi=(e,n,a)=>n.has(e)||Fr("Cannot "+a);var m=(e,n,a)=>(Xi(e,n,"read from private field"),a?a.call(e):n.get(e)),Ke=(e,n,a)=>n.has(e)?Fr("Cannot add the same private member more than once"):n instanceof WeakSet?n.add(e):n.set(e,a),Re=(e,n,a,s)=>(Xi(e,n,"write to private field"),s?s.call(e,a):n.set(e,a),a),rt=(e,n,a)=>(Xi(e,n,"access private method"),a);var Er=Array.isArray,hl=Array.prototype.indexOf,Ii=Array.prototype.includes,Gi=Array.from,gl=Object.defineProperty,si=Object.getOwnPropertyDescriptor,ml=Object.getOwnPropertyDescriptors,bl=Object.prototype,_l=Array.prototype,ms=Object.getPrototypeOf,Kr=Object.isExtensible;const yl=()=>{};function xl(e){for(var n=0;n<e.length;n++)e[n]()}function bs(){var e,n,a=new Promise((s,l)=>{e=s,n=l});return{promise:a,resolve:e,reject:n}}function Bn(e,n){if(Array.isArray(e))return e;if(n===void 0||!(Symbol.iterator in e))return Array.from(e);const a=[];for(const s of e)if(a.push(s),a.length===n)break;return a}const Yt=2,Ga=4,Vi=8,_s=1<<24,zn=16,Pn=32,oa=64,ur=128,Sn=512,Vt=1024,Qt=2048,Nn=4096,an=8192,Mn=16384,Ja=32768,pr=1<<25,Va=65536,Li=1<<17,kl=1<<18,Qa=1<<19,wl=1<<20,Rn=1<<25,Aa=65536,Oi=1<<21,Ia=1<<22,la=1<<23,La=Symbol("$state"),Sl=Symbol(""),Ci=Symbol("attributes"),fr=Symbol("class"),hr=Symbol("style"),ti=Symbol("text"),Ti=Symbol("form reset"),Wi=new class extends Error{constructor(){super(...arguments);vn(this,"name","StaleReactionError");vn(this,"message","The reaction that called `getAbortSignal()` was re-run or destroyed")}};var ps;const Ml=!!((ps=globalThis.document)!=null&&ps.contentType)&&globalThis.document.contentType.includes("xml");function ys(e){throw new Error("https://svelte.dev/e/lifecycle_outside_component")}function El(){throw new Error("https://svelte.dev/e/async_derived_orphan")}function Al(e,n,a){throw new Error("https://svelte.dev/e/each_key_duplicate")}function Cl(e){throw new Error("https://svelte.dev/e/effect_in_teardown")}function Tl(){throw new Error("https://svelte.dev/e/effect_in_unowned_derived")}function zl(e){throw new Error("https://svelte.dev/e/effect_orphan")}function $l(){throw new Error("https://svelte.dev/e/effect_update_depth_exceeded")}function Pl(){throw new Error("https://svelte.dev/e/state_descriptors_fixed")}function Dl(){throw new Error("https://svelte.dev/e/state_prototype_fixed")}function Il(){throw new Error("https://svelte.dev/e/state_unsafe_mutation")}function Ll(){throw new Error("https://svelte.dev/e/svelte_boundary_reset_onerror")}const Ol=1,Bl=2,xs=4,Rl=8,Fl=16,Kl=1,Nl=2,Gt=Symbol("uninitialized"),ks="http://www.w3.org/1999/xhtml",ql="http://www.w3.org/2000/svg",Gl="http://www.w3.org/1998/Math/MathML";function Vl(){console.warn("https://svelte.dev/e/derived_inert")}function Wl(){console.warn("https://svelte.dev/e/select_multiple_invalid_value")}function jl(){console.warn("https://svelte.dev/e/svelte_boundary_reset_noop")}function ws(e){return e===this.v}function Ul(e,n){return e!=e?n==n:e!==n||e!==null&&typeof e=="object"||typeof e=="function"}function Ss(e){return!Ul(e,this.v)}let Zt=null;function Wa(e){Zt=e}function Dn(e,n=!1,a){Zt={p:Zt,i:!1,c:null,e:null,s:e,x:null,r:Ye,l:null}}function In(e){var n=Zt,a=n.e;if(a!==null){n.e=null;for(var s of a)js(s)}return n.i=!0,Zt=n.p,{}}function Ms(){return!0}let pa=[];function Es(){var e=pa;pa=[],xl(e)}function ka(e){if(pa.length===0&&!oi){var n=pa;queueMicrotask(()=>{n===pa&&Es()})}pa.push(e)}function Hl(){for(;pa.length>0;)Es()}function As(e){var n=Ye;if(n===null)return Je.f|=la,e;if((n.f&Ja)===0&&(n.f&Ga)===0)throw e;ra(e,n)}function ra(e,n){if(!(n!==null&&(n.f&Mn)!==0)){for(;n!==null;){if((n.f&ur)!==0){if((n.f&Ja)===0)throw e;try{n.b.error(e);return}catch(a){e=a}}n=n.parent}throw e}}const Jl=-7169;function Bt(e,n){e.f=e.f&Jl|n}function Ar(e){(e.f&Sn)!==0||e.deps===null?Bt(e,Vt):Bt(e,Nn)}function Cs(e){if(e!==null)for(const n of e)(n.f&Yt)===0||(n.f&Aa)===0||(n.f^=Aa,Cs(n.deps))}function Ts(e,n,a){(e.f&Qt)!==0?n.add(e):(e.f&Nn)!==0&&a.add(e),Cs(e.deps),Bt(e,Vt)}function Ql(e){let n=0,a=Ta(0),s;return()=>{Ir()&&(t(a),ji(()=>(n===0&&(s=Za(()=>e(()=>di(a)))),n+=1,()=>{ka(()=>{n-=1,n===0&&(s==null||s(),s=void 0,di(a))})})))}}var Zl=Va|Qa;function Yl(e,n,a,s){new Xl(e,n,a,s)}var yn,Mr,xn,ma,rn,kn,nn,pn,Wn,ba,aa,Oa,hi,gi,jn,Ki,It,eo,to,no,gr,zi,$i,mr,br;class Xl{constructor(n,a,s,l){Ke(this,It);vn(this,"parent");vn(this,"is_pending",!1);vn(this,"transform_error");Ke(this,yn);Ke(this,Mr,null);Ke(this,xn);Ke(this,ma);Ke(this,rn);Ke(this,kn,null);Ke(this,nn,null);Ke(this,pn,null);Ke(this,Wn,null);Ke(this,ba,0);Ke(this,aa,0);Ke(this,Oa,!1);Ke(this,hi,new Set);Ke(this,gi,new Set);Ke(this,jn,null);Ke(this,Ki,Ql(()=>(Re(this,jn,Ta(m(this,ba))),()=>{Re(this,jn,null)})));var o;Re(this,yn,n),Re(this,xn,a),Re(this,ma,d=>{var v=Ye;v.b=this,v.f|=ur,s(d)}),this.parent=Ye.b,this.transform_error=l??((o=this.parent)==null?void 0:o.transform_error)??(d=>d),Re(this,rn,Lr(()=>{rt(this,It,gr).call(this)},Zl))}defer_effect(n){Ts(n,m(this,hi),m(this,gi))}is_rendered(){return!this.is_pending&&(!this.parent||this.parent.is_rendered())}has_pending_snippet(){return!!m(this,xn).pending}update_pending_count(n,a){rt(this,It,mr).call(this,n,a),Re(this,ba,m(this,ba)+n),!(!m(this,jn)||m(this,Oa))&&(Re(this,Oa,!0),ka(()=>{Re(this,Oa,!1),m(this,jn)&&ja(m(this,jn),m(this,ba))}))}get_effect_pending(){return m(this,Ki).call(this),t(m(this,jn))}error(n){if(!m(this,xn).onerror&&!m(this,xn).failed)throw n;me!=null&&me.is_fork?(m(this,kn)&&me.skip_effect(m(this,kn)),m(this,nn)&&me.skip_effect(m(this,nn)),m(this,pn)&&me.skip_effect(m(this,pn)),me.oncommit(()=>{rt(this,It,br).call(this,n)})):rt(this,It,br).call(this,n)}}yn=new WeakMap,Mr=new WeakMap,xn=new WeakMap,ma=new WeakMap,rn=new WeakMap,kn=new WeakMap,nn=new WeakMap,pn=new WeakMap,Wn=new WeakMap,ba=new WeakMap,aa=new WeakMap,Oa=new WeakMap,hi=new WeakMap,gi=new WeakMap,jn=new WeakMap,Ki=new WeakMap,It=new WeakSet,eo=function(){try{Re(this,kn,wn(()=>m(this,ma).call(this,m(this,yn))))}catch(n){this.error(n)}},to=function(n){const a=m(this,xn).failed;a&&Re(this,pn,wn(()=>{a(m(this,yn),()=>n,()=>()=>{})}))},no=function(){const n=m(this,xn).pending;n&&(this.is_pending=!0,Re(this,nn,wn(()=>n(m(this,yn)))),ka(()=>{var a=Re(this,Wn,document.createDocumentFragment()),s=Qn();a.append(s),Re(this,kn,rt(this,It,$i).call(this,()=>wn(()=>m(this,ma).call(this,s)))),m(this,aa)===0&&(m(this,yn).before(a),Re(this,Wn,null),Sa(m(this,nn),()=>{Re(this,nn,null)}),rt(this,It,zi).call(this,me))}))},gr=function(){try{if(this.is_pending=this.has_pending_snippet(),Re(this,aa,0),Re(this,ba,0),Re(this,kn,wn(()=>{m(this,ma).call(this,m(this,yn))})),m(this,aa)>0){var n=Re(this,Wn,document.createDocumentFragment());Br(m(this,kn),n);const a=m(this,xn).pending;Re(this,nn,wn(()=>a(m(this,yn))))}else rt(this,It,zi).call(this,me)}catch(a){this.error(a)}},zi=function(n){this.is_pending=!1,n.transfer_effects(m(this,hi),m(this,gi))},$i=function(n){var a=Ye,s=Je,l=Zt;qn(m(this,rn)),En(m(this,rn)),Wa(m(this,rn).ctx);try{return Ca.ensure(),n()}catch(o){return As(o),null}finally{qn(a),En(s),Wa(l)}},mr=function(n,a){var s;if(!this.has_pending_snippet()){this.parent&&rt(s=this.parent,It,mr).call(s,n,a);return}Re(this,aa,m(this,aa)+n),m(this,aa)===0&&(rt(this,It,zi).call(this,a),m(this,nn)&&Sa(m(this,nn),()=>{Re(this,nn,null)}),m(this,Wn)&&(m(this,yn).before(m(this,Wn)),Re(this,Wn,null)))},br=function(n){m(this,kn)&&(dn(m(this,kn)),Re(this,kn,null)),m(this,nn)&&(dn(m(this,nn)),Re(this,nn,null)),m(this,pn)&&(dn(m(this,pn)),Re(this,pn,null));var a=m(this,xn).onerror;let s=m(this,xn).failed;var l=!1,o=!1;const d=()=>{if(l){jl();return}l=!0,o&&Ll(),m(this,pn)!==null&&Sa(m(this,pn),()=>{Re(this,pn,null)}),rt(this,It,$i).call(this,()=>{rt(this,It,gr).call(this)})},v=c=>{try{o=!0,a==null||a(c,d),o=!1}catch(f){ra(f,m(this,rn)&&m(this,rn).parent)}s&&Re(this,pn,rt(this,It,$i).call(this,()=>{try{return wn(()=>{var f=Ye;f.b=this,f.f|=ur,s(m(this,yn),()=>c,()=>d)})}catch(f){return ra(f,m(this,rn).parent),null}}))};ka(()=>{var c;try{c=this.transform_error(n)}catch(f){ra(f,m(this,rn)&&m(this,rn).parent);return}c!==null&&typeof c=="object"&&typeof c.then=="function"?c.then(v,f=>ra(f,m(this,rn)&&m(this,rn).parent)):v(c)})};function ao(e,n,a,s){const l=Cr;var o=e.filter(x=>!x.settled),d=n.map(l);if(a.length===0&&o.length===0){s(d);return}var v=Ye,c=io(),f=o.length===1?o[0].promise:o.length>1?Promise.all(o.map(x=>x.promise)):null;function b(x){if((v.f&Mn)===0){c();try{s([...d,...x])}catch($){ra($,v)}Bi()}}var T=zs();if(a.length===0){f.then(()=>b([])).finally(T);return}function _(){Promise.all(a.map(x=>ro(x))).then(b).catch(x=>ra(x,v)).finally(T)}f?f.then(()=>{c(),_(),Bi()}):_()}function io(){var e=Ye,n=Je,a=Zt,s=me;return function(o=!0){qn(e),En(n),Wa(a),o&&(e.f&Mn)===0&&(s==null||s.activate(),s==null||s.apply())}}function Bi(e=!0){qn(null),En(null),Wa(null),e&&(me==null||me.deactivate())}function zs(){var e=Ye,n=e.b,a=me,s=!!(n!=null&&n.is_rendered());return n==null||n.update_pending_count(1,a),a.increment(s,e),()=>{n==null||n.update_pending_count(-1,a),a.decrement(s,e)}}function Cr(e){var n=Yt|Qt;return Ye!==null&&(Ye.f|=Qa),{ctx:Zt,deps:null,effects:null,equals:ws,f:n,fn:e,reactions:null,rv:0,v:Gt,wv:0,parent:Ye,ac:null}}const ni=Symbol("obsolete");function ro(e,n,a){let s=Ye;s===null&&El();var l=void 0,o=Ta(Gt),d=!Je,v=new Set;return wo(()=>{var x,$;var c=Ye,f=bs();l=f.promise;try{Promise.resolve(e()).then(f.resolve,R=>{R!==Wi&&f.reject(R)}).finally(Bi)}catch(R){f.reject(R),Bi()}var b=me;if(d){if((c.f&Ja)!==0)var T=zs();if((x=s.b)!=null&&x.is_rendered())($=b.async_deriveds.get(c))==null||$.reject(ni);else for(const R of v.values())R.reject(ni);v.add(f),b.async_deriveds.set(c,f)}const _=(R,A=void 0)=>{T==null||T(),v.delete(f),A!==ni&&(b.activate(),A?(o.f|=la,ja(o,A)):((o.f&la)!==0&&(o.f^=la),ja(o,R)),b.deactivate())};f.promise.then(_,R=>_(null,R||"unknown"))}),Ws(()=>{for(const c of v)c.reject(ni)}),new Promise(c=>{function f(b){function T(){b===l?c(o):f(l)}b.then(T,T)}f(l)})}function V(e){const n=Cr(e);return Xs(n),n}function so(e){const n=Cr(e);return n.equals=Ss,n}function lo(e){var n=e.effects;if(n!==null){e.effects=null;for(var a=0;a<n.length;a+=1)dn(n[a])}}function Tr(e){var n,a=Ye,s=e.parent;if(!da&&s!==null&&e.v!==Gt&&(s.f&(Mn|an))!==0)return Vl(),e.v;qn(s);try{e.f&=~Aa,lo(e),n=al(e)}finally{qn(a)}return n}function $s(e){var n=Tr(e);if(!e.equals(n)&&(e.wv=tl(),(!(me!=null&&me.is_fork)||e.deps===null)&&(me!==null?(me.capture(e,n,!0),li==null||li.capture(e,n,!0)):e.v=n,e.deps===null))){Bt(e,Vt);return}da||(Jt!==null?(Ir()||me!=null&&me.is_fork)&&Jt.set(e,n):Ar(e))}function oo(e){var n,a;if(e.effects!==null)for(const s of e.effects)(s.teardown||s.ac)&&((n=s.teardown)==null||n.call(s),(a=s.ac)==null||a.abort(Wi),s.fn!==null&&(s.teardown=yl),s.ac=null,pi(s,0),Or(s))}function Ps(e){if(e.effects!==null)for(const n of e.effects)n.teardown&&n.fn!==null&&Ua(n)}let er=null,$a=null,me=null,li=null,Jt=null,_r=null,oi=!1,tr=!1,Da=null,Pi=null;var Nr=0;let co=1;var Ba,ia,_a,Ra,Fa,Ka,Un,Na,sn,mi,Hn,Cn,Ln,qa,ya,gt,yr,ai,xr,Ds,Is,Pa,vo,ii;const Ni=class Ni{constructor(){Ke(this,gt);vn(this,"id",co++);Ke(this,Ba,!1);vn(this,"linked",!0);Ke(this,ia,null);Ke(this,_a,null);vn(this,"async_deriveds",new Map);vn(this,"current",new Map);vn(this,"previous",new Map);Ke(this,Ra,new Set);Ke(this,Fa,new Set);Ke(this,Ka,0);Ke(this,Un,new Map);Ke(this,Na,null);Ke(this,sn,[]);Ke(this,mi,[]);Ke(this,Hn,new Set);Ke(this,Cn,new Set);Ke(this,Ln,new Map);Ke(this,qa,new Set);vn(this,"is_fork",!1);Ke(this,ya,!1);$a===null?er=$a=this:(Re($a,_a,this),Re(this,ia,$a)),$a=this}skip_effect(n){m(this,Ln).has(n)||m(this,Ln).set(n,{d:[],m:[]}),m(this,qa).delete(n)}unskip_effect(n,a=s=>this.schedule(s)){var s=m(this,Ln).get(n);if(s){m(this,Ln).delete(n);for(var l of s.d)Bt(l,Qt),a(l);for(l of s.m)Bt(l,Nn),a(l)}m(this,qa).add(n)}capture(n,a,s=!1){n.v!==Gt&&!this.previous.has(n)&&this.previous.set(n,n.v),(n.f&la)===0&&(this.current.set(n,[a,s]),Jt==null||Jt.set(n,a)),this.is_fork||(n.v=a)}activate(){me=this}deactivate(){me=null,Jt=null}flush(){try{tr=!0,me=this,rt(this,gt,ai).call(this)}finally{Nr=0,_r=null,Da=null,Pi=null,tr=!1,me=null,Jt=null,wa.clear()}}discard(){var n;for(const a of m(this,Fa))a(this);m(this,Fa).clear();for(const a of this.async_deriveds.values())a.reject(ni);rt(this,gt,ii).call(this),(n=m(this,Na))==null||n.resolve()}register_created_effect(n){m(this,mi).push(n)}increment(n,a){if(Re(this,Ka,m(this,Ka)+1),n){let s=m(this,Un).get(a)??0;m(this,Un).set(a,s+1)}}decrement(n,a){if(Re(this,Ka,m(this,Ka)-1),n){let s=m(this,Un).get(a)??0;s===1?m(this,Un).delete(a):m(this,Un).set(a,s-1)}m(this,ya)||(Re(this,ya,!0),ka(()=>{Re(this,ya,!1),this.linked&&this.flush()}))}transfer_effects(n,a){for(const s of n)m(this,Hn).add(s);for(const s of a)m(this,Cn).add(s);n.clear(),a.clear()}oncommit(n){m(this,Ra).add(n)}ondiscard(n){m(this,Fa).add(n)}settled(){return(m(this,Na)??Re(this,Na,bs())).promise}static ensure(){if(me===null){const n=me=new Ni;!tr&&!oi&&ka(()=>{m(n,Ba)||n.flush()})}return me}apply(){{Jt=null;return}}schedule(n){var l;if(_r=n,(l=n.b)!=null&&l.is_pending&&(n.f&(Ga|Vi|_s))!==0&&(n.f&Ja)===0){n.b.defer_effect(n);return}for(var a=n;a.parent!==null;){a=a.parent;var s=a.f;if(Da!==null&&a===Ye&&(Je===null||(Je.f&Yt)===0))return;if((s&(oa|Pn))!==0){if((s&Vt)===0)return;a.f^=Vt}}m(this,sn).push(a)}};Ba=new WeakMap,ia=new WeakMap,_a=new WeakMap,Ra=new WeakMap,Fa=new WeakMap,Ka=new WeakMap,Un=new WeakMap,Na=new WeakMap,sn=new WeakMap,mi=new WeakMap,Hn=new WeakMap,Cn=new WeakMap,Ln=new WeakMap,qa=new WeakMap,ya=new WeakMap,gt=new WeakSet,yr=function(){if(this.is_fork)return!0;for(const s of m(this,Un).keys()){for(var n=s,a=!1;n.parent!==null;){if(m(this,Ln).has(n)){a=!0;break}n=n.parent}if(!a)return!0}return!1},ai=function(){var c,f,b,T;Re(this,Ba,!0),Nr++>1e3&&(rt(this,gt,ii).call(this),po());for(const _ of m(this,Hn))m(this,Cn).delete(_),Bt(_,Qt),this.schedule(_);for(const _ of m(this,Cn))Bt(_,Nn),this.schedule(_);const n=m(this,sn);Re(this,sn,[]),this.apply();var a=Da=[],s=[],l=Pi=[];for(const _ of n)try{rt(this,gt,xr).call(this,_,a,s)}catch(x){throw Bs(_),rt(this,gt,yr).call(this)||this.discard(),x}if(me=null,l.length>0){var o=Ni.ensure();for(const _ of l)o.schedule(_)}if(Da=null,Pi=null,rt(this,gt,yr).call(this)){rt(this,gt,Pa).call(this,s),rt(this,gt,Pa).call(this,a);for(const[_,x]of m(this,Ln))Os(_,x);l.length>0&&rt(c=me,gt,ai).call(c);return}const d=rt(this,gt,Ds).call(this);if(d){rt(this,gt,Pa).call(this,s),rt(this,gt,Pa).call(this,a),rt(f=d,gt,Is).call(f,this);return}m(this,Hn).clear(),m(this,Cn).clear();for(const _ of m(this,Ra))_(this);m(this,Ra).clear(),li=this,qr(s),qr(a),li=null,(b=m(this,Na))==null||b.resolve();var v=me;if(m(this,Ka)===0&&(m(this,sn).length===0||v!==null)&&rt(this,gt,ii).call(this),m(this,sn).length>0)if(v!==null){const _=v;m(_,sn).push(...m(this,sn).filter(x=>!m(_,sn).includes(x)))}else v=this;v!==null&&rt(T=v,gt,ai).call(T)},xr=function(n,a,s){n.f^=Vt;for(var l=n.first;l!==null;){var o=l.f,d=(o&(Pn|oa))!==0,v=d&&(o&Vt)!==0,c=v||(o&an)!==0||m(this,Ln).has(l);if(!c&&l.fn!==null){d?l.f^=Vt:(o&Ga)!==0?a.push(l):ki(l)&&((o&zn)!==0&&m(this,Cn).add(l),Ua(l));var f=l.first;if(f!==null){l=f;continue}}for(;l!==null;){var b=l.next;if(b!==null){l=b;break}l=l.parent}}},Ds=function(){for(var n=m(this,ia);n!==null;){if(!n.is_fork){for(const[a,[,s]]of this.current)if(n.current.has(a)&&!s)return n}n=m(n,ia)}return null},Is=function(n){var s;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(m(n,Hn),m(n,Cn));const a=l=>{var o=l.reactions;if(o!==null)for(const c of o){var d=c.f;if((d&Yt)!==0)a(c);else{var v=c;d&(Ia|zn)&&!this.async_deriveds.has(v)&&(m(this,Cn).delete(v),Bt(v,Qt),this.schedule(v))}}};for(const l of this.current.keys())a(l);this.oncommit(()=>n.discard()),rt(s=n,gt,ii).call(s),me=this,rt(this,gt,ai).call(this)},Pa=function(n){for(var a=0;a<n.length;a+=1)Ts(n[a],m(this,Hn),m(this,Cn))},vo=function(){var T;for(let _=er;_!==null;_=m(_,_a)){var n=_.id<this.id,a=[];for(const[x,[$,R]]of this.current){if(_.current.has(x)){var s=_.current.get(x)[0];if(n&&$!==s)_.current.set(x,[$,R]);else continue}a.push(x)}if(n)for(const[x,$]of this.async_deriveds){const R=_.async_deriveds.get(x);R&&$.promise.then(R.resolve).catch(R.reject)}var l=[..._.current.keys()].filter(x=>!_.current.get(x)[1]);if(!(!m(_,Ba)||l.length===0)){var o=l.filter(x=>!this.current.has(x));if(o.length===0)n&&_.discard();else if(a.length>0){if(n)for(const x of m(this,qa))_.unskip_effect(x,$=>{var R;($.f&(zn|Ia))!==0?_.schedule($):rt(R=_,gt,Pa).call(R,[$])});_.activate();var d=new Set,v=new Map;for(var c of a)Ls(c,o,d,v);v=new Map;var f=[..._.current].filter(([x,$])=>{const R=this.current.get(x);return R?R[0]!==$[0]||R[1]!==$[1]:!0}).map(([x])=>x);if(f.length>0)for(const x of m(this,mi))(x.f&(Mn|an|Li))===0&&zr(x,f,v)&&((x.f&(Ia|zn))!==0?(Bt(x,Qt),_.schedule(x)):m(_,Hn).add(x));if(m(_,sn).length>0&&!m(_,ya)){_.apply();for(var b of m(_,sn))rt(T=_,gt,xr).call(T,b,[],[]);Re(_,sn,[])}_.deactivate()}}}},ii=function(){if(this.linked){var n=m(this,ia),a=m(this,_a);n===null?er=a:Re(n,_a,a),a===null?$a=n:Re(a,ia,n),this.linked=!1}};let Ca=Ni;function uo(e){var n=oi;oi=!0;try{for(var a;;){if(Hl(),me===null)return a;me.flush()}}finally{oi=n}}function po(){try{$l()}catch(e){ra(e,_r)}}let An=null;function qr(e){var n=e.length;if(n!==0){for(var a=0;a<n;){var s=e[a++];if((s.f&(Mn|an))===0&&ki(s)&&(An=new Set,Ua(s),s.deps===null&&s.first===null&&s.nodes===null&&s.teardown===null&&s.ac===null&&Qs(s),(An==null?void 0:An.size)>0)){wa.clear();for(const l of An){if((l.f&(Mn|an))!==0)continue;const o=[l];let d=l.parent;for(;d!==null;)An.has(d)&&(An.delete(d),o.push(d)),d=d.parent;for(let v=o.length-1;v>=0;v--){const c=o[v];(c.f&(Mn|an))===0&&Ua(c)}}An.clear()}}An=null}}function Ls(e,n,a,s){if(!a.has(e)&&(a.add(e),e.reactions!==null))for(const l of e.reactions){const o=l.f;(o&Yt)!==0?Ls(l,n,a,s):(o&(Ia|zn))!==0&&(o&Qt)===0&&zr(l,n,s)&&(Bt(l,Qt),$r(l))}}function zr(e,n,a){const s=a.get(e);if(s!==void 0)return s;if(e.deps!==null)for(const l of e.deps){if(Ii.call(n,l))return!0;if((l.f&Yt)!==0&&zr(l,n,a))return a.set(l,!0),!0}return a.set(e,!1),!1}function $r(e){me.schedule(e)}function Os(e,n){if(!((e.f&Pn)!==0&&(e.f&Vt)!==0)){(e.f&Qt)!==0?n.d.push(e):(e.f&Nn)!==0&&n.m.push(e),Bt(e,Vt);for(var a=e.first;a!==null;)Os(a,n),a=a.next}}function Bs(e){Bt(e,Vt);for(var n=e.first;n!==null;)Bs(n),n=n.next}let Ri=new Set;const wa=new Map;let Rs=!1;function Ta(e,n){var a={f:0,v:e,reactions:null,equals:ws,rv:0,wv:0};return a}function B(e,n){const a=Ta(e);return Xs(a),a}function fo(e,n=!1,a=!0){const s=Ta(e);return n||(s.equals=Ss),s}function u(e,n,a=!1){Je!==null&&(!$n||(Je.f&Li)!==0)&&Ms()&&(Je.f&(Yt|zn|Ia|Li))!==0&&(Fn===null||!Fn.has(e))&&Il();let s=a?Rt(n):n;return ja(e,s,Pi)}function ja(e,n,a=null){if(!e.equals(n)){wa.set(e,da?n:e.v);var s=Ca.ensure();if(s.capture(e,n),(e.f&Yt)!==0){const l=e;(e.f&Qt)!==0&&Tr(l),Jt===null&&Ar(l)}e.wv=tl(),Fs(e,Qt,a),Ye!==null&&(Ye.f&Vt)!==0&&(Ye.f&(Pn|oa))===0&&(_n===null?Mo([e]):_n.push(e)),!s.is_fork&&Ri.size>0&&!Rs&&ho()}return n}function ho(){Rs=!1;for(const e of Ri){(e.f&Vt)!==0&&Bt(e,Nn);let n;try{n=ki(e)}catch{n=!0}n&&Ua(e)}Ri.clear()}function di(e){u(e,e.v+1)}function Fs(e,n,a){var s=e.reactions;if(s!==null)for(var l=s.length,o=0;o<l;o++){var d=s[o],v=d.f,c=(v&Qt)===0;if(c&&Bt(d,n),(v&Li)!==0)Ri.add(d);else if((v&Yt)!==0){var f=d;Jt==null||Jt.delete(f),(v&Aa)===0&&(v&Sn&&(Ye===null||(Ye.f&Oi)===0)&&(d.f|=Aa),Fs(f,Nn,a))}else if(c){var b=d;(v&zn)!==0&&An!==null&&An.add(b),a!==null?a.push(b):$r(b)}}}function Rt(e){if(typeof e!="object"||e===null||La in e)return e;const n=ms(e);if(n!==bl&&n!==_l)return e;var a=new Map,s=Er(e),l=B(0),o=Ma,d=v=>{if(Ma===o)return v();var c=Je,f=Ma;En(null),Ur(o);var b=v();return En(c),Ur(f),b};return s&&a.set("length",B(e.length)),new Proxy(e,{defineProperty(v,c,f){(!("value"in f)||f.configurable===!1||f.enumerable===!1||f.writable===!1)&&Pl();var b=a.get(c);return b===void 0?d(()=>{var T=B(f.value);return a.set(c,T),T}):u(b,f.value,!0),!0},deleteProperty(v,c){var f=a.get(c);if(f===void 0){if(c in v){const b=d(()=>B(Gt));a.set(c,b),di(l)}}else u(f,Gt),di(l);return!0},get(v,c,f){var x;if(c===La)return e;var b=a.get(c),T=c in v;if(b===void 0&&(!T||(x=si(v,c))!=null&&x.writable)&&(b=d(()=>{var $=Rt(T?v[c]:Gt),R=B($);return R}),a.set(c,b)),b!==void 0){var _=t(b);return _===Gt?void 0:_}return Reflect.get(v,c,f)},getOwnPropertyDescriptor(v,c){var f=Reflect.getOwnPropertyDescriptor(v,c);if(f&&"value"in f){var b=a.get(c);b&&(f.value=t(b))}else if(f===void 0){var T=a.get(c),_=T==null?void 0:T.v;if(T!==void 0&&_!==Gt)return{enumerable:!0,configurable:!0,value:_,writable:!0}}return f},has(v,c){var _;if(c===La)return!0;var f=a.get(c),b=f!==void 0&&f.v!==Gt||Reflect.has(v,c);if(f!==void 0||Ye!==null&&(!b||(_=si(v,c))!=null&&_.writable)){f===void 0&&(f=d(()=>{var x=b?Rt(v[c]):Gt,$=B(x);return $}),a.set(c,f));var T=t(f);if(T===Gt)return!1}return b},set(v,c,f,b){var Me;var T=a.get(c),_=c in v;if(s&&c==="length")for(var x=f;x<T.v;x+=1){var $=a.get(x+"");$!==void 0?u($,Gt):x in v&&($=d(()=>B(Gt)),a.set(x+"",$))}if(T===void 0)(!_||(Me=si(v,c))!=null&&Me.writable)&&(T=d(()=>B(void 0)),u(T,Rt(f)),a.set(c,T));else{_=T.v!==Gt;var R=d(()=>Rt(f));u(T,R)}var A=Reflect.getOwnPropertyDescriptor(v,c);if(A!=null&&A.set&&A.set.call(b,f),!_){if(s&&typeof c=="string"){var N=a.get("length"),Pe=Number(c);Number.isInteger(Pe)&&Pe>=N.v&&u(N,Pe+1)}di(l)}return!0},ownKeys(v){t(l);var c=Reflect.ownKeys(v).filter(T=>{var _=a.get(T);return _===void 0||_.v!==Gt});for(var[f,b]of a)b.v!==Gt&&!(f in v)&&c.push(f);return c},setPrototypeOf(){Dl()}})}function Gr(e){try{if(e!==null&&typeof e=="object"&&La in e)return e[La]}catch{}return e}function go(e,n){return Object.is(Gr(e),Gr(n))}var Vr,Ks,Ns,qs;function mo(){if(Vr===void 0){Vr=window,Ks=/Firefox/.test(navigator.userAgent);var e=Element.prototype,n=Node.prototype,a=Text.prototype;Ns=si(n,"firstChild").get,qs=si(n,"nextSibling").get,Kr(e)&&(e[fr]=void 0,e[Ci]=null,e[hr]=void 0,e.__e=void 0),Kr(a)&&(a[ti]=void 0)}}function Qn(e=""){return document.createTextNode(e)}function sa(e){return Ns.call(e)}function yi(e){return qs.call(e)}function r(e,n){return sa(e)}function tt(e,n=!1){{var a=sa(e);return a instanceof Comment&&a.data===""?yi(a):a}}function i(e,n=1,a=!1){let s=e;for(;n--;)s=yi(s);return s}function bo(e){e.textContent=""}function Gs(){return!1}function Vs(e,n,a){return n==null||n===ks?a?document.createElement(e,{is:a}):document.createElement(e):a?document.createElementNS(n,e,{is:a}):document.createElementNS(n,e)}let Wr=!1;function _o(){Wr||(Wr=!0,document.addEventListener("reset",e=>{Promise.resolve().then(()=>{var n;if(!e.defaultPrevented)for(const a of e.target.elements)(n=a[Ti])==null||n.call(a)})},{capture:!0}))}function Pr(e){var n=Je,a=Ye;En(null),qn(null);try{return e()}finally{En(n),qn(a)}}function Dr(e,n,a,s=a){e.addEventListener(n,()=>Pr(a));const l=e[Ti];l?e[Ti]=()=>{l(),s(!0)}:e[Ti]=()=>s(!0),_o()}function yo(e){Ye===null&&(Je===null&&zl(),Tl()),da&&Cl()}function xo(e,n){var a=n.last;a===null?n.last=n.first=e:(a.next=e,e.prev=a,n.last=e)}function Zn(e,n){var a=Ye;a!==null&&(a.f&an)!==0&&(e|=an);var s={ctx:Zt,deps:null,nodes:null,f:e|Qt|Sn,first:null,fn:n,last:null,next:null,parent:a,b:a&&a.b,prev:null,teardown:null,wv:0,ac:null};me==null||me.register_created_effect(s);var l=s;if((e&Ga)!==0)Da!==null?Da.push(s):Ca.ensure().schedule(s);else if(n!==null){try{Ua(s)}catch(d){throw dn(s),d}l.deps===null&&l.teardown===null&&l.nodes===null&&l.first===l.last&&(l.f&Qa)===0&&(l=l.first,(e&zn)!==0&&(e&Va)!==0&&l!==null&&(l.f|=Va))}if(l!==null&&(l.parent=a,a!==null&&xo(l,a),Je!==null&&(Je.f&Yt)!==0&&(e&oa)===0)){var o=Je;(o.effects??(o.effects=[])).push(l)}return s}function Ir(){return Je!==null&&!$n}function Ws(e){const n=Zn(Vi,null);return Bt(n,Vt),n.teardown=e,n}function xi(e){yo();var n=Ye.f,a=!Je&&(n&Pn)!==0&&Zt!==null&&!Zt.i;if(a){var s=Zt;(s.e??(s.e=[])).push(e)}else return js(e)}function js(e){return Zn(Ga|wl,e)}function ko(e){Ca.ensure();const n=Zn(oa|Qa,e);return(a={})=>new Promise(s=>{a.outro?Sa(n,()=>{dn(n),s(void 0)}):(dn(n),s(void 0))})}function Us(e){return Zn(Ga,e)}function wo(e){return Zn(Ia|Qa,e)}function ji(e,n=0){return Zn(Vi|n,e)}function z(e,n=[],a=[],s=[]){ao(s,n,a,l=>{Zn(Vi,()=>{e(...l.map(t))})})}function Lr(e,n=0){var a=Zn(zn|n,e);return a}function wn(e){return Zn(Pn|Qa,e)}function Hs(e){var n=e.teardown;if(n!==null){const a=da,s=Je;jr(!0),En(null);try{n.call(null)}finally{jr(a),En(s)}}}function Or(e,n=!1){var a=e.first;for(e.first=e.last=null;a!==null;){const l=a.ac;l!==null&&Pr(()=>{l.abort(Wi)});var s=a.next;(a.f&oa)!==0?a.parent=null:dn(a,n),a=s}}function So(e){for(var n=e.first;n!==null;){var a=n.next;(n.f&Pn)===0&&dn(n),n=a}}function dn(e,n=!0){var a=!1;(n||(e.f&kl)!==0)&&e.nodes!==null&&e.nodes.end!==null&&(Js(e.nodes.start,e.nodes.end),a=!0),e.f|=pr,Or(e,n&&!a),pi(e,0);var s=e.nodes&&e.nodes.t;if(s!==null)for(const o of s)o.stop();Hs(e),e.f^=pr,e.f|=Mn;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 Js(e,n){for(;e!==null;){var a=e===n?null:yi(e);e.remove(),e=a}}function Qs(e){var n=e.parent,a=e.prev,s=e.next;a!==null&&(a.next=s),s!==null&&(s.prev=a),n!==null&&(n.first===e&&(n.first=s),n.last===e&&(n.last=a))}function Sa(e,n,a=!0){var s=[];Zs(e,s,!0);var l=()=>{a&&dn(e),n&&n()},o=s.length;if(o>0){var d=()=>--o||l();for(var v of s)v.out(d)}else l()}function Zs(e,n,a){if((e.f&an)===0){e.f^=an;var s=e.nodes&&e.nodes.t;if(s!==null)for(const v of s)(v.is_global||a)&&n.push(v);for(var l=e.first;l!==null;){var o=l.next;if((l.f&oa)===0){var d=(l.f&Va)!==0||(l.f&Pn)!==0&&(e.f&zn)!==0;Zs(l,n,d?a:!1)}l=o}}}function Fi(e){Ys(e,!0)}function Ys(e,n){if((e.f&an)!==0){e.f^=an,(e.f&Vt)===0&&(Bt(e,Qt),Ca.ensure().schedule(e));for(var a=e.first;a!==null;){var s=a.next,l=(a.f&Va)!==0||(a.f&Pn)!==0;Ys(a,l?n:!1),a=s}var o=e.nodes&&e.nodes.t;if(o!==null)for(const d of o)(d.is_global||n)&&d.in()}}function Br(e,n){if(e.nodes)for(var a=e.nodes.start,s=e.nodes.end;a!==null;){var l=a===s?null:yi(a);n.append(a),a=l}}let Di=!1,da=!1;function jr(e){da=e}let Je=null,$n=!1;function En(e){Je=e}let Ye=null;function qn(e){Ye=e}let Fn=null;function Xs(e){Je!==null&&(Fn??(Fn=new Set)).add(e)}let ln=null,un=0,_n=null;function Mo(e){_n=e}let el=1,fa=0,Ma=fa;function Ur(e){Ma=e}function tl(){return++el}function ki(e){var n=e.f;if((n&Qt)!==0)return!0;if(n&Yt&&(e.f&=~Aa),(n&Nn)!==0){for(var a=e.deps,s=a.length,l=0;l<s;l++){var o=a[l];if(ki(o)&&$s(o),o.wv>e.wv)return!0}(n&Sn)!==0&&Jt===null&&Bt(e,Vt)}return!1}function nl(e,n,a=!0){var s=e.reactions;if(s!==null&&!(Fn!==null&&Fn.has(e)))for(var l=0;l<s.length;l++){var o=s[l];(o.f&Yt)!==0?nl(o,n,!1):n===o&&(a?Bt(o,Qt):(o.f&Vt)!==0&&Bt(o,Nn),$r(o))}}function al(e){var R;var n=ln,a=un,s=_n,l=Je,o=Fn,d=Zt,v=$n,c=Ma,f=e.f;ln=null,un=0,_n=null,Je=(f&(Pn|oa))===0?e:null,Fn=null,Wa(e.ctx),$n=!1,Ma=++fa,e.ac!==null&&(Pr(()=>{e.ac.abort(Wi)}),e.ac=null);try{e.f|=Oi;var b=e.fn,T=b();e.f|=Ja;var _=e.deps,x=me==null?void 0:me.is_fork;if(ln!==null){var $;if(x||pi(e,un),_!==null&&un>0)for(_.length=un+ln.length,$=0;$<ln.length;$++)_[un+$]=ln[$];else e.deps=_=ln;if(Ir()&&(e.f&Sn)!==0)for($=un;$<_.length;$++)((R=_[$]).reactions??(R.reactions=[])).push(e)}else!x&&_!==null&&un<_.length&&(pi(e,un),_.length=un);if(Ms()&&_n!==null&&!$n&&_!==null&&(e.f&(Yt|Nn|Qt))===0)for($=0;$<_n.length;$++)nl(_n[$],e);if(l!==null&&l!==e){if(fa++,l.deps!==null)for(let A=0;A<a;A+=1)l.deps[A].rv=fa;if(n!==null)for(const A of n)A.rv=fa;_n!==null&&(s===null?s=_n:s.push(..._n))}return(e.f&la)!==0&&(e.f^=la),T}catch(A){return As(A)}finally{e.f^=Oi,ln=n,un=a,_n=s,Je=l,Fn=o,Wa(d),$n=v,Ma=c}}function Eo(e,n){let a=n.reactions;if(a!==null){var s=hl.call(a,e);if(s!==-1){var l=a.length-1;l===0?a=n.reactions=null:(a[s]=a[l],a.pop())}}if(a===null&&(n.f&Yt)!==0&&(ln===null||!Ii.call(ln,n))){var o=n;(o.f&Sn)!==0&&(o.f^=Sn,o.f&=~Aa),o.v!==Gt&&Ar(o),oo(o),pi(o,0)}}function pi(e,n){var a=e.deps;if(a!==null)for(var s=n;s<a.length;s++)Eo(e,a[s])}function Ua(e){var n=e.f;if((n&Mn)===0){Bt(e,Vt);var a=Ye,s=Di;Ye=e,Di=!0;try{(n&(zn|_s))!==0?So(e):Or(e),Hs(e);var l=al(e);e.teardown=typeof l=="function"?l:null,e.wv=el;var o}finally{Di=s,Ye=a}}}async function Ao(){await Promise.resolve(),uo()}function t(e){var n=e.f,a=(n&Yt)!==0;if(Je!==null&&!$n){var s=Ye!==null&&(Ye.f&Mn)!==0;if(!s&&(Fn===null||!Fn.has(e))){var l=Je.deps;if((Je.f&Oi)!==0)e.rv<fa&&(e.rv=fa,ln===null&&l!==null&&l[un]===e?un++:ln===null?ln=[e]:ln.push(e));else{Je.deps??(Je.deps=[]),Ii.call(Je.deps,e)||Je.deps.push(e);var o=e.reactions;o===null?e.reactions=[Je]:Ii.call(o,Je)||o.push(Je)}}}if(da&&wa.has(e))return wa.get(e);if(a){var d=e;if(da){var v=d.v;return((d.f&Vt)===0&&d.reactions!==null||rl(d))&&(v=Tr(d)),wa.set(d,v),v}var c=(d.f&Sn)===0&&!$n&&Je!==null&&(Di||(Je.f&Sn)!==0),f=(d.f&Ja)===0;ki(d)&&(c&&(d.f|=Sn),$s(d)),c&&!f&&(Ps(d),il(d))}if(Jt!=null&&Jt.has(e))return Jt.get(e);if((e.f&la)!==0)throw e.v;return e.v}function il(e){if(e.f|=Sn,e.deps!==null)for(const n of e.deps)(n.reactions??(n.reactions=[])).push(e),(n.f&Yt)!==0&&(n.f&Sn)===0&&(Ps(n),il(n))}function rl(e){if(e.v===Gt)return!0;if(e.deps===null)return!1;for(const n of e.deps)if(wa.has(n)||(n.f&Yt)!==0&&rl(n))return!0;return!1}function Za(e){var n=$n;try{return $n=!0,e()}finally{$n=n}}const Co=["touchstart","touchmove"];function To(e){return Co.includes(e)}const ha=Symbol("events"),sl=new Set,kr=new Set;function S(e,n,a){(n[ha]??(n[ha]={}))[e]=a}function Gn(e){for(var n=0;n<e.length;n++)sl.add(e[n]);for(var a of kr)a(e)}let Hr=null;function Jr(e){var R,A;var n=this,a=n.ownerDocument,s=e.type,l=((R=e.composedPath)==null?void 0:R.call(e))||[],o=l[0]||e.target;Hr=e;var d=0,v=Hr===e&&e[ha];if(v){var c=l.indexOf(v);if(c!==-1&&(n===document||n===window)){e[ha]=n;return}var f=l.indexOf(n);if(f===-1)return;c<=f&&(d=c)}if(o=l[d]||e.target,o!==n){gl(e,"currentTarget",{configurable:!0,get(){return o||a}});var b=Je,T=Ye;En(null),qn(null);try{for(var _,x=[];o!==null&&o!==n;){try{var $=(A=o[ha])==null?void 0:A[s];$!=null&&(!o.disabled||e.target===o)&&$.call(o,e)}catch(N){_?x.push(N):_=N}if(e.cancelBubble)break;d++,o=d<l.length?l[d]:null}if(_){for(let N of x)queueMicrotask(()=>{throw N});throw _}}finally{e[ha]=n,delete e.currentTarget,En(b),qn(T)}}}var fs;const nr=((fs=globalThis==null?void 0:globalThis.window)==null?void 0:fs.trustedTypes)&&globalThis.window.trustedTypes.createPolicy("svelte-trusted-html",{createHTML:e=>e});function zo(e){return(nr==null?void 0:nr.createHTML(e))??e}function $o(e){var n=Vs("template");return n.innerHTML=zo(e.replaceAll("<!>","<!---->")),n.content}function Ha(e,n){var a=Ye;a.nodes===null&&(a.nodes={start:e,end:n,a:null,t:null})}function g(e,n){var a=(n&Kl)!==0,s=(n&Nl)!==0,l,o=!e.startsWith("<!>");return()=>{l===void 0&&(l=$o(o?e:"<!>"+e),a||(l=sa(l)));var d=s||Ks?document.importNode(l,!0):l.cloneNode(!0);if(a){var v=sa(d),c=d.lastChild;Ha(v,c)}else Ha(d,d);return d}}function ci(e=""){{var n=Qn(e+"");return Ha(n,n),n}}function Ea(){var e=document.createDocumentFragment(),n=document.createComment(""),a=Qn();return e.append(n,a),Ha(n,a),e}function p(e,n){e!==null&&e.before(n)}function h(e,n){var a=n==null?"":typeof n=="object"?`${n}`:n;a!==(e[ti]??(e[ti]=e.nodeValue))&&(e[ti]=a,e.nodeValue=`${a}`)}function Po(e,n){return Do(e,n)}const Ai=new Map;function Do(e,{target:n,anchor:a,props:s={},events:l,context:o,intro:d=!0,transformError:v}){mo();var c=void 0,f=ko(()=>{var b=a??n.appendChild(Qn());Yl(b,{pending:()=>{}},x=>{Dn({});var $=Zt;o&&($.c=o),l&&(s.$$events=l),c=e(x,s)||{},In()},v);var T=new Set,_=x=>{for(var $=0;$<x.length;$++){var R=x[$];if(!T.has(R)){T.add(R);var A=To(R);for(const Me of[n,document]){var N=Ai.get(Me);N===void 0&&(N=new Map,Ai.set(Me,N));var Pe=N.get(R);Pe===void 0?(Me.addEventListener(R,Jr,{passive:A}),N.set(R,1)):N.set(R,Pe+1)}}}};return _(Gi(sl)),kr.add(_),()=>{var A;for(var x of T)for(const N of[n,document]){var $=Ai.get(N),R=$.get(x);--R==0?(N.removeEventListener(x,Jr),$.delete(x),$.size===0&&Ai.delete(N)):$.set(x,R)}kr.delete(_),b!==a&&((A=b.parentNode)==null||A.removeChild(b))}});return Io.set(c,f),c}let Io=new WeakMap;var Tn,On,fn,xa,bi,_i,qi;class Lo{constructor(n,a=!0){vn(this,"anchor");Ke(this,Tn,new Map);Ke(this,On,new Map);Ke(this,fn,new Map);Ke(this,xa,new Set);Ke(this,bi,!0);Ke(this,_i,n=>{if(m(this,Tn).has(n)){var a=m(this,Tn).get(n),s=m(this,On).get(a);if(s)Fi(s),m(this,xa).delete(a);else{var l=m(this,fn).get(a);l&&(Fi(l.effect),m(this,On).set(a,l.effect),m(this,fn).delete(a),l.fragment.lastChild.remove(),this.anchor.before(l.fragment),s=l.effect)}for(const[o,d]of m(this,Tn)){if(m(this,Tn).delete(o),o===n)break;const v=m(this,fn).get(d);v&&(dn(v.effect),m(this,fn).delete(d))}for(const[o,d]of m(this,On)){if(o===a||m(this,xa).has(o))continue;const v=()=>{if(Array.from(m(this,Tn).values()).includes(o)){var f=document.createDocumentFragment();Br(d,f),f.append(Qn()),m(this,fn).set(o,{effect:d,fragment:f})}else dn(d);m(this,xa).delete(o),m(this,On).delete(o)};m(this,bi)||!s?(m(this,xa).add(o),Sa(d,v,!1)):v()}}});Ke(this,qi,n=>{m(this,Tn).delete(n);const a=Array.from(m(this,Tn).values());for(const[s,l]of m(this,fn))a.includes(s)||(dn(l.effect),m(this,fn).delete(s))});this.anchor=n,Re(this,bi,a)}ensure(n,a){var s=me,l=Gs();if(a&&!m(this,On).has(n)&&!m(this,fn).has(n))if(l){var o=document.createDocumentFragment(),d=Qn();o.append(d),m(this,fn).set(n,{effect:wn(()=>a(d)),fragment:o})}else m(this,On).set(n,wn(()=>a(this.anchor)));if(m(this,Tn).set(s,n),l){for(const[v,c]of m(this,On))v===n?s.unskip_effect(c):s.skip_effect(c);for(const[v,c]of m(this,fn))v===n?s.unskip_effect(c.effect):s.skip_effect(c.effect);s.oncommit(m(this,_i)),s.ondiscard(m(this,qi))}else m(this,_i).call(this,s)}}Tn=new WeakMap,On=new WeakMap,fn=new WeakMap,xa=new WeakMap,bi=new WeakMap,_i=new WeakMap,qi=new WeakMap;function O(e,n,a=!1){var s=new Lo(e),l=a?Va:0;function o(d,v){s.ensure(d,v)}Lr(()=>{var d=!1;n((v,c=0)=>{d=!0,o(c,v)}),d||o(-1,null)},l)}function et(e,n){return n}function Oo(e,n,a){for(var s=[],l=n.length,o,d=n.length,v=0;v<l;v++){let T=n[v];Sa(T,()=>{if(o){if(o.pending.delete(T),o.done.add(T),o.pending.size===0){var _=e.outrogroups;wr(e,Gi(o.done)),_.delete(o),_.size===0&&(e.outrogroups=null)}}else d-=1},!1)}if(d===0){var c=s.length===0&&a!==null;if(c){var f=a,b=f.parentNode;bo(b),b.append(f),e.items.clear()}wr(e,n,!c)}else o={pending:new Set(n),done:new Set},(e.outrogroups??(e.outrogroups=new Set)).add(o)}function wr(e,n,a=!0){var s;if(e.pending.size>0){s=new Set;for(const d of e.pending.values())for(const v of d)s.add(e.items.get(v).e)}for(var l=0;l<n.length;l++){var o=n[l];if(s!=null&&s.has(o)){o.f|=Rn;const d=document.createDocumentFragment();Br(o,d)}else dn(n[l],a)}}var Qr;function Ze(e,n,a,s,l,o=null){var d=e,v=new Map,c=(n&xs)!==0;if(c){var f=e;d=f.appendChild(Qn())}var b=null,T=so(()=>{var Me=a();return Er(Me)?Me:Me==null?[]:Gi(Me)}),_,x=new Map,$=!0;function R(Me){(Pe.effect.f&Mn)===0&&(Pe.pending.delete(Me),Pe.fallback=b,Bo(Pe,_,d,n,s),b!==null&&(_.length===0?(b.f&Rn)===0?Fi(b):(b.f^=Rn,ri(b,null,d)):Sa(b,()=>{b=null})))}function A(Me){Pe.pending.delete(Me)}var N=Lr(()=>{_=t(T);for(var Me=_.length,Ce=new Set,De=me,ie=Gs(),te=0;te<Me;te+=1){var _e=_[te],Ie=s(_e,te),He=$?null:v.get(Ie);He?(He.v&&ja(He.v,_e),He.i&&ja(He.i,te),ie&&De.unskip_effect(He.e)):(He=Ro(v,$?d:Qr??(Qr=Qn()),_e,Ie,te,l,n,a),$||(He.e.f|=Rn),v.set(Ie,He)),Ce.add(Ie)}if(Me===0&&o&&!b&&($?b=wn(()=>o(d)):(b=wn(()=>o(Qr??(Qr=Qn()))),b.f|=Rn)),Me>Ce.size&&Al(),!$)if(x.set(De,Ce),ie){for(const[Ne,ot]of v)Ce.has(Ne)||De.skip_effect(ot.e);De.oncommit(R),De.ondiscard(A)}else R(De);t(T)}),Pe={effect:N,items:v,pending:x,outrogroups:null,fallback:b};$=!1}function ei(e){for(;e!==null&&(e.f&Pn)===0;)e=e.next;return e}function Bo(e,n,a,s,l){var He,Ne,ot,P,ye,qe,Qe,q,oe;var o=(s&Rl)!==0,d=n.length,v=e.items,c=ei(e.effect.first),f,b=null,T,_=[],x=[],$,R,A,N;if(o)for(N=0;N<d;N+=1)$=n[N],R=l($,N),A=v.get(R).e,(A.f&Rn)===0&&((Ne=(He=A.nodes)==null?void 0:He.a)==null||Ne.measure(),(T??(T=new Set)).add(A));for(N=0;N<d;N+=1){if($=n[N],R=l($,N),A=v.get(R).e,e.outrogroups!==null)for(const Le of e.outrogroups)Le.pending.delete(A),Le.done.delete(A);if((A.f&an)!==0&&(Fi(A),o&&((P=(ot=A.nodes)==null?void 0:ot.a)==null||P.unfix(),(T??(T=new Set)).delete(A))),(A.f&Rn)!==0)if(A.f^=Rn,A===c)ri(A,null,a);else{var Pe=b?b.next:c;A===e.effect.last&&(e.effect.last=A.prev),A.prev&&(A.prev.next=A.next),A.next&&(A.next.prev=A.prev),ea(e,b,A),ea(e,A,Pe),ri(A,Pe,a),b=A,_=[],x=[],c=ei(b.next);continue}if(A!==c){if(f!==void 0&&f.has(A)){if(_.length<x.length){var Me=x[0],Ce;b=Me.prev;var De=_[0],ie=_[_.length-1];for(Ce=0;Ce<_.length;Ce+=1)ri(_[Ce],Me,a);for(Ce=0;Ce<x.length;Ce+=1)f.delete(x[Ce]);ea(e,De.prev,ie.next),ea(e,b,De),ea(e,ie,Me),c=Me,b=ie,N-=1,_=[],x=[]}else f.delete(A),ri(A,c,a),ea(e,A.prev,A.next),ea(e,A,b===null?e.effect.first:b.next),ea(e,b,A),b=A;continue}for(_=[],x=[];c!==null&&c!==A;)(f??(f=new Set)).add(c),x.push(c),c=ei(c.next);if(c===null)continue}(A.f&Rn)===0&&_.push(A),b=A,c=ei(A.next)}if(e.outrogroups!==null){for(const Le of e.outrogroups)Le.pending.size===0&&(wr(e,Gi(Le.done)),(ye=e.outrogroups)==null||ye.delete(Le));e.outrogroups.size===0&&(e.outrogroups=null)}if(c!==null||f!==void 0){var te=[];if(f!==void 0)for(A of f)(A.f&an)===0&&te.push(A);for(;c!==null;)(c.f&an)===0&&c!==e.fallback&&te.push(c),c=ei(c.next);var _e=te.length;if(_e>0){var Ie=(s&xs)!==0&&d===0?a:null;if(o){for(N=0;N<_e;N+=1)(Qe=(qe=te[N].nodes)==null?void 0:qe.a)==null||Qe.measure();for(N=0;N<_e;N+=1)(oe=(q=te[N].nodes)==null?void 0:q.a)==null||oe.fix()}Oo(e,te,Ie)}}o&&ka(()=>{var Le,Ge;if(T!==void 0)for(A of T)(Ge=(Le=A.nodes)==null?void 0:Le.a)==null||Ge.apply()})}function Ro(e,n,a,s,l,o,d,v){var c=(d&Ol)!==0?(d&Fl)===0?fo(a,!1,!1):Ta(a):null,f=(d&Bl)!==0?Ta(l):null;return{v:c,i:f,e:wn(()=>(o(n,c??a,f??l,v),()=>{e.delete(s)}))}}function ri(e,n,a){if(e.nodes)for(var s=e.nodes.start,l=e.nodes.end,o=n&&(n.f&Rn)===0?n.nodes.start:a;s!==null;){var d=yi(s);if(o.before(s),s===l)return;s=d}}function ea(e,n,a){n===null?e.effect.first=a:n.next=a,a===null?e.effect.last=n:a.prev=n}function nt(e,n,a=!1,s=!1,l=!1,o=!1){var d=e,v="";if(a)var c=e;z(()=>{var f=Ye;if(v!==(v=n()??"")){if(a){f.nodes=null,c.innerHTML=v,v!==""&&Ha(sa(c),c.lastChild);return}if(f.nodes!==null&&(Js(f.nodes.start,f.nodes.end),f.nodes=null),v!==""){var b=s?ql:l?Gl:void 0,T=Vs(s?"svg":l?"math":"template",b);T.innerHTML=v;var _=s||l?T:T.content;if(Ha(sa(_),_.lastChild),s||l)for(;sa(_);)d.before(sa(_));else d.before(_)}}})}function Fo(e,n,a){var s=e==null?"":""+e;return n&&(s=s?s+" "+n:n),s===""?null:s}function Ko(e,n){return e==null?null:String(e)}function wt(e,n,a,s,l,o){var d=e[fr];if(d!==a||d===void 0){var v=Fo(a,s);v==null?e.removeAttribute("class"):e.className=v,e[fr]=a}return o}function St(e,n,a,s){var l=e[hr];if(l!==n){var o=Ko(n);o==null?e.removeAttribute("style"):e.style.cssText=o,e[hr]=n}return s}function ll(e,n,a=!1){if(e.multiple){if(n==null)return;if(!Er(n))return Wl();for(var s of e.options)s.selected=n.includes(vi(s));return}for(s of e.options){var l=vi(s);if(go(l,n)){s.selected=!0;return}}(!a||n!==void 0)&&(e.selectedIndex=-1)}function No(e){var n=new MutationObserver(()=>{ll(e,e.__value)});n.observe(e,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["value"]}),Ws(()=>{n.disconnect()})}function Jn(e,n,a=n){var s=new WeakSet,l=!0;Dr(e,"change",o=>{var d=o?"[selected]":":checked",v;if(e.multiple)v=[].map.call(e.querySelectorAll(d),vi);else{var c=e.querySelector(d)??e.querySelector("option:not([disabled])");v=c&&vi(c)}a(v),e.__value=v,me!==null&&s.add(me)}),Us(()=>{var o=n();if(e===document.activeElement){var d=me;if(s.has(d))return}if(ll(e,o,l),l&&o===void 0){var v=e.querySelector(":checked");v!==null&&(o=vi(v),a(o))}e.__value=o,l=!1}),No(e)}function vi(e){return"__value"in e?e.__value:e.value}const qo=Symbol("is custom element"),Go=Symbol("is html"),Vo=Ml?"progress":"PROGRESS";function ta(e,n){var a=ol(e);a.value===(a.value=n??void 0)||e.value===n&&(n!==0||e.nodeName!==Vo)||(e.value=n??"")}function za(e,n,a,s){var l=ol(e);l[n]!==(l[n]=a)&&(n==="loading"&&(e[Sl]=a),a==null?e.removeAttribute(n):typeof a!="string"&&Wo(e).includes(n)?e[n]=a:e.setAttribute(n,a))}function ol(e){return e[Ci]??(e[Ci]={[qo]:e.nodeName.includes("-"),[Go]:e.namespaceURI===ks})}var Zr=new Map;function Wo(e){var n=e.getAttribute("is")||e.nodeName,a=Zr.get(n);if(a)return a;Zr.set(n,a=[]);for(var s,l=e,o=Element.prototype;o!==l;){s=ml(l);for(var d in s)s[d].set&&d!=="innerHTML"&&d!=="textContent"&&d!=="innerText"&&a.push(d);l=ms(l)}return a}function on(e,n,a=n){var s=new WeakSet;Dr(e,"input",async l=>{var o=l?e.defaultValue:e.value;if(o=ar(e)?ir(o):o,a(o),me!==null&&s.add(me),await Ao(),o!==(o=n())){var d=e.selectionStart,v=e.selectionEnd,c=e.value.length;if(e.value=o??"",v!==null){var f=e.value.length;d===v&&v===c&&f>c?(e.selectionStart=f,e.selectionEnd=f):(e.selectionStart=d,e.selectionEnd=Math.min(v,f))}}}),Za(n)==null&&e.value&&(a(ar(e)?ir(e.value):e.value),me!==null&&s.add(me)),ji(()=>{var l=n();if(e===document.activeElement){var o=me;if(s.has(o))return}ar(e)&&l===ir(e.value)||e.type==="date"&&!l&&!e.value||l!==e.value&&(e.value=l??"")})}function jo(e,n,a=n){Dr(e,"change",s=>{var l=s?e.defaultChecked:e.checked;a(l)}),Za(n)==null&&a(e.checked),ji(()=>{var s=n();e.checked=!!s})}function ar(e){var n=e.type;return n==="number"||n==="range"}function ir(e){return e===""?null:+e}function rr(e,n){return e===n||(e==null?void 0:e[La])===n}function Uo(e={},n,a,s){var l=Zt.r,o=Ye;return Us(()=>{var d,v;return ji(()=>{d=v,v=[],Za(()=>{rr(a(...v),e)||(n(e,...v),d&&rr(a(...d),e)&&n(null,...d))})}),()=>{let c=o;for(;c!==l&&c.parent!==null&&c.parent.f≺)c=c.parent;const f=()=>{v&&rr(a(...v),e)&&n(null,...v)},b=c.teardown;c.teardown=()=>{f(),b==null||b()}}}),e}function wi(e){Zt===null&&ys(),xi(()=>{const n=Za(e);if(typeof n=="function")return n})}function Ho(e){Zt===null&&ys(),wi(()=>()=>Za(e))}let fi=localStorage.getItem("mc_token")||"";function dl(){return fi}function Jo(e){fi=(e||"").trim(),localStorage.setItem("mc_token",fi)}function Qo(){const e={"Content-Type":"application/json"};return fi&&(e["X-MC-Token"]=fi),e}function ui(){return localStorage.getItem("mc_hf_token")||""}function Zo(e){localStorage.setItem("mc_hf_token",(e||"").trim())}async function Se(e,n={}){const a=await fetch(e,{headers:Qo(),...n}),s=await a.json().catch(()=>({}));if(!a.ok)throw new Error(s.error||"HTTP "+a.status);return s}const Yo=(e,n=document)=>n.querySelector(e),Yr=(e,n=document)=>[...n.querySelectorAll(e)];function Kn(e){return String(e??"").replace(/[&<>]/g,n=>({"&":"&","<":"<",">":">"})[n])}let Xr;function ve(e,n=!1){const a=Yo("#toast");a&&(a.textContent=e,a.className="toast show"+(n?" err":""),clearTimeout(Xr),Xr=setTimeout(()=>a.className="toast",3200))}function Xo(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 ht=e=>`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round">${e}</svg>`,Ui={logo:ht('<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:ht('<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:ht('<rect x="6" y="6" width="12" height="12" rx="2"/><path d="M9 1v3M15 1v3M9 20v3M15 20v3M1 9h3M1 15h3M20 9h3M20 15h3"/>'),pulse:ht('<path d="M3 12h4l2 6 4-14 2 8h6"/>'),server:ht('<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:ht('<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:ht('<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:ht('<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:ht('<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:ht('<rect x="3" y="4" width="18" height="12" rx="2"/><path d="M8 20h8M12 16v4"/>'),layers:ht('<path d="m12 2 9 5-9 5-9-5z"/><path d="m3 12 9 5 9-5M3 17l9 5 9-5"/>'),alert:ht('<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:ht('<path d="M12 14 16 9"/><circle cx="12" cy="13" r="9"/><path d="M12 4v2M21 13h-2M5 13H3"/>'),search:ht('<circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/>'),compass:ht('<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:ht('<polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/>'),eye:ht('<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:ht('<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:ht('<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:ht('<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:ht('<path d="M14 14.76V5a2 2 0 0 0-4 0v9.76a4 4 0 1 0 4 0z"/>'),shield:ht('<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:ht('<circle cx="12" cy="12" r="9"/><path d="M12 16v-4M12 8h.01"/>'),chevron:ht('<path d="m9 6 6 6-6 6"/>'),bolt:ht('<path d="M13 2 3 14h7l-1 8 10-12h-7z"/>'),x:ht('<path d="M18 6 6 18M6 6l12 12"/>'),check:ht('<path d="M20 6 9 17l-5-5"/>'),download:ht('<path d="M12 3v12M7 10l5 5 5-5"/><path d="M5 21h14"/>'),clock:ht('<circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/>')};function qt(e){return Ui[e]||""}function Sr(e){return`<span class="info-dot" tabindex="0" title="${Kn(e)}" aria-label="${Kn(e)}">${Ui.info}</span>`}function ua(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 hn({title:e,body:n,confirmLabel:a="Bestätigen",cancelLabel:s="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>${Kn(e)}</h3>
|
||
<p>${n}</p>
|
||
<div class="modal-actions">
|
||
<button data-x="0">${Kn(s)}</button>
|
||
<button class="${l?"danger":"primary"}" data-x="1">${Kn(a)}</button>
|
||
</div></div>`;const v=c=>{d.remove(),o(c)};d.addEventListener("click",c=>{if(c.target===d)return v(!1);const f=c.target.closest("[data-x]");f&&v(f.getAttribute("data-x")==="1")}),document.body.appendChild(d),d.querySelector('[data-x="1"]').focus()})}function sr({title:e,body:n="",placeholder:a="",password:s=!1,confirmLabel:l="Weiter",danger:o=!1}){return new Promise(d=>{const v=document.createElement("div");v.className="modal-overlay",v.innerHTML=`<div class="modal-card" role="dialog" aria-modal="true">
|
||
<h3>${Kn(e)}</h3>
|
||
${n?`<p>${n}</p>`:""}
|
||
<input type="${s?"password":"text"}" placeholder="${Kn(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">${Kn(l)}</button>
|
||
</div></div>`;const c=v.querySelector("input"),f=b=>{v.remove(),d(b)};v.addEventListener("click",b=>{if(b.target===v)return f(null);const T=b.target.closest("[data-x]");T&&f(T.getAttribute("data-x")==="1"?c.value||"":null)}),c.addEventListener("keydown",b=>{b.key==="Enter"&&f(c.value||""),b.key==="Escape"&&f(null)}),document.body.appendChild(v),c.focus()})}function ed(e="overview"){const n=Yr(".nav-item[data-view]:not(.disabled)"),a=Yr(".view[data-view]"),s=new Set(a.map(o=>o.dataset.view));function l(o){s.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 es=B(null);const Si={get value(){return t(es)},set(e){u(es,e,!0)}};let ts=B(Rt([])),na=B(Rt([]));const ga={get value(){return t(ts)},set(e){u(ts,e||[],!0)},get tracked(){return t(na)},track(e){t(na).includes(e)||u(na,[...t(na),e],!0)},toggle(e){u(na,t(na).includes(e)?t(na).filter(n=>n!==e):[...t(na),e],!0)}};let ns=B(null);const Rr={get value(){return t(ns)},set(e){u(ns,e,!0)}},td="5";var hs;typeof window<"u"&&((hs=window.__svelte??(window.__svelte={})).v??(hs.v=new Set)).add(td);var nd=g('<span style="font-size:13px;font-weight:400;color:var(--mut)">— bereit für Anfragen</span>'),ad=g('<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),id=g('<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),rd=g('<div class="meter"><div class="meter-h"><span class="mk"> </span><span class="mv"> </span></div> <div><i></i></div></div>'),sd=g('<div class="empty">Warte auf Messwerte…</div>'),ld=g('<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),od=g('<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),dd=g('<span class="tag img">Bild</span>'),cd=g('<span class="tag code">Code</span>'),vd=g('<span class="tag text">Text</span>'),ud=g('<span class="chip" style="padding:2px 7px;font-size:11px">∞ aktiv</span>'),pd=g('<button class="ghost"> </button>'),fd=g('<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>'),as=g('<div class="list"></div>'),hd=g('<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>'),gd=g('<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>'),md=g('<div class="empty">News gerade nicht ladbar.</div>'),bd=g('<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 _d(e,n){Dn(n,!0);const a=V(()=>Si.value),s=V(()=>Rr.value),l=V(()=>{var w;return((w=t(a))==null?void 0:w.models)||[]}),o=V(()=>{var w;return((w=t(a))==null?void 0:w.swap_ok)??!1}),d=["running","ready","loading","starting"],v=V(()=>t(l).find(w=>d.includes(w.state))),c=V(()=>t(l).filter(w=>!w.incomplete)),f=V(()=>t(a)?t(o)?t(s)&&t(s).ram.percent>=90?"Achtung: Speicher wird knapp.":"Alles läuft rund.":"LLM-Engine offline":"Verbinde…"),b=V(()=>t(a)?t(o)?t(s)&&t(s).ram.percent>=90?`Arbeitsspeicher bei ${Math.round(t(s).ram.percent)} % — eventuell Speicher freigeben.`:`${t(c).length} ${t(c).length===1?"Modell":"Modelle"} konfiguriert · ${t(v)?`„${t(v).name}" geladen`:"keines geladen"} · keine Warnungen.`:"Der llama-swap-Dienst antwortet gerade nicht.":""),T=V(()=>()=>{var j;const w=(j=t(s))==null?void 0:j.gpu;return w&&w.vram.total+w.gtt.total>0?(w.vram.used+w.gtt.used)/(w.vram.total+w.gtt.total)*100:0});let _=B(Rt([])),x=B(null);wi(async()=>{try{u(_,((await Se("/api/news")).items||[]).slice(0,4),!0)}catch{}});async function $(){await hn({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"}),A())}async function R(w){u(x,w,!0);try{await Se("/api/preload?model="+encodeURIComponent(w),{method:"POST"})}catch(j){ve("Laden fehlgeschlagen: "+(j.message||"Engine nicht erreichbar?"),!0)}u(x,null),A()}function A(){document.dispatchEvent(new Event("mc:refresh"))}function N(w){var j;(j=document.querySelector(`.nav-item[data-view="${w}"]`))==null||j.dispatchEvent(new MouseEvent("click"))}function Pe(w){return w>=90?"red":w>=75?"":"green"}function Me(w){return w==null?"":w>=75?"red":w>=55?"":"green"}function Ce(w){return w>=90?"red":w>=70?"":"green"}var De=bd(),ie=tt(De),te=r(ie),_e=r(te),Ie=r(_e),He=i(Ie);{var Ne=w=>{var j=nd();p(w,j)};O(He,w=>{t(o)&&!t(v)&&w(Ne)})}var ot=i(_e,2),P=r(ot),ye=i(ie,2),qe=r(ye),Qe=r(qe),q=i(r(Qe),2);nt(q,()=>qt("server"),!0);var oe=i(Qe,2),Le=r(oe),Ge=i(oe,2),je=r(Ge),Oe=i(qe,2),dt=r(Oe),Xe=i(r(dt),2);nt(Xe,()=>qt("cpu"),!0);var pt=i(dt,2),ct=r(pt),mt=i(pt,2),Ct=r(mt);{var Tt=w=>{var j=ci();z(pe=>h(j,`${pe??""} · ${t(v).state??""}`),[()=>{var pe;return(pe=t(v).meta)!=null&&pe.ctx?Math.round(t(v).meta.ctx/1024)+"k ctx":""}]),p(w,j)},Mt=w=>{var j=ci("lädt bei erster Anfrage");p(w,j)};O(Ct,w=>{t(v)?w(Tt):w(Mt,-1)})}var Ft=i(Oe,2);{var zt=w=>{const j=V(()=>{var gn;return t(s).gpu_temp??((gn=t(s).cpu)==null?void 0:gn.temp)??null}),pe=V(()=>Me(t(j))),U=V(()=>t(s).ram.total-t(s).ram.used),we=V(()=>100-t(s).ram.percent);var Be=ad(),Fe=tt(Be),$e=r(Fe),H=i(r($e));nt(H,()=>qt("thermo"),!0);var Y=i($e,2),X=r(Y),K=i(Y,2),ae=r(K),fe=i(Fe,2),he=r(fe),ue=i(r(he));nt(ue,()=>qt("database"),!0);var ge=i(he,2),kt=r(ge),$t=i(ge,2),Dt=r($t);z((gn,ca,Yn,Ya)=>{wt(Fe,1,`kpi ${t(pe)??""}`),h(X,gn),h(ae,t(j)==null?"messe…":t(j)<55?"kühl":t(j)<75?"normal":"⚠ heiß"),wt(fe,1,`kpi ${t(we)<15?"red":t(we)<30?"":"green"}`),h(kt,ca),h(Dt,`von ${Yn??""} GB · ${Ya??""} % frei`)},[()=>t(j)!=null?`${Math.round(t(j))}°C`:"–",()=>Math.round(t(U)/1073741824),()=>Math.round(t(s).ram.total/1073741824),()=>Math.round(t(we))]),p(w,Be)},Et=w=>{var j=id();p(w,j)};O(Ft,w=>{t(s)?w(zt):w(Et,-1)})}var D=i(ye,2),J=r(D),I=i(r(J),4);{var W=w=>{const j=V(()=>t(T)());var pe=Ea(),U=tt(pe);Ze(U,17,()=>{var we;return[["Prozessor (CPU)",((we=t(s).cpu)==null?void 0:we.percent)??0,""],["Arbeitsspeicher (RAM)",t(s).ram.percent,Pe(t(s).ram.percent)],["Grafikspeicher (VRAM)",t(j),Ce(t(j))]]},et,(we,Be)=>{var Fe=V(()=>Bn(t(Be),3));let $e=()=>t(Fe)[0],H=()=>t(Fe)[1];const Y=V(()=>Math.max(0,Math.min(100,H()||0)));var X=rd(),K=r(X),ae=r(K),fe=r(ae),he=i(ae),ue=r(he),ge=i(K,2),kt=r(ge);z(($t,Dt)=>{h(fe,$e()),h(ue,`${$t??""} %`),wt(ge,1,`bar ${t(Y)>=90?"bad":t(Y)>=75?"warn":""}`),St(kt,`width:${Dt??""}%`)},[()=>Math.round(t(Y)),()=>Math.max(2,t(Y))]),p(we,X)}),p(w,pe)},M=w=>{var j=sd();p(w,j)};O(I,w=>{t(s)?w(W):w(M,-1)})}var ee=i(J,2),xe=i(r(ee),2);{var Te=w=>{var j=ld(),pe=i(tt(j),2),U=r(pe);nt(U,()=>qt("search"),!0);var we=i(U,4);nt(we,()=>qt("chevron"),!0);var Be=i(pe,2),Fe=r(Be);nt(Fe,()=>qt("swap"),!0);var $e=i(Fe,4);nt($e,()=>qt("chevron"),!0);var H=i(Be,2),Y=r(H);nt(Y,()=>qt("file"),!0);var X=i(Y,4);nt(X,()=>qt("chevron"),!0),S("click",pe,()=>N("cookbook")),S("click",Be,()=>N("connect")),S("click",H,()=>N("guides")),p(w,j)},C=w=>{var j=od(),pe=i(tt(j),2),U=r(pe);nt(U,()=>qt("search"),!0);var we=i(U,4);nt(we,()=>qt("chevron"),!0);var Be=i(pe,2),Fe=r(Be);nt(Fe,()=>qt("refresh"),!0);var $e=i(Fe,4);nt($e,()=>qt("chevron"),!0);var H=i(Be,2),Y=r(H);nt(Y,()=>qt("file"),!0);var X=i(Y,4);nt(X,()=>qt("chevron"),!0);var K=i(H,2),ae=r(K);nt(ae,()=>qt("swap"),!0);var fe=i(ae,4);nt(fe,()=>qt("chevron"),!0),S("click",pe,()=>N("cookbook")),S("click",Be,$),S("click",H,()=>N("server")),S("click",K,()=>N("connect")),p(w,j)};O(xe,w=>{t(c).length?w(C,-1):w(Te)})}var F=i(D,2),re=r(F),se=r(re),ne=i(r(se),2),ke=r(ne),de=i(se,2);{var E=w=>{var j=as();Ze(j,21,()=>t(c),et,(pe,U)=>{const we=V(()=>d.includes(t(U).state)),Be=V(()=>t(U).state==="downloading"),Fe=V(()=>t(U).state==="loading"||t(U).state==="starting"||t(Be)?"load":t(we)?"on":""),$e=V(()=>t(Be)?`↓ ${t(U).download_progress!=null?Math.round(t(U).download_progress)+"%":"..."}`:t(U).state==="loading"||t(U).state==="starting"?"lädt…":t(we)?"geladen ✓":"bereit");var H=fd(),Y=r(H),X=i(Y,2),K=r(X),ae=r(K),fe=r(ae),he=i(ae,2);{var ue=y=>{var L=dd();p(y,L)},ge=V(()=>{var y,L;return(L=(y=t(U).meta)==null?void 0:y.caps)==null?void 0:L.includes("Bild")}),kt=y=>{var L=cd();p(y,L)},$t=V(()=>{var y,L;return(L=(y=t(U).meta)==null?void 0:y.caps)==null?void 0:L.includes("Code")}),Dt=y=>{var L=vd();p(y,L)};O(he,y=>{t(ge)?y(ue):t($t)?y(kt,1):y(Dt,-1)})}var gn=i(he,2);{var ca=y=>{var L=ud();p(y,L)};O(gn,y=>{t(U).ttl>=99999&&y(ca)})}var Yn=i(K,2),Ya=r(Yn),Mi=i(X,2),Xa=r(Mi),Ji=r(Xa),Qi=i(Xa,2);{var k=y=>{var L=pd(),G=r(L);z(()=>{St(L,`padding:3px 9px;font-size:12px;opacity:${t(x)===t(U).name?".5":"1"}`),L.disabled=t(x)===t(U).name,h(G,t(x)===t(U).name?"…":"Laden")}),S("click",L,()=>R(t(U).name)),p(y,L)};O(Qi,y=>{!t(we)&&!t(Be)&&t(o)&&y(k)})}z((y,L)=>{var G;wt(Y,1,`li-dot ${t(Fe)??""}`),St(ae,t(we)?"color:var(--accent)":""),h(fe,t(U).name),h(Ya,`${y??""}
|
||
${(G=t(U).meta)!=null&&G.quant?" · "+t(U).meta.quant:""}
|
||
${L??""}`),St(Xa,`white-space:nowrap;color:${t(we)?"var(--on)":"var(--mut)"}`),h(Ji,t($e))},[()=>{var y;return(y=t(U).meta)!=null&&y.ctx?Math.round(t(U).meta.ctx/1024)+"k ctx":""},()=>{var y;return(y=t(U).meta)!=null&&y.size_bytes?" · "+(t(U).meta.size_bytes/1073741824).toFixed(1)+" GB":""}]),p(pe,H)}),p(w,j)},Q=w=>{var j=hd(),pe=i(r(j),4);S("click",pe,()=>N("cookbook")),p(w,j)};O(de,w=>{t(c).length?w(E):w(Q,-1)})}var ce=i(re,2),Ee=r(ce),Z=i(r(Ee),2),le=i(Ee,2);{var Ae=w=>{var j=as();Ze(j,21,()=>t(_),et,(pe,U)=>{var we=gd(),Be=r(we),Fe=r(Be),$e=r(Fe),H=i(Fe,2),Y=r(H);z(()=>{za(we,"href",t(U).link),h($e,t(U).title),h(Y,`${t(U).source??""}${t(U).relevant?" · für dich":""}`)}),p(pe,we)}),p(w,j)},ze=w=>{var j=md();p(w,j)};O(le,w=>{t(_).length?w(Ae):w(ze,-1)})}z(w=>{h(Ie,`${t(f)??""} `),h(P,t(b)),wt(qe,1,`kpi ${t(o)?"green":"red"}`),h(Le,t(o)?"Online":"Offline"),h(je,w),wt(Oe,1,`kpi ${t(v)?"blue":"muted"}`),h(ct,t(v)?t(v).name:"Keins"),h(ke,t(c).length?t(c).length+" konfiguriert":"")},[()=>{var w,j;return((j=(w=t(a))==null?void 0:w.swap_url)==null?void 0:j.replace(/^https?:\/\//,""))??"—"}]),S("click",Z,()=>N("news")),S("keydown",Z,w=>w.key==="Enter"&&N("news")),p(e,De),In()}Gn(["click","keydown"]);var yd=g("<option> </option>"),xd=g('<div class="reply" style="margin-top:12px"> </div>'),kd=g('<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>'),wd=g('<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>'),Sd=g('<span class="tag" style="background:rgba(45,212,191,.14);color:var(--accent);border-color:rgba(45,212,191,.3)"> </span>'),Md=g('<div class="li-sub mono-sm"> </div>'),Ed=g('<code style="cursor:pointer" title="Klicken zum Kopieren"> </code>'),Ad=g('<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>'),Cd=g('<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>'),Td=g('<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>'),zd=g('<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>'),$d=g('<button style="border-radius:999px"> </button>'),Pd=g('<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>'),Dd=g('<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 Id(e,n){Dn(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.",s="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=V(()=>{var D;return((D=Si.value)==null?void 0:D.models)||[]});function d(){document.dispatchEvent(new Event("mc:refresh"))}let v=B(""),c=B(""),f=B(""),b=B(!1);const T=V(()=>t(o).filter(D=>!D.incomplete));async function _(){var J;const D=t(v)||((J=t(T)[0])==null?void 0:J.name);if(!(!D||!t(c).trim())){u(b,!0),u(f,"(wecke Modell, kann beim Laden kurz dauern…)");try{const I=await Se("/api/chat",{method:"POST",body:JSON.stringify({model:D,message:t(c)})});u(f,I.reply,!0)}catch(I){u(f,"Fehler: "+I.message)}u(b,!1),d()}}const x=300;let $=B(!1),R=B(null),A=B(8192),N=B(!1);function Pe(D){var J;u(R,t(o).find(I=>I.name===D),!0),t(R)&&(u(A,((J=t(R).meta)==null?void 0:J.ctx)||8192,!0),u(N,(t(R).ttl??x)>=99999),u($,!0))}async function Me(){const D=t(N)?99999:x;try{await Se("/api/update_model",{method:"POST",body:JSON.stringify({alias:t(R).name,ctx:t(A),ttl:D})}),ve("Gespeichert — aktiv beim nächsten Modell-Start."),u($,!1),d()}catch(J){ve(J.message,!0)}}let Ce=B(!1),De=B(""),ie=B(""),te=B("");function _e(D){const J=t(o).find(I=>I.name===D);u(De,D,!0),u(te,(J==null?void 0:J.role)||"",!0),u(ie,""),u(Ce,!0)}async function Ie(D){try{await Se("/api/set_role",{method:"POST",body:JSON.stringify({alias:t(De),role:D})}),ve(D?`Rolle gesetzt: ${D}`:"Rolle entfernt."),u(Ce,!1),d()}catch(J){ve(J.message,!0)}}async function He(D){if(await hn({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"}),ve("Entladen: "+D),setTimeout(d,600)}catch(J){ve(J.message,!0)}}async function Ne(D){if(await hn({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 J=await Se("/api/delete_model",{method:"POST",body:JSON.stringify({alias:D})});ve(J.note||"Gelöscht: "+D),setTimeout(d,600)}catch(J){ve(J.message,!0)}}function ot(D){if(!D)return"–";const J=[];return D.coder&&J.push('<span class="tag code">Code</span>'),D.vision&&J.push('<span class="tag img">Bild</span>'),D.reasoning&&J.push('<span class="tag" style="border-color:#a78bfa;color:#a78bfa">🧠 Reason</span>'),D.moe&&J.push(`<span class="tag" style="border-color:#f59e0b;color:#f59e0b">🧩 MoE${D.active_b?" ·"+D.active_b+"B":""}</span>`),D.tools==="yes"?J.push('<span class="tag" style="border-color:var(--accent);color:var(--accent)" title="Tool-Calling vom Template/Flag unterstützt">🛠 Tools</span>'):D.tools==="likely"&&J.push('<span class="tag" style="opacity:.55" title="laut Modell-Familie wahrscheinlich tool-fähig">🛠 Tools?</span>'),D.embedding&&J.push('<span class="tag" style="opacity:.7">🔢 Embed</span>'),!D.coder&&!D.vision&&!D.embedding&&J.unshift('<span class="tag text">Text</span>'),J.length?J.join(" "):"–"}function P(D){if(!D)return"–";const J=D.quant||"?",I=D.ctx?Math.round(D.ctx/1024)+"K":"?",W=D.size_bytes?(D.size_bytes/1024**3).toFixed(1)+" GB":"?";return`<span class="mono-sm">${J} · ${I} · ${W}</span>`}function ye(D){var J;(J=navigator.clipboard)==null||J.writeText(D),ve("Kopiert: "+D)}var qe=Dd(),Qe=i(tt(qe),2),q=i(r(Qe),6);Ze(q,21,()=>t(T),et,(D,J)=>{var I=yd(),W=r(I),M={};z(()=>{h(W,t(J).name),M!==(M=t(J).name)&&(I.value=(I.__value=t(J).name)??"")}),p(D,I)});var oe=i(q,4),Le=i(oe,2),Ge=r(Le),je=i(Le,2);{var Oe=D=>{var J=xd(),I=r(J);z(()=>h(I,t(f))),p(D,J)};O(je,D=>{t(f)&&D(Oe)})}var dt=i(Qe,2),Xe=r(dt),pt=i(r(Xe)),ct=r(pt),mt=i(Xe,4);{var Ct=D=>{var J=kd();p(D,J)},Tt=D=>{var J=Cd(),I=i(r(J));Ze(I,21,()=>t(o),et,(W,M)=>{var ee=Ea(),xe=tt(ee);{var Te=F=>{var re=wd(),se=r(re),ne=r(se),ke=i(se,5),de=r(ke),E=i(de,2);z(()=>h(ne,t(M).name)),S("click",de,()=>{var Q;ve("Lade im Cookbook ein Modell und setze den Alias auf: "+t(M).name),(Q=document.querySelector(".nav-item[data-view='cookbook']"))==null||Q.dispatchEvent(new MouseEvent("click"))}),S("click",E,()=>Ne(t(M).name)),p(F,re)},C=F=>{var re=Ad(),se=r(re),ne=r(se),ke=r(ne),de=i(ke);{var E=$e=>{var H=Sd(),Y=r(H);z(()=>h(Y,t(M).role)),p($e,H)};O(de,$e=>{t(M).role&&$e(E)})}var Q=i(ne,2);{var ce=$e=>{var H=Md(),Y=r(H);z(()=>h(Y,t(M).meta.filename)),p($e,H)};O(Q,$e=>{var H;(H=t(M).meta)!=null&&H.filename&&$e(ce)})}var Ee=i(Q,2),Z=i(r(Ee),2);Ze(Z,17,()=>{var $e;return($e=t(M).api_ids)!=null&&$e.length?t(M).api_ids:[t(M).name]},et,($e,H)=>{var Y=Ed(),X=r(Y);z(()=>h(X,t(H))),S("click",Y,()=>ye(t(H))),p($e,Y)});var le=i(se);nt(le,()=>{var $e;return ot(($e=t(M).meta)==null?void 0:$e.capabilities)},!0);var Ae=i(le);nt(Ae,()=>P(t(M).meta),!0);var ze=i(Ae);nt(ze,()=>Xo(t(M).state,t(M).download_progress),!0);var w=i(ze),j=r(w),pe=i(w),U=r(pe),we=i(U,2),Be=i(we,2),Fe=i(Be,2);z(()=>{h(ke,`${t(M).name??""} `),h(j,t(M).port??"auto")}),S("click",U,()=>_e(t(M).name)),S("click",we,()=>Pe(t(M).name)),S("click",Be,()=>He(t(M).name)),S("click",Fe,()=>Ne(t(M).name)),p(F,re)};O(xe,F=>{t(M).incomplete?F(Te):F(C,-1)})}p(W,ee)}),p(D,J)};O(mt,D=>{t(o).length?D(Tt,-1):D(Ct)})}var Mt=i(dt,2);{var Ft=D=>{var J=zd(),I=r(J),W=r(I),M=i(W,4),ee=r(M),xe=i(M,2),Te=i(r(xe));nt(Te,()=>Sr(a));var C=i(xe,2),F=i(C,2);{var re=ce=>{var Ee=Td(),Z=r(Ee),le=i(r(Z),2),Ae=r(le),ze=i(Ae,2),w=i(Z,2);z((j,pe)=>{h(Ae,`Optimal ~${j??""}k → ~${t(R).meta.peak_ram_optimal_gb??""} GB Spitzenbedarf.`),h(ze,` Aktuell ~${pe??""}k → ~${t(R).meta.peak_ram_gb??""} GB.`)},[()=>Math.round(t(R).meta.optimal_ctx/1024),()=>Math.round((t(R).meta.ctx||0)/1024)]),S("click",w,()=>u(A,t(R).meta.optimal_ctx,!0)),p(ce,Ee)};O(F,ce=>{var Ee;(Ee=t(R).meta)!=null&&Ee.optimal_ctx&&ce(re)})}var se=i(F,4),ne=i(r(se),2),ke=r(ne),de=i(ke,2),E=r(de),Q=i(se,2);z(()=>{h(ee,t(R).name),St(de,`color:${t(N)?"var(--accent)":"var(--mut)"}`),h(E,t(N)?"An (TTL = ∞)":"Aus (TTL = 5 min)")}),S("click",J,ce=>{ce.target.classList.contains("modal-overlay")&&u($,!1)}),S("click",W,()=>u($,!1)),on(C,()=>t(A),ce=>u(A,ce)),jo(ke,()=>t(N),ce=>u(N,ce)),S("click",Q,Me),p(D,J)};O(Mt,D=>{t($)&&t(R)&&D(Ft)})}var zt=i(Mt,2);{var Et=D=>{var J=Pd(),I=r(J),W=r(I),M=i(W,2),ee=i(r(M));nt(ee,()=>Sr(s));var xe=i(M,2),Te=r(xe),C=i(xe,4);Ze(C,21,()=>l,et,(ke,de)=>{var E=$d(),Q=r(E);z(()=>{wt(E,1,t(te)===t(de).id?"primary":"ghost"),za(E,"title",t(de).desc),h(Q,t(de).label)}),S("click",E,()=>Ie(t(de).id)),p(ke,E)});var F=i(C,4),re=i(F,2),se=r(re),ne=i(se,2);z(()=>h(Te,t(De))),S("click",J,ke=>{ke.target.classList.contains("modal-overlay")&&u(Ce,!1)}),S("click",W,()=>u(Ce,!1)),on(F,()=>t(ie),ke=>u(ie,ke)),S("click",se,()=>Ie("")),S("click",ne,()=>Ie(t(ie).trim().toLowerCase())),p(D,J)};O(zt,D=>{t(Ce)&&D(Et)})}z(()=>{Le.disabled=t(b),h(Ge,t(b)?"…":"Senden"),h(ct,t(o).length?t(o).length+" konfiguriert":"")}),Jn(q,()=>t(v),D=>u(v,D)),on(oe,()=>t(c),D=>u(c,D)),S("click",Le,_),p(e,qe),In()}Gn(["click"]);var Ld=g('<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),Od=g('<button class="ghost" style="margin-left:auto;padding:4px 11px;font-size:12px">Verlauf leeren</button>'),Bd=g('<div class="empty-c"><div class="e-t">Gerade nichts los.</div> <div class="e-s">Alles ruhig — keine laufenden Aufgaben.</div></div>'),Rd=g('<span class="mono-sm" style="margin-left:auto"> </span>'),Fd=g('<button class="ghost">Abbrechen</button>'),Kd=g('<button class="ghost" title="Aus Verlauf entfernen" style="margin-left:auto;margin-right:2px;padding:2px 9px;font-size:14px;line-height:1">×</button>'),Nd=g('<div class="bar" style="margin-top:8px"><i></i></div>'),qd=g('<div class="log"> </div>'),Gd=g('<div class="job"><div class="job-h" role="button" tabindex="0"><span></span> <span class="mid"> </span> <!> <!> <!></div> <!> <!></div>'),Vd=g('<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 Wd(e,n){Dn(n,!0);const a=V(()=>ga.value),s=V(()=>ga.tracked),l=V(()=>Rr.value);let o=Rt({cpu:[],ram:[],gpu:[]});xi(()=>{var qe;if(!t(l))return;const P=t(l).gpu,ye=P&&P.vram.total+P.gtt.total>0?(P.vram.used+P.gtt.used)/(P.vram.total+P.gtt.total)*100:0;o.cpu=[...o.cpu,((qe=t(l).cpu)==null?void 0:qe.percent)??0].slice(-60),o.ram=[...o.ram,t(l).ram.percent].slice(-60),o.gpu=[...o.gpu,ye].slice(-60)});const d=V(()=>()=>{var ye;const P=(ye=t(l))==null?void 0:ye.gpu;return P&&P.vram.total+P.gtt.total>0?(P.vram.used+P.gtt.used)/(P.vram.total+P.gtt.total)*100:0}),v=V(()=>t(a).filter(P=>P.state!=="running"&&P.state!=="queued").length),c=V(()=>t(a).filter(P=>P.state==="failed").length);function f(P){if(P.state!=="running")return null;if(typeof P.progress=="number")return Math.min(100,P.progress);const qe=((P.log||[]).at(-1)||"").match(/(\d+(?:\.\d+)?)\s*%/);return qe?Math.min(100,parseFloat(qe[1])):null}function b(P){return P==null||P<0?"":P>=90?`noch ~${Math.round(P/60)} min`:`noch ~${Math.max(1,Math.round(P))} s`}function T(P){return P==="done"?'<span class="badge b-run">fertig</span>':P==="failed"?'<span class="badge b-err">fehler</span>':P==="canceled"?'<span class="badge">abgebrochen</span>':'<span class="badge b-load">läuft…</span>'}function _(P){return P==="done"?"on":P==="failed"||P==="canceled"?"":"load"}async function x(P){try{await Se(`/api/jobs/${P}/cancel`,{method:"POST"}),ve("Abbruch angefordert…")}catch(ye){ve(ye.message,!0)}}async function $(P){try{await Se(`/api/jobs/${P}`,{method:"DELETE"})}catch(ye){ve(ye.message,!0)}}async function R(){try{const P=await Se("/api/jobs/clear",{method:"POST"});ve(`${P.removed} Einträge entfernt.`)}catch(P){ve(P.message,!0)}}function A(P,ye){return P.map(qe=>`<div style="width:4px;background:var(${ye});opacity:.55;height:${Math.max(2,qe)}%;border-radius:2px"></div>`).join("")}var N=Vd(),Pe=i(tt(N),2);{var Me=P=>{const ye=V(()=>t(d)());var qe=Ld(),Qe=tt(qe),q=r(Qe),oe=i(r(q),2),Le=r(oe),Ge=i(oe,2),je=r(Ge),Oe=i(q,2),dt=i(r(Oe),2),Xe=r(dt),pt=i(dt,2),ct=r(pt),mt=i(Oe,2),Ct=i(r(mt),2),Tt=r(Ct),Mt=i(Ct,2),Ft=r(Mt),zt=i(Qe,2),Et=i(r(zt),4),D=r(Et),J=i(r(D)),I=r(J),W=i(D,2),M=i(r(W),2),ee=r(M),xe=i(W,2),Te=i(r(xe)),C=r(Te),F=i(xe,2),re=i(r(F),2),se=r(re),ne=i(Et,2),ke=r(ne),de=i(r(ke));nt(de,()=>A(o.cpu,"--accent"),!0);var E=i(ke,2),Q=i(r(E));nt(Q,()=>A(o.ram,"--purple"),!0);var ce=i(E,2),Ee=i(r(ce));nt(Ee,()=>A(o.gpu,"--on"),!0),z((Z,le,Ae,ze,w,j,pe,U,we,Be,Fe,$e,H)=>{h(Le,Z),h(je,le),h(Xe,Ae),h(ct,`${ze??""} / ${w??""}`),h(Tt,j),h(Ft,pe),h(I,`${U??""} / ${we??""}`),h(ee,Be),h(C,`${Fe??""} % belegt`),h(se,`${$e??""} / ${H??""}`)},[()=>{var Z;return Math.round(((Z=t(l).cpu)==null?void 0:Z.percent)??0)},()=>{var Z;return((Z=t(l).cpu)==null?void 0:Z.temp)!=null?`${Math.round(t(l).cpu.temp)}° CPU-Temp`:"Auslastung"},()=>Math.round(t(l).ram.percent),()=>ua(t(l).ram.used),()=>ua(t(l).ram.total),()=>Math.round(t(ye)),()=>t(l).gpu_temp!=null?`${Math.round(t(l).gpu_temp)}° GPU-Temp`:"VRAM + GTT",()=>ua(t(l).ram.used),()=>ua(t(l).ram.total),()=>t(l).gpu?`${ua(t(l).gpu.vram.used+t(l).gpu.gtt.used)} / ${ua(t(l).gpu.vram.total+t(l).gpu.gtt.total)}`:"–",()=>{var Z;return Math.round(((Z=t(l).disk)==null?void 0:Z.percent)??0)},()=>t(l).gpu_temp!=null?Math.round(t(l).gpu_temp)+"°":"–",()=>{var Z;return((Z=t(l).cpu)==null?void 0:Z.temp)!=null?Math.round(t(l).cpu.temp)+"°":"–"}]),p(P,qe)};O(Pe,P=>{t(l)&&P(Me)})}var Ce=i(Pe,2),De=r(Ce),ie=i(r(De),2),te=r(ie),_e=i(ie,2);{var Ie=P=>{var ye=Od();S("click",ye,R),p(P,ye)};O(_e,P=>{t(v)&&P(Ie)})}var He=i(De,4);{var Ne=P=>{var ye=Bd();p(P,ye)},ot=P=>{var ye=Ea(),qe=tt(ye);Ze(qe,17,()=>t(a),et,(Qe,q)=>{const oe=V(()=>f(t(q))),Le=V(()=>t(q).state==="running"?b(t(q).eta_s):""),Ge=V(()=>t(q).state==="running"&&t(q).rate_bps?ua(t(q).rate_bps)+"/s":""),je=V(()=>[t(Le),t(Ge)].filter(Boolean).join(" · ")),Oe=V(()=>t(s).includes(t(q).id));var dt=Gd(),Xe=r(dt),pt=r(Xe),ct=i(pt,2),mt=r(ct),Ct=i(ct,2);{var Tt=M=>{var ee=Rd(),xe=r(ee);z(Te=>h(xe,`${Te??""} %${t(je)?` · ${t(je)}`:""}`),[()=>Math.round(t(oe))]),p(M,ee)};O(Ct,M=>{t(oe)!=null&&M(Tt)})}var Mt=i(Ct,2);{var Ft=M=>{var ee=Fd();z(()=>St(ee,`${t(oe)==null?"margin-left:auto;":""}margin-right:2px;padding:2px 9px;font-size:12px`)),S("click",ee,xe=>{xe.stopPropagation(),x(t(q).id)}),p(M,ee)},zt=M=>{var ee=Kd();S("click",ee,xe=>{xe.stopPropagation(),$(t(q).id)}),p(M,ee)};O(Mt,M=>{t(q).state==="running"?M(Ft):M(zt,-1)})}var Et=i(Mt,2);nt(Et,()=>T(t(q).state));var D=i(Xe,2);{var J=M=>{var ee=Nd(),xe=r(ee);z(()=>St(xe,`width:${t(oe)??""}%`)),p(M,ee)};O(D,M=>{t(oe)!=null&&t(q).state==="running"&&M(J)})}var I=i(D,2);{var W=M=>{var ee=qd(),xe=r(ee);z(Te=>h(xe,Te),[()=>(t(q).log||[]).join(`
|
||
`)]),p(M,ee)};O(I,M=>{t(Oe)&&M(W)})}z(M=>{wt(pt,1,`li-dot ${M??""}`),h(mt,t(q).label)},[()=>_(t(q).state)]),S("click",Xe,()=>ga.toggle(t(q).id)),S("keydown",Xe,M=>M.key==="Enter"&&ga.toggle(t(q).id)),p(Qe,dt)}),p(P,ye)};O(He,P=>{t(a).length?P(ot,-1):P(Ne)})}z(()=>h(te,t(a).length?t(c)?t(c)+" Fehler":t(a).length+" gesamt":"")),p(e,N),In()}Gn(["click","keydown"]);var jd=g('<span class="mono-sm"> </span>'),Ud=g('<button class="ghost" style="margin-left:auto;padding:3px 12px">Abbrechen</button>'),Hd=g('<span class="badge b-run">✓ fertig</span>'),Jd=g('<span class="badge b-err">✗ fehlgeschlagen</span>'),Qd=g('<span class="badge">abgebrochen</span>'),Zd=g('<span class="badge b-load">läuft…</span>'),Yd=g('<div class="bar" style="margin-bottom:10px"><i></i></div>'),Xd=g('<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>'),ec=g('<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 tc(e,n){Dn(n,!0);const a=V(()=>Si.value),s=V(()=>ga.value);let l=null,o=B(`Verbinde…
|
||
`),d=B("llama-swap"),v,c=B(null),f=B("");const b=new Set,T=V(()=>t(c)?t(s).find(E=>E.id===t(c)):null);xi(()=>{if(!t(T))return;const E=t(T),Q=E.state==="done",ce=E.state==="failed",Ee=E.state==="canceled";(Q||ce||Ee)&&!b.has(E.id)&&(b.add(E.id),ve(Q?`✓ ${t(f)} abgeschlossen.`:Ee?`${t(f)} abgebrochen.`:`✗ ${t(f)} fehlgeschlagen.`,ce),Q&&setTimeout(()=>document.dispatchEvent(new Event("mc:refresh")),800))});function _(E,Q){u(c,E,!0),u(f,Q,!0),ga.track(E)}wi(()=>{x()}),Ho(()=>{l==null||l.close()});function x(){l==null||l.close();const E=t(d);u(o,`Verbinde mit ${E}…
|
||
`);const Q=location.protocol==="https:"?"wss:":"ws:";l=new WebSocket(`${Q}//${location.host}/api/logs/${E}?token=${encodeURIComponent(dl())}`),l.onmessage=ce=>{u(o,t(o)+ce.data),v&&(v.scrollTop=v.scrollHeight)},l.onclose=()=>{u(o,t(o)+`
|
||
— Verbindung getrennt —`)},l.onerror=()=>l==null?void 0:l.close()}async function $(E,Q,ce){if(await hn({title:Q,body:ce,confirmLabel:"Neustarten"}))try{await Se(`/api/service/${E}/restart`,{method:"POST"}),ve("Neustart ausgelöst: "+E),setTimeout(()=>document.dispatchEvent(new Event("mc:refresh")),2e3)}catch(Ee){ve(Ee.message,!0)}}async function R(){if(await hn({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 E=await Se("/api/self-update",{method:"POST"});ve("Update läuft — Dashboard startet gleich neu."),_(E.job_id,"Mission Control Update")}catch(E){ve(E.message,!0)}}async function A(){if(!await hn({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."}))return;const E=await sr({title:"sudo-Passwort",body:"Für das Engine-Update wird einmalig dein sudo-Passwort gebraucht (für den Update-Befehl).",placeholder:"sudo-Passwort",password:!0,confirmLabel:"Update starten"});if(E!==null)try{const Q=await Se("/api/update",{method:"POST",body:JSON.stringify({password:E})});ve("LLM-Engine-Update läuft."),_(Q.job_id,"LLM-Engine-Update")}catch(Q){ve(Q.message,!0)}}async function N(){if(await hn({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"}),ve("Grafikspeicher geleert."),setTimeout(()=>document.dispatchEvent(new Event("mc:refresh")),600)}catch(E){ve(E.message,!0)}}async function Pe(){if(!await hn({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 E=await sr({title:"sudo-Passwort",body:"Für die System-Updates wird einmalig dein sudo-Passwort gebraucht.",placeholder:"sudo-Passwort",password:!0,confirmLabel:"Installieren"});if(E)try{const Q=await Se("/api/os-update",{method:"POST",body:JSON.stringify({password:E})});ve("OS-Update gestartet."),_(Q.job_id,"OS-Update")}catch(Q){ve(Q.message,!0)}}async function Me(){if(!await hn({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 E=await sr({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(E)try{await Se("/api/reboot",{method:"POST",body:JSON.stringify({password:E})}),ve("Reboot ausgelöst — bis gleich.")}catch(Q){ve(Q.message,!0)}}async function Ce(){u(De,"prüfe…");try{const E=await Se("/api/integration/test");u(De,E.ok?`✓ Engine antwortet — ${E.models.length} Modell(e): ${E.models.join(", ")}`:`✗ keine Verbindung: ${E.error}`,!0),u(ie,E.ok,!0)}catch(E){u(De,"✗ "+E.message),u(ie,!1)}}let De=B(""),ie=B(!1);const te=V(()=>{var E;return((E=t(a))==null?void 0:E.models)||[]}),_e=["running","ready","loading","starting"],Ie=V(()=>t(te).find(E=>_e.includes(E.state)));function He(E){if(!E||E.state!=="running")return null;if(typeof E.progress=="number")return Math.min(100,E.progress);const ce=((E.log||[]).at(-1)||"").match(/(\d+(?:\.\d+)?)\s*%/);return ce?Math.min(100,parseFloat(ce[1])):null}var Ne=ec(),ot=i(tt(Ne),2),P=r(ot),ye=i(r(P),2),qe=r(ye),Qe=i(P,4),q=r(Qe),oe=i(r(q)),Le=r(oe),Ge=i(q,2),je=i(r(Ge),2),Oe=r(je),dt=i(Ge,2),Xe=i(r(dt),2),pt=r(Xe),ct=i(Qe,2),mt=r(ct),Ct=i(mt,2);{var Tt=E=>{var Q=jd(),ce=r(Q);z(()=>{St(Q,`color:${t(ie)?"#7ee29a":"#ff9b95"}`),h(ce,t(De))}),p(E,Q)};O(Ct,E=>{t(De)&&E(Tt)})}var Mt=i(ot,2),Ft=i(r(Mt),4),zt=i(Ft,2),Et=i(zt,2),D=i(Et,2),J=i(D,2),I=i(Mt,2),W=i(r(I),4),M=i(W,2),ee=i(I,2);{var xe=E=>{const Q=V(()=>t(T)),ce=V(()=>t(Q).state==="done"),Ee=V(()=>t(Q).state==="failed"),Z=V(()=>t(Q).state==="canceled"),le=V(()=>t(ce)||t(Ee)||t(Z)),Ae=V(()=>He(t(Q)));var ze=Xd(),w=r(ze),j=i(r(w),2);{var pe=ue=>{var ge=Ud();S("click",ge,async()=>{await hn({title:t(f)+" abbrechen?",body:"Der laufende Vorgang wird gestoppt.",confirmLabel:"Abbrechen",danger:!0})&&Se(`/api/jobs/${t(Q).id}/cancel`,{method:"POST"})}),p(ue,ge)};O(j,ue=>{t(le)||ue(pe)})}var U=i(j,2),we=r(U);{var Be=ue=>{var ge=Hd();p(ue,ge)},Fe=ue=>{var ge=Jd();p(ue,ge)},$e=ue=>{var ge=Qd();p(ue,ge)},H=ue=>{var ge=Zd();p(ue,ge)};O(we,ue=>{t(ce)?ue(Be):t(Ee)?ue(Fe,1):t(Z)?ue($e,2):ue(H,-1)})}var Y=i(w,2),X=r(Y),K=i(Y,2);{var ae=ue=>{var ge=Yd(),kt=r(ge);z(()=>St(kt,`width:${t(Ae)??""}%`)),p(ue,ge)};O(K,ue=>{t(Ae)!=null&&!t(le)&&ue(ae)})}var fe=i(K,2),he=r(fe);z(ue=>{h(X,`${t(f)??""}${t(le)?t(ce)?" — erfolgreich.":t(Z)?" — abgebrochen.":" — fehlgeschlagen.":" läuft…"}`),h(he,ue)},[()=>(t(Q).log||[]).join(`
|
||
`)]),p(E,ze)};O(ee,E=>{t(T)&&E(xe)})}var Te=i(ee,2),C=r(Te),F=i(r(C),2),re=r(F);re.value=re.__value="llama-swap";var se=i(re);se.value=se.__value="mission-control";var ne=i(se);ne.value=ne.__value="system";var ke=i(C,4),de=r(ke);Uo(ke,E=>v=E,()=>v),z(E=>{var Q,ce,Ee;St(ye,`margin-left:auto;${(Q=t(a))!=null&&Q.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"}`),h(qe,(ce=t(a))!=null&&ce.swap_ok?"● erreichbar":"● offline"),h(Le,(((Ee=t(a))==null?void 0:Ee.swap_url)||"—")+"/v1"),h(Oe,t(Ie)?t(Ie).name+` (${t(Ie).state})`:"nichts geladen — lädt bei der nächsten Anfrage"),h(pt,E),h(de,t(o))},[()=>t(te).filter(E=>!E.incomplete).length||"keine"]),S("click",mt,Ce),S("click",Ft,()=>$("llama-swap","LLM-Engine neustarten?","Die Engine startet neu. Geladene Modelle werden kurz entladen (~5 Sekunden), laden danach automatisch wieder.")),S("click",zt,()=>$("mission-control","Dashboard neustarten?","Diese Oberfläche trennt sich kurz und verbindet automatisch wieder.")),S("click",Et,R),S("click",D,A),S("click",J,N),S("click",W,Pe),S("click",M,Me),S("change",F,x),Jn(F,()=>t(d),E=>u(d,E)),p(e,Ne),In()}Gn(["click","change"]);var nc=g('<div class="empty" style="text-align:center;padding:30px">Lade Setups…</div>'),ac=g('<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),lr=g('<div class="cb-best-tag">★ Beste Wahl für dein System</div>'),ic=g('<div class="cb-best-tag" style="background:var(--act);color:#fff">Dein Setup</div>'),rc=g('<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>'),sc=g('<div id="cb-recipes" class="grid grid-3" style="gap:10px;margin-top:6px"></div>'),lc=g('<span style="color:var(--warn)">· ⚠ Cache veraltet</span>'),oc=g("<!> <!>",1),dc=g('<div class="empty" style="text-align:center;padding:30px">Frage Quellen ab…</div>'),cc=g('<div class="li-sub" style="color:var(--warn);margin-top:3px"> </div>'),vc=g('<span class="fit-badge ok">✓ installiert</span>'),uc=g('<button class="primary" style="padding:6px 12px;font-size:12.5px">Installieren</button>'),pc=g('<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>'),fc=g('<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>'),hc=g('<button style="padding:4px 10px;border-radius:999px;font-size:12px"> </button>'),gc=g('<button class="ghost" style="padding:4px 10px;border-radius:999px;font-size:12px;color:var(--mut)">✕ zurücksetzen</button>'),mc=g('<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>'),bc=g('<div class="grid grid-3" id="cb-grid"></div>'),_c=g('<div class="li-sub"> </div>'),yc=g('<div class="li-sub mono-sm"> </div>'),xc=g("<span> </span>"),kc=g('<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>'),wc=g('<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>'),Sc=g('Alternative: <a href="#" style="color:var(--accent)"> </a> — passt auf dein System.',1),Mc=g('<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>'),Ec=g('<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>'),Ac=g('<div class="hint">Lade Dateien von HuggingFace…</div>'),is=g("<option> </option>"),Cc=g('<div class="hint" style="margin:-6px 0 14px">Empfohlener Kontext für deine Hardware: <b> </b> — <a href="#">übernehmen</a></div>'),Tc=g('<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>'),zc=g('<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>'),$c=g('<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>'),Pc=g('<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),Dc=g('<div class="hint">Keine GGUF-Dateien im Repo gefunden.</div>'),Ic=g('<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>'),Lc=g('<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>'),Oc=g('<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>'),Bc=g('<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;align-items:center"><span class="text-xs text-mut" style="margin-right:2px">Filter:</span> <!> <!></div> <!></div> <!> <!> <!>',1);function Rc(e,n){Dn(n,!0);const a="Kontext = das Kurzzeitgedächtnis des Modells. Größer = merkt sich mehr, braucht aber mehr Speicher und wird etwas langsamer.",s="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=["qwen2.5","qwen3","qwen2","hermes","mistral","mixtral","devstral","command-r","command_r","llama-3.1","llama3.1","llama-3.3","llama-4","llama4","functionary","watt","firefunction","granite","glm-4","ministral","gemma-3","gemma3"],d=["-r1","deepseek-r1","qwq","magistral","-think","thinking","-o1","gpt-oss","reasoning","exaone-deep","phi-4-reasoning"];function v(k,y=[]){const L=(k||"").toLowerCase(),G=(y||[]).map(Ue=>String(Ue).toLowerCase()),be=G.some(Ue=>Ue.includes("function-calling")||Ue.includes("tool-use")||Ue.includes("tools")),vt=o.some(Ue=>L.includes(Ue));return{moe:_(L),active_b:x(L),vision:["-vl","vision","llava","pixtral","multimodal","-mm-"].some(Ue=>L.includes(Ue))||G.includes("image-text-to-text"),coder:["coder","-code","code-","codestral","starcoder"].some(Ue=>L.includes(Ue)),reasoning:d.some(Ue=>L.includes(Ue))||G.includes("reasoning"),tools:be?"yes":vt?"likely":"no"}}let c=B(Rt({tools:!1,moe:!1,reasoning:!1,vision:!1,coder:!1}));const f=[["tools","🛠 Tools"],["moe","🧩 MoE"],["reasoning","🧠 Logik"],["vision","👁 Bild"],["coder","💻 Code"]];function b(k,y=[]){const L=Object.keys(t(c)).filter(be=>t(c)[be]);if(!L.length)return!0;const G=v(k,y);return L.every(be=>be==="tools"?G.tools!=="no":G[be])}function T(k,y=[]){const L=v(k,y),G=[];return L.coder&&G.push('<span class="chip">💻 Code</span>'),L.vision&&G.push('<span class="chip">👁 Bild</span>'),L.reasoning&&G.push('<span class="chip">🧠 Logik</span>'),L.moe&&G.push(`<span class="chip" title="${Kn(s)}">🧩 MoE${L.active_b?` · ~${L.active_b}B`:""}</span>`),L.tools==="yes"?G.push('<span class="chip" title="Tool-Calling unterstützt">🛠 Tools</span>'):L.tools==="likely"&&G.push('<span class="chip" style="opacity:.55" title="laut Modell-Familie wahrscheinlich tool-fähig">🛠 Tools?</span>'),!L.coder&&!L.vision&&G.unshift('<span class="chip">💬 Chat</span>'),G.join(" ")}function _(k=""){const y=k.toLowerCase();return/\d+x\d+(\.\d+)?b/.test(y)||new RegExp("(?<![a-z])a\\d+(\\.\\d+)?b\\b").test(y)||y.includes("mixtral")||/\bmoe\b/.test(y)}function x(k=""){const y=k.toLowerCase().match(new RegExp("(?<![a-z])a(\\d+(?:\\.\\d+)?)b\\b"));return y?y[1]:null}function $(k){return k==="perfect"?"ok":k==="marginal"?"warn":"bad"}function R(k){return k==="perfect"?"Passt":k==="marginal"?"Knapp":"Zu groß"}function A(k){return`~${(k.req_gb??0).toFixed(1)} GB · ~${Math.round(k.tps??0)} Tok/s`}let N=B(Rt([])),Pe=B(null),Me=B(!0),Ce=B(null),De=B(!1),ie=B(!1),te=B(""),_e=B(Rt([])),Ie=B(!1),He=B("downloads"),Ne=B(Rt([])),ot=B(-1),P=B(null),ye=B(!1),qe=B(""),Qe=B(""),q=B(null),oe=B(""),Le=B(""),Ge=B(8192),je=B(!1),Oe=B(null),dt=B(!1),Xe=B(""),pt=B(""),ct=B(Rt([{repo:"",role:"",quant:"Q4_K_M"}])),mt=B(null);function Ct(k){var y;(y=document.querySelector(`.nav-item[data-view="${k}"]`))==null||y.dispatchEvent(new MouseEvent("click"))}wi(()=>{Tt(),Mt()});async function Tt(){u(Me,!0);try{const k=await Se("/api/cookbook/recipes");u(N,k.recipes||[],!0),u(Pe,k.recommended_id||null,!0)}catch(k){ve(k.message,!0)}u(Me,!1)}async function Mt(k=!1){u(De,!0);try{const y=await Se("/api/cookbook/discover"+(k?"?force=true":""));u(Ce,y,!0),u(ie,y.stale,!0)}catch(y){ve("Empfehlungen nicht ladbar: "+y.message,!0)}u(De,!1)}function Ft(k){k=k.trim();const y=k.match(/huggingface\.co\/([^\s/]+\/[^\s/?#]+)/i);return y?y[1]:/^[\w.-]+\/[\w.-]+$/.test(k)?k:null}async function zt(){const k=t(te).trim(),y=Ft(k),L=k;if(!L&&!y){u(_e,[],!0);return}u(Ie,!0),u(Ne,[],!0),u(ot,-1);try{if(y)u(_e,[{id:y,author:y.split("/")[0],downloads:0}],!0);else{const G=`https://huggingface.co/api/models?search=${encodeURIComponent(L)}&filter=gguf&full=true&sort=${encodeURIComponent(t(He))}&direction=-1&limit=40`,be=await fetch(G);u(_e,await be.json(),!0)}t(_e).forEach((G,be)=>Et(be,G.id))}catch(G){ve(G.message,!0),u(_e,[],!0)}u(Ie,!1)}async function Et(k,y){var L;try{const G=await Se("/api/cookbook/analyze",{method:"POST",body:JSON.stringify({repo_id:y,ctx:8192})});if(!((L=G.files)!=null&&L.length)){t(Ne)[k]=null,D();return}const be=G.files.find(vt=>{var Ue;return(Ue=vt.quant)==null?void 0:Ue.includes("Q4_K_M")})||G.files[0];t(Ne)[k]=be.fit.level,D()}catch{t(Ne)[k]=null,D()}}function D(){let k=-1,y=99;t(Ne).forEach((L,G)=>{if(L==null)return;const be=l[L]??99;be<y&&(y=be,k=G)}),u(ot,k>=0&&y<=1?k:-1,!0)}function J(k){u(P,t(N).find(y=>y.id===k),!0)}async function I(k){const y=document.getElementById("cb-r-install-btn");y&&(y.disabled=!0,y.textContent="Starte…");try{const L=await Se("/api/cookbook/install-recipe",{method:"POST",body:JSON.stringify({recipe_id:k,hf_token:ui()})});ve(`${L.count} Download${L.count!==1?"s":""} läuft — Modelle erscheinen danach automatisch im Modelle-Tab.`),u(P,null),Ct("activity")}catch(L){ve(L.message,!0),y&&(y.disabled=!1,y.textContent="Installieren")}}async function W(k,y){var L,G;u(ye,!0),u(qe,y,!0),u(Qe,k,!0),u(Le,""),u(Ge,8192),u(q,null),u(Oe,null),u(oe,""),u(je,!0);try{if(u(q,await Se("/api/cookbook/analyze",{method:"POST",body:JSON.stringify({repo_id:k,ctx:8192})}),!0),(G=(L=t(q))==null?void 0:L.files)!=null&&G.length){const be=t(q).files.find(vt=>{var Ue;return(Ue=vt.quant)==null?void 0:Ue.includes("Q4_K_M")})||t(q).files[0];u(oe,be.filename,!0),be.optimal_ctx&&t(Ge)===8192&&u(Ge,be.optimal_ctx,!0),M()}}catch(be){ve(be.message,!0)}u(je,!1)}function M(){var k,y,L;!((y=(k=t(q))==null?void 0:k.files)!=null&&y.length)||!t(oe)||(u(Oe,t(q).files.find(G=>G.filename===t(oe))||null,!0),(L=t(Oe))!=null&&L.optimal_ctx&&t(Ge)===8192&&u(Ge,t(Oe).optimal_ctx,!0))}async function ee(){var k,y;if(!t(Qe)||!t(oe))return ve("Bitte eine GGUF-Datei wählen.",!0);u(je,!0);try{const L=((k=t(q))==null?void 0:k.params_b)??7,G=((y=t(Oe))==null?void 0:y.quant)??"Q4_K_M";await Se("/api/cookbook/install-model",{method:"POST",body:JSON.stringify({repo:t(Qe),role:t(Le),params_b:L,quant:G,file:t(oe),ctx:t(Ge),hf_token:ui()})}),ve("Download läuft — Modell erscheint danach automatisch im Modelle-Tab."),u(ye,!1),Ct("activity")}catch(L){ve("Fehler: "+L.message,!0)}u(je,!1)}async function xe(k,y,L,G){G.disabled=!0,G.textContent="Starte…";try{await Se("/api/cookbook/install-model",{method:"POST",body:JSON.stringify({repo:k,role:y,params_b:L,quant:"Q4_K_M",hf_token:ui()})}),ve("Download läuft — Modell erscheint danach automatisch im Modelle-Tab."),Ct("activity")}catch(be){ve(be.message,!0),G.disabled=!1,G.textContent="Installieren"}}function Te(){u(mt,null),u(Xe,""),u(pt,""),u(ct,[{repo:"",role:"",quant:"Q4_K_M"}],!0),u(dt,!0)}function C(k){const y=t(N).find(L=>L.id===k);y&&(u(mt,k,!0),u(Xe,y.title,!0),u(pt,y.desc||"",!0),u(ct,y.models.map(L=>({repo:L.repo,role:L.role,quant:L.quant||"Q4_K_M"})),!0),u(dt,!0))}async function F(){if(!t(Xe).trim())return ve("Bitte einen Titel angeben.",!0);const k=t(ct).filter(y=>y.repo.trim());if(!k.length)return ve("Mindestens ein Modell (Repo) angeben.",!0);try{t(mt)?(await Se("/api/cookbook/user-recipe/"+encodeURIComponent(t(mt)),{method:"PUT",body:JSON.stringify({title:t(Xe),desc:t(pt),models:k})}),ve("Setup aktualisiert.")):(await Se("/api/cookbook/user-recipe",{method:"POST",body:JSON.stringify({title:t(Xe),desc:t(pt),models:k})}),ve("Setup gespeichert.")),u(dt,!1),Tt()}catch(y){ve(y.message,!0)}}async function re(k){const y=t(N).find(L=>L.id===k);if(await hn({title:`„${(y==null?void 0:y.title)||k}" 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(k),{method:"DELETE"}),ve("Setup gelöscht."),Tt()}catch(L){ve(L.message,!0)}}function se(k){if(!_(k))return"";const y=x(k);return`<span class="chip" title="${Kn(s)}">MoE${y?` · ~${y}B aktiv`:""}</span>`}var ne=Bc(),ke=i(tt(ne),2),de=r(ke),E=i(r(de),2),Q=i(de,4);{var ce=k=>{var y=nc();p(k,y)},Ee=k=>{var y=sc();Ze(y,21,()=>t(N),et,(L,G)=>{const be=V(()=>t(G).id===t(Pe));var vt=rc(),Ue=r(vt);{var Xt=Ve=>{var bt=ac(),jt=tt(bt),Ut=i(jt,2);S("click",jt,Kt=>{Kt.stopPropagation(),C(t(G).id)}),S("keydown",jt,Kt=>{Kt.key==="Enter"&&(Kt.stopPropagation(),C(t(G).id))}),S("click",Ut,Kt=>{Kt.stopPropagation(),re(t(G).id)}),S("keydown",Ut,Kt=>{Kt.key==="Enter"&&(Kt.stopPropagation(),re(t(G).id))}),p(Ve,bt)};O(Ue,Ve=>{t(G).user&&Ve(Xt)})}var en=i(Ue,2);{var ft=Ve=>{var bt=lr();p(Ve,bt)},yt=Ve=>{var bt=ic();p(Ve,bt)};O(en,Ve=>{t(be)?Ve(ft):t(G).user&&Ve(yt,1)})}var at=i(en,2),ut=r(at),xt=r(ut),Lt=r(xt),tn=i(ut,2),At=r(tn),st=i(at,2),Ot=r(st),Wt=i(st,2),Pt=r(Wt);z((Ve,bt)=>{wt(vt,1,`card-btn${t(be)?" cb-best":""}`),h(Lt,t(G).title),wt(tn,1,`fit-badge ${Ve??""}`),h(At,bt),h(Ot,t(G).desc),h(Pt,`${t(G).models.length??""} Modell${t(G).models.length>1?"e":""} im Setup`)},[()=>$(t(G).fit_level),()=>R(t(G).fit_level)]),S("click",vt,()=>J(t(G).id)),p(L,vt)}),p(k,y)};O(Q,k=>{t(Me)?k(ce):k(Ee,-1)})}var Z=i(ke,2),le=r(Z),Ae=i(r(le),2),ze=r(Ae);{var w=k=>{const y=V(()=>Math.round((Date.now()/1e3-t(Ce).updated)/60));var L=oc(),G=tt(L);{var be=ft=>{var yt=ci();z(()=>h(yt,`Quellen befragt vor ${t(y)??""} min`)),p(ft,yt)},vt=ft=>{var yt=ci();z(at=>h(yt,`Quellen befragt vor ${at??""} h`),[()=>Math.round(t(y)/60)]),p(ft,yt)},Ue=ft=>{var yt=ci();z(at=>h(yt,`Quellen befragt vor ${at??""} Tg.`),[()=>Math.round(t(y)/1440)]),p(ft,yt)};O(G,ft=>{t(y)<60?ft(be):t(y)<1440?ft(vt,1):ft(Ue,-1)})}var Xt=i(G,2);{var en=ft=>{var yt=lc();p(ft,yt)};O(Xt,ft=>{t(ie)&&ft(en)})}p(k,L)};O(ze,k=>{var y;(y=t(Ce))!=null&&y.updated&&k(w)})}var j=i(Ae,2),pe=r(j),U=i(le,4);{var we=k=>{var y=dc();p(k,y)},Be=k=>{var y=Ea(),L=tt(y);Ze(L,17,()=>t(Ce).categories,et,(G,be)=>{var vt=fc(),Ue=r(vt),Xt=r(Ue),en=r(Xt),ft=i(Ue,2);Ze(ft,21,()=>t(be).models,et,(yt,at)=>{const ut=V(()=>t(be).recommended&&t(at).repo===t(be).recommended);var xt=pc(),Lt=r(xt);{var tn=We=>{var it=lr();p(We,it)};O(Lt,We=>{t(ut)&&We(tn)})}var At=i(Lt,2),st=r(At),Ot=r(st),Wt=r(Ot),Pt=i(Ot,2),Ve=r(Pt),bt=i(st,2),jt=r(bt),Ut=i(At,2);nt(Ut,()=>T(t(at).repo,t(at).tags),!0);var Kt=i(Ut,2),Vn=r(Kt),mn=i(Kt,2);Ze(mn,17,()=>t(at).requirements||[],et,(We,it)=>{var Nt=cc(),Ht=r(Nt);z(()=>h(Ht,`⚠ ${t(it)??""}`)),p(We,Nt)});var bn=i(mn,4),va=r(bn);{var _t=We=>{var it=vc();z(()=>za(it,"title",`bereits eingerichtet als ${t(at).installed??""}`)),p(We,it)},lt=We=>{var it=uc();S("click",it,Nt=>xe(t(at).repo,t(at).role,t(at).params_b,Nt.currentTarget)),p(We,it)};O(va,We=>{t(at).installed?We(_t):We(lt,-1)})}z((We,it,Nt)=>{wt(xt,1,`card${t(ut)?" res-best":""}`),h(Wt,t(at).name),h(Ve,`${t(at).author??""} · ${t(at).params_b??""}B`),wt(bt,1,`fit-badge ${We??""}`),h(jt,t(at).fit.text),h(Vn,`${it??""} · ⬇ ${Nt??""}`)},[()=>$(t(at).fit.level),()=>A(t(at).fit),()=>(t(at).downloads||0).toLocaleString()]),p(yt,xt)}),z(()=>h(en,t(be).title)),p(G,vt)}),p(k,y)};O(U,k=>{var y;t(De)&&!t(Ce)?k(we):(y=t(Ce))!=null&&y.categories&&k(Be,1)})}var Fe=i(Z,2),$e=i(r(Fe),4),H=r($e),Y=i(H,2),X=r(Y);X.value=X.__value="downloads";var K=i(X);K.value=K.__value="trending";var ae=i(K);ae.value=ae.__value="created_at";var fe=i(Y,2),he=r(fe),ue=i($e,2),ge=i(r(ue),2);Ze(ge,17,()=>f,et,(k,y)=>{var L=V(()=>Bn(t(y),2));let G=()=>t(L)[0],be=()=>t(L)[1];var vt=hc(),Ue=r(vt);z(()=>{wt(vt,1,t(c)[G()]?"primary":"ghost"),h(Ue,be())}),S("click",vt,()=>t(c)[G()]=!t(c)[G()]),p(k,vt)});var kt=i(ge,2);{var $t=k=>{var y=gc();S("click",y,()=>u(c,{tools:!1,moe:!1,reasoning:!1,vision:!1,coder:!1},!0)),p(k,y)},Dt=V(()=>Object.values(t(c)).some(k=>k));O(kt,k=>{t(Dt)&&k($t)})}var gn=i(ue,2);{var ca=k=>{var y=bc();Ze(y,21,()=>t(_e),et,(L,G,be)=>{var vt=Ea(),Ue=tt(vt);{var Xt=ft=>{var yt=mc(),at=r(yt);{var ut=mn=>{var bn=lr();p(mn,bn)};O(at,mn=>{be===t(ot)&&mn(ut)})}var xt=i(at,2),Lt=r(xt),tn=r(Lt),At=r(tn),st=i(tn,2),Ot=r(st),Wt=i(Lt,2),Pt=r(Wt),Ve=i(xt,2);nt(Ve,()=>T(t(G).id,t(G).tags),!0);var bt=i(Ve,4),jt=r(bt),Ut=r(jt),Kt=i(jt,2),Vn=r(Kt);z((mn,bn,va,_t,lt)=>{wt(yt,1,`card${be===t(ot)?" res-best":""}`),h(At,mn),h(Ot,t(G).author||""),wt(Wt,1,`fit-badge ${bn??""}`),h(Pt,va),h(Ut,_t),h(Vn,`⬇ ${lt??""}`)},[()=>t(G).id.split("/").pop(),()=>t(Ne)[be]?$(t(Ne)[be]):"warn",()=>t(Ne)[be]?R(t(Ne)[be]):"prüfe…",()=>t(Ne)[be]?A({req_gb:0,tps:0}):"Hardware-Fit…",()=>(t(G).downloads||0).toLocaleString()]),S("click",yt,()=>W(t(G).id,t(G).id.split("/").pop())),p(ft,yt)},en=V(()=>b(t(G).id,t(G).tags));O(Ue,ft=>{t(en)&&ft(Xt)})}p(L,vt)}),p(k,y)};O(gn,k=>{t(_e).length&&k(ca)})}var Yn=i(Fe,2);{var Ya=k=>{const y=V(()=>t(P));var L=Ec(),G=r(L),be=r(G),vt=i(be,2),Ue=r(vt),Xt=i(vt,2),en=r(Xt),ft=i(Xt,2);Ze(ft,21,()=>t(y).models,et,(At,st)=>{var Ot=kc(),Wt=r(Ot),Pt=r(Wt),Ve=r(Pt),bt=r(Ve),jt=i(Ve,2),Ut=r(jt),Kt=i(jt,2);nt(Kt,()=>se(t(st).repo));var Vn=i(Pt,2);{var mn=We=>{var it=_c(),Nt=r(it);z(()=>h(Nt,t(st).why)),p(We,it)};O(Vn,We=>{t(st).why&&We(mn)})}var bn=i(Vn,2);{var va=We=>{var it=yc(),Nt=r(it);z((Ht,cn,Xn)=>h(Nt,`~${Ht??""} GB · ~${cn??""} Tok/s · optimal ~${Xn??""}k Kontext`),[()=>(t(st).fit.req_gb??0).toFixed(1),()=>Math.round(t(st).fit.tps??0),()=>Math.round((t(st).optimal_ctx||8192)/1024)]),p(We,it)};O(bn,We=>{t(st).fit&&We(va)})}var _t=i(Wt,2);{var lt=We=>{var it=xc(),Nt=r(it);z(Ht=>{wt(it,1,`fit-badge ${Ht??""}`),h(Nt,t(st).fit.text)},[()=>$(t(st).fit.level)]),p(We,it)};O(_t,We=>{t(st).fit&&We(lt)})}z(()=>{h(bt,t(st).name),h(Ut,t(st).role)}),p(At,Ot)});var yt=i(ft,2);{var at=At=>{const st=V(()=>Math.max(...t(y).models.map(Ve=>{var bt;return((bt=Ve.fit)==null?void 0:bt.req_gb)??0})));var Ot=wc(),Wt=i(r(Ot)),Pt=r(Wt);z(Ve=>h(Pt,`~${Ve??""} GB`),[()=>t(st).toFixed(1)]),p(At,Ot)};O(yt,At=>{t(y).models.length&&t(y).models[0].fit&&At(at)})}var ut=i(yt,2);{var xt=At=>{const st=V(()=>t(N).find(Ve=>!Ve.user&&Ve.fit_level!=="too_tight"&&Ve.id!==t(y).id));var Ot=Mc(),Wt=i(r(Ot));{var Pt=Ve=>{var bt=Sc(),jt=i(tt(bt)),Ut=r(jt);z(()=>h(Ut,`„${t(st).title??""}" ansehen`)),S("click",jt,Kt=>{Kt.preventDefault(),u(P,null),setTimeout(()=>J(t(st).id),50)}),p(Ve,bt)};O(Wt,Ve=>{t(st)&&Ve(Pt)})}p(At,Ot)};O(ut,At=>{t(y).fit_level==="too_tight"&&At(xt)})}var Lt=i(ut,2),tn=r(Lt);z(()=>{h(Ue,t(y).title),h(en,t(y).desc),wt(Lt,1,`primary${t(y).fit_level==="too_tight"?" warn":""}`),h(tn,t(y).fit_level==="too_tight"?"Trotzdem installieren (nicht empfohlen)":"Komplettes Setup installieren")}),S("click",L,At=>{At.target.classList.contains("modal-overlay")&&u(P,null)}),S("click",be,()=>u(P,null)),S("click",Lt,()=>I(t(y).id)),p(k,L)};O(Yn,k=>{t(P)&&k(Ya)})}var Mi=i(Yn,2);{var Xa=k=>{var y=Ic(),L=r(y),G=r(L),be=i(G,2),vt=r(be),Ue=i(be,2),Xt=r(Ue),en=i(Ue,2);{var ft=ut=>{var xt=Ac();p(ut,xt)},yt=ut=>{var xt=Pc(),Lt=i(tt(xt),2);Ze(Lt,21,()=>t(q).files,et,(_t,lt)=>{const We=V(()=>t(lt).fit.level==="perfect"?"●":t(lt).fit.level==="marginal"?"◐":"○");var it=is(),Nt=r(it),Ht={};z(()=>{h(Nt,`${t(We)??""} ${t(lt).filename??""}`),Ht!==(Ht=t(lt).filename)&&(it.value=(it.__value=t(lt).filename)??"")}),p(_t,it)});var tn=i(Lt,2),At=r(tn),st=i(r(At),2),Ot=i(At,2),Wt=r(Ot),Pt=i(r(Wt));nt(Pt,()=>Sr(a));var Ve=i(Wt,2),bt=i(tn,2);{var jt=_t=>{var lt=Cc(),We=i(r(lt)),it=r(We),Nt=i(We,2);z(Ht=>h(it,`~${Ht??""}k`),[()=>Math.round(t(Oe).optimal_ctx/1024)]),S("click",Nt,Ht=>{Ht.preventDefault(),u(Ge,t(Oe).optimal_ctx,!0)}),p(_t,lt)};O(bt,_t=>{var lt;(lt=t(Oe))!=null&<.optimal_ctx&&_t(jt)})}var Ut=i(bt,2);{var Kt=_t=>{var lt=Tc(),We=r(lt),it=i(r(We),2),Nt=r(it),Ht=i(We,2),cn=r(Ht);z((Xn,Ei,Zi)=>{h(Nt,`~${Xn??""} GB · ~${Ei??""} Tok/s · ${(t(Oe).quant||"GGUF")??""}`),wt(Ht,1,`fit-badge ${Zi??""}`),h(cn,t(Oe).fit.text)},[()=>(t(Oe).fit.req_gb??0).toFixed(1),()=>Math.round(t(Oe).fit.tps??0),()=>$(t(Oe).fit.level)]),p(_t,lt)};O(Ut,_t=>{t(Oe)&&_t(Kt)})}var Vn=i(Ut,2);{var mn=_t=>{const lt=V(()=>t(q).files.find(cn=>cn.fit.level!=="too_tight"&&cn.filename!==t(oe)));var We=Ea(),it=tt(We);{var Nt=cn=>{var Xn=zc(),Ei=i(r(Xn)),Zi=r(Ei);z(Yi=>h(Zi,`${t(lt).filename??""} (${Yi??""})`),[()=>R(t(lt).fit.level)]),S("click",Ei,Yi=>{Yi.preventDefault(),u(oe,t(lt).filename,!0),M()}),p(cn,Xn)},Ht=cn=>{var Xn=$c();p(cn,Xn)};O(it,cn=>{t(lt)?cn(Nt):cn(Ht,-1)})}p(_t,We)};O(Vn,_t=>{var lt,We;((lt=t(Oe))==null?void 0:lt.fit.level)==="too_tight"&&((We=t(q))!=null&&We.files)&&_t(mn)})}var bn=i(Vn,2),va=r(bn);z(()=>{var _t,lt;wt(bn,1,`primary${((_t=t(Oe))==null?void 0:_t.fit.level)==="too_tight"?" warn":""}`),bn.disabled=t(je),h(va,t(je)?"Starte…":((lt=t(Oe))==null?void 0:lt.fit.level)==="too_tight"?"Trotzdem holen (zu groß — nicht empfohlen)":"Herunterladen & Einpflegen")}),S("change",Lt,M),Jn(Lt,()=>t(oe),_t=>u(oe,_t)),on(st,()=>t(Le),_t=>u(Le,_t)),on(Ve,()=>t(Ge),_t=>u(Ge,_t)),S("click",bn,ee),p(ut,xt)},at=ut=>{var xt=Dc();p(ut,xt)};O(en,ut=>{var xt,Lt;t(je)&&!t(q)?ut(ft):(Lt=(xt=t(q))==null?void 0:xt.files)!=null&&Lt.length?ut(yt,1):t(je)||ut(at,2)})}z(()=>{h(vt,t(qe)),h(Xt,t(Qe))}),S("click",y,ut=>{ut.target.classList.contains("modal-overlay")&&u(ye,!1)}),S("click",G,()=>u(ye,!1)),p(k,y)};O(Mi,k=>{t(ye)&&k(Xa)})}var Ji=i(Mi,2);{var Qi=k=>{var y=Oc(),L=r(y),G=r(L),be=i(G,2),vt=r(be),Ue=i(be,6),Xt=i(Ue,4),en=i(Xt,4);Ze(en,17,()=>t(ct),et,(ut,xt,Lt)=>{var tn=Lc(),At=r(tn),st=i(At,2),Ot=i(st,2);Ze(Ot,20,()=>["Q4_K_M","Q5_K_M","Q6_K","Q8_0","Q3_K_M"],et,(Pt,Ve)=>{var bt=is(),jt=r(bt),Ut={};z(()=>{h(jt,Ve),Ut!==(Ut=Ve)&&(bt.__value=Ve)}),p(Pt,bt)});var Wt=i(Ot,2);on(At,()=>t(xt).repo,Pt=>t(xt).repo=Pt),on(st,()=>t(xt).role,Pt=>t(xt).role=Pt),Jn(Ot,()=>t(xt).quant,Pt=>t(xt).quant=Pt),S("click",Wt,()=>u(ct,t(ct).filter((Pt,Ve)=>Ve!==Lt),!0)),p(ut,tn)});var ft=i(en,2),yt=i(ft,4),at=r(yt);z(()=>{h(vt,t(mt)?"Setup bearbeiten":"Eigenes Setup erstellen"),h(at,t(mt)?"Änderungen speichern":"Setup speichern")}),S("click",y,ut=>{ut.target.classList.contains("modal-overlay")&&u(dt,!1)}),S("click",G,()=>u(dt,!1)),on(Ue,()=>t(Xe),ut=>u(Xe,ut)),on(Xt,()=>t(pt),ut=>u(pt,ut)),S("click",ft,()=>u(ct,[...t(ct),{repo:"",role:"",quant:"Q4_K_M"}],!0)),S("click",yt,F),p(k,y)};O(Ji,k=>{t(dt)&&k(Qi)})}z(()=>{j.disabled=t(De),h(pe,t(De)?"Suche…":"Aktualisieren"),fe.disabled=t(Ie),h(he,t(Ie)?"Lade…":"Suchen")}),S("click",E,Te),S("click",j,()=>Mt(!0)),S("keydown",H,k=>k.key==="Enter"&&zt()),on(H,()=>t(te),k=>u(te,k)),Jn(Y,()=>t(He),k=>u(He,k)),S("click",fe,zt),p(e,ne),In()}Gn(["click","keydown","change"]);var Fc=g(`<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>`),Kc=g('<span class="mono-sm"> </span>'),Nc=g('<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>'),qc=g('<span class="chip" role="button" tabindex="0"> </span>'),Gc=g('<div style="margin-top:10px"><a href="#" style="color:var(--mut);font-size:12.5px">Auswahl aufheben (alle)</a></div>'),rs=g('<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>'),Vc=g('<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),Wc=g('<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),jc=g('<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),Uc=g('<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> <div class="hint" style="margin-top:4px">Zed herunterladen: <a href="https://zed.dev" target="_blank" rel="noopener">zed.dev</a> — kostenlos, native Performance, Windows/macOS/Linux.</div>',1),Hc=g('<p>Datei anlegen oder öffnen (OpenCode Desktop nutzt <b>.jsonc</b> — JSON mit Kommentaren):</p> <p class="mono-sm" style="line-height:1.6">Windows: <code>%USERPROFILE%\\.config\\opencode\\opencode.jsonc</code></p> <div class="alert warn" style="margin:8px 0 12px;padding:10px 14px"><span class="a-dot"></span><span>Den <code>"providers"</code>-Block in die bestehende <code>opencode.jsonc</code> einfügen (nicht die ganze Datei ersetzen). Falls bereits ein <code>"llama-swap"</code>-Eintrag existiert: <b>vorher löschen</b>.</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> <div class="hint">OpenCode Desktop: <a href="https://opencode.ai" target="_blank" rel="noopener">opencode.ai</a></div>',1),Jc=g('<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> <div class="hint" style="margin-top:4px">Cline für VS Code: <a href="https://marketplace.visualstudio.com/items?itemName=saoudrizwan.claude-dev" target="_blank" rel="noopener">VS Code Marketplace</a> · für JetBrains: <a href="https://plugins.jetbrains.com/plugin/24604-cline" target="_blank" rel="noopener">JetBrains Marketplace</a></div>',1),Qc=g('<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),Zc=g('<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>'),Yc=g('<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),Xc=g('<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>'),ev=g('<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>'),tv=g('<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),nv=g('<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),av=g('<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>'),iv=g(`<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:4px"><input class="mono-sm" readonly="" style="flex:1;margin:0"/> <button class="ghost">Kopieren</button></div> <div class="flex gap-2" style="align-items:stretch;margin-bottom:12px"><input class="mono-sm" placeholder="LAN-IP überschreiben, z.B. 192.168.178.151 (leer = auto)" style="flex:1;margin:0;font-size:12px;opacity:.7"/></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 rv(e,n){Dn(n,!0);const a=V(()=>Si.value),s=V(()=>{var C;return(((C=t(a))==null?void 0:C.models)||[]).filter(F=>!F.incomplete)});let l=B("zed"),o=B(Rt([])),d=B(""),v=B(!1),c=B("cline"),f=B(Rt(localStorage.getItem("mc_ip_override")||""));function b(C){return/^\d{1,3}(\.\d{1,3}){3}$/.test(C)}function T(){return location.protocol==="https:"||!b(location.hostname)}function _(){return`http://${t(f).trim()||location.hostname}:8080/v1`}const x=V(_);function $(){const C=t(f).trim();C?localStorage.setItem("mc_ip_override",C):localStorage.removeItem("mc_ip_override")}const R=V(()=>Ie(t(c))),A=V(()=>t(o).length?t(o):t(s).map(C=>C.name)),N=V(()=>t(A)[0]||"coder"),Pe=V(()=>{var C;return(C=t(s).find(F=>{var re,se;return(se=(re=F.meta)==null?void 0:re.caps)==null?void 0:se.includes("Bild")}))==null?void 0:C.name});function Me(C,F){const se=(F.length?t(s).filter(ne=>F.includes(ne.name)):t(s).length?t(s):[{name:"coder",meta:{}}]).map(ne=>{var E,Q;const ke=(((E=ne.meta)==null?void 0:E.caps)||[]).some(ce=>/Bild|Vision/i.test(ce)),de=((Q=ne.meta)==null?void 0:Q.ctx)||131072;return` { "name": "${ne.name}", "display_name": "${ne.name}", "max_tokens": ${de}${ke?', "capabilities": { "tools": true, "images": true }':""} }`}).join(`,
|
||
`);return`"language_models": {
|
||
"openai_compatible": {
|
||
"bosgame": {
|
||
"api_url": "${C}",
|
||
"available_models": [
|
||
${se}
|
||
]
|
||
}
|
||
}
|
||
}`}function Ce(C,F){const se=(F.length?t(s).filter(ne=>F.includes(ne.name)):t(s).length?t(s):[{name:"coder",meta:{}}]).map(ne=>{var de;const ke=((de=ne.meta)==null?void 0:de.ctx)||131072;return` "${ne.name}": { "name": "${ne.name}", "contextWindowSize": ${ke} }`}).join(`,
|
||
`);return`"providers": {
|
||
"llama-swap": {
|
||
"npm": "@ai-sdk/openai-compatible",
|
||
"name": "Bosgame (llama-swap)",
|
||
"options": {
|
||
"baseURL": "${C}",
|
||
"apiKey": "local"
|
||
},
|
||
"models": {
|
||
${se}
|
||
}
|
||
}
|
||
}`}function De(C,F){return`{
|
||
"models": [
|
||
${(F.length?t(s).filter(ne=>F.includes(ne.name)):t(s).length?t(s):[{name:"coder",meta:{}}]).map(ne=>` {
|
||
"title": "llama-swap / ${ne.name}",
|
||
"provider": "openai",
|
||
"model": "${ne.name}",
|
||
"apiBase": "${C}",
|
||
"apiKey": "local"
|
||
}`).join(`,
|
||
`)}
|
||
]
|
||
}`}async function ie(){u(d,"Teste…");try{const C=await Se("/api/integration/test");u(v,C.ok,!0),u(d,C.ok?`✓ Verbunden — ${C.models.length} Modell(e): ${C.models.join(", ")}`:`✗ Keine Verbindung: ${C.error}`,!0)}catch(C){u(v,!1),u(d,"✗ "+C.message)}}function te(C){var re;const F=C.querySelector("code");F&&((re=navigator.clipboard)==null||re.writeText(F.textContent||""))}function _e(C){var F;(F=navigator.clipboard)==null||F.writeText(C.value)}function Ie(C){return`{
|
||
"mcpServers": {
|
||
"mission-control-memory": {
|
||
"command": "${C==="bosgame"?"/opt/mission-control/.venv/bin/python":"python"}",
|
||
"args": ["${C==="bosgame"?"/opt/mission-control/mcp_memory.py":"C:\\\\Users\\\\<DeinUsername>\\\\mission-control\\\\mcp_memory.py"}"],
|
||
"env": {
|
||
"MC_URL": "http://192.168.178.151:9000"
|
||
}
|
||
}
|
||
}
|
||
}`}var He=iv(),Ne=i(tt(He),2),ot=i(r(Ne),6),P=r(ot),ye=i(P,2),qe=i(ot,2),Qe=r(qe),q=i(qe,2);{var oe=C=>{var F=Fc();p(C,F)},Le=V(()=>T());O(q,C=>{t(Le)&&C(oe)})}var Ge=i(q,2),je=r(Ge),Oe=i(je,2);{var dt=C=>{var F=Kc(),re=r(F);z(()=>{St(F,`color:${t(v)?"#7ee29a":"#ff9b95"}`),h(re,t(d))}),p(C,F)};O(Oe,C=>{t(d)&&C(dt)})}var Xe=i(Ne,2),pt=i(r(Xe),2);Ze(pt,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."]],et,(C,F)=>{var re=V(()=>Bn(F,3));let se=()=>t(re)[0],ne=()=>t(re)[1],ke=()=>t(re)[2];var de=Nc(),E=r(de),Q=r(E),ce=i(E,2),Ee=r(ce),Z=r(Ee),le=i(Ee,2),Ae=r(le);z(()=>{h(Q,se()),h(Z,ne()),h(Ae,ke())}),p(C,de)});var ct=i(Xe,2);{var mt=C=>{var F=Yc(),re=tt(F),se=r(re),ne=i(r(se),2),ke=r(ne),de=i(se,4);Ze(de,21,()=>t(s),et,(H,Y)=>{const X=V(()=>t(o).includes(t(Y).name));var K=qc(),ae=r(K);z(()=>{St(K,`cursor:pointer;${t(X)?"background:rgba(45,212,191,.2);border-color:var(--accent);color:var(--accent)":""}`),h(ae,t(Y).name)}),S("click",K,()=>u(o,t(X)?t(o).filter(fe=>fe!==t(Y).name):[...t(o),t(Y).name],!0)),S("keydown",K,fe=>fe.key==="Enter"&&u(o,t(X)?t(o).filter(he=>he!==t(Y).name):[...t(o),t(Y).name],!0)),p(H,K)});var E=i(de,2);{var Q=H=>{var Y=Gc(),X=r(Y);S("click",X,K=>{K.preventDefault(),u(o,[],!0)}),p(H,Y)};O(E,H=>{t(o).length&&H(Q)})}var ce=i(re,2),Ee=i(r(ce),6);Ze(Ee,20,()=>[["janai","Jan AI","Einfachstes Chat-Interface — Desktop-App, kein Setup"],["openwebui","OpenWebUI","Browser-Chat für Teams — mehr Features, mehr Setup"]],et,(H,Y)=>{var X=V(()=>Bn(Y,3));let K=()=>t(X)[0],ae=()=>t(X)[1],fe=()=>t(X)[2];var he=rs(),ue=r(he),ge=r(ue),kt=i(ue,2),$t=r(kt);z(()=>{wt(he,1,`card-btn${t(l)===K()?" cb-best":""}`),h(ge,ae()),h($t,fe())}),S("click",he,()=>u(l,K(),!0)),p(H,he)});var Z=i(Ee,4);Ze(Z,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"]],et,(H,Y)=>{var X=V(()=>Bn(Y,3));let K=()=>t(X)[0],ae=()=>t(X)[1],fe=()=>t(X)[2];var he=rs(),ue=r(he),ge=r(ue),kt=i(ue,2),$t=r(kt);z(()=>{wt(he,1,`card-btn${t(l)===K()?" cb-best":""}`),h(ge,ae()),h($t,fe())}),S("click",he,()=>u(l,K(),!0)),p(H,he)});var le=i(ce,2),Ae=i(r(le),2);{var ze=H=>{var Y=Vc(),X=i(tt(Y),6),K=r(X),ae=i(K,2),fe=i(X,4),he=r(fe),ue=i(he,2);z(()=>{ta(K,t(x)),ta(he,t(N))}),S("click",ae,ge=>_e(ge.currentTarget.previousElementSibling)),S("click",ue,ge=>_e(ge.currentTarget.previousElementSibling)),p(H,Y)},w=H=>{const Y=V(()=>De(t(x),t(A)));var X=Wc(),K=i(tt(X),4),ae=r(K),fe=i(ae,2),he=r(fe),ue=r(he),ge=i(K,2),kt=i(r(ge)),$t=r(kt);z(()=>{h(ue,t(Y)),h($t,`llama-swap / ${t(N)??""}`)}),S("click",ae,Dt=>te(Dt.currentTarget.parentElement)),p(H,X)},j=H=>{var Y=jc(),X=i(tt(Y),6),K=r(X),ae=i(K,2),fe=i(X,4),he=r(fe),ue=i(he,2),ge=i(fe,2),kt=i(r(ge),3),$t=r(kt);z(()=>{ta(K,t(x)),ta(he,t(N)),h($t,t(N))}),S("click",ae,Dt=>_e(Dt.currentTarget.previousElementSibling)),S("click",ue,Dt=>_e(Dt.currentTarget.previousElementSibling)),p(H,Y)},pe=H=>{const Y=V(()=>Me(t(x),t(A)));var X=Uc(),K=i(tt(X),4),ae=r(K),fe=i(ae,2),he=r(fe),ue=r(he),ge=i(K,4),kt=i(r(ge)),$t=r(kt);z(()=>{h(ue,t(Y)),h($t,`bosgame / ${t(N)??""}`)}),S("click",ae,Dt=>te(Dt.currentTarget.parentElement)),p(H,X)},U=H=>{const Y=V(()=>Ce(t(x),t(A)));var X=Hc(),K=i(tt(X),6),ae=r(K),fe=i(ae,2),he=r(fe),ue=r(he),ge=i(K,2),kt=i(r(ge),3),$t=r(kt);z(()=>{h(ue,t(Y)),h($t,`llama-swap/${t(N)??""}`)}),S("click",ae,Dt=>te(Dt.currentTarget.parentElement)),p(H,X)},we=H=>{var Y=Jc(),X=i(tt(Y),4),K=r(X),ae=i(K,2),fe=i(X,4),he=r(fe),ue=i(he,2);z(()=>{ta(K,t(x)),ta(he,t(N))}),S("click",ae,ge=>_e(ge.currentTarget.previousElementSibling)),S("click",ue,ge=>_e(ge.currentTarget.previousElementSibling)),p(H,Y)},Be=H=>{var Y=Qc(),X=i(tt(Y),4),K=r(X),ae=i(K,2),fe=i(X,4),he=r(fe),ue=i(he,2);z(()=>ta(K,t(x))),S("click",ae,ge=>_e(ge.currentTarget.previousElementSibling)),S("click",ue,ge=>_e(ge.currentTarget.previousElementSibling)),p(H,Y)};O(Ae,H=>{t(l)==="janai"?H(ze):t(l)==="continue"?H(w,1):t(l)==="antigravity"?H(j,2):t(l)==="zed"?H(pe,3):t(l)==="opencode"?H(U,4):t(l)==="cline"?H(we,5):t(l)==="openwebui"&&H(Be,6)})}var Fe=i(le,2);{var $e=H=>{const Y=V(()=>`curl ${t(x)}/chat/completions \\
|
||
-H "Content-Type: application/json" \\
|
||
-d '{
|
||
"model": "${t(Pe)}",
|
||
"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 X=Zc(),K=r(X),ae=i(r(K),2),fe=r(ae);nt(fe,()=>qt("check"));var he=i(fe),ue=i(K,4),ge=r(ue),kt=i(ge,2),$t=r(kt),Dt=r($t);z(()=>{h(he,` „${t(Pe)??""}" bereit`),h(Dt,t(Y))}),S("click",ge,gn=>te(gn.currentTarget.parentElement)),p(H,X)};O(Fe,H=>{t(Pe)&&H($e)})}z(()=>h(ke,t(o).length?`${t(o).length} von ${t(s).length} ausgewählt`:"alle werden eingeschlossen")),p(C,F)},Ct=C=>{var F=Xc(),re=i(r(F),2),se=i(r(re),4);S("click",se,()=>{var ne;return(ne=document.querySelector(".nav-item[data-view='cookbook']"))==null?void 0:ne.dispatchEvent(new MouseEvent("click"))}),p(C,F)};O(ct,C=>{t(s).length?C(mt):C(Ct,-1)})}var Tt=i(ct,2),Mt=i(r(Tt),2),Ft=i(r(Mt)),zt=i(Mt,2);Ze(zt,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"]],et,(C,F)=>{var re=V(()=>Bn(F,3));let se=()=>t(re)[0],ne=()=>t(re)[1],ke=()=>t(re)[2];var de=ev(),E=r(de),Q=r(E),ce=i(E,2),Ee=r(ce);z(()=>{wt(de,1,`card-btn${t(c)===se()?" cb-best":""}`),h(Q,ne()),h(Ee,ke())}),S("click",de,()=>u(c,se(),!0)),p(C,de)});var Et=i(zt,2),D=r(Et),J=i(D,2),I=r(J),W=r(I),M=i(Et,2);{var ee=C=>{var F=tv();p(C,F)},xe=C=>{var F=nv();p(C,F)},Te=C=>{var F=av();p(C,F)};O(M,C=>{t(c)==="cline"?C(ee):t(c)==="opencode"?C(xe,1):C(Te,-1)})}z(()=>{ta(P,t(x)),h(W,t(R))}),S("click",ye,C=>{const F=C.currentTarget.previousElementSibling;_e(F)}),S("input",Qe,$),on(Qe,()=>t(f),C=>u(f,C)),S("click",je,ie),S("click",Ft,C=>{var F;C.preventDefault(),(F=document.querySelector(".nav-item[data-view='memory']"))==null||F.click()}),S("click",D,C=>te(C.currentTarget.parentElement)),p(e,He),In()}Gn(["click","input","keydown"]);var sv=g('<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>'),lv=g('<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>'),ov=g('<div class="empty" style="text-align:center;padding:40px">Lade News… (erstes Laden kann kurz dauern)</div>'),dv=g('<div class="alert err" style="margin:0"> </div>'),cv=g('<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>'),vv=g('<span class="news-rel">für dich</span>'),uv=g('<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>'),pv=g('<div class="news-grid"></div>'),fv=g('<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 hv(e,n){Dn(n,!0);let a=B(Rt([])),s=B(Rt([])),l=B(!0),o=B("");const d=ie=>ie==="perfect"?"ok":ie==="marginal"?"warn":"bad";function v(ie){const te=Math.max(0,Date.now()/1e3-ie);return te<60?te+"s":te<3600?Math.floor(te/60)+"m":te<86400?Math.floor(te/3600)+"h":Math.floor(te/86400)+"d"}async function c(){u(l,!0),u(o,"");try{u(a,(await Se("/api/news")).items||[],!0)}catch(ie){u(o,ie.message||"Fehler beim Laden",!0)}finally{u(l,!1)}}async function f(){try{u(s,(await Se("/api/cookbook/upgrades")).upgrades||[],!0)}catch{u(s,[],!0)}}async function b(ie,te){var _e;te.disabled=!0,te.textContent="Starte…";try{await Se("/api/cookbook/install-model",{method:"POST",body:JSON.stringify({repo:ie.repo,role:ie.role,params_b:ie.params_b,quant:ie.quant,hf_token:ui()})}),(_e=document.querySelector(".nav-item[data-view='activity']"))==null||_e.dispatchEvent(new MouseEvent("click"))}catch(Ie){te.disabled=!1,te.textContent="Installieren",alert("Fehler: "+Ie.message)}}function T(){c(),f()}wi(()=>{c(),f()});var _=fv(),x=tt(_),$=i(r(x),2),R=i(x,2);{var A=ie=>{var te=lv(),_e=r(te),Ie=i(r(_e),2),He=r(Ie),Ne=i(_e,4);Ze(Ne,21,()=>t(s),et,(ot,P)=>{var ye=sv(),qe=r(ye),Qe=r(qe),q=r(Qe),oe=r(q),Le=i(q,2),Ge=r(Le),je=i(Qe,2),Oe=r(je),dt=i(qe,2);z(Xe=>{h(oe,t(P).name),wt(Le,1,`fit-badge ${Xe??""}`),h(Ge,t(P).fit.text),h(Oe,`Ersetzt dein „${t(P).old??""}". ${t(P).why??""}`)},[()=>d(t(P).fit.level)]),S("click",dt,Xe=>b(t(P),Xe.currentTarget)),p(ot,ye)}),z(()=>h(He,t(s).length)),p(ie,te)};O(R,ie=>{t(s).length&&ie(A)})}var N=i(R,2);{var Pe=ie=>{var te=ov();p(ie,te)},Me=ie=>{var te=dv(),_e=r(te);z(()=>h(_e,t(o))),p(ie,te)},Ce=ie=>{var te=cv();p(ie,te)},De=ie=>{var te=pv();Ze(te,21,()=>t(a),et,(_e,Ie,He)=>{var Ne=uv();wt(Ne,1,`news-card${He===0?" featured":""}`);var ot=r(Ne),P=r(ot),ye=r(P),qe=i(P,2);{var Qe=je=>{var Oe=vv();p(je,Oe)};O(qe,je=>{t(Ie).relevant&&je(Qe)})}var q=i(qe,2),oe=r(q),Le=i(ot,2),Ge=r(Le);z(je=>{za(Ne,"href",t(Ie).link),h(ye,t(Ie).source),h(oe,je),h(Ge,t(Ie).title)},[()=>t(Ie).ts?v(t(Ie).ts):""]),p(_e,Ne)}),p(ie,te)};O(N,ie=>{t(l)?ie(Pe):t(o)?ie(Me,1):t(a).length?ie(De,-1):ie(Ce,2)})}S("click",$,T),p(e,_),In()}Gn(["click"]);const ss=[{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>`]]}],gv=[["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 mv=g('<div class="concept"><h4> </h4> <p> </p></div>'),bv=g("<button> </button>"),_v=g('<details class="guide-acc"><summary> </summary> <div class="acc-body"></div></details>'),yv=g('<div class="card guide-card svelte-112sh7i"><div class="guide-group-hd svelte-112sh7i"> </div> <!></div>'),xv=g('<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"><div class="card-h"><h3>Begriffe kurz erklärt</h3></div> <div class="concept-grid" style="margin-top:8px"></div></div> <div class="guide-tabs svelte-112sh7i"></div> <!>',1);function kv(e,n){Dn(n,!0);let a=B(0);function s(f){var b;u(a,f,!0),(b=document.getElementById(`guide-group-${f}`))==null||b.scrollIntoView({behavior:"smooth",block:"start"})}var l=xv(),o=i(tt(l),2),d=i(r(o),2);Ze(d,21,()=>gv,et,(f,b)=>{var T=V(()=>Bn(t(b),2));let _=()=>t(T)[0],x=()=>t(T)[1];var $=mv(),R=r($),A=r(R),N=i(R,2),Pe=r(N);z(()=>{h(A,_()),h(Pe,x())}),p(f,$)});var v=i(o,2);Ze(v,21,()=>ss,et,(f,b,T)=>{var _=bv(),x=r(_);z(()=>{wt(_,1,`guide-tab${t(a)===T?" active":""}`,"svelte-112sh7i"),h(x,t(b).label)}),S("click",_,()=>s(T)),p(f,_)});var c=i(v,2);Ze(c,17,()=>ss,et,(f,b,T)=>{var _=yv();za(_,"id",`guide-group-${T}`);var x=r(_),$=r(x),R=i(x,2);Ze(R,17,()=>t(b).tutorials,et,(A,N,Pe)=>{var Me=V(()=>Bn(t(N),2));let Ce=()=>t(Me)[0],De=()=>t(Me)[1];var ie=_v();ie.open=T===0&&Pe===0;var te=r(ie),_e=r(te),Ie=i(te,2);nt(Ie,De,!0),z(()=>h(_e,Ce())),p(A,ie)}),z(()=>h($,t(b).label)),p(f,_)}),p(e,l),In()}Gn(["click"]);var wv=g('<div class="card-sub" style="margin-bottom:10px"> </div>'),Sv=g('<div class="card" style="border-color:rgba(45,212,191,.25)"><div class="card-h"><h3>Import aus Claude / Gemini / ChatGPT</h3></div> <div class="card-sub" style="margin-bottom:10px">Füge Erkenntnisse aus anderen KI-Sessions ein — jede Zeile wird ein eigener Eintrag.</div> <label>Einträge (eine Zeile = ein Eintrag)</label> <textarea rows="8" style="width:100%;box-sizing:border-box;resize:vertical;margin-bottom:10px;font-family:var(--mono);font-size:12.5px"></textarea> <div style="display:flex;gap:12px;flex-wrap:wrap;margin-bottom:14px"><div style="flex:1;min-width:160px"><label>Kategorie für alle Einträge</label> <select style="margin-bottom:0"><option>Über mich — Wer du bist, Präferenzen</option><option>Verhalten — Regeln für alle KI-Tools</option><option>Stabil — Projektfakten</option><option>Versioniert — Tech-Versionen</option><option>Temporär — 7 Tage, dann weg</option></select></div> <div style="flex:1;min-width:120px"><label>Quelle</label> <select style="margin-bottom:0"><option>import</option><option>claude</option><option>gemini</option><option>chatgpt</option><option>manual</option></select></div></div> <!> <div class="btn-row"><button class="primary"> </button> <button class="ghost">Abbrechen</button></div></div>'),Mv=g('<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>Über mich — Wer du bist, Präferenzen, Arbeitsweise</option><option>Verhalten — Wie alle KI-Tools sich verhalten sollen</option><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>'),Ev=g('<span class="chip" role="button" tabindex="0"> <span style="color:var(--mut);margin-left:2px"> </span></span>'),Av=g('<div class="card"><div class="card-sub">Lade…</div></div>'),Cv=g('<button class="primary" style="margin-top:14px">+ Ersten Eintrag anlegen</button>'),Tv=g('<div class="card"><div class="empty-c" style="padding:8px 0 4px"><div class="e-t"> </div> <div class="e-s"> </div> <!></div></div>'),zv=g('<textarea rows="3" style="width:100%;box-sizing:border-box;resize:vertical;margin-bottom:8px"></textarea> <select style="margin-bottom:10px"><option>Über mich</option><option>Verhalten</option><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),$v=g('<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>'),Pv=g("<div><!></div>"),Dv=g('<div class="card" style="padding:0;overflow:hidden"></div>'),Iv=g(`<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> <div class="flex gap-2" style="flex-shrink:0;margin-top:4px"><button class="ghost" title="Doppelte Einträge zusammenführen"> </button> <button class="ghost"> </button> <button class="primary"> </button></div></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"><b style="color:#a78bfa">Über mich</b> = wer du bist, Präferenzen · <b style="color:#fb923c">Verhalten</b> = Regeln für alle KI-Tools · <b style="color:var(--accent)">Stabil</b> = Projektfakten · <b style="color:#f59e0b">Versioniert</b> = Tech-Versionen · <b style="color:var(--mut)">Temporär</b> = 7 Tage, dann weg</div></div>`,1);function Lv(e,n){Dn(n,!0);let a=B(Rt([])),s=B(!0),l=B("all"),o=B(!1),d=B(""),v=B("stable"),c=B(null),f=B(""),b=B("stable"),T=B(!1),_=B(""),x=B("stable"),$=B("import"),R=B(!1);const A=V(()=>t(_).split(`
|
||
`).map(I=>I.trim()).filter(I=>I.length>0)),N=V(()=>t(l)==="all"?t(a):t(a).filter(I=>I.category===t(l))),Pe={user:{label:"Über mich",color:"#a78bfa"},instruction:{label:"Verhalten",color:"#fb923c"},stable:{label:"Stabil",color:"var(--accent)"},versioned:{label:"Versioniert",color:"#f59e0b"},ephemeral:{label:"Temporär",color:"var(--mut)"}};function Me(I){const W=Math.floor((Date.now()-new Date(I).getTime())/1e3);return W<60?"gerade eben":W<3600?`vor ${Math.floor(W/60)} Min`:W<86400?`vor ${Math.floor(W/3600)} Std`:`vor ${Math.floor(W/86400)} Tagen`}function Ce(I){return t(a).filter(W=>W.category===I).length}async function De(){try{u(a,await Se("/api/memory"),!0)}catch(I){ve("Laden fehlgeschlagen: "+I.message,!0)}finally{u(s,!1)}}async function ie(){if(t(d).trim())try{const I=await Se("/api/memory",{method:"POST",body:JSON.stringify({content:t(d).trim(),category:t(v),source:"manual"})});u(a,[I,...t(a)],!0),u(d,""),u(v,"stable"),u(o,!1),ve("Gespeichert")}catch(I){ve("Fehler: "+I.message,!0)}}async function te(I){try{const W=await Se(`/api/memory/${I.id}`,{method:"PUT",body:JSON.stringify({content:t(f),category:t(b)})});u(a,t(a).map(M=>M.id===I.id?W:M),!0),u(c,null),ve("Aktualisiert")}catch(W){ve("Fehler: "+W.message,!0)}}async function _e(I){if(await hn({title:"Eintrag löschen?",body:`„${I.content.length>80?I.content.slice(0,80)+"…":I.content}" wird dauerhaft entfernt.`,danger:!0}))try{await Se(`/api/memory/${I.id}`,{method:"DELETE"}),u(a,t(a).filter(M=>M.id!==I.id),!0),ve("Gelöscht")}catch(M){ve("Fehler: "+M.message,!0)}}function Ie(I){u(c,I.id,!0),u(f,I.content,!0),u(b,I.category,!0)}let He=B(!1);async function Ne(){u(He,!0);try{const I=await Se("/api/memory/dedupe",{method:"POST",body:JSON.stringify({apply:!1})});if(I.duplicate_count===0){ve("Keine Dubletten gefunden 🎉");return}if(!await hn({title:`${I.duplicate_count} Dubletten entfernen?`,body:`${I.duplicate_count} doppelte Einträge werden gelöscht; die ${I.groups.length} vollständigeren bleiben erhalten. Nur exakte/enthaltene/sehr ähnliche Einträge derselben Kategorie.`,danger:!0}))return;const M=await Se("/api/memory/dedupe",{method:"POST",body:JSON.stringify({apply:!0})});ve(`${M.removed} Dubletten entfernt`),await De()}catch(I){ve("Fehler: "+I.message,!0)}finally{u(He,!1)}}async function ot(){if(t(A).length===0)return;u(R,!0);let I=0;for(const W of t(A))try{const M=await Se("/api/memory",{method:"POST",body:JSON.stringify({content:W,category:t(x),source:t($)})});u(a,[M,...t(a)],!0),I++}catch{}u(R,!1),u(T,!1),u(_,""),ve(`${I} von ${t(A).length} Einträgen importiert`)}xi(()=>{De()});var P=Iv(),ye=tt(P),qe=i(r(ye),2),Qe=r(qe),q=r(Qe),oe=i(Qe,2),Le=r(oe),Ge=i(oe,2),je=r(Ge),Oe=i(ye,2);{var dt=I=>{var W=Sv(),M=i(r(W),6);za(M,"placeholder",`Tobi arbeitet am liebsten abends.
|
||
Projektsprache: Deutsch.
|
||
Bosgame M5 läuft mit Ubuntu 26.04.
|
||
...`);var ee=i(M,2),xe=r(ee),Te=i(r(xe),2),C=r(Te);C.value=C.__value="user";var F=i(C);F.value=F.__value="instruction";var re=i(F);re.value=re.__value="stable";var se=i(re);se.value=se.__value="versioned";var ne=i(se);ne.value=ne.__value="ephemeral";var ke=i(xe,2),de=i(r(ke),2),E=r(de);E.value=E.__value="import";var Q=i(E);Q.value=Q.__value="claude";var ce=i(Q);ce.value=ce.__value="gemini";var Ee=i(ce);Ee.value=Ee.__value="chatgpt";var Z=i(Ee);Z.value=Z.__value="manual";var le=i(ee,2);{var Ae=U=>{var we=wv(),Be=r(we);z(()=>h(Be,`${t(A).length??""} Eintrag/Einträge erkannt`)),p(U,we)};O(le,U=>{t(A).length>0&&U(Ae)})}var ze=i(le,2),w=r(ze),j=r(w),pe=i(w,2);z(()=>{w.disabled=t(A).length===0||t(R),h(j,t(R)?"Importiere…":`${t(A).length} Einträge speichern`)}),on(M,()=>t(_),U=>u(_,U)),Jn(Te,()=>t(x),U=>u(x,U)),Jn(de,()=>t($),U=>u($,U)),S("click",w,ot),S("click",pe,()=>{u(T,!1),u(_,"")}),p(I,W)};O(Oe,I=>{t(T)&&I(dt)})}var Xe=i(Oe,2);{var pt=I=>{var W=Mv(),M=i(r(W),4),ee=i(M,4),xe=r(ee);xe.value=xe.__value="user";var Te=i(xe);Te.value=Te.__value="instruction";var C=i(Te);C.value=C.__value="stable";var F=i(C);F.value=F.__value="versioned";var re=i(F);re.value=re.__value="ephemeral";var se=i(ee,2),ne=r(se),ke=i(ne,2);z(de=>ne.disabled=de,[()=>!t(d).trim()]),S("keydown",M,de=>{de.key==="Enter"&&(de.ctrlKey||de.metaKey)&&ie()}),on(M,()=>t(d),de=>u(d,de)),Jn(ee,()=>t(v),de=>u(v,de)),S("click",ne,ie),S("click",ke,()=>{u(o,!1),u(d,"")}),p(I,W)};O(Xe,I=>{t(o)&&I(pt)})}var ct=i(Xe,2),mt=r(ct),Ct=i(r(mt),2);Ze(Ct,17,()=>[["all","Alle","",t(a).length],["user","Über mich","#a78bfa",Ce("user")],["instruction","Verhalten","#fb923c",Ce("instruction")],["stable","Stabil","var(--accent)",Ce("stable")],["versioned","Versioniert","#f59e0b",Ce("versioned")],["ephemeral","Temporär","var(--mut)",Ce("ephemeral")]],et,(I,W)=>{var M=V(()=>Bn(t(W),4));let ee=()=>t(M)[0],xe=()=>t(M)[1],Te=()=>t(M)[2],C=()=>t(M)[3];var F=Ev(),re=r(F),se=i(re),ne=r(se);z(()=>{St(F,`cursor:pointer;${t(l)===ee()?`background:rgba(45,212,191,.12);border-color:${Te()||"var(--accent)"};color:${Te()||"var(--accent)"}`:""}`),h(re,`${xe()??""} `),h(ne,C())}),S("click",F,()=>u(l,ee(),!0)),S("keydown",F,ke=>ke.key==="Enter"&&u(l,ee(),!0)),p(I,F)});var Tt=i(ct,2);{var Mt=I=>{var W=Av();p(I,W)},Ft=I=>{var W=Tv(),M=r(W),ee=r(M),xe=r(ee),Te=i(ee,2),C=r(Te),F=i(Te,2);{var re=se=>{var ne=Cv();S("click",ne,()=>u(o,!0)),p(se,ne)};O(F,se=>{t(a).length===0&&se(re)})}z(()=>{h(xe,t(a).length===0?"Noch keine Einträge":"Keine Treffer"),h(C,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.")}),p(I,W)},zt=I=>{var W=Dv();Ze(W,23,()=>t(N),M=>M.id,(M,ee,xe)=>{var Te=Pv(),C=r(Te);{var F=se=>{var ne=zv(),ke=tt(ne),de=i(ke,2),E=r(de);E.value=E.__value="user";var Q=i(E);Q.value=Q.__value="instruction";var ce=i(Q);ce.value=ce.__value="stable";var Ee=i(ce);Ee.value=Ee.__value="versioned";var Z=i(Ee);Z.value=Z.__value="ephemeral";var le=i(de,2),Ae=r(le),ze=i(Ae,2);on(ke,()=>t(f),w=>u(f,w)),Jn(de,()=>t(b),w=>u(b,w)),S("click",Ae,()=>te(t(ee))),S("click",ze,()=>u(c,null)),p(se,ne)},re=se=>{var ne=$v(),ke=r(ne),de=r(ke),E=r(de),Q=i(de,2),ce=r(Q),Ee=r(ce),Z=i(ce,2),le=r(Z),Ae=i(Z,2),ze=r(Ae),w=i(ke,2),j=r(w),pe=i(j,2);z(U=>{var we,Be,Fe;h(E,t(ee).content),St(ce,`border-color:${(((we=Pe[t(ee).category])==null?void 0:we.color)||"var(--mut)")??""};color:${(((Be=Pe[t(ee).category])==null?void 0:Be.color)||"var(--mut)")??""}`),h(Ee,((Fe=Pe[t(ee).category])==null?void 0:Fe.label)||t(ee).category),h(le,t(ee).source),h(ze,U)},[()=>Me(t(ee).updated_at)]),S("click",j,()=>Ie(t(ee))),S("click",pe,()=>_e(t(ee))),p(se,ne)};O(C,se=>{t(c)===t(ee).id?se(F):se(re,-1)})}z(()=>St(Te,`padding:14px 16px;${t(xe)<t(N).length-1?"border-bottom:1px solid var(--brd, rgba(255,255,255,.07))":""}`)),p(M,Te)}),p(I,W)};O(Tt,I=>{t(s)?I(Mt):t(N).length===0?I(Ft,1):I(zt,-1)})}var Et=i(Tt,2),D=i(r(Et),2),J=i(r(D),3);z(()=>{Qe.disabled=t(He),h(q,t(He)?"…":"🧹 Aufräumen"),h(Le,t(T)?"Abbrechen":"⇩ Import"),h(je,t(o)?"Abbrechen":"+ Eintrag")}),S("click",Qe,Ne),S("click",oe,()=>{u(T,!t(T)),u(o,!1),u(_,"")}),S("click",Ge,()=>{u(o,!t(o)),u(T,!1),u(d,"")}),S("click",J,I=>{var W;I.preventDefault(),(W=document.querySelector(".nav-item[data-view='connect']"))==null||W.click()}),p(e,P),In()}Gn(["click","keydown"]);var ls=g('<span class="chip" style="font-size:11px;color:var(--mut)"> </span>'),Ov=g('<span><b style="color:var(--accent)"> </b> <span class="card-sub">Sessions</span></span>'),Bv=g('<span><b style="color:var(--accent)"> </b> <span class="card-sub">Nachrichten</span></span>'),Rv=g('<span><b style="color:var(--accent)"> </b> <span class="card-sub">Tool-Calls</span></span>'),Fv=g('<span><b style="color:var(--accent)"> </b> <span class="card-sub">Tokens</span></span>'),Kv=g('<span><b style="color:var(--accent)"> </b> <span class="card-sub">aktiv</span></span>'),Nv=g('<div style="display:flex;align-items:center;gap:8px;font-size:12px"><span style="min-width:230px"> </span> <span style="flex:1;height:6px;background:rgba(255,255,255,.05);border-radius:3px;overflow:hidden"><span></span></span> <span class="card-sub" style="font-size:11px;min-width:64px;text-align:right"> </span></div>'),qv=g('<div class="card-sub" style="font-size:11px;margin-bottom:4px">Meistgenutzte Tools</div> <div style="display:flex;flex-direction:column;gap:3px"></div>',1),Gv=g('<div class="tile" style="margin-bottom:10px"><div style="margin-bottom:8px"><b>Aktivität</b> <span class="card-sub" style="font-size:11px">(letzte 30 Tage)</span></div> <div style="display:flex;gap:18px;flex-wrap:wrap;font-size:12.5px;margin-bottom:8px"><!> <!> <!> <!> <!></div> <!></div>'),Vv=g('<li style="font-size:12.5px;line-height:1.45"> </li>'),Wv=g('<ul style="margin:0 0 6px;padding-left:18px;display:flex;flex-direction:column;gap:3px"></ul>'),jv=g('<div class="card-sub" style="font-size:11.5px;border-top:1px solid rgba(255,255,255,.06);padding-top:6px;margin-top:2px"> </div>'),Uv=g('<div class="tile" style="margin-bottom:10px"><div style="margin-bottom:6px"><b>Was Hermes über dich gelernt hat</b> <span class="card-sub" style="font-size:11px">(automatisches Profil)</span></div> <!> <!></div>'),Hv=g(`<div class="card-sub" style="font-size:12px">Keine geplanten Jobs. Hermes kann selbst welche anlegen — sag ihm z. B.
|
||
„Erinnere mich jeden Morgen um 9 Uhr an die offenen Modell-Upgrades".</div>`),Jv=g('<span style="color:var(--mut)"><span style="opacity:.6"> </span> </span>'),Qv=g(`<div style="display:flex;align-items:center;gap:8px;font-size:12.5px;
|
||
padding:6px 8px;background:rgba(255,255,255,.02);border-radius:6px"></div>`),Zv=g('<div style="display:flex;flex-direction:column;gap:6px"></div>'),Yv=g('<div class="card-sub" style="font-size:12px">Keine Skills geladen (oder Agent offline).</div>'),Xv=g('<span class="card-sub" style="font-size:11px"> </span>'),eu=g('<span class="chip" style="font-size:10px;color:var(--accent);border-color:rgba(45,212,191,.3)"> </span>'),tu=g('<div><span></span> <span style="font-weight:500"> </span> <!> <span style="flex:1"></span> <!> <span class="card-sub" style="font-size:10px"> </span></div>'),nu=g('<div style="max-height:260px;overflow-y:auto;display:flex;flex-direction:column;gap:3px"></div>'),au=g('<div class="card" style="border-color:rgba(45,212,191,.3)"><div class="card-h" style="display:flex;justify-content:space-between;align-items:center"><h3>Agent-Cockpit</h3> <button class="ghost" style="font-size:11px;padding:2px 10px"> </button></div> <div class="tile" style="margin-bottom:10px"><div style="display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:8px"><div><b>Status</b> <div class="card-sub" style="font-size:12px">Hermes-Gateway-Dienst (:8642) auf dem Bosgame</div></div> <div class="flex gap-2" style="flex-wrap:wrap;align-items:center"><span class="chip"> </span> <span class="chip"> </span> <!> <!></div></div></div> <!> <!> <div class="tile" style="margin-bottom:10px"><div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:6px"><b>Geplante Aufgaben <span class="card-sub" style="font-size:11px"> </span></b></div> <!></div> <div class="tile"><div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:6px"><b>Skills <span class="card-sub" style="font-size:11px"> </span></b></div> <!></div></div>'),iu=g('<div class="log" style="margin-top:8px"><code>pip install faster-whisper</code></div>'),ru=g('<div class="log" style="margin-top:8px"><code> </code></div>'),su=g('<div style="margin-bottom:8px"><div class="card-sub" style="font-size:11.5px;margin-bottom:4px">4. Bosgame-Key eintragen (in Windows PowerShell):</div> <div style="position:relative"><button class="ghost" style="position:absolute;top:6px;right:6px;font-size:11px;padding:2px 8px;z-index:1">Kopieren</button> <div class="log"><code> </code></div></div></div>'),lu=g('<div class="card-sub" style="font-size:11.5px">SSH-Key nicht gefunden — bitte auf dem Bosgame generieren: <code style="display:block;margin-top:4px">ssh-keygen -t ed25519 -C "hermes-agent@bosgame" -f ~/.ssh/id_ed25519_hermes_agent -N ""</code></div>'),ou=g('<div style="margin-top:12px"><div style="font-size:12.5px;font-weight:500;margin-bottom:8px">Einrichtung (einmalig, ~3 Minuten):</div> <div style="margin-bottom:8px"><div class="card-sub" style="font-size:11.5px;margin-bottom:4px">1. PowerShell als Admin — OpenSSH Server installieren:</div> <div class="log"><code>Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0</code></div></div> <div style="margin-bottom:8px"><div class="card-sub" style="font-size:11.5px;margin-bottom:4px">2. Dienst starten und dauerhaft aktivieren:</div> <div class="log"><code></code></div></div> <div style="margin-bottom:8px"><div class="card-sub" style="font-size:11.5px;margin-bottom:4px">3. SSH-Ordner erstellen:</div> <div class="log"><code></code></div></div> <!> <div style="margin-bottom:8px"><div class="card-sub" style="font-size:11.5px;margin-bottom:4px">5. Windows-IP in Mission Control Env-Var setzen:</div> <div class="log"><code>HERMES_WINDOWS_HOST=192.168.178.XXX</code></div></div> <button class="primary" style="margin-top:4px">Verbindung testen</button></div>'),du=g('<div class="card" style="border-color:rgba(45,212,191,.3)"><div class="card-h"><h3>Hermes Setup-Wizard</h3></div> <div class="tile" style="margin-bottom:10px"><div style="display:flex;justify-content:space-between;align-items:center"><div><b>Whisper (Sprache → Text)</b> <div class="card-sub" style="font-size:12px">faster-whisper muss auf dem Bosgame installiert sein</div></div> <span class="chip"> </span></div> <!></div> <div class="tile" style="margin-bottom:10px"><div style="display:flex;justify-content:space-between;align-items:center"><div><b>Piper TTS (Text → Sprache)</b> <div class="card-sub" style="font-size:12px">Piper-Binary + deutsche Stimme</div></div> <span class="chip"> </span></div> <!></div> <div class="tile"><div style="display:flex;justify-content:space-between;align-items:center"><div><b>Windows SSH-Verbindung</b> <div class="card-sub" style="font-size:12px">Damit Hermes Dateien auf deinem Windows-PC ändern kann</div></div> <span class="chip"> </span></div> <!></div></div>'),cu=g('<iframe title="Hermes Chat" src="/hermes-ui/chat" style="width:100%;height:calc(100dvh - 116px);min-height:520px;border:0;display:block;background:#0f1720"></iframe>'),vu=g(`<div class="empty-c" style="padding:48px 24px"><div class="e-t">Hermes-Agent offline</div> <div class="e-s">Der Hermes-Gateway (:8642) bzw. das Dashboard (:9119) ist nicht erreichbar.
|
||
Status im Cockpit prüfen oder den Dienst neu starten.</div></div>`),uu=g('<div class="pagehead" style="display:flex;justify-content:space-between;align-items:center;margin-bottom:10px"><h1 style="margin:0;font-size:20px">Hermes</h1> <div class="flex gap-2" style="flex-shrink:0;flex-wrap:wrap;align-items:center"><span class="chip"> </span> <button class="ghost">📡 Cockpit</button> <button class="ghost" style="padding:4px 10px;font-size:12px">⚙ Setup</button></div></div> <!> <!> <div class="card" style="padding:0;overflow:hidden;border-radius:12px"><!></div>',1);function pu(e,n){Dn(n,!0);let a=B(null),s=B(!1),l=B(!1),o=B(!1),d=B(null),v=B(Rt([])),c=B(Rt([])),f=B(null),b=B(null),T=B("");async function _(){try{u(a,await Se("/api/hermes/status"),!0)}catch{u(a,null)}}async function x(){try{const q=await Se("/api/hermes/pubkey");u(T,q.pubkey,!0)}catch{u(T,"")}}async function $(){u(o,!0);try{const[q,oe,Le,Ge,je]=await Promise.all([Se("/api/hermes/agent"),Se("/api/hermes/cron"),Se("/api/hermes/skills"),Se("/api/hermes/learned"),Se("/api/hermes/insights")]);u(d,q,!0),u(v,oe.jobs||[],!0),u(c,Le.skills||[],!0),u(f,Ge,!0),u(b,je,!0)}catch{u(d,null)}u(o,!1)}let R=V(()=>[...t(c)].sort((q,oe)=>(oe.use_count||0)-(q.use_count||0)||(q.name||"").localeCompare(oe.name||""))),A=V(()=>t(c).filter(q=>(q.status||"").includes("enabled")).length);function N(){var q;(q=navigator.clipboard)==null||q.writeText(t(T)),ve("SSH-Key kopiert")}xi(()=>{_()});var Pe=uu(),Me=tt(Pe),Ce=i(r(Me),2),De=r(Ce),ie=r(De),te=i(De,2),_e=i(te,2),Ie=i(Me,2);{var He=q=>{var oe=au(),Le=r(oe),Ge=i(r(Le),2),je=r(Ge),Oe=i(Le,2),dt=r(Oe),Xe=i(r(dt),2),pt=r(Xe),ct=r(pt),mt=i(pt,2),Ct=r(mt),Tt=i(mt,2);{var Mt=Z=>{var le=ls(),Ae=r(le);z(()=>h(Ae,`Ticker vor ${t(d).heartbeat_age_s??""}s`)),p(Z,le)};O(Tt,Z=>{var le;((le=t(d))==null?void 0:le.heartbeat_age_s)!=null&&Z(Mt)})}var Ft=i(Tt,2);{var zt=Z=>{var le=ls(),Ae=r(le);z(ze=>{za(le,"title",t(d).version),h(Ae,ze)},[()=>t(d).version.split(" · ")[0]]),p(Z,le)};O(Ft,Z=>{var le;(le=t(d))!=null&&le.version&&Z(zt)})}var Et=i(Oe,2);{var D=Z=>{var le=Gv(),Ae=i(r(le),2),ze=r(Ae);{var w=K=>{var ae=Ov(),fe=r(ae),he=r(fe);z(()=>h(he,t(b).sessions)),p(K,ae)};O(ze,K=>{t(b).sessions&&K(w)})}var j=i(ze,2);{var pe=K=>{var ae=Bv(),fe=r(ae),he=r(fe);z(()=>h(he,t(b).messages)),p(K,ae)};O(j,K=>{t(b).messages&&K(pe)})}var U=i(j,2);{var we=K=>{var ae=Rv(),fe=r(ae),he=r(fe);z(()=>h(he,t(b).tool_calls)),p(K,ae)};O(U,K=>{t(b).tool_calls&&K(we)})}var Be=i(U,2);{var Fe=K=>{var ae=Fv(),fe=r(ae),he=r(fe);z(()=>h(he,t(b).total_tokens)),p(K,ae)};O(Be,K=>{t(b).total_tokens&&K(Fe)})}var $e=i(Be,2);{var H=K=>{var ae=Kv(),fe=r(ae),he=r(fe);z(()=>h(he,t(b).active_time)),p(K,ae)};O($e,K=>{t(b).active_time&&K(H)})}var Y=i(Ae,2);{var X=K=>{var ae=qv(),fe=i(tt(ae),2);Ze(fe,21,()=>t(b).top_tools.slice(0,6),et,(he,ue)=>{var ge=Nv(),kt=r(ge),$t=r(kt),Dt=i(kt,2),gn=r(Dt),ca=i(Dt,2),Yn=r(ca);z(()=>{h($t,t(ue).name),St(gn,`display:block;height:100%;width:${t(ue).pct??""}%;background:var(--accent)`),h(Yn,`${t(ue).calls??""}× · ${t(ue).pct??""}%`)}),p(he,ge)}),p(K,ae)};O(Y,K=>{var ae;(ae=t(b).top_tools)!=null&&ae.length&&K(X)})}p(Z,le)};O(Et,Z=>{t(b)&&(t(b).sessions||t(b).total_tokens)&&Z(D)})}var J=i(Et,2);{var I=Z=>{var le=Uv(),Ae=i(r(le),2);{var ze=pe=>{var U=Wv();Ze(U,21,()=>t(f).user_facts,et,(we,Be)=>{var Fe=Vv(),$e=r(Fe);z(()=>h($e,t(Be))),p(we,Fe)}),p(pe,U)};O(Ae,pe=>{var U;(U=t(f).user_facts)!=null&&U.length&&pe(ze)})}var w=i(Ae,2);{var j=pe=>{var U=jv(),we=r(U);z(()=>h(we,t(f).memory)),p(pe,U)};O(w,pe=>{t(f).memory&&pe(j)})}p(Z,le)};O(J,Z=>{var le,Ae,ze;((Ae=(le=t(f))==null?void 0:le.user_facts)!=null&&Ae.length||(ze=t(f))!=null&&ze.memory)&&Z(I)})}var W=i(J,2),M=r(W),ee=r(M),xe=i(r(ee)),Te=r(xe),C=i(M,2);{var F=Z=>{var le=Hv();p(Z,le)},re=Z=>{var le=Zv();Ze(le,21,()=>t(v),et,(Ae,ze)=>{var w=Qv();Ze(w,21,()=>Object.entries(t(ze)),et,(j,pe)=>{var U=V(()=>Bn(t(pe),2));let we=()=>t(U)[0],Be=()=>t(U)[1];var Fe=Ea(),$e=tt(Fe);{var H=Y=>{var X=Jv(),K=r(X),ae=r(K),fe=i(K);z(()=>{h(ae,`${we()??""}:`),h(fe,` ${Be()??""}`)}),p(Y,X)};O($e,Y=>{Be()&&Y(H)})}p(j,Fe)}),p(Ae,w)}),p(Z,le)};O(C,Z=>{t(v).length===0?Z(F):Z(re,-1)})}var se=i(W,2),ne=r(se),ke=r(ne),de=i(r(ke)),E=r(de),Q=i(ne,2);{var ce=Z=>{var le=Yv();p(Z,le)},Ee=Z=>{var le=nu();Ze(le,21,()=>t(R),et,(Ae,ze)=>{var w=tu(),j=r(w),pe=i(j,2),U=r(pe),we=i(pe,2);{var Be=X=>{var K=Xv(),ae=r(K);z(()=>h(ae,t(ze).category)),p(X,K)};O(we,X=>{t(ze).category&&X(Be)})}var Fe=i(we,4);{var $e=X=>{var K=eu(),ae=r(K);z(()=>h(ae,`${t(ze).use_count??""}× genutzt`)),p(X,K)};O(Fe,X=>{t(ze).use_count>0&&X($e)})}var H=i(Fe,2),Y=r(H);z((X,K)=>{St(w,`display:flex;align-items:center;gap:8px;font-size:12.5px;padding:4px 8px;
|
||
border-radius:6px;${X??""}`),St(j,`width:7px;height:7px;border-radius:50%;flex-shrink:0;
|
||
background:${K??""}`),h(U,t(ze).name),h(Y,t(ze).source)},[()=>(t(ze).status||"").includes("enabled")?"":"opacity:.45",()=>(t(ze).status||"").includes("enabled")?"var(--accent)":"var(--mut)"]),p(Ae,w)}),p(Z,le)};O(Q,Z=>{t(c).length===0?Z(ce):Z(Ee,-1)})}z(()=>{var Z,le,Ae,ze;h(je,t(o)?"…":"↻ Aktualisieren"),St(pt,`font-size:11px;${((Z=t(d))==null?void 0:Z.gateway_state)==="running"?"color:#7ee29a;border-color:rgba(126,226,154,.4)":"color:#ff9b95;border-color:rgba(255,155,149,.4)"}`),h(ct,`● ${((le=t(d))==null?void 0:le.gateway_state)??"offline"??""}`),St(mt,`font-size:11px;${(Ae=t(d))!=null&&Ae.cron_running?"color:var(--accent);border-color:var(--accent)":"color:var(--mut)"}`),h(Ct,`⏱ Scheduler ${(ze=t(d))!=null&&ze.cron_running?"läuft":"inaktiv"}`),h(Te,`(${t(v).length??""})`),h(E,`(${t(A)??""} aktiv von ${t(c).length??""})`)}),S("click",Ge,$),p(q,oe)};O(Ie,q=>{t(l)&&q(He)})}var Ne=i(Ie,2);{var ot=q=>{var oe=du(),Le=i(r(oe),2),Ge=r(Le),je=i(r(Ge),2),Oe=r(je),dt=i(Ge,2);{var Xe=W=>{var M=iu();p(W,M)};O(dt,W=>{var M;((M=t(a))==null?void 0:M.whisper)==="not_installed"&&W(Xe)})}var pt=i(Le,2),ct=r(pt),mt=i(r(ct),2),Ct=r(mt),Tt=i(ct,2);{var Mt=W=>{var M=ru(),ee=r(M),xe=r(ee);z(Te=>h(xe,Te),[()=>["# 1. Piper Binary (Linux x86_64)","mkdir -p /opt/mission-control/piper/voices","cd /tmp && wget -q https://github.com/rhasspy/piper/releases/download/2023.11.14-2/piper_linux_x86_64.tar.gz","tar -xzf piper_linux_x86_64.tar.gz -C /opt/mission-control/piper/ --strip-components=1","","# 2. Deutsche Stimme — Kerstin (weiblich, ~25 MB)","wget -q -O /opt/mission-control/piper/voices/de_DE-kerstin-low.onnx \\",' "https://huggingface.co/rhasspy/piper-voices/resolve/v1.0.0/de/de_DE/kerstin/low/de_DE-kerstin-low.onnx"',"wget -q -O /opt/mission-control/piper/voices/de_DE-kerstin-low.onnx.json \\",' "https://huggingface.co/rhasspy/piper-voices/resolve/v1.0.0/de/de_DE/kerstin/low/de_DE-kerstin-low.onnx.json"'].join(`
|
||
`)]),p(W,M)};O(Tt,W=>{var M;((M=t(a))==null?void 0:M.piper)!=="ready"&&W(Mt)})}var Ft=i(pt,2),zt=r(Ft),Et=i(r(zt),2),D=r(Et),J=i(zt,2);{var I=W=>{var M=ou(),ee=i(r(M),4),xe=i(r(ee),2),Te=r(xe);Te.textContent=`Start-Service sshd
|
||
Set-Service -Name sshd -StartupType Automatic`;var C=i(ee,2),F=i(r(C),2),re=r(F);re.textContent='New-Item -ItemType Directory -Force -Path "$env:USERPROFILE\\.ssh"';var se=i(C,2);{var ne=E=>{var Q=su(),ce=i(r(Q),2),Ee=r(ce),Z=i(Ee,2),le=r(Z),Ae=r(le);z(()=>h(Ae,'echo "'+t(T)+'" >> "$env:USERPROFILE\\.ssh\\authorized_keys"')),S("click",Ee,N),p(E,Q)},ke=E=>{var Q=lu();p(E,Q)};O(se,E=>{t(T)?E(ne):E(ke,-1)})}var de=i(se,4);S("click",de,()=>{_(),ve("Status aktualisiert")}),p(W,M)};O(J,W=>{var M;(M=t(a))!=null&&M.ssh_ok||W(I)})}z(()=>{var W,M,ee,xe,Te,C;St(je,`font-size:11px;${((W=t(a))==null?void 0:W.whisper)!=="not_installed"?"color:#7ee29a":"color:#ff9b95"}`),h(Oe,((M=t(a))==null?void 0:M.whisper)!=="not_installed"?"✓ OK":"✗ fehlt"),St(mt,`font-size:11px;${((ee=t(a))==null?void 0:ee.piper)==="ready"?"color:#7ee29a":"color:#ff9b95"}`),h(Ct,((xe=t(a))==null?void 0:xe.piper)==="ready"?"✓ OK":"✗ fehlt"),St(Et,`font-size:11px;${(Te=t(a))!=null&&Te.ssh_ok?"color:#7ee29a":"color:var(--mut)"}`),h(D,(C=t(a))!=null&&C.ssh_ok?"✓ verbunden":"optional")}),p(q,oe)};O(Ne,q=>{t(s)&&q(ot)})}var P=i(Ne,2),ye=r(P);{var qe=q=>{var oe=cu();p(q,oe)},Qe=q=>{var oe=vu();p(q,oe)};O(ye,q=>{var oe;((oe=t(a))==null?void 0:oe.hermes)==="ready"?q(qe):q(Qe,-1)})}z(()=>{var q,oe;St(De,`font-size:11px;${((q=t(a))==null?void 0:q.hermes)==="ready"?"color:#7ee29a;border-color:rgba(126,226,154,.4)":"color:#ff9b95;border-color:rgba(255,155,149,.4)"}`),h(ie,`● Agent: ${((oe=t(a))==null?void 0:oe.hermes)==="ready"?"online":"offline"}`),St(te,`padding:4px 10px;font-size:12px;${t(l)?"border-color:var(--accent);color:var(--accent)":""}`)}),S("click",te,()=>{u(l,!t(l)),t(l)&&$()}),S("click",_e,()=>{u(s,!t(s)),t(s)&&(_(),x())}),p(e,Pe),In()}Gn(["click"]);let os={};function fu(){const e=document.getElementById("top-active-text");e&&(e.classList.add("swap-flash"),setTimeout(()=>e.classList.remove("swap-flash"),900))}function ds(e){var l;const n=document.getElementById("swdot"),a=document.getElementById("swlabel"),s=document.getElementById("top-active-text");if(!e)n&&(n.className="dot off"),a&&(a.textContent="Backend nicht erreichbar"),s&&(s.textContent="Backend offline"),cs("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"],v=(e.models||[]).find(f=>d.includes(f.state));if(s)if(v){const f=(l=v.meta)!=null&&l.ctx?` <span style="color:var(--mut);font-size:11.5px">· ${Math.round(v.meta.ctx/1024)}k ctx</span>`:"",b=v.state==="loading"||v.state==="starting"?' <span style="color:var(--warn);font-size:11.5px">lädt…</span>':"";s.innerHTML=`<b style="color:var(--accent)">${v.name}</b>${f}${b}`}else s.innerHTML='<span style="color:var(--mut)">Kein Modell im VRAM</span>';e.swap_ok?bu():cs(`LLM-Engine nicht erreichbar unter <b>${o}</b> – läuft der llama-swap Dienst?`,!0);const c={};for(const f of e.models||[])c[f.name]=f.state;for(const[f,b]of Object.entries(c)){const T=os[f];if(T&&T!==b&&(b==="running"||b==="loading")){fu();break}}os=c}hu(e),Si.set(e)}function hu(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 gu(e){ga.set(e||[])}function mu(e){Rr.set(e)}function cs(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 bu(){const e=document.getElementById("alert");e&&(e.style.display="none")}const _u=e=>{var n;return(n=document.querySelector(`.nav-item[data-view="${e}"]`))==null?void 0:n.click()};function or(e,n,a,s){const l=document.createElement("span");return l.className="upd-badge"+(n?" "+n:""),l.textContent=e,s&&(l.title=s),l.onclick=()=>_u(a),l}async function cl(){try{const e=await Se("/api/updates"),n=document.getElementById("update-badges");if(!n)return;const a=e.apt_cache_age_h,s=a!=null&&a>24,l=a!=null?` · apt-Cache: vor ${a}h`:"";n.innerHTML="",n.appendChild(or(e.os>0?`OS: ${e.os} Updates`:s?"OS: ?":"OS: aktuell",e.os>0||s?"warn":"ok","server",e.os>0?`${e.os} Pakete${l}`:s?`apt-Cache veraltet (${a}h)`:`Keine Updates${l}`)),n.appendChild(or(e.engine>0?"Engine: Update":"Engine: aktuell",e.engine>0?"warn":"ok","server")),n.appendChild(or(e.models>0?`Modelle: ${e.models}`:"Modelle: aktuell",e.models>0?"warn":"ok","news"))}catch{}}async function Hi(){try{ds(await Se("/api/status"))}catch{ds(null)}}async function vl(){try{gu(await Se("/api/jobs"))}catch{}}function ul(){const e=window.location.protocol==="https:"?"wss:":"ws:",n=new WebSocket(`${e}//${window.location.host}/api/system/stream`);n.onmessage=a=>{try{mu(JSON.parse(a.data))}catch{}},n.onclose=()=>{setTimeout(ul,3e3)},n.onerror=()=>n.close()}var gs;((gs=document.getElementById("logo"))==null?void 0:gs.innerHTML)!==void 0&&(document.getElementById("logo").innerHTML=Ui.logo);document.querySelectorAll("[data-ic]").forEach(e=>{e.innerHTML=Ui[e.dataset.ic||""]||""});const yu=[["overview",_d],["models",Id],["activity",Wd],["server",tc],["cookbook",Rc],["connect",rv],["news",hv],["guides",kv],["memory",Lv],["hermes",pu]];for(const[e,n]of yu){const a=document.querySelector(`.view[data-view="${e}"]`);a&&Po(n,{target:a})}ed("overview");const dr=document.getElementById("token");dr&&(dr.value=dl(),dr.addEventListener("change",e=>{Jo(e.target.value),Hi()}));const cr=document.getElementById("hf-token");cr&&(cr.value=ui(),cr.addEventListener("change",e=>Zo(e.target.value)));const vs=document.getElementById("nav-settings"),vr=document.getElementById("settings-modal"),us=document.getElementById("sm-close");vs&&vr&&us&&(vs.addEventListener("click",()=>vr.style.display="flex"),us.addEventListener("click",()=>vr.style.display="none"));function xu(){const e=document.getElementById("clock");e&&(e.textContent=new Date().toTimeString().slice(0,5))}document.addEventListener("mc:refresh",Hi);Hi();vl();ul();setInterval(xu,1e3);setInterval(Hi,3e3);setInterval(vl,1500);cl();setInterval(cl,6e4);
|