6f4f25480a
- MemoryPanel: "Import"-Button öffnet Formular - Jede Zeile wird ein eigener Gedächtnis-Eintrag (Batch-POST) - Kategorie + Quelle (claude/gemini/chatgpt/import) wählbar - Zeilen-Vorschau zeigt erkannte Einträge vor dem Speichern Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
673 lines
216 KiB
JavaScript
673 lines
216 KiB
JavaScript
var sl=Object.defineProperty;var $r=e=>{throw TypeError(e)};var ll=(e,n,a)=>n in e?sl(e,n,{enumerable:!0,configurable:!0,writable:!0,value:a}):e[n]=a;var vn=(e,n,a)=>ll(e,typeof n!="symbol"?n+"":n,a),Ui=(e,n,a)=>n.has(e)||$r("Cannot "+a);var h=(e,n,a)=>(Ui(e,n,"read from private field"),a?a.call(e):n.get(e)),Oe=(e,n,a)=>n.has(e)?$r("Cannot add the same private member more than once"):n instanceof WeakSet?n.add(e):n.set(e,a),Pe=(e,n,a,s)=>(Ui(e,n,"write to private field"),s?s.call(e,a):n.set(e,a),a),nt=(e,n,a)=>(Ui(e,n,"access private method"),a);var yr=Array.isArray,ol=Array.prototype.indexOf,zi=Array.prototype.includes,Fi=Array.from,dl=Object.defineProperty,ii=Object.getOwnPropertyDescriptor,cl=Object.getOwnPropertyDescriptors,vl=Object.prototype,ul=Array.prototype,cs=Object.getPrototypeOf,Ir=Object.isExtensible;const pl=()=>{};function fl(e){for(var n=0;n<e.length;n++)e[n]()}function vs(){var e,n,a=new Promise((s,l)=>{e=s,n=l});return{promise:a,resolve:e,reject:n}}function aa(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 tn=2,Na=4,Ki=8,us=1<<24,Cn=16,zn=32,la=64,sr=128,kn=512,Ht=1024,Xt=2048,Kn=4096,rn=8192,wn=16384,Ja=32768,lr=1<<25,qa=65536,Pi=1<<17,hl=1<<18,Qa=1<<19,gl=1<<20,Bn=1<<25,Sa=65536,Di=1<<21,Da=1<<22,sa=1<<23,$a=Symbol("$state"),ml=Symbol(""),Si=Symbol("attributes"),or=Symbol("class"),dr=Symbol("style"),Xa=Symbol("text"),Mi=Symbol("form reset"),Ni=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 ss;const bl=!!((ss=globalThis.document)!=null&&ss.contentType)&&globalThis.document.contentType.includes("xml");function ps(e){throw new Error("https://svelte.dev/e/lifecycle_outside_component")}function _l(){throw new Error("https://svelte.dev/e/async_derived_orphan")}function yl(e,n,a){throw new Error("https://svelte.dev/e/each_key_duplicate")}function xl(e){throw new Error("https://svelte.dev/e/effect_in_teardown")}function kl(){throw new Error("https://svelte.dev/e/effect_in_unowned_derived")}function wl(e){throw new Error("https://svelte.dev/e/effect_orphan")}function Sl(){throw new Error("https://svelte.dev/e/effect_update_depth_exceeded")}function Ml(){throw new Error("https://svelte.dev/e/state_descriptors_fixed")}function El(){throw new Error("https://svelte.dev/e/state_prototype_fixed")}function Al(){throw new Error("https://svelte.dev/e/state_unsafe_mutation")}function Cl(){throw new Error("https://svelte.dev/e/svelte_boundary_reset_onerror")}const Tl=1,zl=2,fs=4,Pl=8,Dl=16,$l=1,Il=2,Ut=Symbol("uninitialized"),hs="http://www.w3.org/1999/xhtml",Ll="http://www.w3.org/2000/svg",Ol="http://www.w3.org/1998/Math/MathML";function Bl(){console.warn("https://svelte.dev/e/derived_inert")}function Rl(){console.warn("https://svelte.dev/e/select_multiple_invalid_value")}function Fl(){console.warn("https://svelte.dev/e/svelte_boundary_reset_noop")}function gs(e){return e===this.v}function Kl(e,n){return e!=e?n==n:e!==n||e!==null&&typeof e=="object"||typeof e=="function"}function ms(e){return!Kl(e,this.v)}let en=null;function Va(e){en=e}function Pn(e,n=!1,a){en={p:en,i:!1,c:null,e:null,s:e,x:null,r:Ge,l:null}}function Dn(e){var n=en,a=n.e;if(a!==null){n.e=null;for(var s of a)Fs(s)}return n.i=!0,en=n.p,{}}function bs(){return!0}let va=[];function _s(){var e=va;va=[],fl(e)}function ya(e){if(va.length===0&&!si){var n=va;queueMicrotask(()=>{n===va&&_s()})}va.push(e)}function Nl(){for(;va.length>0;)_s()}function ys(e){var n=Ge;if(n===null)return Ve.f|=sa,e;if((n.f&Ja)===0&&(n.f&Na)===0)throw e;ia(e,n)}function ia(e,n){if(!(n!==null&&(n.f&wn)!==0)){for(;n!==null;){if((n.f&sr)!==0){if((n.f&Ja)===0)throw e;try{n.b.error(e);return}catch(a){e=a}}n=n.parent}throw e}}const ql=-7169;function Nt(e,n){e.f=e.f&ql|n}function xr(e){(e.f&kn)!==0||e.deps===null?Nt(e,Ht):Nt(e,Kn)}function xs(e){if(e!==null)for(const n of e)(n.f&tn)===0||(n.f&Sa)===0||(n.f^=Sa,xs(n.deps))}function ks(e,n,a){(e.f&Xt)!==0?n.add(e):(e.f&Kn)!==0&&a.add(e),xs(e.deps),Nt(e,Ht)}function Vl(e){let n=0,a=Ea(0),s;return()=>{Cr()&&(t(a),qi(()=>(n===0&&(s=Za(()=>e(()=>li(a)))),n+=1,()=>{ya(()=>{n-=1,n===0&&(s==null||s(),s=void 0,li(a))})})))}}var Wl=qa|Qa;function Gl(e,n,a,s){new jl(e,n,a,s)}var mn,_r,bn,ha,ln,_n,nn,pn,Wn,ga,ta,Ia,pi,fi,Gn,Oi,It,Ul,Hl,Jl,cr,Ei,Ai,vr,ur;class jl{constructor(n,a,s,l){Oe(this,It);vn(this,"parent");vn(this,"is_pending",!1);vn(this,"transform_error");Oe(this,mn);Oe(this,_r,null);Oe(this,bn);Oe(this,ha);Oe(this,ln);Oe(this,_n,null);Oe(this,nn,null);Oe(this,pn,null);Oe(this,Wn,null);Oe(this,ga,0);Oe(this,ta,0);Oe(this,Ia,!1);Oe(this,pi,new Set);Oe(this,fi,new Set);Oe(this,Gn,null);Oe(this,Oi,Vl(()=>(Pe(this,Gn,Ea(h(this,ga))),()=>{Pe(this,Gn,null)})));var o;Pe(this,mn,n),Pe(this,bn,a),Pe(this,ha,v=>{var d=Ge;d.b=this,d.f|=sr,s(v)}),this.parent=Ge.b,this.transform_error=l??((o=this.parent)==null?void 0:o.transform_error)??(v=>v),Pe(this,ln,Tr(()=>{nt(this,It,cr).call(this)},Wl))}defer_effect(n){ks(n,h(this,pi),h(this,fi))}is_rendered(){return!this.is_pending&&(!this.parent||this.parent.is_rendered())}has_pending_snippet(){return!!h(this,bn).pending}update_pending_count(n,a){nt(this,It,vr).call(this,n,a),Pe(this,ga,h(this,ga)+n),!(!h(this,Gn)||h(this,Ia))&&(Pe(this,Ia,!0),ya(()=>{Pe(this,Ia,!1),h(this,Gn)&&Wa(h(this,Gn),h(this,ga))}))}get_effect_pending(){return h(this,Oi).call(this),t(h(this,Gn))}error(n){if(!h(this,bn).onerror&&!h(this,bn).failed)throw n;ge!=null&&ge.is_fork?(h(this,_n)&&ge.skip_effect(h(this,_n)),h(this,nn)&&ge.skip_effect(h(this,nn)),h(this,pn)&&ge.skip_effect(h(this,pn)),ge.oncommit(()=>{nt(this,It,ur).call(this,n)})):nt(this,It,ur).call(this,n)}}mn=new WeakMap,_r=new WeakMap,bn=new WeakMap,ha=new WeakMap,ln=new WeakMap,_n=new WeakMap,nn=new WeakMap,pn=new WeakMap,Wn=new WeakMap,ga=new WeakMap,ta=new WeakMap,Ia=new WeakMap,pi=new WeakMap,fi=new WeakMap,Gn=new WeakMap,Oi=new WeakMap,It=new WeakSet,Ul=function(){try{Pe(this,_n,yn(()=>h(this,ha).call(this,h(this,mn))))}catch(n){this.error(n)}},Hl=function(n){const a=h(this,bn).failed;a&&Pe(this,pn,yn(()=>{a(h(this,mn),()=>n,()=>()=>{})}))},Jl=function(){const n=h(this,bn).pending;n&&(this.is_pending=!0,Pe(this,nn,yn(()=>n(h(this,mn)))),ya(()=>{var a=Pe(this,Wn,document.createDocumentFragment()),s=Jn();a.append(s),Pe(this,_n,nt(this,It,Ai).call(this,()=>yn(()=>h(this,ha).call(this,s)))),h(this,ta)===0&&(h(this,mn).before(a),Pe(this,Wn,null),ka(h(this,nn),()=>{Pe(this,nn,null)}),nt(this,It,Ei).call(this,ge))}))},cr=function(){try{if(this.is_pending=this.has_pending_snippet(),Pe(this,ta,0),Pe(this,ga,0),Pe(this,_n,yn(()=>{h(this,ha).call(this,h(this,mn))})),h(this,ta)>0){var n=Pe(this,Wn,document.createDocumentFragment());Pr(h(this,_n),n);const a=h(this,bn).pending;Pe(this,nn,yn(()=>a(h(this,mn))))}else nt(this,It,Ei).call(this,ge)}catch(a){this.error(a)}},Ei=function(n){this.is_pending=!1,n.transfer_effects(h(this,pi),h(this,fi))},Ai=function(n){var a=Ge,s=Ve,l=en;Nn(h(this,ln)),Sn(h(this,ln)),Va(h(this,ln).ctx);try{return Ma.ensure(),n()}catch(o){return ys(o),null}finally{Nn(a),Sn(s),Va(l)}},vr=function(n,a){var s;if(!this.has_pending_snippet()){this.parent&&nt(s=this.parent,It,vr).call(s,n,a);return}Pe(this,ta,h(this,ta)+n),h(this,ta)===0&&(nt(this,It,Ei).call(this,a),h(this,nn)&&ka(h(this,nn),()=>{Pe(this,nn,null)}),h(this,Wn)&&(h(this,mn).before(h(this,Wn)),Pe(this,Wn,null)))},ur=function(n){h(this,_n)&&(cn(h(this,_n)),Pe(this,_n,null)),h(this,nn)&&(cn(h(this,nn)),Pe(this,nn,null)),h(this,pn)&&(cn(h(this,pn)),Pe(this,pn,null));var a=h(this,bn).onerror;let s=h(this,bn).failed;var l=!1,o=!1;const v=()=>{if(l){Fl();return}l=!0,o&&Cl(),h(this,pn)!==null&&ka(h(this,pn),()=>{Pe(this,pn,null)}),nt(this,It,Ai).call(this,()=>{nt(this,It,cr).call(this)})},d=u=>{try{o=!0,a==null||a(u,v),o=!1}catch(p){ia(p,h(this,ln)&&h(this,ln).parent)}s&&Pe(this,pn,nt(this,It,Ai).call(this,()=>{try{return yn(()=>{var p=Ge;p.b=this,p.f|=sr,s(h(this,mn),()=>u,()=>v)})}catch(p){return ia(p,h(this,ln).parent),null}}))};ya(()=>{var u;try{u=this.transform_error(n)}catch(p){ia(p,h(this,ln)&&h(this,ln).parent);return}u!==null&&typeof u=="object"&&typeof u.then=="function"?u.then(d,p=>ia(p,h(this,ln)&&h(this,ln).parent)):d(u)})};function Ql(e,n,a,s){const l=kr;var o=e.filter(y=>!y.settled),v=n.map(l);if(a.length===0&&o.length===0){s(v);return}var d=Ge,u=Zl(),p=o.length===1?o[0].promise:o.length>1?Promise.all(o.map(y=>y.promise)):null;function _(y){if((d.f&wn)===0){u();try{s([...v,...y])}catch($){ia($,d)}$i()}}var C=ws();if(a.length===0){p.then(()=>_([])).finally(C);return}function m(){Promise.all(a.map(y=>Yl(y))).then(_).catch(y=>ia(y,d)).finally(C)}p?p.then(()=>{u(),m(),$i()}):m()}function Zl(){var e=Ge,n=Ve,a=en,s=ge;return function(o=!0){Nn(e),Sn(n),Va(a),o&&(e.f&wn)===0&&(s==null||s.activate(),s==null||s.apply())}}function $i(e=!0){Nn(null),Sn(null),Va(null),e&&(ge==null||ge.deactivate())}function ws(){var e=Ge,n=e.b,a=ge,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 kr(e){var n=tn|Xt;return Ge!==null&&(Ge.f|=Qa),{ctx:en,deps:null,effects:null,equals:gs,f:n,fn:e,reactions:null,rv:0,v:Ut,wv:0,parent:Ge,ac:null}}const ei=Symbol("obsolete");function Yl(e,n,a){let s=Ge;s===null&&_l();var l=void 0,o=Ea(Ut),v=!Ve,d=new Set;return go(()=>{var y,$;var u=Ge,p=vs();l=p.promise;try{Promise.resolve(e()).then(p.resolve,O=>{O!==Ni&&p.reject(O)}).finally($i)}catch(O){p.reject(O),$i()}var _=ge;if(v){if((u.f&Ja)!==0)var C=ws();if((y=s.b)!=null&&y.is_rendered())($=_.async_deriveds.get(u))==null||$.reject(ei);else for(const O of d.values())O.reject(ei);d.add(p),_.async_deriveds.set(u,p)}const m=(O,M=void 0)=>{C==null||C(),d.delete(p),M!==ei&&(_.activate(),M?(o.f|=sa,Wa(o,M)):((o.f&sa)!==0&&(o.f^=sa),Wa(o,O)),_.deactivate())};p.promise.then(m,O=>m(null,O||"unknown"))}),Rs(()=>{for(const u of d)u.reject(ei)}),new Promise(u=>{function p(_){function C(){_===l?u(o):p(l)}_.then(C,C)}p(l)})}function G(e){const n=kr(e);return js(n),n}function Xl(e){const n=kr(e);return n.equals=ms,n}function eo(e){var n=e.effects;if(n!==null){e.effects=null;for(var a=0;a<n.length;a+=1)cn(n[a])}}function wr(e){var n,a=Ge,s=e.parent;if(!oa&&s!==null&&e.v!==Ut&&(s.f&(wn|rn))!==0)return Bl(),e.v;Nn(s);try{e.f&=~Sa,eo(e),n=Qs(e)}finally{Nn(a)}return n}function Ss(e){var n=wr(e);if(!e.equals(n)&&(e.wv=Hs(),(!(ge!=null&&ge.is_fork)||e.deps===null)&&(ge!==null?(ge.capture(e,n,!0),ri==null||ri.capture(e,n,!0)):e.v=n,e.deps===null))){Nt(e,Ht);return}oa||(Yt!==null?(Cr()||ge!=null&&ge.is_fork)&&Yt.set(e,n):xr(e))}function to(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(Ni),s.fn!==null&&(s.teardown=pl),s.ac=null,vi(s,0),zr(s))}function Ms(e){if(e.effects!==null)for(const n of e.effects)n.teardown&&n.fn!==null&&ja(n)}let Hi=null,Ta=null,ge=null,ri=null,Yt=null,pr=null,si=!1,Ji=!1,Pa=null,Ci=null;var Lr=0;let no=1;var La,na,ma,Oa,Ba,Ra,jn,Fa,on,hi,Un,En,Ln,Ka,ba,pt,fr,ti,hr,Es,As,za,ao,ni;const Bi=class Bi{constructor(){Oe(this,pt);vn(this,"id",no++);Oe(this,La,!1);vn(this,"linked",!0);Oe(this,na,null);Oe(this,ma,null);vn(this,"async_deriveds",new Map);vn(this,"current",new Map);vn(this,"previous",new Map);Oe(this,Oa,new Set);Oe(this,Ba,new Set);Oe(this,Ra,0);Oe(this,jn,new Map);Oe(this,Fa,null);Oe(this,on,[]);Oe(this,hi,[]);Oe(this,Un,new Set);Oe(this,En,new Set);Oe(this,Ln,new Map);Oe(this,Ka,new Set);vn(this,"is_fork",!1);Oe(this,ba,!1);Ta===null?Hi=Ta=this:(Pe(Ta,ma,this),Pe(this,na,Ta)),Ta=this}skip_effect(n){h(this,Ln).has(n)||h(this,Ln).set(n,{d:[],m:[]}),h(this,Ka).delete(n)}unskip_effect(n,a=s=>this.schedule(s)){var s=h(this,Ln).get(n);if(s){h(this,Ln).delete(n);for(var l of s.d)Nt(l,Xt),a(l);for(l of s.m)Nt(l,Kn),a(l)}h(this,Ka).add(n)}capture(n,a,s=!1){n.v!==Ut&&!this.previous.has(n)&&this.previous.set(n,n.v),(n.f&sa)===0&&(this.current.set(n,[a,s]),Yt==null||Yt.set(n,a)),this.is_fork||(n.v=a)}activate(){ge=this}deactivate(){ge=null,Yt=null}flush(){try{Ji=!0,ge=this,nt(this,pt,ti).call(this)}finally{Lr=0,pr=null,Pa=null,Ci=null,Ji=!1,ge=null,Yt=null,xa.clear()}}discard(){var n;for(const a of h(this,Ba))a(this);h(this,Ba).clear();for(const a of this.async_deriveds.values())a.reject(ei);nt(this,pt,ni).call(this),(n=h(this,Fa))==null||n.resolve()}register_created_effect(n){h(this,hi).push(n)}increment(n,a){if(Pe(this,Ra,h(this,Ra)+1),n){let s=h(this,jn).get(a)??0;h(this,jn).set(a,s+1)}}decrement(n,a){if(Pe(this,Ra,h(this,Ra)-1),n){let s=h(this,jn).get(a)??0;s===1?h(this,jn).delete(a):h(this,jn).set(a,s-1)}h(this,ba)||(Pe(this,ba,!0),ya(()=>{Pe(this,ba,!1),this.linked&&this.flush()}))}transfer_effects(n,a){for(const s of n)h(this,Un).add(s);for(const s of a)h(this,En).add(s);n.clear(),a.clear()}oncommit(n){h(this,Oa).add(n)}ondiscard(n){h(this,Ba).add(n)}settled(){return(h(this,Fa)??Pe(this,Fa,vs())).promise}static ensure(){if(ge===null){const n=ge=new Bi;!Ji&&!si&&ya(()=>{h(n,La)||n.flush()})}return ge}apply(){{Yt=null;return}}schedule(n){var l;if(pr=n,(l=n.b)!=null&&l.is_pending&&(n.f&(Na|Ki|us))!==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(Pa!==null&&a===Ge&&(Ve===null||(Ve.f&tn)===0))return;if((s&(la|zn))!==0){if((s&Ht)===0)return;a.f^=Ht}}h(this,on).push(a)}};La=new WeakMap,na=new WeakMap,ma=new WeakMap,Oa=new WeakMap,Ba=new WeakMap,Ra=new WeakMap,jn=new WeakMap,Fa=new WeakMap,on=new WeakMap,hi=new WeakMap,Un=new WeakMap,En=new WeakMap,Ln=new WeakMap,Ka=new WeakMap,ba=new WeakMap,pt=new WeakSet,fr=function(){if(this.is_fork)return!0;for(const s of h(this,jn).keys()){for(var n=s,a=!1;n.parent!==null;){if(h(this,Ln).has(n)){a=!0;break}n=n.parent}if(!a)return!0}return!1},ti=function(){var u,p,_,C;Pe(this,La,!0),Lr++>1e3&&(nt(this,pt,ni).call(this),ro());for(const m of h(this,Un))h(this,En).delete(m),Nt(m,Xt),this.schedule(m);for(const m of h(this,En))Nt(m,Kn),this.schedule(m);const n=h(this,on);Pe(this,on,[]),this.apply();var a=Pa=[],s=[],l=Ci=[];for(const m of n)try{nt(this,pt,hr).call(this,m,a,s)}catch(y){throw zs(m),nt(this,pt,fr).call(this)||this.discard(),y}if(ge=null,l.length>0){var o=Bi.ensure();for(const m of l)o.schedule(m)}if(Pa=null,Ci=null,nt(this,pt,fr).call(this)){nt(this,pt,za).call(this,s),nt(this,pt,za).call(this,a);for(const[m,y]of h(this,Ln))Ts(m,y);l.length>0&&nt(u=ge,pt,ti).call(u);return}const v=nt(this,pt,Es).call(this);if(v){nt(this,pt,za).call(this,s),nt(this,pt,za).call(this,a),nt(p=v,pt,As).call(p,this);return}h(this,Un).clear(),h(this,En).clear();for(const m of h(this,Oa))m(this);h(this,Oa).clear(),ri=this,Or(s),Or(a),ri=null,(_=h(this,Fa))==null||_.resolve();var d=ge;if(h(this,Ra)===0&&(h(this,on).length===0||d!==null)&&nt(this,pt,ni).call(this),h(this,on).length>0)if(d!==null){const m=d;h(m,on).push(...h(this,on).filter(y=>!h(m,on).includes(y)))}else d=this;d!==null&&nt(C=d,pt,ti).call(C)},hr=function(n,a,s){n.f^=Ht;for(var l=n.first;l!==null;){var o=l.f,v=(o&(zn|la))!==0,d=v&&(o&Ht)!==0,u=d||(o&rn)!==0||h(this,Ln).has(l);if(!u&&l.fn!==null){v?l.f^=Ht:(o&Na)!==0?a.push(l):_i(l)&&((o&Cn)!==0&&h(this,En).add(l),ja(l));var p=l.first;if(p!==null){l=p;continue}}for(;l!==null;){var _=l.next;if(_!==null){l=_;break}l=l.parent}}},Es=function(){for(var n=h(this,na);n!==null;){if(!n.is_fork){for(const[a,[,s]]of this.current)if(n.current.has(a)&&!s)return n}n=h(n,na)}return null},As=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 v=this.async_deriveds.get(l);v&&o.promise.then(v.resolve).catch(v.reject)}n.async_deriveds.clear(),this.transfer_effects(h(n,Un),h(n,En));const a=l=>{var o=l.reactions;if(o!==null)for(const u of o){var v=u.f;if((v&tn)!==0)a(u);else{var d=u;v&(Da|Cn)&&!this.async_deriveds.has(d)&&(h(this,En).delete(d),Nt(d,Xt),this.schedule(d))}}};for(const l of this.current.keys())a(l);this.oncommit(()=>n.discard()),nt(s=n,pt,ni).call(s),ge=this,nt(this,pt,ti).call(this)},za=function(n){for(var a=0;a<n.length;a+=1)ks(n[a],h(this,Un),h(this,En))},ao=function(){var C;for(let m=Hi;m!==null;m=h(m,ma)){var n=m.id<this.id,a=[];for(const[y,[$,O]]of this.current){if(m.current.has(y)){var s=m.current.get(y)[0];if(n&&$!==s)m.current.set(y,[$,O]);else continue}a.push(y)}if(n)for(const[y,$]of this.async_deriveds){const O=m.async_deriveds.get(y);O&&$.promise.then(O.resolve).catch(O.reject)}var l=[...m.current.keys()].filter(y=>!m.current.get(y)[1]);if(!(!h(m,La)||l.length===0)){var o=l.filter(y=>!this.current.has(y));if(o.length===0)n&&m.discard();else if(a.length>0){if(n)for(const y of h(this,Ka))m.unskip_effect(y,$=>{var O;($.f&(Cn|Da))!==0?m.schedule($):nt(O=m,pt,za).call(O,[$])});m.activate();var v=new Set,d=new Map;for(var u of a)Cs(u,o,v,d);d=new Map;var p=[...m.current].filter(([y,$])=>{const O=this.current.get(y);return O?O[0]!==$[0]||O[1]!==$[1]:!0}).map(([y])=>y);if(p.length>0)for(const y of h(this,hi))(y.f&(wn|rn|Pi))===0&&Sr(y,p,d)&&((y.f&(Da|Cn))!==0?(Nt(y,Xt),m.schedule(y)):h(m,Un).add(y));if(h(m,on).length>0&&!h(m,ba)){m.apply();for(var _ of h(m,on))nt(C=m,pt,hr).call(C,_,[],[]);Pe(m,on,[])}m.deactivate()}}}},ni=function(){if(this.linked){var n=h(this,na),a=h(this,ma);n===null?Hi=a:Pe(n,ma,a),a===null?Ta=n:Pe(a,na,n),this.linked=!1}};let Ma=Bi;function io(e){var n=si;si=!0;try{for(var a;;){if(Nl(),ge===null)return a;ge.flush()}}finally{si=n}}function ro(){try{Sl()}catch(e){ia(e,pr)}}let Mn=null;function Or(e){var n=e.length;if(n!==0){for(var a=0;a<n;){var s=e[a++];if((s.f&(wn|rn))===0&&_i(s)&&(Mn=new Set,ja(s),s.deps===null&&s.first===null&&s.nodes===null&&s.teardown===null&&s.ac===null&&Vs(s),(Mn==null?void 0:Mn.size)>0)){xa.clear();for(const l of Mn){if((l.f&(wn|rn))!==0)continue;const o=[l];let v=l.parent;for(;v!==null;)Mn.has(v)&&(Mn.delete(v),o.push(v)),v=v.parent;for(let d=o.length-1;d>=0;d--){const u=o[d];(u.f&(wn|rn))===0&&ja(u)}}Mn.clear()}}Mn=null}}function Cs(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&tn)!==0?Cs(l,n,a,s):(o&(Da|Cn))!==0&&(o&Xt)===0&&Sr(l,n,s)&&(Nt(l,Xt),Mr(l))}}function Sr(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(zi.call(n,l))return!0;if((l.f&tn)!==0&&Sr(l,n,a))return a.set(l,!0),!0}return a.set(e,!1),!1}function Mr(e){ge.schedule(e)}function Ts(e,n){if(!((e.f&zn)!==0&&(e.f&Ht)!==0)){(e.f&Xt)!==0?n.d.push(e):(e.f&Kn)!==0&&n.m.push(e),Nt(e,Ht);for(var a=e.first;a!==null;)Ts(a,n),a=a.next}}function zs(e){Nt(e,Ht);for(var n=e.first;n!==null;)zs(n),n=n.next}let Ii=new Set;const xa=new Map;let Ps=!1;function Ea(e,n){var a={f:0,v:e,reactions:null,equals:gs,rv:0,wv:0};return a}function L(e,n){const a=Ea(e);return js(a),a}function so(e,n=!1,a=!0){const s=Ea(e);return n||(s.equals=ms),s}function c(e,n,a=!1){Ve!==null&&(!Tn||(Ve.f&Pi)!==0)&&bs()&&(Ve.f&(tn|Cn|Da|Pi))!==0&&(Rn===null||!Rn.has(e))&&Al();let s=a?Jt(n):n;return Wa(e,s,Ci)}function Wa(e,n,a=null){if(!e.equals(n)){xa.set(e,oa?n:e.v);var s=Ma.ensure();if(s.capture(e,n),(e.f&tn)!==0){const l=e;(e.f&Xt)!==0&&wr(l),Yt===null&&xr(l)}e.wv=Hs(),Ds(e,Xt,a),Ge!==null&&(Ge.f&Ht)!==0&&(Ge.f&(zn|la))===0&&(gn===null?bo([e]):gn.push(e)),!s.is_fork&&Ii.size>0&&!Ps&&lo()}return n}function lo(){Ps=!1;for(const e of Ii){(e.f&Ht)!==0&&Nt(e,Kn);let n;try{n=_i(e)}catch{n=!0}n&&ja(e)}Ii.clear()}function li(e){c(e,e.v+1)}function Ds(e,n,a){var s=e.reactions;if(s!==null)for(var l=s.length,o=0;o<l;o++){var v=s[o],d=v.f,u=(d&Xt)===0;if(u&&Nt(v,n),(d&Pi)!==0)Ii.add(v);else if((d&tn)!==0){var p=v;Yt==null||Yt.delete(p),(d&Sa)===0&&(d&kn&&(Ge===null||(Ge.f&Di)===0)&&(v.f|=Sa),Ds(p,Kn,a))}else if(u){var _=v;(d&Cn)!==0&&Mn!==null&&Mn.add(_),a!==null?a.push(_):Mr(_)}}}function Jt(e){if(typeof e!="object"||e===null||$a in e)return e;const n=cs(e);if(n!==vl&&n!==ul)return e;var a=new Map,s=yr(e),l=L(0),o=wa,v=d=>{if(wa===o)return d();var u=Ve,p=wa;Sn(null),Nr(o);var _=d();return Sn(u),Nr(p),_};return s&&a.set("length",L(e.length)),new Proxy(e,{defineProperty(d,u,p){(!("value"in p)||p.configurable===!1||p.enumerable===!1||p.writable===!1)&&Ml();var _=a.get(u);return _===void 0?v(()=>{var C=L(p.value);return a.set(u,C),C}):c(_,p.value,!0),!0},deleteProperty(d,u){var p=a.get(u);if(p===void 0){if(u in d){const _=v(()=>L(Ut));a.set(u,_),li(l)}}else c(p,Ut),li(l);return!0},get(d,u,p){var y;if(u===$a)return e;var _=a.get(u),C=u in d;if(_===void 0&&(!C||(y=ii(d,u))!=null&&y.writable)&&(_=v(()=>{var $=Jt(C?d[u]:Ut),O=L($);return O}),a.set(u,_)),_!==void 0){var m=t(_);return m===Ut?void 0:m}return Reflect.get(d,u,p)},getOwnPropertyDescriptor(d,u){var p=Reflect.getOwnPropertyDescriptor(d,u);if(p&&"value"in p){var _=a.get(u);_&&(p.value=t(_))}else if(p===void 0){var C=a.get(u),m=C==null?void 0:C.v;if(C!==void 0&&m!==Ut)return{enumerable:!0,configurable:!0,value:m,writable:!0}}return p},has(d,u){var m;if(u===$a)return!0;var p=a.get(u),_=p!==void 0&&p.v!==Ut||Reflect.has(d,u);if(p!==void 0||Ge!==null&&(!_||(m=ii(d,u))!=null&&m.writable)){p===void 0&&(p=v(()=>{var y=_?Jt(d[u]):Ut,$=L(y);return $}),a.set(u,p));var C=t(p);if(C===Ut)return!1}return _},set(d,u,p,_){var xe;var C=a.get(u),m=u in d;if(s&&u==="length")for(var y=p;y<C.v;y+=1){var $=a.get(y+"");$!==void 0?c($,Ut):y in d&&($=v(()=>L(Ut)),a.set(y+"",$))}if(C===void 0)(!m||(xe=ii(d,u))!=null&&xe.writable)&&(C=v(()=>L(void 0)),c(C,Jt(p)),a.set(u,C));else{m=C.v!==Ut;var O=v(()=>Jt(p));c(C,O)}var M=Reflect.getOwnPropertyDescriptor(d,u);if(M!=null&&M.set&&M.set.call(_,p),!m){if(s&&typeof u=="string"){var F=a.get("length"),ye=Number(u);Number.isInteger(ye)&&ye>=F.v&&c(F,ye+1)}li(l)}return!0},ownKeys(d){t(l);var u=Reflect.ownKeys(d).filter(C=>{var m=a.get(C);return m===void 0||m.v!==Ut});for(var[p,_]of a)_.v!==Ut&&!(p in d)&&u.push(p);return u},setPrototypeOf(){El()}})}function Br(e){try{if(e!==null&&typeof e=="object"&&$a in e)return e[$a]}catch{}return e}function oo(e,n){return Object.is(Br(e),Br(n))}var Rr,$s,Is,Ls;function co(){if(Rr===void 0){Rr=window,$s=/Firefox/.test(navigator.userAgent);var e=Element.prototype,n=Node.prototype,a=Text.prototype;Is=ii(n,"firstChild").get,Ls=ii(n,"nextSibling").get,Ir(e)&&(e[or]=void 0,e[Si]=null,e[dr]=void 0,e.__e=void 0),Ir(a)&&(a[Xa]=void 0)}}function Jn(e=""){return document.createTextNode(e)}function ra(e){return Is.call(e)}function bi(e){return Ls.call(e)}function r(e,n){return ra(e)}function Xe(e,n=!1){{var a=ra(e);return a instanceof Comment&&a.data===""?bi(a):a}}function i(e,n=1,a=!1){let s=e;for(;n--;)s=bi(s);return s}function vo(e){e.textContent=""}function Os(){return!1}function Bs(e,n,a){return n==null||n===hs?a?document.createElement(e,{is:a}):document.createElement(e):a?document.createElementNS(n,e,{is:a}):document.createElementNS(n,e)}let Fr=!1;function uo(){Fr||(Fr=!0,document.addEventListener("reset",e=>{Promise.resolve().then(()=>{var n;if(!e.defaultPrevented)for(const a of e.target.elements)(n=a[Mi])==null||n.call(a)})},{capture:!0}))}function Er(e){var n=Ve,a=Ge;Sn(null),Nn(null);try{return e()}finally{Sn(n),Nn(a)}}function Ar(e,n,a,s=a){e.addEventListener(n,()=>Er(a));const l=e[Mi];l?e[Mi]=()=>{l(),s(!0)}:e[Mi]=()=>s(!0),uo()}function po(e){Ge===null&&(Ve===null&&wl(),kl()),oa&&xl()}function fo(e,n){var a=n.last;a===null?n.last=n.first=e:(a.next=e,e.prev=a,n.last=e)}function Qn(e,n){var a=Ge;a!==null&&(a.f&rn)!==0&&(e|=rn);var s={ctx:en,deps:null,nodes:null,f:e|Xt|kn,first:null,fn:n,last:null,next:null,parent:a,b:a&&a.b,prev:null,teardown:null,wv:0,ac:null};ge==null||ge.register_created_effect(s);var l=s;if((e&Na)!==0)Pa!==null?Pa.push(s):Ma.ensure().schedule(s);else if(n!==null){try{ja(s)}catch(v){throw cn(s),v}l.deps===null&&l.teardown===null&&l.nodes===null&&l.first===l.last&&(l.f&Qa)===0&&(l=l.first,(e&Cn)!==0&&(e&qa)!==0&&l!==null&&(l.f|=qa))}if(l!==null&&(l.parent=a,a!==null&&fo(l,a),Ve!==null&&(Ve.f&tn)!==0&&(e&la)===0)){var o=Ve;(o.effects??(o.effects=[])).push(l)}return s}function Cr(){return Ve!==null&&!Tn}function Rs(e){const n=Qn(Ki,null);return Nt(n,Ht),n.teardown=e,n}function Ga(e){po();var n=Ge.f,a=!Ve&&(n&zn)!==0&&en!==null&&!en.i;if(a){var s=en;(s.e??(s.e=[])).push(e)}else return Fs(e)}function Fs(e){return Qn(Na|gl,e)}function ho(e){Ma.ensure();const n=Qn(la|Qa,e);return(a={})=>new Promise(s=>{a.outro?ka(n,()=>{cn(n),s(void 0)}):(cn(n),s(void 0))})}function Ks(e){return Qn(Na,e)}function go(e){return Qn(Da|Qa,e)}function qi(e,n=0){return Qn(Ki|n,e)}function D(e,n=[],a=[],s=[]){Ql(s,n,a,l=>{Qn(Ki,()=>{e(...l.map(t))})})}function Tr(e,n=0){var a=Qn(Cn|n,e);return a}function yn(e){return Qn(zn|Qa,e)}function Ns(e){var n=e.teardown;if(n!==null){const a=oa,s=Ve;Kr(!0),Sn(null);try{n.call(null)}finally{Kr(a),Sn(s)}}}function zr(e,n=!1){var a=e.first;for(e.first=e.last=null;a!==null;){const l=a.ac;l!==null&&Er(()=>{l.abort(Ni)});var s=a.next;(a.f&la)!==0?a.parent=null:cn(a,n),a=s}}function mo(e){for(var n=e.first;n!==null;){var a=n.next;(n.f&zn)===0&&cn(n),n=a}}function cn(e,n=!0){var a=!1;(n||(e.f&hl)!==0)&&e.nodes!==null&&e.nodes.end!==null&&(qs(e.nodes.start,e.nodes.end),a=!0),e.f|=lr,zr(e,n&&!a),vi(e,0);var s=e.nodes&&e.nodes.t;if(s!==null)for(const o of s)o.stop();Ns(e),e.f^=lr,e.f|=wn;var l=e.parent;l!==null&&l.first!==null&&Vs(e),e.next=e.prev=e.teardown=e.ctx=e.deps=e.fn=e.nodes=e.ac=e.b=null}function qs(e,n){for(;e!==null;){var a=e===n?null:bi(e);e.remove(),e=a}}function Vs(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 ka(e,n,a=!0){var s=[];Ws(e,s,!0);var l=()=>{a&&cn(e),n&&n()},o=s.length;if(o>0){var v=()=>--o||l();for(var d of s)d.out(v)}else l()}function Ws(e,n,a){if((e.f&rn)===0){e.f^=rn;var s=e.nodes&&e.nodes.t;if(s!==null)for(const d of s)(d.is_global||a)&&n.push(d);for(var l=e.first;l!==null;){var o=l.next;if((l.f&la)===0){var v=(l.f&qa)!==0||(l.f&zn)!==0&&(e.f&Cn)!==0;Ws(l,n,v?a:!1)}l=o}}}function Li(e){Gs(e,!0)}function Gs(e,n){if((e.f&rn)!==0){e.f^=rn,(e.f&Ht)===0&&(Nt(e,Xt),Ma.ensure().schedule(e));for(var a=e.first;a!==null;){var s=a.next,l=(a.f&qa)!==0||(a.f&zn)!==0;Gs(a,l?n:!1),a=s}var o=e.nodes&&e.nodes.t;if(o!==null)for(const v of o)(v.is_global||n)&&v.in()}}function Pr(e,n){if(e.nodes)for(var a=e.nodes.start,s=e.nodes.end;a!==null;){var l=a===s?null:bi(a);n.append(a),a=l}}let Ti=!1,oa=!1;function Kr(e){oa=e}let Ve=null,Tn=!1;function Sn(e){Ve=e}let Ge=null;function Nn(e){Ge=e}let Rn=null;function js(e){Ve!==null&&(Rn??(Rn=new Set)).add(e)}let dn=null,un=0,gn=null;function bo(e){gn=e}let Us=1,ua=0,wa=ua;function Nr(e){wa=e}function Hs(){return++Us}function _i(e){var n=e.f;if((n&Xt)!==0)return!0;if(n&tn&&(e.f&=~Sa),(n&Kn)!==0){for(var a=e.deps,s=a.length,l=0;l<s;l++){var o=a[l];if(_i(o)&&Ss(o),o.wv>e.wv)return!0}(n&kn)!==0&&Yt===null&&Nt(e,Ht)}return!1}function Js(e,n,a=!0){var s=e.reactions;if(s!==null&&!(Rn!==null&&Rn.has(e)))for(var l=0;l<s.length;l++){var o=s[l];(o.f&tn)!==0?Js(o,n,!1):n===o&&(a?Nt(o,Xt):(o.f&Ht)!==0&&Nt(o,Kn),Mr(o))}}function Qs(e){var O;var n=dn,a=un,s=gn,l=Ve,o=Rn,v=en,d=Tn,u=wa,p=e.f;dn=null,un=0,gn=null,Ve=(p&(zn|la))===0?e:null,Rn=null,Va(e.ctx),Tn=!1,wa=++ua,e.ac!==null&&(Er(()=>{e.ac.abort(Ni)}),e.ac=null);try{e.f|=Di;var _=e.fn,C=_();e.f|=Ja;var m=e.deps,y=ge==null?void 0:ge.is_fork;if(dn!==null){var $;if(y||vi(e,un),m!==null&&un>0)for(m.length=un+dn.length,$=0;$<dn.length;$++)m[un+$]=dn[$];else e.deps=m=dn;if(Cr()&&(e.f&kn)!==0)for($=un;$<m.length;$++)((O=m[$]).reactions??(O.reactions=[])).push(e)}else!y&&m!==null&&un<m.length&&(vi(e,un),m.length=un);if(bs()&&gn!==null&&!Tn&&m!==null&&(e.f&(tn|Kn|Xt))===0)for($=0;$<gn.length;$++)Js(gn[$],e);if(l!==null&&l!==e){if(ua++,l.deps!==null)for(let M=0;M<a;M+=1)l.deps[M].rv=ua;if(n!==null)for(const M of n)M.rv=ua;gn!==null&&(s===null?s=gn:s.push(...gn))}return(e.f&sa)!==0&&(e.f^=sa),C}catch(M){return ys(M)}finally{e.f^=Di,dn=n,un=a,gn=s,Ve=l,Rn=o,Va(v),Tn=d,wa=u}}function _o(e,n){let a=n.reactions;if(a!==null){var s=ol.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&tn)!==0&&(dn===null||!zi.call(dn,n))){var o=n;(o.f&kn)!==0&&(o.f^=kn,o.f&=~Sa),o.v!==Ut&&xr(o),to(o),vi(o,0)}}function vi(e,n){var a=e.deps;if(a!==null)for(var s=n;s<a.length;s++)_o(e,a[s])}function ja(e){var n=e.f;if((n&wn)===0){Nt(e,Ht);var a=Ge,s=Ti;Ge=e,Ti=!0;try{(n&(Cn|us))!==0?mo(e):zr(e),Ns(e);var l=Qs(e);e.teardown=typeof l=="function"?l:null,e.wv=Us;var o}finally{Ti=s,Ge=a}}}async function yo(){await Promise.resolve(),io()}function t(e){var n=e.f,a=(n&tn)!==0;if(Ve!==null&&!Tn){var s=Ge!==null&&(Ge.f&wn)!==0;if(!s&&(Rn===null||!Rn.has(e))){var l=Ve.deps;if((Ve.f&Di)!==0)e.rv<ua&&(e.rv=ua,dn===null&&l!==null&&l[un]===e?un++:dn===null?dn=[e]:dn.push(e));else{Ve.deps??(Ve.deps=[]),zi.call(Ve.deps,e)||Ve.deps.push(e);var o=e.reactions;o===null?e.reactions=[Ve]:zi.call(o,Ve)||o.push(Ve)}}}if(oa&&xa.has(e))return xa.get(e);if(a){var v=e;if(oa){var d=v.v;return((v.f&Ht)===0&&v.reactions!==null||Ys(v))&&(d=wr(v)),xa.set(v,d),d}var u=(v.f&kn)===0&&!Tn&&Ve!==null&&(Ti||(Ve.f&kn)!==0),p=(v.f&Ja)===0;_i(v)&&(u&&(v.f|=kn),Ss(v)),u&&!p&&(Ms(v),Zs(v))}if(Yt!=null&&Yt.has(e))return Yt.get(e);if((e.f&sa)!==0)throw e.v;return e.v}function Zs(e){if(e.f|=kn,e.deps!==null)for(const n of e.deps)(n.reactions??(n.reactions=[])).push(e),(n.f&tn)!==0&&(n.f&kn)===0&&(Ms(n),Zs(n))}function Ys(e){if(e.v===Ut)return!0;if(e.deps===null)return!1;for(const n of e.deps)if(xa.has(n)||(n.f&tn)!==0&&Ys(n))return!0;return!1}function Za(e){var n=Tn;try{return Tn=!0,e()}finally{Tn=n}}const xo=["touchstart","touchmove"];function ko(e){return xo.includes(e)}const pa=Symbol("events"),Xs=new Set,gr=new Set;function k(e,n,a){(n[pa]??(n[pa]={}))[e]=a}function qn(e){for(var n=0;n<e.length;n++)Xs.add(e[n]);for(var a of gr)a(e)}let qr=null;function Vr(e){var O,M;var n=this,a=n.ownerDocument,s=e.type,l=((O=e.composedPath)==null?void 0:O.call(e))||[],o=l[0]||e.target;qr=e;var v=0,d=qr===e&&e[pa];if(d){var u=l.indexOf(d);if(u!==-1&&(n===document||n===window)){e[pa]=n;return}var p=l.indexOf(n);if(p===-1)return;u<=p&&(v=u)}if(o=l[v]||e.target,o!==n){dl(e,"currentTarget",{configurable:!0,get(){return o||a}});var _=Ve,C=Ge;Sn(null),Nn(null);try{for(var m,y=[];o!==null&&o!==n;){try{var $=(M=o[pa])==null?void 0:M[s];$!=null&&(!o.disabled||e.target===o)&&$.call(o,e)}catch(F){m?y.push(F):m=F}if(e.cancelBubble)break;v++,o=v<l.length?l[v]:null}if(m){for(let F of y)queueMicrotask(()=>{throw F});throw m}}finally{e[pa]=n,delete e.currentTarget,Sn(_),Nn(C)}}}var ls;const Qi=((ls=globalThis==null?void 0:globalThis.window)==null?void 0:ls.trustedTypes)&&globalThis.window.trustedTypes.createPolicy("svelte-trusted-html",{createHTML:e=>e});function wo(e){return(Qi==null?void 0:Qi.createHTML(e))??e}function So(e){var n=Bs("template");return n.innerHTML=wo(e.replaceAll("<!>","<!---->")),n.content}function Ua(e,n){var a=Ge;a.nodes===null&&(a.nodes={start:e,end:n,a:null,t:null})}function b(e,n){var a=(n&$l)!==0,s=(n&Il)!==0,l,o=!e.startsWith("<!>");return()=>{l===void 0&&(l=So(o?e:"<!>"+e),a||(l=ra(l)));var v=s||$s?document.importNode(l,!0):l.cloneNode(!0);if(a){var d=ra(v),u=v.lastChild;Ua(d,u)}else Ua(v,v);return v}}function oi(e=""){{var n=Jn(e+"");return Ua(n,n),n}}function Ha(){var e=document.createDocumentFragment(),n=document.createComment(""),a=Jn();return e.append(n,a),Ua(n,a),e}function f(e,n){e!==null&&e.before(n)}function g(e,n){var a=n==null?"":typeof n=="object"?`${n}`:n;a!==(e[Xa]??(e[Xa]=e.nodeValue))&&(e[Xa]=a,e.nodeValue=`${a}`)}function Mo(e,n){return Eo(e,n)}const wi=new Map;function Eo(e,{target:n,anchor:a,props:s={},events:l,context:o,intro:v=!0,transformError:d}){co();var u=void 0,p=ho(()=>{var _=a??n.appendChild(Jn());Gl(_,{pending:()=>{}},y=>{Pn({});var $=en;o&&($.c=o),l&&(s.$$events=l),u=e(y,s)||{},Dn()},d);var C=new Set,m=y=>{for(var $=0;$<y.length;$++){var O=y[$];if(!C.has(O)){C.add(O);var M=ko(O);for(const xe of[n,document]){var F=wi.get(xe);F===void 0&&(F=new Map,wi.set(xe,F));var ye=F.get(O);ye===void 0?(xe.addEventListener(O,Vr,{passive:M}),F.set(O,1)):F.set(O,ye+1)}}}};return m(Fi(Xs)),gr.add(m),()=>{var M;for(var y of C)for(const F of[n,document]){var $=wi.get(F),O=$.get(y);--O==0?(F.removeEventListener(y,Vr),$.delete(y),$.size===0&&wi.delete(F)):$.set(y,O)}gr.delete(m),_!==a&&((M=_.parentNode)==null||M.removeChild(_))}});return Ao.set(u,p),u}let Ao=new WeakMap;var An,On,fn,_a,gi,mi,Ri;class Co{constructor(n,a=!0){vn(this,"anchor");Oe(this,An,new Map);Oe(this,On,new Map);Oe(this,fn,new Map);Oe(this,_a,new Set);Oe(this,gi,!0);Oe(this,mi,n=>{if(h(this,An).has(n)){var a=h(this,An).get(n),s=h(this,On).get(a);if(s)Li(s),h(this,_a).delete(a);else{var l=h(this,fn).get(a);l&&(Li(l.effect),h(this,On).set(a,l.effect),h(this,fn).delete(a),l.fragment.lastChild.remove(),this.anchor.before(l.fragment),s=l.effect)}for(const[o,v]of h(this,An)){if(h(this,An).delete(o),o===n)break;const d=h(this,fn).get(v);d&&(cn(d.effect),h(this,fn).delete(v))}for(const[o,v]of h(this,On)){if(o===a||h(this,_a).has(o))continue;const d=()=>{if(Array.from(h(this,An).values()).includes(o)){var p=document.createDocumentFragment();Pr(v,p),p.append(Jn()),h(this,fn).set(o,{effect:v,fragment:p})}else cn(v);h(this,_a).delete(o),h(this,On).delete(o)};h(this,gi)||!s?(h(this,_a).add(o),ka(v,d,!1)):d()}}});Oe(this,Ri,n=>{h(this,An).delete(n);const a=Array.from(h(this,An).values());for(const[s,l]of h(this,fn))a.includes(s)||(cn(l.effect),h(this,fn).delete(s))});this.anchor=n,Pe(this,gi,a)}ensure(n,a){var s=ge,l=Os();if(a&&!h(this,On).has(n)&&!h(this,fn).has(n))if(l){var o=document.createDocumentFragment(),v=Jn();o.append(v),h(this,fn).set(n,{effect:yn(()=>a(v)),fragment:o})}else h(this,On).set(n,yn(()=>a(this.anchor)));if(h(this,An).set(s,n),l){for(const[d,u]of h(this,On))d===n?s.unskip_effect(u):s.skip_effect(u);for(const[d,u]of h(this,fn))d===n?s.unskip_effect(u.effect):s.skip_effect(u.effect);s.oncommit(h(this,mi)),s.ondiscard(h(this,Ri))}else h(this,mi).call(this,s)}}An=new WeakMap,On=new WeakMap,fn=new WeakMap,_a=new WeakMap,gi=new WeakMap,mi=new WeakMap,Ri=new WeakMap;function q(e,n,a=!1){var s=new Co(e),l=a?qa:0;function o(v,d){s.ensure(v,d)}Tr(()=>{var v=!1;n((d,u=0)=>{v=!0,o(u,d)}),v||o(-1,null)},l)}function lt(e,n){return n}function To(e,n,a){for(var s=[],l=n.length,o,v=n.length,d=0;d<l;d++){let C=n[d];ka(C,()=>{if(o){if(o.pending.delete(C),o.done.add(C),o.pending.size===0){var m=e.outrogroups;mr(e,Fi(o.done)),m.delete(o),m.size===0&&(e.outrogroups=null)}}else v-=1},!1)}if(v===0){var u=s.length===0&&a!==null;if(u){var p=a,_=p.parentNode;vo(_),_.append(p),e.items.clear()}mr(e,n,!u)}else o={pending:new Set(n),done:new Set},(e.outrogroups??(e.outrogroups=new Set)).add(o)}function mr(e,n,a=!0){var s;if(e.pending.size>0){s=new Set;for(const v of e.pending.values())for(const d of v)s.add(e.items.get(d).e)}for(var l=0;l<n.length;l++){var o=n[l];if(s!=null&&s.has(o)){o.f|=Bn;const v=document.createDocumentFragment();Pr(o,v)}else cn(n[l],a)}}var Wr;function Ye(e,n,a,s,l,o=null){var v=e,d=new Map,u=(n&fs)!==0;if(u){var p=e;v=p.appendChild(Jn())}var _=null,C=Xl(()=>{var xe=a();return yr(xe)?xe:xe==null?[]:Fi(xe)}),m,y=new Map,$=!0;function O(xe){(ye.effect.f&wn)===0&&(ye.pending.delete(xe),ye.fallback=_,zo(ye,m,v,n,s),_!==null&&(m.length===0?(_.f&Bn)===0?Li(_):(_.f^=Bn,ai(_,null,v)):ka(_,()=>{_=null})))}function M(xe){ye.pending.delete(xe)}var F=Tr(()=>{m=t(C);for(var xe=m.length,ke=new Set,Ie=ge,Z=Os(),X=0;X<xe;X+=1){var ve=m[X],ze=s(ve,X),Re=$?null:d.get(ze);Re?(Re.v&&Wa(Re.v,ve),Re.i&&Wa(Re.i,X),Z&&Ie.unskip_effect(Re.e)):(Re=Po(d,$?v:Wr??(Wr=Jn()),ve,ze,X,l,n,a),$||(Re.e.f|=Bn),d.set(ze,Re)),ke.add(ze)}if(xe===0&&o&&!_&&($?_=yn(()=>o(v)):(_=yn(()=>o(Wr??(Wr=Jn()))),_.f|=Bn)),xe>ke.size&&yl(),!$)if(y.set(Ie,ke),Z){for(const[je,ot]of d)ke.has(je)||Ie.skip_effect(ot.e);Ie.oncommit(O),Ie.ondiscard(M)}else O(Ie);t(C)}),ye={effect:F,items:d,pending:y,outrogroups:null,fallback:_};$=!1}function Ya(e){for(;e!==null&&(e.f&zn)===0;)e=e.next;return e}function zo(e,n,a,s,l){var Re,je,ot,I,re,be,Je,de,Fe;var o=(s&Pl)!==0,v=n.length,d=e.items,u=Ya(e.effect.first),p,_=null,C,m=[],y=[],$,O,M,F;if(o)for(F=0;F<v;F+=1)$=n[F],O=l($,F),M=d.get(O).e,(M.f&Bn)===0&&((je=(Re=M.nodes)==null?void 0:Re.a)==null||je.measure(),(C??(C=new Set)).add(M));for(F=0;F<v;F+=1){if($=n[F],O=l($,F),M=d.get(O).e,e.outrogroups!==null)for(const ue of e.outrogroups)ue.pending.delete(M),ue.done.delete(M);if((M.f&rn)!==0&&(Li(M),o&&((I=(ot=M.nodes)==null?void 0:ot.a)==null||I.unfix(),(C??(C=new Set)).delete(M))),(M.f&Bn)!==0)if(M.f^=Bn,M===u)ai(M,null,a);else{var ye=_?_.next:u;M===e.effect.last&&(e.effect.last=M.prev),M.prev&&(M.prev.next=M.next),M.next&&(M.next.prev=M.prev),Yn(e,_,M),Yn(e,M,ye),ai(M,ye,a),_=M,m=[],y=[],u=Ya(_.next);continue}if(M!==u){if(p!==void 0&&p.has(M)){if(m.length<y.length){var xe=y[0],ke;_=xe.prev;var Ie=m[0],Z=m[m.length-1];for(ke=0;ke<m.length;ke+=1)ai(m[ke],xe,a);for(ke=0;ke<y.length;ke+=1)p.delete(y[ke]);Yn(e,Ie.prev,Z.next),Yn(e,_,Ie),Yn(e,Z,xe),u=xe,_=Z,F-=1,m=[],y=[]}else p.delete(M),ai(M,u,a),Yn(e,M.prev,M.next),Yn(e,M,_===null?e.effect.first:_.next),Yn(e,_,M),_=M;continue}for(m=[],y=[];u!==null&&u!==M;)(p??(p=new Set)).add(u),y.push(u),u=Ya(u.next);if(u===null)continue}(M.f&Bn)===0&&m.push(M),_=M,u=Ya(M.next)}if(e.outrogroups!==null){for(const ue of e.outrogroups)ue.pending.size===0&&(mr(e,Fi(ue.done)),(re=e.outrogroups)==null||re.delete(ue));e.outrogroups.size===0&&(e.outrogroups=null)}if(u!==null||p!==void 0){var X=[];if(p!==void 0)for(M of p)(M.f&rn)===0&&X.push(M);for(;u!==null;)(u.f&rn)===0&&u!==e.fallback&&X.push(u),u=Ya(u.next);var ve=X.length;if(ve>0){var ze=(s&fs)!==0&&v===0?a:null;if(o){for(F=0;F<ve;F+=1)(Je=(be=X[F].nodes)==null?void 0:be.a)==null||Je.measure();for(F=0;F<ve;F+=1)(Fe=(de=X[F].nodes)==null?void 0:de.a)==null||Fe.fix()}To(e,X,ze)}}o&&ya(()=>{var ue,at;if(C!==void 0)for(M of C)(at=(ue=M.nodes)==null?void 0:ue.a)==null||at.apply()})}function Po(e,n,a,s,l,o,v,d){var u=(v&Tl)!==0?(v&Dl)===0?so(a,!1,!1):Ea(a):null,p=(v&zl)!==0?Ea(l):null;return{v:u,i:p,e:yn(()=>(o(n,u??a,p??l,d),()=>{e.delete(s)}))}}function ai(e,n,a){if(e.nodes)for(var s=e.nodes.start,l=e.nodes.end,o=n&&(n.f&Bn)===0?n.nodes.start:a;s!==null;){var v=bi(s);if(o.before(s),s===l)return;s=v}}function Yn(e,n,a){n===null?e.effect.first=a:n.next=a,a===null?e.effect.last=n:a.prev=n}function He(e,n,a=!1,s=!1,l=!1,o=!1){var v=e,d="";if(a)var u=e;D(()=>{var p=Ge;if(d!==(d=n()??"")){if(a){p.nodes=null,u.innerHTML=d,d!==""&&Ua(ra(u),u.lastChild);return}if(p.nodes!==null&&(qs(p.nodes.start,p.nodes.end),p.nodes=null),d!==""){var _=s?Ll:l?Ol:void 0,C=Bs(s?"svg":l?"math":"template",_);C.innerHTML=d;var m=s||l?C:C.content;if(Ua(ra(m),m.lastChild),s||l)for(;ra(m);)v.before(ra(m));else v.before(m)}}})}function Do(e,n,a){var s=e==null?"":""+e;return n&&(s=s?s+" "+n:n),s===""?null:s}function $o(e,n){return e==null?null:String(e)}function At(e,n,a,s,l,o){var v=e[or];if(v!==a||v===void 0){var d=Do(a,s);d==null?e.removeAttribute("class"):e.className=d,e[or]=a}return o}function $t(e,n,a,s){var l=e[dr];if(l!==n){var o=$o(n);o==null?e.removeAttribute("style"):e.style.cssText=o,e[dr]=n}return s}function el(e,n,a=!1){if(e.multiple){if(n==null)return;if(!yr(n))return Rl();for(var s of e.options)s.selected=n.includes(di(s));return}for(s of e.options){var l=di(s);if(oo(l,n)){s.selected=!0;return}}(!a||n!==void 0)&&(e.selectedIndex=-1)}function Io(e){var n=new MutationObserver(()=>{el(e,e.__value)});n.observe(e,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["value"]}),Rs(()=>{n.disconnect()})}function Hn(e,n,a=n){var s=new WeakSet,l=!0;Ar(e,"change",o=>{var v=o?"[selected]":":checked",d;if(e.multiple)d=[].map.call(e.querySelectorAll(v),di);else{var u=e.querySelector(v)??e.querySelector("option:not([disabled])");d=u&&di(u)}a(d),e.__value=d,ge!==null&&s.add(ge)}),Ks(()=>{var o=n();if(e===document.activeElement){var v=ge;if(s.has(v))return}if(el(e,o,l),l&&o===void 0){var d=e.querySelector(":checked");d!==null&&(o=di(d),a(o))}e.__value=o,l=!1}),Io(e)}function di(e){return"__value"in e?e.__value:e.value}const Lo=Symbol("is custom element"),Oo=Symbol("is html"),Bo=bl?"progress":"PROGRESS";function Xn(e,n){var a=tl(e);a.value===(a.value=n??void 0)||e.value===n&&(n!==0||e.nodeName!==Bo)||(e.value=n??"")}function Aa(e,n,a,s){var l=tl(e);l[n]!==(l[n]=a)&&(n==="loading"&&(e[ml]=a),a==null?e.removeAttribute(n):typeof a!="string"&&Ro(e).includes(n)?e[n]=a:e.setAttribute(n,a))}function tl(e){return e[Si]??(e[Si]={[Lo]:e.nodeName.includes("-"),[Oo]:e.namespaceURI===hs})}var Gr=new Map;function Ro(e){var n=e.getAttribute("is")||e.nodeName,a=Gr.get(n);if(a)return a;Gr.set(n,a=[]);for(var s,l=e,o=Element.prototype;o!==l;){s=cl(l);for(var v in s)s[v].set&&v!=="innerHTML"&&v!=="textContent"&&v!=="innerText"&&a.push(v);l=cs(l)}return a}function an(e,n,a=n){var s=new WeakSet;Ar(e,"input",async l=>{var o=l?e.defaultValue:e.value;if(o=Zi(e)?Yi(o):o,a(o),ge!==null&&s.add(ge),await yo(),o!==(o=n())){var v=e.selectionStart,d=e.selectionEnd,u=e.value.length;if(e.value=o??"",d!==null){var p=e.value.length;v===d&&d===u&&p>u?(e.selectionStart=p,e.selectionEnd=p):(e.selectionStart=v,e.selectionEnd=Math.min(d,p))}}}),Za(n)==null&&e.value&&(a(Zi(e)?Yi(e.value):e.value),ge!==null&&s.add(ge)),qi(()=>{var l=n();if(e===document.activeElement){var o=ge;if(s.has(o))return}Zi(e)&&l===Yi(e.value)||e.type==="date"&&!l&&!e.value||l!==e.value&&(e.value=l??"")})}function Fo(e,n,a=n){Ar(e,"change",s=>{var l=s?e.defaultChecked:e.checked;a(l)}),Za(n)==null&&a(e.checked),qi(()=>{var s=n();e.checked=!!s})}function Zi(e){var n=e.type;return n==="number"||n==="range"}function Yi(e){return e===""?null:+e}function Xi(e,n){return e===n||(e==null?void 0:e[$a])===n}function Ko(e={},n,a,s){var l=en.r,o=Ge;return Ks(()=>{var v,d;return qi(()=>{v=d,d=[],Za(()=>{Xi(a(...d),e)||(n(e,...d),v&&Xi(a(...v),e)&&n(null,...v))})}),()=>{let u=o;for(;u!==l&&u.parent!==null&&u.parent.f&lr;)u=u.parent;const p=()=>{d&&Xi(a(...d),e)&&n(null,...d)},_=u.teardown;u.teardown=()=>{p(),_==null||_()}}}),e}function yi(e){en===null&&ps(),Ga(()=>{const n=Za(e);if(typeof n=="function")return n})}function No(e){en===null&&ps(),yi(()=>()=>Za(e))}let ui=localStorage.getItem("mc_token")||"";function nl(){return ui}function qo(e){ui=(e||"").trim(),localStorage.setItem("mc_token",ui)}function Vo(){const e={"Content-Type":"application/json"};return ui&&(e["X-MC-Token"]=ui),e}function ci(){return localStorage.getItem("mc_hf_token")||""}function Wo(e){localStorage.setItem("mc_hf_token",(e||"").trim())}async function De(e,n={}){const a=await fetch(e,{headers:Vo(),...n}),s=await a.json().catch(()=>({}));if(!a.ok)throw new Error(s.error||"HTTP "+a.status);return s}const Go=(e,n=document)=>n.querySelector(e),jr=(e,n=document)=>[...n.querySelectorAll(e)];function Fn(e){return String(e??"").replace(/[&<>]/g,n=>({"&":"&","<":"<",">":">"})[n])}let Ur;function ie(e,n=!1){const a=Go("#toast");a&&(a.textContent=e,a.className="toast show"+(n?" err":""),clearTimeout(Ur),Ur=setTimeout(()=>a.className="toast",3200))}function jo(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 ut=e=>`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round">${e}</svg>`,Vi={logo:ut('<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:ut('<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:ut('<rect x="6" y="6" width="12" height="12" rx="2"/><path d="M9 1v3M15 1v3M9 20v3M15 20v3M1 9h3M1 15h3M20 9h3M20 15h3"/>'),pulse:ut('<path d="M3 12h4l2 6 4-14 2 8h6"/>'),server:ut('<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:ut('<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:ut('<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:ut('<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:ut('<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:ut('<rect x="3" y="4" width="18" height="12" rx="2"/><path d="M8 20h8M12 16v4"/>'),layers:ut('<path d="m12 2 9 5-9 5-9-5z"/><path d="m3 12 9 5 9-5M3 17l9 5 9-5"/>'),alert:ut('<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:ut('<path d="M12 14 16 9"/><circle cx="12" cy="13" r="9"/><path d="M12 4v2M21 13h-2M5 13H3"/>'),search:ut('<circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/>'),compass:ut('<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:ut('<polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/>'),eye:ut('<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:ut('<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:ut('<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:ut('<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:ut('<path d="M14 14.76V5a2 2 0 0 0-4 0v9.76a4 4 0 1 0 4 0z"/>'),shield:ut('<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:ut('<circle cx="12" cy="12" r="9"/><path d="M12 16v-4M12 8h.01"/>'),chevron:ut('<path d="m9 6 6 6-6 6"/>'),bolt:ut('<path d="M13 2 3 14h7l-1 8 10-12h-7z"/>'),x:ut('<path d="M18 6 6 18M6 6l12 12"/>'),check:ut('<path d="M20 6 9 17l-5-5"/>'),download:ut('<path d="M12 3v12M7 10l5 5 5-5"/><path d="M5 21h14"/>'),clock:ut('<circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/>')};function jt(e){return Vi[e]||""}function br(e){return`<span class="info-dot" tabindex="0" title="${Fn(e)}" aria-label="${Fn(e)}">${Vi.info}</span>`}function ca(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 xn({title:e,body:n,confirmLabel:a="Bestätigen",cancelLabel:s="Abbrechen",danger:l=!1}){return new Promise(o=>{const v=document.createElement("div");v.className="modal-overlay",v.innerHTML=`<div class="modal-card" role="dialog" aria-modal="true">
|
||
<h3>${Fn(e)}</h3>
|
||
<p>${n}</p>
|
||
<div class="modal-actions">
|
||
<button data-x="0">${Fn(s)}</button>
|
||
<button class="${l?"danger":"primary"}" data-x="1">${Fn(a)}</button>
|
||
</div></div>`;const d=u=>{v.remove(),o(u)};v.addEventListener("click",u=>{if(u.target===v)return d(!1);const p=u.target.closest("[data-x]");p&&d(p.getAttribute("data-x")==="1")}),document.body.appendChild(v),v.querySelector('[data-x="1"]').focus()})}function er({title:e,body:n="",placeholder:a="",password:s=!1,confirmLabel:l="Weiter",danger:o=!1}){return new Promise(v=>{const d=document.createElement("div");d.className="modal-overlay",d.innerHTML=`<div class="modal-card" role="dialog" aria-modal="true">
|
||
<h3>${Fn(e)}</h3>
|
||
${n?`<p>${n}</p>`:""}
|
||
<input type="${s?"password":"text"}" placeholder="${Fn(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">${Fn(l)}</button>
|
||
</div></div>`;const u=d.querySelector("input"),p=_=>{d.remove(),v(_)};d.addEventListener("click",_=>{if(_.target===d)return p(null);const C=_.target.closest("[data-x]");C&&p(C.getAttribute("data-x")==="1"?u.value||"":null)}),u.addEventListener("keydown",_=>{_.key==="Enter"&&p(u.value||""),_.key==="Escape"&&p(null)}),document.body.appendChild(d),u.focus()})}function Uo(e="overview"){const n=jr(".nav-item[data-view]:not(.disabled)"),a=jr(".view[data-view]"),s=new Set(a.map(o=>o.dataset.view));function l(o){s.has(o)||(o=e),a.forEach(v=>v.hidden=v.dataset.view!==o),n.forEach(v=>v.classList.toggle("active",v.dataset.view===o)),location.hash!=="#/"+o&&(location.hash="#/"+o)}return n.forEach(o=>o.addEventListener("click",v=>{v.preventDefault(),l(o.dataset.view)})),window.addEventListener("hashchange",()=>l(location.hash.replace("#/",""))),l(location.hash.replace("#/","")||e),{show:l}}let Hr=L(null);const xi={get value(){return t(Hr)},set(e){c(Hr,e,!0)}};let Jr=L(Jt([])),ea=L(Jt([]));const fa={get value(){return t(Jr)},set(e){c(Jr,e||[],!0)},get tracked(){return t(ea)},track(e){t(ea).includes(e)||c(ea,[...t(ea),e],!0)},toggle(e){c(ea,t(ea).includes(e)?t(ea).filter(n=>n!==e):[...t(ea),e],!0)}};let Qr=L(null);const Dr={get value(){return t(Qr)},set(e){c(Qr,e,!0)}},Ho="5";var os;typeof window<"u"&&((os=window.__svelte??(window.__svelte={})).v??(os.v=new Set)).add(Ho);var Jo=b('<span style="font-size:13px;font-weight:400;color:var(--mut)">— bereit für Anfragen</span>'),Qo=b('<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),Zo=b('<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),Yo=b('<div class="meter"><div class="meter-h"><span class="mk"> </span><span class="mv"> </span></div> <div><i></i></div></div>'),Xo=b('<div class="empty">Warte auf Messwerte…</div>'),ed=b('<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),td=b('<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),nd=b('<span class="tag img">Bild</span>'),ad=b('<span class="tag code">Code</span>'),id=b('<span class="tag text">Text</span>'),rd=b('<span class="chip" style="padding:2px 7px;font-size:11px">∞ aktiv</span>'),sd=b('<button class="ghost"> </button>'),ld=b('<div class="li" style="padding:10px 4px"><span></span> <div class="li-main"><div class="flex items-center gap-2" style="flex-wrap:wrap"><span class="li-id"> </span> <!> <!></div> <div class="li-sub mono-sm"> </div></div> <div class="flex items-center gap-2"><span class="li-meta"> </span> <!></div></div>'),Zr=b('<div class="list"></div>'),od=b('<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>'),dd=b('<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>'),cd=b('<div class="empty">News gerade nicht ladbar.</div>'),vd=b('<div class="pagehead" style="margin-bottom:10px"><div><h1 style="display:flex;align-items:center;gap:10px"> <!></h1> <div class="sub"> </div></div></div> <div class="tiles"><div><div class="k-h"><span class="k-t">LLM-Engine</span> <span class="k-ic"></span></div> <div class="k-v"> </div> <div class="k-s"> </div></div> <div><div class="k-h"><span class="k-t">Aktives Modell</span> <span class="k-ic"></span></div> <div class="k-v" style="font-size:16px;word-break:break-word"> </div> <div class="k-s"><!></div></div> <!></div> <div class="split"><div class="card"><div class="card-h"><h3>System-Gesundheit</h3></div> <div class="card-sub">Auslastung in Echtzeit.</div> <!></div> <div class="card"><div class="card-h"><h3>Schnellstart</h3></div> <!></div></div> <div class="grid grid-2"><div class="card"><div class="card-h"><h3>Dein Stack</h3> <span class="meta"> </span></div> <!></div> <div class="card"><div class="card-h"><h3>Top-News</h3> <span class="meta" style="cursor:pointer" role="button" tabindex="0">Alle →</span></div> <!></div></div>',1);function ud(e,n){Pn(n,!0);const a=G(()=>xi.value),s=G(()=>Dr.value),l=G(()=>{var T;return((T=t(a))==null?void 0:T.models)||[]}),o=G(()=>{var T;return((T=t(a))==null?void 0:T.swap_ok)??!1}),v=["running","ready","loading","starting"],d=G(()=>t(l).find(T=>v.includes(T.state))),u=G(()=>t(l).filter(T=>!T.incomplete)),p=G(()=>t(a)?t(o)?t(s)&&t(s).ram.percent>=90?"Achtung: Speicher wird knapp.":"Alles läuft rund.":"LLM-Engine offline":"Verbinde…"),_=G(()=>t(a)?t(o)?t(s)&&t(s).ram.percent>=90?`Arbeitsspeicher bei ${Math.round(t(s).ram.percent)} % — eventuell Speicher freigeben.`:`${t(u).length} ${t(u).length===1?"Modell":"Modelle"} konfiguriert · ${t(d)?`„${t(d).name}" geladen`:"keines geladen"} · keine Warnungen.`:"Der llama-swap-Dienst antwortet gerade nicht.":""),C=G(()=>()=>{var Q;const T=(Q=t(s))==null?void 0:Q.gpu;return T&&T.vram.total+T.gtt.total>0?(T.vram.used+T.gtt.used)/(T.vram.total+T.gtt.total)*100:0});let m=L(Jt([])),y=L(null);yi(async()=>{try{c(m,((await De("/api/news")).items||[]).slice(0,4),!0)}catch{}});async function $(){await xn({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 De("/api/unload",{method:"POST"}),M())}async function O(T){c(y,T,!0);try{await De("/api/preload?model="+encodeURIComponent(T),{method:"POST"})}catch(Q){ie("Laden fehlgeschlagen: "+(Q.message||"Engine nicht erreichbar?"),!0)}c(y,null),M()}function M(){document.dispatchEvent(new Event("mc:refresh"))}function F(T){var Q;(Q=document.querySelector(`.nav-item[data-view="${T}"]`))==null||Q.dispatchEvent(new MouseEvent("click"))}function ye(T){return T>=90?"red":T>=75?"":"green"}function xe(T){return T==null?"":T>=75?"red":T>=55?"":"green"}function ke(T){return T>=90?"red":T>=70?"":"green"}var Ie=vd(),Z=Xe(Ie),X=r(Z),ve=r(X),ze=r(ve),Re=i(ze);{var je=T=>{var Q=Jo();f(T,Q)};q(Re,T=>{t(o)&&!t(d)&&T(je)})}var ot=i(ve,2),I=r(ot),re=i(Z,2),be=r(re),Je=r(be),de=i(r(Je),2);He(de,()=>jt("server"),!0);var Fe=i(Je,2),ue=r(Fe),at=i(Fe,2),Qe=r(at),it=i(be,2),dt=r(it),rt=i(r(dt),2);He(rt,()=>jt("cpu"),!0);var Tt=i(dt,2),zt=r(Tt),Wt=i(Tt,2),qt=r(Wt);{var Gt=T=>{var Q=oi();D(Be=>g(Q,`${Be??""} · ${t(d).state??""}`),[()=>{var Be;return(Be=t(d).meta)!=null&&Be.ctx?Math.round(t(d).meta.ctx/1024)+"k ctx":""}]),f(T,Q)},Lt=T=>{var Q=oi("lädt bei erster Anfrage");f(T,Q)};q(qt,T=>{t(d)?T(Gt):T(Lt,-1)})}var Ot=i(it,2);{var U=T=>{const Q=G(()=>{var hn;return t(s).gpu_temp??((hn=t(s).cpu)==null?void 0:hn.temp)??null}),Be=G(()=>xe(t(Q))),ne=G(()=>t(s).ram.total-t(s).ram.used),he=G(()=>100-t(s).ram.percent);var Ne=Qo(),We=Xe(Ne),Ee=r(We),W=i(r(Ee));He(W,()=>jt("thermo"),!0);var J=i(Ee,2),le=r(J),oe=i(J,2),$e=r(oe),Le=i(We,2),Te=r(Le),se=i(r(Te));He(se,()=>jt("database"),!0);var ce=i(Te,2),wt=r(ce),St=i(ce,2),Bt=r(St);D((hn,da,E,S)=>{At(We,1,`kpi ${t(Be)??""}`),g(le,hn),g($e,t(Q)==null?"messe…":t(Q)<55?"kühl":t(Q)<75?"normal":"⚠ heiß"),At(Le,1,`kpi ${t(he)<15?"red":t(he)<30?"":"green"}`),g(wt,da),g(Bt,`von ${E??""} GB · ${S??""} % frei`)},[()=>t(Q)!=null?`${Math.round(t(Q))}°C`:"–",()=>Math.round(t(ne)/1073741824),()=>Math.round(t(s).ram.total/1073741824),()=>Math.round(t(he))]),f(T,Ne)},ae=T=>{var Q=Zo();f(T,Q)};q(Ot,T=>{t(s)?T(U):T(ae,-1)})}var A=i(re,2),B=r(A),_e=i(r(B),4);{var Ce=T=>{const Q=G(()=>t(C)());var Be=Ha(),ne=Xe(Be);Ye(ne,17,()=>{var he;return[["Prozessor (CPU)",((he=t(s).cpu)==null?void 0:he.percent)??0,""],["Arbeitsspeicher (RAM)",t(s).ram.percent,ye(t(s).ram.percent)],["Grafikspeicher (VRAM)",t(Q),ke(t(Q))]]},lt,(he,Ne)=>{var We=G(()=>aa(t(Ne),3));let Ee=()=>t(We)[0],W=()=>t(We)[1];const J=G(()=>Math.max(0,Math.min(100,W()||0)));var le=Yo(),oe=r(le),$e=r(oe),Le=r($e),Te=i($e),se=r(Te),ce=i(oe,2),wt=r(ce);D((St,Bt)=>{g(Le,Ee()),g(se,`${St??""} %`),At(ce,1,`bar ${t(J)>=90?"bad":t(J)>=75?"warn":""}`),$t(wt,`width:${Bt??""}%`)},[()=>Math.round(t(J)),()=>Math.max(2,t(J))]),f(he,le)}),f(T,Be)},V=T=>{var Q=Xo();f(T,Q)};q(_e,T=>{t(s)?T(Ce):T(V,-1)})}var pe=i(B,2),z=i(r(pe),2);{var R=T=>{var Q=ed(),Be=i(Xe(Q),2),ne=r(Be);He(ne,()=>jt("search"),!0);var he=i(ne,4);He(he,()=>jt("chevron"),!0);var Ne=i(Be,2),We=r(Ne);He(We,()=>jt("swap"),!0);var Ee=i(We,4);He(Ee,()=>jt("chevron"),!0);var W=i(Ne,2),J=r(W);He(J,()=>jt("file"),!0);var le=i(J,4);He(le,()=>jt("chevron"),!0),k("click",Be,()=>F("cookbook")),k("click",Ne,()=>F("connect")),k("click",W,()=>F("guides")),f(T,Q)},x=T=>{var Q=td(),Be=i(Xe(Q),2),ne=r(Be);He(ne,()=>jt("search"),!0);var he=i(ne,4);He(he,()=>jt("chevron"),!0);var Ne=i(Be,2),We=r(Ne);He(We,()=>jt("refresh"),!0);var Ee=i(We,4);He(Ee,()=>jt("chevron"),!0);var W=i(Ne,2),J=r(W);He(J,()=>jt("file"),!0);var le=i(J,4);He(le,()=>jt("chevron"),!0);var oe=i(W,2),$e=r(oe);He($e,()=>jt("swap"),!0);var Le=i($e,4);He(Le,()=>jt("chevron"),!0),k("click",Be,()=>F("cookbook")),k("click",Ne,$),k("click",W,()=>F("server")),k("click",oe,()=>F("connect")),f(T,Q)};q(z,T=>{t(u).length?T(x,-1):T(R)})}var P=i(A,2),N=r(P),j=r(N),H=i(r(j),2),fe=r(H),me=i(j,2);{var w=T=>{var Q=Zr();Ye(Q,21,()=>t(u),lt,(Be,ne)=>{const he=G(()=>v.includes(t(ne).state)),Ne=G(()=>t(ne).state==="downloading"),We=G(()=>t(ne).state==="loading"||t(ne).state==="starting"||t(Ne)?"load":t(he)?"on":""),Ee=G(()=>t(Ne)?`↓ ${t(ne).download_progress!=null?Math.round(t(ne).download_progress)+"%":"..."}`:t(ne).state==="loading"||t(ne).state==="starting"?"lädt…":t(he)?"geladen ✓":"bereit");var W=ld(),J=r(W),le=i(J,2),oe=r(le),$e=r(oe),Le=r($e),Te=i($e,2);{var se=Me=>{var qe=nd();f(Me,qe)},ce=G(()=>{var Me,qe;return(qe=(Me=t(ne).meta)==null?void 0:Me.caps)==null?void 0:qe.includes("Bild")}),wt=Me=>{var qe=ad();f(Me,qe)},St=G(()=>{var Me,qe;return(qe=(Me=t(ne).meta)==null?void 0:Me.caps)==null?void 0:qe.includes("Code")}),Bt=Me=>{var qe=id();f(Me,qe)};q(Te,Me=>{t(ce)?Me(se):t(St)?Me(wt,1):Me(Bt,-1)})}var hn=i(Te,2);{var da=Me=>{var qe=rd();f(Me,qe)};q(hn,Me=>{t(ne).ttl>=99999&&Me(da)})}var E=i(oe,2),S=r(E),te=i(le,2),Y=r(te),Ae=r(Y),mt=i(Y,2);{var yt=Me=>{var qe=sd(),Ze=r(qe);D(()=>{$t(qe,`padding:3px 9px;font-size:12px;opacity:${t(y)===t(ne).name?".5":"1"}`),qe.disabled=t(y)===t(ne).name,g(Ze,t(y)===t(ne).name?"…":"Laden")}),k("click",qe,()=>O(t(ne).name)),f(Me,qe)};q(mt,Me=>{!t(he)&&!t(Ne)&&t(o)&&Me(yt)})}D((Me,qe)=>{var Ze;At(J,1,`li-dot ${t(We)??""}`),$t($e,t(he)?"color:var(--accent)":""),g(Le,t(ne).name),g(S,`${Me??""}
|
||
${(Ze=t(ne).meta)!=null&&Ze.quant?" · "+t(ne).meta.quant:""}
|
||
${qe??""}`),$t(Y,`white-space:nowrap;color:${t(he)?"var(--on)":"var(--mut)"}`),g(Ae,t(Ee))},[()=>{var Me;return(Me=t(ne).meta)!=null&&Me.ctx?Math.round(t(ne).meta.ctx/1024)+"k ctx":""},()=>{var Me;return(Me=t(ne).meta)!=null&&Me.size_bytes?" · "+(t(ne).meta.size_bytes/1073741824).toFixed(1)+" GB":""}]),f(Be,W)}),f(T,Q)},K=T=>{var Q=od(),Be=i(r(Q),4);k("click",Be,()=>F("cookbook")),f(T,Q)};q(me,T=>{t(u).length?T(w):T(K,-1)})}var ee=i(N,2),we=r(ee),Se=i(r(we),2),ft=i(we,2);{var st=T=>{var Q=Zr();Ye(Q,21,()=>t(m),lt,(Be,ne)=>{var he=dd(),Ne=r(he),We=r(Ne),Ee=r(We),W=i(We,2),J=r(W);D(()=>{Aa(he,"href",t(ne).link),g(Ee,t(ne).title),g(J,`${t(ne).source??""}${t(ne).relevant?" · für dich":""}`)}),f(Be,he)}),f(T,Q)},Ue=T=>{var Q=cd();f(T,Q)};q(ft,T=>{t(m).length?T(st):T(Ue,-1)})}D(T=>{g(ze,`${t(p)??""} `),g(I,t(_)),At(be,1,`kpi ${t(o)?"green":"red"}`),g(ue,t(o)?"Online":"Offline"),g(Qe,T),At(it,1,`kpi ${t(d)?"blue":"muted"}`),g(zt,t(d)?t(d).name:"Keins"),g(fe,t(u).length?t(u).length+" konfiguriert":"")},[()=>{var T,Q;return((Q=(T=t(a))==null?void 0:T.swap_url)==null?void 0:Q.replace(/^https?:\/\//,""))??"—"}]),k("click",Se,()=>F("news")),k("keydown",Se,T=>T.key==="Enter"&&F("news")),f(e,Ie),Dn()}qn(["click","keydown"]);var pd=b("<option> </option>"),fd=b('<div class="reply" style="margin-top:12px"> </div>'),hd=b('<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>'),gd=b('<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>'),md=b('<span class="tag" style="background:rgba(45,212,191,.14);color:var(--accent);border-color:rgba(45,212,191,.3)"> </span>'),bd=b('<div class="li-sub mono-sm"> </div>'),_d=b('<code style="cursor:pointer" title="Klicken zum Kopieren"> </code>'),yd=b('<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>'),xd=b('<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>'),kd=b('<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>'),wd=b('<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>'),Sd=b('<button style="border-radius:999px"> </button>'),Md=b('<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>'),Ed=b('<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 Ad(e,n){Pn(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=G(()=>{var A;return((A=xi.value)==null?void 0:A.models)||[]});function v(){document.dispatchEvent(new Event("mc:refresh"))}let d=L(""),u=L(""),p=L(""),_=L(!1);const C=G(()=>t(o).filter(A=>!A.incomplete));async function m(){var B;const A=t(d)||((B=t(C)[0])==null?void 0:B.name);if(!(!A||!t(u).trim())){c(_,!0),c(p,"(wecke Modell, kann beim Laden kurz dauern…)");try{const _e=await De("/api/chat",{method:"POST",body:JSON.stringify({model:A,message:t(u)})});c(p,_e.reply,!0)}catch(_e){c(p,"Fehler: "+_e.message)}c(_,!1),v()}}const y=300;let $=L(!1),O=L(null),M=L(8192),F=L(!1);function ye(A){var B;c(O,t(o).find(_e=>_e.name===A),!0),t(O)&&(c(M,((B=t(O).meta)==null?void 0:B.ctx)||8192,!0),c(F,(t(O).ttl??y)>=99999),c($,!0))}async function xe(){const A=t(F)?99999:y;try{await De("/api/update_model",{method:"POST",body:JSON.stringify({alias:t(O).name,ctx:t(M),ttl:A})}),ie("Gespeichert — aktiv beim nächsten Modell-Start."),c($,!1),v()}catch(B){ie(B.message,!0)}}let ke=L(!1),Ie=L(""),Z=L(""),X=L("");function ve(A){const B=t(o).find(_e=>_e.name===A);c(Ie,A,!0),c(X,(B==null?void 0:B.role)||"",!0),c(Z,""),c(ke,!0)}async function ze(A){try{await De("/api/set_role",{method:"POST",body:JSON.stringify({alias:t(Ie),role:A})}),ie(A?`Rolle gesetzt: ${A}`:"Rolle entfernt."),c(ke,!1),v()}catch(B){ie(B.message,!0)}}async function Re(A){if(await xn({title:`„${A}" entladen?`,body:"Das Modell wird aus dem Grafikspeicher geworfen und lädt beim nächsten Aufruf automatisch neu.",confirmLabel:"Entladen"}))try{await De("/api/unload?model="+encodeURIComponent(A),{method:"POST"}),ie("Entladen: "+A),setTimeout(v,600)}catch(B){ie(B.message,!0)}}async function je(A){if(await xn({title:`„${A}" 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 B=await De("/api/delete_model",{method:"POST",body:JSON.stringify({alias:A})});ie(B.note||"Gelöscht: "+A),setTimeout(v,600)}catch(B){ie(B.message,!0)}}function ot(A){return A!=null&&A.length?A.map(B=>B==="Code"?'<span class="tag code">Code</span>':B==="Bild"?'<span class="tag img">Bild</span>':'<span class="tag text">Text</span>').join(" "):"–"}function I(A){if(!A)return"–";const B=A.quant||"?",_e=A.ctx?Math.round(A.ctx/1024)+"K":"?",Ce=A.size_bytes?(A.size_bytes/1024**3).toFixed(1)+" GB":"?";return`<span class="mono-sm">${B} · ${_e} · ${Ce}</span>`}function re(A){var B;(B=navigator.clipboard)==null||B.writeText(A),ie("Kopiert: "+A)}var be=Ed(),Je=i(Xe(be),2),de=i(r(Je),6);Ye(de,21,()=>t(C),lt,(A,B)=>{var _e=pd(),Ce=r(_e),V={};D(()=>{g(Ce,t(B).name),V!==(V=t(B).name)&&(_e.value=(_e.__value=t(B).name)??"")}),f(A,_e)});var Fe=i(de,4),ue=i(Fe,2),at=r(ue),Qe=i(ue,2);{var it=A=>{var B=fd(),_e=r(B);D(()=>g(_e,t(p))),f(A,B)};q(Qe,A=>{t(p)&&A(it)})}var dt=i(Je,2),rt=r(dt),Tt=i(r(rt)),zt=r(Tt),Wt=i(rt,4);{var qt=A=>{var B=hd();f(A,B)},Gt=A=>{var B=xd(),_e=i(r(B));Ye(_e,21,()=>t(o),lt,(Ce,V)=>{var pe=Ha(),z=Xe(pe);{var R=P=>{var N=gd(),j=r(N),H=r(j),fe=i(j,5),me=r(fe),w=i(me,2);D(()=>g(H,t(V).name)),k("click",me,()=>{var K;ie("Lade im Cookbook ein Modell und setze den Alias auf: "+t(V).name),(K=document.querySelector(".nav-item[data-view='cookbook']"))==null||K.dispatchEvent(new MouseEvent("click"))}),k("click",w,()=>je(t(V).name)),f(P,N)},x=P=>{var N=yd(),j=r(N),H=r(j),fe=r(H),me=i(fe);{var w=Ee=>{var W=md(),J=r(W);D(()=>g(J,t(V).role)),f(Ee,W)};q(me,Ee=>{t(V).role&&Ee(w)})}var K=i(H,2);{var ee=Ee=>{var W=bd(),J=r(W);D(()=>g(J,t(V).meta.filename)),f(Ee,W)};q(K,Ee=>{var W;(W=t(V).meta)!=null&&W.filename&&Ee(ee)})}var we=i(K,2),Se=i(r(we),2);Ye(Se,17,()=>{var Ee;return(Ee=t(V).api_ids)!=null&&Ee.length?t(V).api_ids:[t(V).name]},lt,(Ee,W)=>{var J=_d(),le=r(J);D(()=>g(le,t(W))),k("click",J,()=>re(t(W))),f(Ee,J)});var ft=i(j);He(ft,()=>{var Ee;return ot((Ee=t(V).meta)==null?void 0:Ee.caps)},!0);var st=i(ft);He(st,()=>I(t(V).meta),!0);var Ue=i(st);He(Ue,()=>jo(t(V).state,t(V).download_progress),!0);var T=i(Ue),Q=r(T),Be=i(T),ne=r(Be),he=i(ne,2),Ne=i(he,2),We=i(Ne,2);D(()=>{g(fe,`${t(V).name??""} `),g(Q,t(V).port??"auto")}),k("click",ne,()=>ve(t(V).name)),k("click",he,()=>ye(t(V).name)),k("click",Ne,()=>Re(t(V).name)),k("click",We,()=>je(t(V).name)),f(P,N)};q(z,P=>{t(V).incomplete?P(R):P(x,-1)})}f(Ce,pe)}),f(A,B)};q(Wt,A=>{t(o).length?A(Gt,-1):A(qt)})}var Lt=i(dt,2);{var Ot=A=>{var B=wd(),_e=r(B),Ce=r(_e),V=i(Ce,4),pe=r(V),z=i(V,2),R=i(r(z));He(R,()=>br(a));var x=i(z,2),P=i(x,2);{var N=ee=>{var we=kd(),Se=r(we),ft=i(r(Se),2),st=r(ft),Ue=i(st,2),T=i(Se,2);D((Q,Be)=>{g(st,`Optimal ~${Q??""}k → ~${t(O).meta.peak_ram_optimal_gb??""} GB Spitzenbedarf.`),g(Ue,` Aktuell ~${Be??""}k → ~${t(O).meta.peak_ram_gb??""} GB.`)},[()=>Math.round(t(O).meta.optimal_ctx/1024),()=>Math.round((t(O).meta.ctx||0)/1024)]),k("click",T,()=>c(M,t(O).meta.optimal_ctx,!0)),f(ee,we)};q(P,ee=>{var we;(we=t(O).meta)!=null&&we.optimal_ctx&&ee(N)})}var j=i(P,4),H=i(r(j),2),fe=r(H),me=i(fe,2),w=r(me),K=i(j,2);D(()=>{g(pe,t(O).name),$t(me,`color:${t(F)?"var(--accent)":"var(--mut)"}`),g(w,t(F)?"An (TTL = ∞)":"Aus (TTL = 5 min)")}),k("click",B,ee=>{ee.target.classList.contains("modal-overlay")&&c($,!1)}),k("click",Ce,()=>c($,!1)),an(x,()=>t(M),ee=>c(M,ee)),Fo(fe,()=>t(F),ee=>c(F,ee)),k("click",K,xe),f(A,B)};q(Lt,A=>{t($)&&t(O)&&A(Ot)})}var U=i(Lt,2);{var ae=A=>{var B=Md(),_e=r(B),Ce=r(_e),V=i(Ce,2),pe=i(r(V));He(pe,()=>br(s));var z=i(V,2),R=r(z),x=i(z,4);Ye(x,21,()=>l,lt,(fe,me)=>{var w=Sd(),K=r(w);D(()=>{At(w,1,t(X)===t(me).id?"primary":"ghost"),Aa(w,"title",t(me).desc),g(K,t(me).label)}),k("click",w,()=>ze(t(me).id)),f(fe,w)});var P=i(x,4),N=i(P,2),j=r(N),H=i(j,2);D(()=>g(R,t(Ie))),k("click",B,fe=>{fe.target.classList.contains("modal-overlay")&&c(ke,!1)}),k("click",Ce,()=>c(ke,!1)),an(P,()=>t(Z),fe=>c(Z,fe)),k("click",j,()=>ze("")),k("click",H,()=>ze(t(Z).trim().toLowerCase())),f(A,B)};q(U,A=>{t(ke)&&A(ae)})}D(()=>{ue.disabled=t(_),g(at,t(_)?"…":"Senden"),g(zt,t(o).length?t(o).length+" konfiguriert":"")}),Hn(de,()=>t(d),A=>c(d,A)),an(Fe,()=>t(u),A=>c(u,A)),k("click",ue,m),f(e,be),Dn()}qn(["click"]);var Cd=b('<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),Td=b('<button class="ghost" style="margin-left:auto;padding:4px 11px;font-size:12px">Verlauf leeren</button>'),zd=b('<div class="empty-c"><div class="e-t">Gerade nichts los.</div> <div class="e-s">Alles ruhig — keine laufenden Aufgaben.</div></div>'),Pd=b('<span class="mono-sm" style="margin-left:auto"> </span>'),Dd=b('<button class="ghost">Abbrechen</button>'),$d=b('<button class="ghost" title="Aus Verlauf entfernen" style="margin-left:auto;margin-right:2px;padding:2px 9px;font-size:14px;line-height:1">×</button>'),Id=b('<div class="bar" style="margin-top:8px"><i></i></div>'),Ld=b('<div class="log"> </div>'),Od=b('<div class="job"><div class="job-h" role="button" tabindex="0"><span></span> <span class="mid"> </span> <!> <!> <!></div> <!> <!></div>'),Bd=b('<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 Rd(e,n){Pn(n,!0);const a=G(()=>fa.value),s=G(()=>fa.tracked),l=G(()=>Dr.value);let o=Jt({cpu:[],ram:[],gpu:[]});Ga(()=>{var be;if(!t(l))return;const I=t(l).gpu,re=I&&I.vram.total+I.gtt.total>0?(I.vram.used+I.gtt.used)/(I.vram.total+I.gtt.total)*100:0;o.cpu=[...o.cpu,((be=t(l).cpu)==null?void 0:be.percent)??0].slice(-60),o.ram=[...o.ram,t(l).ram.percent].slice(-60),o.gpu=[...o.gpu,re].slice(-60)});const v=G(()=>()=>{var re;const I=(re=t(l))==null?void 0:re.gpu;return I&&I.vram.total+I.gtt.total>0?(I.vram.used+I.gtt.used)/(I.vram.total+I.gtt.total)*100:0}),d=G(()=>t(a).filter(I=>I.state!=="running"&&I.state!=="queued").length),u=G(()=>t(a).filter(I=>I.state==="failed").length);function p(I){if(I.state!=="running")return null;if(typeof I.progress=="number")return Math.min(100,I.progress);const be=((I.log||[]).at(-1)||"").match(/(\d+(?:\.\d+)?)\s*%/);return be?Math.min(100,parseFloat(be[1])):null}function _(I){return I==null||I<0?"":I>=90?`noch ~${Math.round(I/60)} min`:`noch ~${Math.max(1,Math.round(I))} s`}function C(I){return I==="done"?'<span class="badge b-run">fertig</span>':I==="failed"?'<span class="badge b-err">fehler</span>':I==="canceled"?'<span class="badge">abgebrochen</span>':'<span class="badge b-load">läuft…</span>'}function m(I){return I==="done"?"on":I==="failed"||I==="canceled"?"":"load"}async function y(I){try{await De(`/api/jobs/${I}/cancel`,{method:"POST"}),ie("Abbruch angefordert…")}catch(re){ie(re.message,!0)}}async function $(I){try{await De(`/api/jobs/${I}`,{method:"DELETE"})}catch(re){ie(re.message,!0)}}async function O(){try{const I=await De("/api/jobs/clear",{method:"POST"});ie(`${I.removed} Einträge entfernt.`)}catch(I){ie(I.message,!0)}}function M(I,re){return I.map(be=>`<div style="width:4px;background:var(${re});opacity:.55;height:${Math.max(2,be)}%;border-radius:2px"></div>`).join("")}var F=Bd(),ye=i(Xe(F),2);{var xe=I=>{const re=G(()=>t(v)());var be=Cd(),Je=Xe(be),de=r(Je),Fe=i(r(de),2),ue=r(Fe),at=i(Fe,2),Qe=r(at),it=i(de,2),dt=i(r(it),2),rt=r(dt),Tt=i(dt,2),zt=r(Tt),Wt=i(it,2),qt=i(r(Wt),2),Gt=r(qt),Lt=i(qt,2),Ot=r(Lt),U=i(Je,2),ae=i(r(U),4),A=r(ae),B=i(r(A)),_e=r(B),Ce=i(A,2),V=i(r(Ce),2),pe=r(V),z=i(Ce,2),R=i(r(z)),x=r(R),P=i(z,2),N=i(r(P),2),j=r(N),H=i(ae,2),fe=r(H),me=i(r(fe));He(me,()=>M(o.cpu,"--accent"),!0);var w=i(fe,2),K=i(r(w));He(K,()=>M(o.ram,"--purple"),!0);var ee=i(w,2),we=i(r(ee));He(we,()=>M(o.gpu,"--on"),!0),D((Se,ft,st,Ue,T,Q,Be,ne,he,Ne,We,Ee,W)=>{g(ue,Se),g(Qe,ft),g(rt,st),g(zt,`${Ue??""} / ${T??""}`),g(Gt,Q),g(Ot,Be),g(_e,`${ne??""} / ${he??""}`),g(pe,Ne),g(x,`${We??""} % belegt`),g(j,`${Ee??""} / ${W??""}`)},[()=>{var Se;return Math.round(((Se=t(l).cpu)==null?void 0:Se.percent)??0)},()=>{var Se;return((Se=t(l).cpu)==null?void 0:Se.temp)!=null?`${Math.round(t(l).cpu.temp)}° CPU-Temp`:"Auslastung"},()=>Math.round(t(l).ram.percent),()=>ca(t(l).ram.used),()=>ca(t(l).ram.total),()=>Math.round(t(re)),()=>t(l).gpu_temp!=null?`${Math.round(t(l).gpu_temp)}° GPU-Temp`:"VRAM + GTT",()=>ca(t(l).ram.used),()=>ca(t(l).ram.total),()=>t(l).gpu?`${ca(t(l).gpu.vram.used+t(l).gpu.gtt.used)} / ${ca(t(l).gpu.vram.total+t(l).gpu.gtt.total)}`:"–",()=>{var Se;return Math.round(((Se=t(l).disk)==null?void 0:Se.percent)??0)},()=>t(l).gpu_temp!=null?Math.round(t(l).gpu_temp)+"°":"–",()=>{var Se;return((Se=t(l).cpu)==null?void 0:Se.temp)!=null?Math.round(t(l).cpu.temp)+"°":"–"}]),f(I,be)};q(ye,I=>{t(l)&&I(xe)})}var ke=i(ye,2),Ie=r(ke),Z=i(r(Ie),2),X=r(Z),ve=i(Z,2);{var ze=I=>{var re=Td();k("click",re,O),f(I,re)};q(ve,I=>{t(d)&&I(ze)})}var Re=i(Ie,4);{var je=I=>{var re=zd();f(I,re)},ot=I=>{var re=Ha(),be=Xe(re);Ye(be,17,()=>t(a),lt,(Je,de)=>{const Fe=G(()=>p(t(de))),ue=G(()=>t(de).state==="running"?_(t(de).eta_s):""),at=G(()=>t(de).state==="running"&&t(de).rate_bps?ca(t(de).rate_bps)+"/s":""),Qe=G(()=>[t(ue),t(at)].filter(Boolean).join(" · ")),it=G(()=>t(s).includes(t(de).id));var dt=Od(),rt=r(dt),Tt=r(rt),zt=i(Tt,2),Wt=r(zt),qt=i(zt,2);{var Gt=V=>{var pe=Pd(),z=r(pe);D(R=>g(z,`${R??""} %${t(Qe)?` · ${t(Qe)}`:""}`),[()=>Math.round(t(Fe))]),f(V,pe)};q(qt,V=>{t(Fe)!=null&&V(Gt)})}var Lt=i(qt,2);{var Ot=V=>{var pe=Dd();D(()=>$t(pe,`${t(Fe)==null?"margin-left:auto;":""}margin-right:2px;padding:2px 9px;font-size:12px`)),k("click",pe,z=>{z.stopPropagation(),y(t(de).id)}),f(V,pe)},U=V=>{var pe=$d();k("click",pe,z=>{z.stopPropagation(),$(t(de).id)}),f(V,pe)};q(Lt,V=>{t(de).state==="running"?V(Ot):V(U,-1)})}var ae=i(Lt,2);He(ae,()=>C(t(de).state));var A=i(rt,2);{var B=V=>{var pe=Id(),z=r(pe);D(()=>$t(z,`width:${t(Fe)??""}%`)),f(V,pe)};q(A,V=>{t(Fe)!=null&&t(de).state==="running"&&V(B)})}var _e=i(A,2);{var Ce=V=>{var pe=Ld(),z=r(pe);D(R=>g(z,R),[()=>(t(de).log||[]).join(`
|
||
`)]),f(V,pe)};q(_e,V=>{t(it)&&V(Ce)})}D(V=>{At(Tt,1,`li-dot ${V??""}`),g(Wt,t(de).label)},[()=>m(t(de).state)]),k("click",rt,()=>fa.toggle(t(de).id)),k("keydown",rt,V=>V.key==="Enter"&&fa.toggle(t(de).id)),f(Je,dt)}),f(I,re)};q(Re,I=>{t(a).length?I(ot,-1):I(je)})}D(()=>g(X,t(a).length?t(u)?t(u)+" Fehler":t(a).length+" gesamt":"")),f(e,F),Dn()}qn(["click","keydown"]);var Fd=b('<span class="mono-sm"> </span>'),Kd=b('<button class="ghost" style="margin-left:auto;padding:3px 12px">Abbrechen</button>'),Nd=b('<span class="badge b-run">✓ fertig</span>'),qd=b('<span class="badge b-err">✗ fehlgeschlagen</span>'),Vd=b('<span class="badge">abgebrochen</span>'),Wd=b('<span class="badge b-load">läuft…</span>'),Gd=b('<div class="bar" style="margin-bottom:10px"><i></i></div>'),jd=b('<div class="card"><div class="card-h"><h3>Aktueller Vorgang</h3> <!> <span style="margin-left:10px"><!></span></div> <div class="card-sub"> </div> <!> <div class="log" style="max-height:280px"> </div></div>'),Ud=b('<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 Hd(e,n){Pn(n,!0);const a=G(()=>xi.value),s=G(()=>fa.value);let l=null,o=L(`Verbinde…
|
||
`),v=L("llama-swap"),d,u=L(null),p=L("");const _=new Set,C=G(()=>t(u)?t(s).find(w=>w.id===t(u)):null);Ga(()=>{if(!t(C))return;const w=t(C),K=w.state==="done",ee=w.state==="failed",we=w.state==="canceled";(K||ee||we)&&!_.has(w.id)&&(_.add(w.id),ie(K?`✓ ${t(p)} abgeschlossen.`:we?`${t(p)} abgebrochen.`:`✗ ${t(p)} fehlgeschlagen.`,ee),K&&setTimeout(()=>document.dispatchEvent(new Event("mc:refresh")),800))});function m(w,K){c(u,w,!0),c(p,K,!0),fa.track(w)}yi(()=>{y()}),No(()=>{l==null||l.close()});function y(){l==null||l.close();const w=t(v);c(o,`Verbinde mit ${w}…
|
||
`);const K=location.protocol==="https:"?"wss:":"ws:";l=new WebSocket(`${K}//${location.host}/api/logs/${w}?token=${encodeURIComponent(nl())}`),l.onmessage=ee=>{c(o,t(o)+ee.data),d&&(d.scrollTop=d.scrollHeight)},l.onclose=()=>{c(o,t(o)+`
|
||
— Verbindung getrennt —`)},l.onerror=()=>l==null?void 0:l.close()}async function $(w,K,ee){if(await xn({title:K,body:ee,confirmLabel:"Neustarten"}))try{await De(`/api/service/${w}/restart`,{method:"POST"}),ie("Neustart ausgelöst: "+w),setTimeout(()=>document.dispatchEvent(new Event("mc:refresh")),2e3)}catch(we){ie(we.message,!0)}}async function O(){if(await xn({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 w=await De("/api/self-update",{method:"POST"});ie("Update läuft — Dashboard startet gleich neu."),m(w.job_id,"Mission Control Update")}catch(w){ie(w.message,!0)}}async function M(){if(!await xn({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 w=await er({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(w!==null)try{const K=await De("/api/update",{method:"POST",body:JSON.stringify({password:w})});ie("LLM-Engine-Update läuft."),m(K.job_id,"LLM-Engine-Update")}catch(K){ie(K.message,!0)}}async function F(){if(await xn({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 De("/api/unload",{method:"POST"}),ie("Grafikspeicher geleert."),setTimeout(()=>document.dispatchEvent(new Event("mc:refresh")),600)}catch(w){ie(w.message,!0)}}async function ye(){if(!await xn({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 w=await er({title:"sudo-Passwort",body:"Für die System-Updates wird einmalig dein sudo-Passwort gebraucht.",placeholder:"sudo-Passwort",password:!0,confirmLabel:"Installieren"});if(w)try{const K=await De("/api/os-update",{method:"POST",body:JSON.stringify({password:w})});ie("OS-Update gestartet."),m(K.job_id,"OS-Update")}catch(K){ie(K.message,!0)}}async function xe(){if(!await xn({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 w=await er({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(w)try{await De("/api/reboot",{method:"POST",body:JSON.stringify({password:w})}),ie("Reboot ausgelöst — bis gleich.")}catch(K){ie(K.message,!0)}}async function ke(){c(Ie,"prüfe…");try{const w=await De("/api/integration/test");c(Ie,w.ok?`✓ Engine antwortet — ${w.models.length} Modell(e): ${w.models.join(", ")}`:`✗ keine Verbindung: ${w.error}`,!0),c(Z,w.ok,!0)}catch(w){c(Ie,"✗ "+w.message),c(Z,!1)}}let Ie=L(""),Z=L(!1);const X=G(()=>{var w;return((w=t(a))==null?void 0:w.models)||[]}),ve=["running","ready","loading","starting"],ze=G(()=>t(X).find(w=>ve.includes(w.state)));function Re(w){if(!w||w.state!=="running")return null;if(typeof w.progress=="number")return Math.min(100,w.progress);const ee=((w.log||[]).at(-1)||"").match(/(\d+(?:\.\d+)?)\s*%/);return ee?Math.min(100,parseFloat(ee[1])):null}var je=Ud(),ot=i(Xe(je),2),I=r(ot),re=i(r(I),2),be=r(re),Je=i(I,4),de=r(Je),Fe=i(r(de)),ue=r(Fe),at=i(de,2),Qe=i(r(at),2),it=r(Qe),dt=i(at,2),rt=i(r(dt),2),Tt=r(rt),zt=i(Je,2),Wt=r(zt),qt=i(Wt,2);{var Gt=w=>{var K=Fd(),ee=r(K);D(()=>{$t(K,`color:${t(Z)?"#7ee29a":"#ff9b95"}`),g(ee,t(Ie))}),f(w,K)};q(qt,w=>{t(Ie)&&w(Gt)})}var Lt=i(ot,2),Ot=i(r(Lt),4),U=i(Ot,2),ae=i(U,2),A=i(ae,2),B=i(A,2),_e=i(Lt,2),Ce=i(r(_e),4),V=i(Ce,2),pe=i(_e,2);{var z=w=>{const K=G(()=>t(C)),ee=G(()=>t(K).state==="done"),we=G(()=>t(K).state==="failed"),Se=G(()=>t(K).state==="canceled"),ft=G(()=>t(ee)||t(we)||t(Se)),st=G(()=>Re(t(K)));var Ue=jd(),T=r(Ue),Q=i(r(T),2);{var Be=se=>{var ce=Kd();k("click",ce,async()=>{await xn({title:t(p)+" abbrechen?",body:"Der laufende Vorgang wird gestoppt.",confirmLabel:"Abbrechen",danger:!0})&&De(`/api/jobs/${t(K).id}/cancel`,{method:"POST"})}),f(se,ce)};q(Q,se=>{t(ft)||se(Be)})}var ne=i(Q,2),he=r(ne);{var Ne=se=>{var ce=Nd();f(se,ce)},We=se=>{var ce=qd();f(se,ce)},Ee=se=>{var ce=Vd();f(se,ce)},W=se=>{var ce=Wd();f(se,ce)};q(he,se=>{t(ee)?se(Ne):t(we)?se(We,1):t(Se)?se(Ee,2):se(W,-1)})}var J=i(T,2),le=r(J),oe=i(J,2);{var $e=se=>{var ce=Gd(),wt=r(ce);D(()=>$t(wt,`width:${t(st)??""}%`)),f(se,ce)};q(oe,se=>{t(st)!=null&&!t(ft)&&se($e)})}var Le=i(oe,2),Te=r(Le);D(se=>{g(le,`${t(p)??""}${t(ft)?t(ee)?" — erfolgreich.":t(Se)?" — abgebrochen.":" — fehlgeschlagen.":" läuft…"}`),g(Te,se)},[()=>(t(K).log||[]).join(`
|
||
`)]),f(w,Ue)};q(pe,w=>{t(C)&&w(z)})}var R=i(pe,2),x=r(R),P=i(r(x),2),N=r(P);N.value=N.__value="llama-swap";var j=i(N);j.value=j.__value="mission-control";var H=i(j);H.value=H.__value="system";var fe=i(x,4),me=r(fe);Ko(fe,w=>d=w,()=>d),D(w=>{var K,ee,we;$t(re,`margin-left:auto;${(K=t(a))!=null&&K.swap_ok?"background:rgba(63,185,80,.12);border-color:rgba(63,185,80,.25);color:#7ee29a":"background:rgba(248,81,73,.12);border-color:rgba(248,81,73,.3);color:#ff9b95"}`),g(be,(ee=t(a))!=null&&ee.swap_ok?"● erreichbar":"● offline"),g(ue,(((we=t(a))==null?void 0:we.swap_url)||"—")+"/v1"),g(it,t(ze)?t(ze).name+` (${t(ze).state})`:"nichts geladen — lädt bei der nächsten Anfrage"),g(Tt,w),g(me,t(o))},[()=>t(X).filter(w=>!w.incomplete).length||"keine"]),k("click",Wt,ke),k("click",Ot,()=>$("llama-swap","LLM-Engine neustarten?","Die Engine startet neu. Geladene Modelle werden kurz entladen (~5 Sekunden), laden danach automatisch wieder.")),k("click",U,()=>$("mission-control","Dashboard neustarten?","Diese Oberfläche trennt sich kurz und verbindet automatisch wieder.")),k("click",ae,O),k("click",A,M),k("click",B,F),k("click",Ce,ye),k("click",V,xe),k("change",P,y),Hn(P,()=>t(v),w=>c(v,w)),f(e,je),Dn()}qn(["click","change"]);var Jd=b('<div class="empty" style="text-align:center;padding:30px">Lade Setups…</div>'),Qd=b('<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),tr=b('<div class="cb-best-tag">★ Beste Wahl für dein System</div>'),Zd=b('<div class="cb-best-tag" style="background:var(--act);color:#fff">Dein Setup</div>'),Yd=b('<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>'),Xd=b('<div id="cb-recipes" class="grid grid-3" style="gap:10px;margin-top:6px"></div>'),ec=b('<span style="color:var(--warn)">· ⚠ Cache veraltet</span>'),tc=b("<!> <!>",1),nc=b('<div class="empty" style="text-align:center;padding:30px">Frage Quellen ab…</div>'),ac=b('<div class="li-sub" style="color:var(--warn);margin-top:3px"> </div>'),ic=b('<span class="fit-badge ok">✓ installiert</span>'),rc=b('<button class="primary" style="padding:6px 12px;font-size:12.5px">Installieren</button>'),sc=b('<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>'),lc=b('<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>'),oc=b('<button style="padding:4px 10px;border-radius:999px;font-size:12px"> </button>'),dc=b('<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>'),cc=b('<div class="grid grid-3" id="cb-grid"></div>'),vc=b('<div class="li-sub"> </div>'),uc=b('<div class="li-sub mono-sm"> </div>'),pc=b("<span> </span>"),fc=b('<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>'),hc=b('<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>'),gc=b('Alternative: <a href="#" style="color:var(--accent)"> </a> — passt auf dein System.',1),mc=b('<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>'),bc=b('<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>'),_c=b('<div class="hint">Lade Dateien von HuggingFace…</div>'),Yr=b("<option> </option>"),yc=b('<div class="hint" style="margin:-6px 0 14px">Empfohlener Kontext für deine Hardware: <b> </b> — <a href="#">übernehmen</a></div>'),xc=b('<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>'),kc=b('<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>'),wc=b('<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>'),Sc=b('<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),Mc=b('<div class="hint">Keine GGUF-Dateien im Repo gefunden.</div>'),Ec=b('<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>'),Ac=b('<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>'),Cc=b('<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>'),Tc=b('<div class="pagehead"><div><h1>Cookbook</h1><div class="sub">Modelle finden, installieren und eigene Setups zusammenstellen.</div></div></div> <div class="card"><div class="card-h"><h3>1 · Anwendungsfall wählen & installieren</h3> <button class="ghost" style="margin-left:auto">+ Eigenes Setup</button></div> <div class="card-sub">Hier starten: Fertige Modell-Bundles für deinen Anwendungsfall — ein Klick installiert alles. Die Hardware-Ampel zeigt vorab, ob das Setup auf deinen PC passt.</div> <!></div> <div class="card"><div class="card-h"><h3>Aktuell die besten Modelle für dein System</h3> <span class="meta" style="margin-left:auto"><!></span> <button class="ghost" style="margin-left:8px"> </button></div> <div class="card-sub">Top-Modelle je Kategorie von HuggingFace — Hardware-Fit wird live für dein System berechnet.</div> <!></div> <div class="card"><div class="card-h"><h3>Profi-Suche (HuggingFace)</h3></div> <div class="card-sub">Direkt HuggingFace durchsuchen — oder eine Modell-URL einfügen für den direkten Sprung.</div> <div class="flex gap-2" style="align-items:stretch;margin-bottom:10px"><input placeholder="Suchbegriff oder HuggingFace-URL…" style="flex:1;margin:0"/> <select style="width:auto;margin:0"><option>Downloads</option><option>Trending</option><option>Neu</option></select> <button class="primary"> </button></div> <div class="flex gap-2" style="flex-wrap:wrap;margin-bottom:12px"></div> <!></div> <!> <!> <!>',1);function zc(e,n){Pn(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={vision:"Bilder",coder:"Coden",reasoning:"Logik",agent:"Agenten & Tools",scout:"Allrounder",reviewer:"Review",manager:"Manager"},v=[{label:"Bilder",kw:["-vl-","-vl","vision","llava","multimodal","-mm-","pixtral"]},{label:"Coden",kw:["coder","-code-","code-","codestral","starcoder"]},{label:"Logik",kw:["-r1","deepseek-r1","reasoning","qwq","magistral","-think","thinking","-o1"]},{label:"Agenten & Tools",kw:["hermes","-tool","command-r","watt","-fc-","function"]}];function d(E){const S=(E||"").toLowerCase();for(const te of v)if(te.kw.some(Y=>S.includes(Y)))return te.label;return"Allrounder"}function u(E=""){const S=E.toLowerCase();return/\d+x\d+(\.\d+)?b/.test(S)||new RegExp("(?<![a-z])a\\d+(\\.\\d+)?b\\b").test(S)||S.includes("mixtral")||/\bmoe\b/.test(S)}function p(E=""){const S=E.toLowerCase().match(new RegExp("(?<![a-z])a(\\d+(?:\\.\\d+)?)b\\b"));return S?S[1]:null}function _(E){return E==="perfect"?"ok":E==="marginal"?"warn":"bad"}function C(E){return E==="perfect"?"Passt":E==="marginal"?"Knapp":"Zu groß"}function m(E){return`~${(E.req_gb??0).toFixed(1)} GB · ~${Math.round(E.tps??0)} Tok/s`}let y=L(Jt([])),$=L(null),O=L(!0),M=L(null),F=L(!1),ye=L(!1),xe=L(""),ke=L(Jt([])),Ie=L(!1),Z=L(""),X=L("downloads"),ve=L(Jt([])),ze=L(-1),Re=L(null),je=L(!1),ot=L(""),I=L(""),re=L(null),be=L(""),Je=L(""),de=L(8192),Fe=L(!1),ue=L(null),at=L(!1),Qe=L(""),it=L(""),dt=L(Jt([{repo:"",role:"",quant:"Q4_K_M"}])),rt=L(null);function Tt(E){var S;(S=document.querySelector(`.nav-item[data-view="${E}"]`))==null||S.dispatchEvent(new MouseEvent("click"))}yi(()=>{zt(),Wt()});async function zt(){c(O,!0);try{const E=await De("/api/cookbook/recipes");c(y,E.recipes||[],!0),c($,E.recommended_id||null,!0)}catch(E){ie(E.message,!0)}c(O,!1)}async function Wt(E=!1){c(F,!0);try{const S=await De("/api/cookbook/discover"+(E?"?force=true":""));c(M,S,!0),c(ye,S.stale,!0)}catch(S){ie("Empfehlungen nicht ladbar: "+S.message,!0)}c(F,!1)}function qt(E){E=E.trim();const S=E.match(/huggingface\.co\/([^\s/]+\/[^\s/?#]+)/i);return S?S[1]:/^[\w.-]+\/[\w.-]+$/.test(E)?E:null}async function Gt(){const E=t(xe).trim(),S=qt(E);let te=E;if(t(Z)&&!S&&(te=te?te+" "+t(Z):t(Z)),!te&&!S){c(ke,[],!0);return}c(Ie,!0),c(ve,[],!0),c(ze,-1);try{if(S)c(ke,[{id:S,author:S.split("/")[0],downloads:0}],!0);else{const Y=`https://huggingface.co/api/models?search=${encodeURIComponent(te)}&filter=gguf&sort=${encodeURIComponent(t(X))}&direction=-1&limit=40`,Ae=await fetch(Y);c(ke,await Ae.json(),!0)}t(ke).forEach((Y,Ae)=>Lt(Ae,Y.id))}catch(Y){ie(Y.message,!0),c(ke,[],!0)}c(Ie,!1)}async function Lt(E,S){var te;try{const Y=await De("/api/cookbook/analyze",{method:"POST",body:JSON.stringify({repo_id:S,ctx:8192})});if(!((te=Y.files)!=null&&te.length)){t(ve)[E]=null,Ot();return}const Ae=Y.files.find(mt=>{var yt;return(yt=mt.quant)==null?void 0:yt.includes("Q4_K_M")})||Y.files[0];t(ve)[E]=Ae.fit.level,Ot()}catch{t(ve)[E]=null,Ot()}}function Ot(){let E=-1,S=99;t(ve).forEach((te,Y)=>{if(te==null)return;const Ae=l[te]??99;Ae<S&&(S=Ae,E=Y)}),c(ze,E>=0&&S<=1?E:-1,!0)}function U(E){c(Re,t(y).find(S=>S.id===E),!0)}async function ae(E){const S=document.getElementById("cb-r-install-btn");S&&(S.disabled=!0,S.textContent="Starte…");try{const te=await De("/api/cookbook/install-recipe",{method:"POST",body:JSON.stringify({recipe_id:E,hf_token:ci()})});ie(`${te.count} Download${te.count!==1?"s":""} läuft — Modelle erscheinen danach automatisch im Modelle-Tab.`),c(Re,null),Tt("activity")}catch(te){ie(te.message,!0),S&&(S.disabled=!1,S.textContent="Installieren")}}async function A(E,S){var te,Y;c(je,!0),c(ot,S,!0),c(I,E,!0),c(Je,""),c(de,8192),c(re,null),c(ue,null),c(be,""),c(Fe,!0);try{if(c(re,await De("/api/cookbook/analyze",{method:"POST",body:JSON.stringify({repo_id:E,ctx:8192})}),!0),(Y=(te=t(re))==null?void 0:te.files)!=null&&Y.length){const Ae=t(re).files.find(mt=>{var yt;return(yt=mt.quant)==null?void 0:yt.includes("Q4_K_M")})||t(re).files[0];c(be,Ae.filename,!0),Ae.optimal_ctx&&t(de)===8192&&c(de,Ae.optimal_ctx,!0),B()}}catch(Ae){ie(Ae.message,!0)}c(Fe,!1)}function B(){var E,S,te;!((S=(E=t(re))==null?void 0:E.files)!=null&&S.length)||!t(be)||(c(ue,t(re).files.find(Y=>Y.filename===t(be))||null,!0),(te=t(ue))!=null&&te.optimal_ctx&&t(de)===8192&&c(de,t(ue).optimal_ctx,!0))}async function _e(){var E,S;if(!t(I)||!t(be))return ie("Bitte eine GGUF-Datei wählen.",!0);c(Fe,!0);try{const te=((E=t(re))==null?void 0:E.params_b)??7,Y=((S=t(ue))==null?void 0:S.quant)??"Q4_K_M";await De("/api/cookbook/install-model",{method:"POST",body:JSON.stringify({repo:t(I),role:t(Je),params_b:te,quant:Y,file:t(be),ctx:t(de),hf_token:ci()})}),ie("Download läuft — Modell erscheint danach automatisch im Modelle-Tab."),c(je,!1),Tt("activity")}catch(te){ie("Fehler: "+te.message,!0)}c(Fe,!1)}async function Ce(E,S,te,Y){Y.disabled=!0,Y.textContent="Starte…";try{await De("/api/cookbook/install-model",{method:"POST",body:JSON.stringify({repo:E,role:S,params_b:te,quant:"Q4_K_M",hf_token:ci()})}),ie("Download läuft — Modell erscheint danach automatisch im Modelle-Tab."),Tt("activity")}catch(Ae){ie(Ae.message,!0),Y.disabled=!1,Y.textContent="Installieren"}}function V(){c(rt,null),c(Qe,""),c(it,""),c(dt,[{repo:"",role:"",quant:"Q4_K_M"}],!0),c(at,!0)}function pe(E){const S=t(y).find(te=>te.id===E);S&&(c(rt,E,!0),c(Qe,S.title,!0),c(it,S.desc||"",!0),c(dt,S.models.map(te=>({repo:te.repo,role:te.role,quant:te.quant||"Q4_K_M"})),!0),c(at,!0))}async function z(){if(!t(Qe).trim())return ie("Bitte einen Titel angeben.",!0);const E=t(dt).filter(S=>S.repo.trim());if(!E.length)return ie("Mindestens ein Modell (Repo) angeben.",!0);try{t(rt)?(await De("/api/cookbook/user-recipe/"+encodeURIComponent(t(rt)),{method:"PUT",body:JSON.stringify({title:t(Qe),desc:t(it),models:E})}),ie("Setup aktualisiert.")):(await De("/api/cookbook/user-recipe",{method:"POST",body:JSON.stringify({title:t(Qe),desc:t(it),models:E})}),ie("Setup gespeichert.")),c(at,!1),zt()}catch(S){ie(S.message,!0)}}async function R(E){const S=t(y).find(te=>te.id===E);if(await xn({title:`„${(S==null?void 0:S.title)||E}" löschen?`,body:"Dein eigenes Setup wird aus dem Cookbook entfernt. Bereits installierte Modelle bleiben unangetastet.",confirmLabel:"Löschen",danger:!0}))try{await De("/api/cookbook/user-recipe/"+encodeURIComponent(E),{method:"DELETE"}),ie("Setup gelöscht."),zt()}catch(te){ie(te.message,!0)}}function x(E){if(!u(E))return"";const S=p(E);return`<span class="chip" title="${Fn(s)}">MoE${S?` · ~${S}B aktiv`:""}</span>`}function P(E){return E?`<span class="chip">${Fn(E)}</span>`:""}var N=Tc(),j=i(Xe(N),2),H=r(j),fe=i(r(H),2),me=i(H,4);{var w=E=>{var S=Jd();f(E,S)},K=E=>{var S=Xd();Ye(S,21,()=>t(y),lt,(te,Y)=>{const Ae=G(()=>t(Y).id===t($));var mt=Yd(),yt=r(mt);{var Me=Ke=>{var ht=Qd(),Zt=Xe(ht),Kt=i(Zt,2);k("click",Zt,Pt=>{Pt.stopPropagation(),pe(t(Y).id)}),k("keydown",Zt,Pt=>{Pt.key==="Enter"&&(Pt.stopPropagation(),pe(t(Y).id))}),k("click",Kt,Pt=>{Pt.stopPropagation(),R(t(Y).id)}),k("keydown",Kt,Pt=>{Pt.key==="Enter"&&(Pt.stopPropagation(),R(t(Y).id))}),f(Ke,ht)};q(yt,Ke=>{t(Y).user&&Ke(Me)})}var qe=i(yt,2);{var Ze=Ke=>{var ht=tr();f(Ke,ht)},Mt=Ke=>{var ht=Zd();f(Ke,ht)};q(qe,Ke=>{t(Ae)?Ke(Ze):t(Y).user&&Ke(Mt,1)})}var et=i(qe,2),ct=r(et),xt=r(ct),Rt=r(xt),sn=i(ct,2),Et=r(sn),tt=i(et,2),Ft=r(tt),Qt=i(tt,2),Ct=r(Qt);D((Ke,ht)=>{At(mt,1,`card-btn${t(Ae)?" cb-best":""}`),g(Rt,t(Y).title),At(sn,1,`fit-badge ${Ke??""}`),g(Et,ht),g(Ft,t(Y).desc),g(Ct,`${t(Y).models.length??""} Modell${t(Y).models.length>1?"e":""} im Setup`)},[()=>_(t(Y).fit_level),()=>C(t(Y).fit_level)]),k("click",mt,()=>U(t(Y).id)),f(te,mt)}),f(E,S)};q(me,E=>{t(O)?E(w):E(K,-1)})}var ee=i(j,2),we=r(ee),Se=i(r(we),2),ft=r(Se);{var st=E=>{const S=G(()=>Math.round((Date.now()/1e3-t(M).updated)/60));var te=tc(),Y=Xe(te);{var Ae=Ze=>{var Mt=oi();D(()=>g(Mt,`Quellen befragt vor ${t(S)??""} min`)),f(Ze,Mt)},mt=Ze=>{var Mt=oi();D(et=>g(Mt,`Quellen befragt vor ${et??""} h`),[()=>Math.round(t(S)/60)]),f(Ze,Mt)},yt=Ze=>{var Mt=oi();D(et=>g(Mt,`Quellen befragt vor ${et??""} Tg.`),[()=>Math.round(t(S)/1440)]),f(Ze,Mt)};q(Y,Ze=>{t(S)<60?Ze(Ae):t(S)<1440?Ze(mt,1):Ze(yt,-1)})}var Me=i(Y,2);{var qe=Ze=>{var Mt=ec();f(Ze,Mt)};q(Me,Ze=>{t(ye)&&Ze(qe)})}f(E,te)};q(ft,E=>{var S;(S=t(M))!=null&&S.updated&&E(st)})}var Ue=i(Se,2),T=r(Ue),Q=i(we,4);{var Be=E=>{var S=nc();f(E,S)},ne=E=>{var S=Ha(),te=Xe(S);Ye(te,17,()=>t(M).categories,lt,(Y,Ae)=>{var mt=lc(),yt=r(mt),Me=r(yt),qe=r(Me),Ze=i(yt,2);Ye(Ze,21,()=>t(Ae).models,lt,(Mt,et)=>{const ct=G(()=>t(Ae).recommended&&t(et).repo===t(Ae).recommended);var xt=sc(),Rt=r(xt);{var sn=gt=>{var _t=tr();f(gt,_t)};q(Rt,gt=>{t(ct)&>(sn)})}var Et=i(Rt,2),tt=r(Et),Ft=r(tt),Qt=r(Ft),Ct=i(Ft,2),Ke=r(Ct),ht=i(tt,2),Zt=r(ht),Kt=i(Et,2),Pt=r(Kt);He(Pt,()=>P(o[t(et).role]||d(t(et).repo)));var Vn=i(Pt,2);He(Vn,()=>x(t(et).repo));var Zn=i(Kt,2),$n=r(Zn),Ca=i(Zn,2);Ye(Ca,17,()=>t(et).requirements||[],lt,(gt,_t)=>{var Vt=ac(),In=r(Vt);D(()=>g(In,`⚠ ${t(_t)??""}`)),f(gt,Vt)});var kt=i(Ca,4),vt=r(kt);{var bt=gt=>{var _t=ic();D(()=>Aa(_t,"title",`bereits eingerichtet als ${t(et).installed??""}`)),f(gt,_t)},Dt=gt=>{var _t=rc();k("click",_t,Vt=>Ce(t(et).repo,t(et).role,t(et).params_b,Vt.currentTarget)),f(gt,_t)};q(vt,gt=>{t(et).installed?gt(bt):gt(Dt,-1)})}D((gt,_t,Vt)=>{At(xt,1,`card${t(ct)?" res-best":""}`),g(Qt,t(et).name),g(Ke,`${t(et).author??""} · ${t(et).params_b??""}B`),At(ht,1,`fit-badge ${gt??""}`),g(Zt,t(et).fit.text),g($n,`${_t??""} · ⬇ ${Vt??""}`)},[()=>_(t(et).fit.level),()=>m(t(et).fit),()=>(t(et).downloads||0).toLocaleString()]),f(Mt,xt)}),D(()=>g(qe,t(Ae).title)),f(Y,mt)}),f(E,S)};q(Q,E=>{var S;t(F)&&!t(M)?E(Be):(S=t(M))!=null&&S.categories&&E(ne,1)})}var he=i(ee,2),Ne=i(r(he),4),We=r(Ne),Ee=i(We,2),W=r(Ee);W.value=W.__value="downloads";var J=i(W);J.value=J.__value="trending";var le=i(J);le.value=le.__value="created_at";var oe=i(Ee,2),$e=r(oe),Le=i(Ne,2);Ye(Le,20,()=>["","coder","vision","reasoning","chat","agent"],lt,(E,S)=>{var te=oc(),Y=r(te);D(()=>{At(te,1,t(Z)===S?"primary":"ghost"),g(Y,S||"Alle")}),k("click",te,()=>{c(Z,S,!0),Gt()}),f(E,te)});var Te=i(Le,2);{var se=E=>{var S=cc();Ye(S,21,()=>t(ke),lt,(te,Y,Ae)=>{var mt=dc(),yt=r(mt);{var Me=Kt=>{var Pt=tr();f(Kt,Pt)};q(yt,Kt=>{Ae===t(ze)&&Kt(Me)})}var qe=i(yt,2),Ze=r(qe),Mt=r(Ze),et=r(Mt),ct=i(Mt,2),xt=r(ct),Rt=i(Ze,2),sn=r(Rt),Et=i(qe,2),tt=r(Et);He(tt,()=>P(d(t(Y).id)));var Ft=i(tt,2);He(Ft,()=>x(t(Y).id));var Qt=i(Et,4),Ct=r(Qt),Ke=r(Ct),ht=i(Ct,2),Zt=r(ht);D((Kt,Pt,Vn,Zn,$n)=>{At(mt,1,`card${Ae===t(ze)?" res-best":""}`),g(et,Kt),g(xt,t(Y).author||""),At(Rt,1,`fit-badge ${Pt??""}`),g(sn,Vn),g(Ke,Zn),g(Zt,`⬇ ${$n??""}`)},[()=>t(Y).id.split("/").pop(),()=>t(ve)[Ae]?_(t(ve)[Ae]):"warn",()=>t(ve)[Ae]?C(t(ve)[Ae]):"prüfe…",()=>t(ve)[Ae]?m({req_gb:0,tps:0}):"Hardware-Fit…",()=>(t(Y).downloads||0).toLocaleString()]),k("click",mt,()=>A(t(Y).id,t(Y).id.split("/").pop())),f(te,mt)}),f(E,S)};q(Te,E=>{t(ke).length&&E(se)})}var ce=i(he,2);{var wt=E=>{const S=G(()=>t(Re));var te=bc(),Y=r(te),Ae=r(Y),mt=i(Ae,2),yt=r(mt),Me=i(mt,2),qe=r(Me),Ze=i(Me,2);Ye(Ze,21,()=>t(S).models,lt,(Et,tt)=>{var Ft=fc(),Qt=r(Ft),Ct=r(Qt),Ke=r(Ct),ht=r(Ke),Zt=i(Ke,2),Kt=r(Zt),Pt=i(Zt,2);He(Pt,()=>x(t(tt).repo));var Vn=i(Ct,2);{var Zn=bt=>{var Dt=vc(),gt=r(Dt);D(()=>g(gt,t(tt).why)),f(bt,Dt)};q(Vn,bt=>{t(tt).why&&bt(Zn)})}var $n=i(Vn,2);{var Ca=bt=>{var Dt=uc(),gt=r(Dt);D((_t,Vt,In)=>g(gt,`~${_t??""} GB · ~${Vt??""} Tok/s · optimal ~${In??""}k Kontext`),[()=>(t(tt).fit.req_gb??0).toFixed(1),()=>Math.round(t(tt).fit.tps??0),()=>Math.round((t(tt).optimal_ctx||8192)/1024)]),f(bt,Dt)};q($n,bt=>{t(tt).fit&&bt(Ca)})}var kt=i(Qt,2);{var vt=bt=>{var Dt=pc(),gt=r(Dt);D(_t=>{At(Dt,1,`fit-badge ${_t??""}`),g(gt,t(tt).fit.text)},[()=>_(t(tt).fit.level)]),f(bt,Dt)};q(kt,bt=>{t(tt).fit&&bt(vt)})}D(()=>{g(ht,t(tt).name),g(Kt,t(tt).role)}),f(Et,Ft)});var Mt=i(Ze,2);{var et=Et=>{const tt=G(()=>Math.max(...t(S).models.map(Ke=>{var ht;return((ht=Ke.fit)==null?void 0:ht.req_gb)??0})));var Ft=hc(),Qt=i(r(Ft)),Ct=r(Qt);D(Ke=>g(Ct,`~${Ke??""} GB`),[()=>t(tt).toFixed(1)]),f(Et,Ft)};q(Mt,Et=>{t(S).models.length&&t(S).models[0].fit&&Et(et)})}var ct=i(Mt,2);{var xt=Et=>{const tt=G(()=>t(y).find(Ke=>!Ke.user&&Ke.fit_level!=="too_tight"&&Ke.id!==t(S).id));var Ft=mc(),Qt=i(r(Ft));{var Ct=Ke=>{var ht=gc(),Zt=i(Xe(ht)),Kt=r(Zt);D(()=>g(Kt,`„${t(tt).title??""}" ansehen`)),k("click",Zt,Pt=>{Pt.preventDefault(),c(Re,null),setTimeout(()=>U(t(tt).id),50)}),f(Ke,ht)};q(Qt,Ke=>{t(tt)&&Ke(Ct)})}f(Et,Ft)};q(ct,Et=>{t(S).fit_level==="too_tight"&&Et(xt)})}var Rt=i(ct,2),sn=r(Rt);D(()=>{g(yt,t(S).title),g(qe,t(S).desc),At(Rt,1,`primary${t(S).fit_level==="too_tight"?" warn":""}`),g(sn,t(S).fit_level==="too_tight"?"Trotzdem installieren (nicht empfohlen)":"Komplettes Setup installieren")}),k("click",te,Et=>{Et.target.classList.contains("modal-overlay")&&c(Re,null)}),k("click",Ae,()=>c(Re,null)),k("click",Rt,()=>ae(t(S).id)),f(E,te)};q(ce,E=>{t(Re)&&E(wt)})}var St=i(ce,2);{var Bt=E=>{var S=Ec(),te=r(S),Y=r(te),Ae=i(Y,2),mt=r(Ae),yt=i(Ae,2),Me=r(yt),qe=i(yt,2);{var Ze=ct=>{var xt=_c();f(ct,xt)},Mt=ct=>{var xt=Sc(),Rt=i(Xe(xt),2);Ye(Rt,21,()=>t(re).files,lt,(kt,vt)=>{const bt=G(()=>t(vt).fit.level==="perfect"?"●":t(vt).fit.level==="marginal"?"◐":"○");var Dt=Yr(),gt=r(Dt),_t={};D(()=>{g(gt,`${t(bt)??""} ${t(vt).filename??""}`),_t!==(_t=t(vt).filename)&&(Dt.value=(Dt.__value=t(vt).filename)??"")}),f(kt,Dt)});var sn=i(Rt,2),Et=r(sn),tt=i(r(Et),2),Ft=i(Et,2),Qt=r(Ft),Ct=i(r(Qt));He(Ct,()=>br(a));var Ke=i(Qt,2),ht=i(sn,2);{var Zt=kt=>{var vt=yc(),bt=i(r(vt)),Dt=r(bt),gt=i(bt,2);D(_t=>g(Dt,`~${_t??""}k`),[()=>Math.round(t(ue).optimal_ctx/1024)]),k("click",gt,_t=>{_t.preventDefault(),c(de,t(ue).optimal_ctx,!0)}),f(kt,vt)};q(ht,kt=>{var vt;(vt=t(ue))!=null&&vt.optimal_ctx&&kt(Zt)})}var Kt=i(ht,2);{var Pt=kt=>{var vt=xc(),bt=r(vt),Dt=i(r(bt),2),gt=r(Dt),_t=i(bt,2),Vt=r(_t);D((In,ki,Gi)=>{g(gt,`~${In??""} GB · ~${ki??""} Tok/s · ${(t(ue).quant||"GGUF")??""}`),At(_t,1,`fit-badge ${Gi??""}`),g(Vt,t(ue).fit.text)},[()=>(t(ue).fit.req_gb??0).toFixed(1),()=>Math.round(t(ue).fit.tps??0),()=>_(t(ue).fit.level)]),f(kt,vt)};q(Kt,kt=>{t(ue)&&kt(Pt)})}var Vn=i(Kt,2);{var Zn=kt=>{const vt=G(()=>t(re).files.find(Vt=>Vt.fit.level!=="too_tight"&&Vt.filename!==t(be)));var bt=Ha(),Dt=Xe(bt);{var gt=Vt=>{var In=kc(),ki=i(r(In)),Gi=r(ki);D(ji=>g(Gi,`${t(vt).filename??""} (${ji??""})`),[()=>C(t(vt).fit.level)]),k("click",ki,ji=>{ji.preventDefault(),c(be,t(vt).filename,!0),B()}),f(Vt,In)},_t=Vt=>{var In=wc();f(Vt,In)};q(Dt,Vt=>{t(vt)?Vt(gt):Vt(_t,-1)})}f(kt,bt)};q(Vn,kt=>{var vt,bt;((vt=t(ue))==null?void 0:vt.fit.level)==="too_tight"&&((bt=t(re))!=null&&bt.files)&&kt(Zn)})}var $n=i(Vn,2),Ca=r($n);D(()=>{var kt,vt;At($n,1,`primary${((kt=t(ue))==null?void 0:kt.fit.level)==="too_tight"?" warn":""}`),$n.disabled=t(Fe),g(Ca,t(Fe)?"Starte…":((vt=t(ue))==null?void 0:vt.fit.level)==="too_tight"?"Trotzdem holen (zu groß — nicht empfohlen)":"Herunterladen & Einpflegen")}),k("change",Rt,B),Hn(Rt,()=>t(be),kt=>c(be,kt)),an(tt,()=>t(Je),kt=>c(Je,kt)),an(Ke,()=>t(de),kt=>c(de,kt)),k("click",$n,_e),f(ct,xt)},et=ct=>{var xt=Mc();f(ct,xt)};q(qe,ct=>{var xt,Rt;t(Fe)&&!t(re)?ct(Ze):(Rt=(xt=t(re))==null?void 0:xt.files)!=null&&Rt.length?ct(Mt,1):t(Fe)||ct(et,2)})}D(()=>{g(mt,t(ot)),g(Me,t(I))}),k("click",S,ct=>{ct.target.classList.contains("modal-overlay")&&c(je,!1)}),k("click",Y,()=>c(je,!1)),f(E,S)};q(St,E=>{t(je)&&E(Bt)})}var hn=i(St,2);{var da=E=>{var S=Cc(),te=r(S),Y=r(te),Ae=i(Y,2),mt=r(Ae),yt=i(Ae,6),Me=i(yt,4),qe=i(Me,4);Ye(qe,17,()=>t(dt),lt,(ct,xt,Rt)=>{var sn=Ac(),Et=r(sn),tt=i(Et,2),Ft=i(tt,2);Ye(Ft,20,()=>["Q4_K_M","Q5_K_M","Q6_K","Q8_0","Q3_K_M"],lt,(Ct,Ke)=>{var ht=Yr(),Zt=r(ht),Kt={};D(()=>{g(Zt,Ke),Kt!==(Kt=Ke)&&(ht.__value=Ke)}),f(Ct,ht)});var Qt=i(Ft,2);an(Et,()=>t(xt).repo,Ct=>t(xt).repo=Ct),an(tt,()=>t(xt).role,Ct=>t(xt).role=Ct),Hn(Ft,()=>t(xt).quant,Ct=>t(xt).quant=Ct),k("click",Qt,()=>c(dt,t(dt).filter((Ct,Ke)=>Ke!==Rt),!0)),f(ct,sn)});var Ze=i(qe,2),Mt=i(Ze,4),et=r(Mt);D(()=>{g(mt,t(rt)?"Setup bearbeiten":"Eigenes Setup erstellen"),g(et,t(rt)?"Änderungen speichern":"Setup speichern")}),k("click",S,ct=>{ct.target.classList.contains("modal-overlay")&&c(at,!1)}),k("click",Y,()=>c(at,!1)),an(yt,()=>t(Qe),ct=>c(Qe,ct)),an(Me,()=>t(it),ct=>c(it,ct)),k("click",Ze,()=>c(dt,[...t(dt),{repo:"",role:"",quant:"Q4_K_M"}],!0)),k("click",Mt,z),f(E,S)};q(hn,E=>{t(at)&&E(da)})}D(()=>{Ue.disabled=t(F),g(T,t(F)?"Suche…":"Aktualisieren"),oe.disabled=t(Ie),g($e,t(Ie)?"Lade…":"Suchen")}),k("click",fe,V),k("click",Ue,()=>Wt(!0)),k("keydown",We,E=>E.key==="Enter"&&Gt()),an(We,()=>t(xe),E=>c(xe,E)),Hn(Ee,()=>t(X),E=>c(X,E)),k("click",oe,Gt),f(e,N),Dn()}qn(["click","keydown","change"]);var Pc=b(`<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>`),Dc=b('<span class="mono-sm"> </span>'),$c=b('<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>'),Ic=b('<span class="chip" role="button" tabindex="0"> </span>'),Lc=b('<div style="margin-top:10px"><a href="#" style="color:var(--mut);font-size:12.5px">Auswahl aufheben (alle)</a></div>'),Xr=b('<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>'),Oc=b('<p><b>Jan AI</b> ist eine Desktop-App — kein Browser, kein Server, kein Admin-Panel. Einfach installieren und loslegen.</p> <p>Jan AI öffnen → linke Leiste → <b>Remote-Modelle</b> → <b>+ Modell hinzufügen</b>:</p> <label>Basis-URL (kopieren und in Jan AI einfügen)</label> <div class="flex gap-2" style="align-items:stretch;margin-bottom:12px"><input class="mono-sm" readonly="" style="flex:1;margin:0"/> <button class="ghost">Kopieren</button></div> <label>Modell-ID (in Jan AI als „Model name" eintragen)</label> <div class="flex gap-2" style="align-items:stretch;margin-bottom:12px"><input class="mono-sm" readonly="" style="flex:1;margin:0"/> <button class="ghost">Kopieren</button></div> <div class="hint">API-Key: ein beliebiger Wert (z.B. <code>local</code>). Jan AI fragt danach beim Einrichten.</div> <div class="hint" style="margin-top:8px">Jan AI herunterladen: <a href="https://jan.ai" target="_blank" rel="noopener">jan.ai</a> — kostenlos, open source, Windows/macOS/Linux.</div>',1),Bc=b('<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),Rc=b('<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),Fc=b('<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),Kc=b('<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),Nc=b('<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=b('<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),Vc=b('<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>'),Wc=b('<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),Gc=b('<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>'),jc=b('<button style="text-align:left;padding:10px 14px"><div style="font-weight:500;font-size:13px"> </div> <div class="card-sub" style="margin:2px 0 0;font-size:11.5px"> </div></button>'),Uc=b('<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),Hc=b('<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),Jc=b('<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>'),Qc=b(`<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 Zc(e,n){Pn(n,!0);const a=G(()=>xi.value),s=G(()=>{var x;return(((x=t(a))==null?void 0:x.models)||[]).filter(P=>!P.incomplete)});let l=L("zed"),o=L(Jt([])),v=L(""),d=L(!1),u=L("cline"),p=L(Jt(localStorage.getItem("mc_ip_override")||""));function _(x){return/^\d{1,3}(\.\d{1,3}){3}$/.test(x)}function C(){return location.protocol==="https:"||!_(location.hostname)}function m(){return`http://${t(p).trim()||location.hostname}:8080/v1`}const y=G(m);function $(){const x=t(p).trim();x?localStorage.setItem("mc_ip_override",x):localStorage.removeItem("mc_ip_override")}const O=G(()=>ze(t(u))),M=G(()=>t(o).length?t(o):t(s).map(x=>x.name)),F=G(()=>t(M)[0]||"coder"),ye=G(()=>{var x;return(x=t(s).find(P=>{var N,j;return(j=(N=P.meta)==null?void 0:N.caps)==null?void 0:j.includes("Bild")}))==null?void 0:x.name});function xe(x,P){const j=(P.length?t(s).filter(H=>P.includes(H.name)):t(s).length?t(s):[{name:"coder",meta:{}}]).map(H=>{var w,K;const fe=(((w=H.meta)==null?void 0:w.caps)||[]).some(ee=>/Bild|Vision/i.test(ee)),me=((K=H.meta)==null?void 0:K.ctx)||131072;return` { "name": "${H.name}", "display_name": "${H.name}", "max_tokens": ${me}${fe?', "capabilities": { "tools": true, "images": true }':""} }`}).join(`,
|
||
`);return`"language_models": {
|
||
"openai_compatible": {
|
||
"bosgame": {
|
||
"api_url": "${x}",
|
||
"available_models": [
|
||
${j}
|
||
]
|
||
}
|
||
}
|
||
}`}function ke(x,P){const j=(P.length?t(s).filter(H=>P.includes(H.name)):t(s).length?t(s):[{name:"coder",meta:{}}]).map(H=>{var me;const fe=((me=H.meta)==null?void 0:me.ctx)||131072;return` "${H.name}": { "name": "${H.name}", "contextWindowSize": ${fe} }`}).join(`,
|
||
`);return`"providers": {
|
||
"llama-swap": {
|
||
"npm": "@ai-sdk/openai-compatible",
|
||
"name": "Bosgame (llama-swap)",
|
||
"options": {
|
||
"baseURL": "${x}",
|
||
"apiKey": "local"
|
||
},
|
||
"models": {
|
||
${j}
|
||
}
|
||
}
|
||
}`}function Ie(x,P){return`{
|
||
"models": [
|
||
${(P.length?t(s).filter(H=>P.includes(H.name)):t(s).length?t(s):[{name:"coder",meta:{}}]).map(H=>` {
|
||
"title": "llama-swap / ${H.name}",
|
||
"provider": "openai",
|
||
"model": "${H.name}",
|
||
"apiBase": "${x}",
|
||
"apiKey": "local"
|
||
}`).join(`,
|
||
`)}
|
||
]
|
||
}`}async function Z(){c(v,"Teste…");try{const x=await De("/api/integration/test");c(d,x.ok,!0),c(v,x.ok?`✓ Verbunden — ${x.models.length} Modell(e): ${x.models.join(", ")}`:`✗ Keine Verbindung: ${x.error}`,!0)}catch(x){c(d,!1),c(v,"✗ "+x.message)}}function X(x){var N;const P=x.querySelector("code");P&&((N=navigator.clipboard)==null||N.writeText(P.textContent||""))}function ve(x){var P;(P=navigator.clipboard)==null||P.writeText(x.value)}function ze(x){return`{
|
||
"mcpServers": {
|
||
"mission-control-memory": {
|
||
"command": "${x==="bosgame"?"/opt/mission-control/.venv/bin/python":"python"}",
|
||
"args": ["${x==="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 Re=Qc(),je=i(Xe(Re),2),ot=i(r(je),6),I=r(ot),re=i(I,2),be=i(ot,2),Je=r(be),de=i(be,2);{var Fe=x=>{var P=Pc();f(x,P)},ue=G(()=>C());q(de,x=>{t(ue)&&x(Fe)})}var at=i(de,2),Qe=r(at),it=i(Qe,2);{var dt=x=>{var P=Dc(),N=r(P);D(()=>{$t(P,`color:${t(d)?"#7ee29a":"#ff9b95"}`),g(N,t(v))}),f(x,P)};q(it,x=>{t(v)&&x(dt)})}var rt=i(je,2),Tt=i(r(rt),2);Ye(Tt,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."]],lt,(x,P)=>{var N=G(()=>aa(P,3));let j=()=>t(N)[0],H=()=>t(N)[1],fe=()=>t(N)[2];var me=$c(),w=r(me),K=r(w),ee=i(w,2),we=r(ee),Se=r(we),ft=i(we,2),st=r(ft);D(()=>{g(K,j()),g(Se,H()),g(st,fe())}),f(x,me)});var zt=i(rt,2);{var Wt=x=>{var P=Wc(),N=Xe(P),j=r(N),H=i(r(j),2),fe=r(H),me=i(j,4);Ye(me,21,()=>t(s),lt,(W,J)=>{const le=G(()=>t(o).includes(t(J).name));var oe=Ic(),$e=r(oe);D(()=>{$t(oe,`cursor:pointer;${t(le)?"background:rgba(45,212,191,.2);border-color:var(--accent);color:var(--accent)":""}`),g($e,t(J).name)}),k("click",oe,()=>c(o,t(le)?t(o).filter(Le=>Le!==t(J).name):[...t(o),t(J).name],!0)),k("keydown",oe,Le=>Le.key==="Enter"&&c(o,t(le)?t(o).filter(Te=>Te!==t(J).name):[...t(o),t(J).name],!0)),f(W,oe)});var w=i(me,2);{var K=W=>{var J=Lc(),le=r(J);k("click",le,oe=>{oe.preventDefault(),c(o,[],!0)}),f(W,J)};q(w,W=>{t(o).length&&W(K)})}var ee=i(N,2),we=i(r(ee),6);Ye(we,20,()=>[["janai","Jan AI","Einfachstes Chat-Interface — Desktop-App, kein Setup"],["openwebui","OpenWebUI","Browser-Chat für Teams — mehr Features, mehr Setup"]],lt,(W,J)=>{var le=G(()=>aa(J,3));let oe=()=>t(le)[0],$e=()=>t(le)[1],Le=()=>t(le)[2];var Te=Xr(),se=r(Te),ce=r(se),wt=i(se,2),St=r(wt);D(()=>{At(Te,1,`card-btn${t(l)===oe()?" cb-best":""}`),g(ce,$e()),g(St,Le())}),k("click",Te,()=>c(l,oe(),!0)),f(W,Te)});var Se=i(we,4);Ye(Se,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"]],lt,(W,J)=>{var le=G(()=>aa(J,3));let oe=()=>t(le)[0],$e=()=>t(le)[1],Le=()=>t(le)[2];var Te=Xr(),se=r(Te),ce=r(se),wt=i(se,2),St=r(wt);D(()=>{At(Te,1,`card-btn${t(l)===oe()?" cb-best":""}`),g(ce,$e()),g(St,Le())}),k("click",Te,()=>c(l,oe(),!0)),f(W,Te)});var ft=i(ee,2),st=i(r(ft),2);{var Ue=W=>{var J=Oc(),le=i(Xe(J),6),oe=r(le),$e=i(oe,2),Le=i(le,4),Te=r(Le),se=i(Te,2);D(()=>{Xn(oe,t(y)),Xn(Te,t(F))}),k("click",$e,ce=>ve(ce.currentTarget.previousElementSibling)),k("click",se,ce=>ve(ce.currentTarget.previousElementSibling)),f(W,J)},T=W=>{const J=G(()=>Ie(t(y),t(M)));var le=Bc(),oe=i(Xe(le),4),$e=r(oe),Le=i($e,2),Te=r(Le),se=r(Te),ce=i(oe,2),wt=i(r(ce)),St=r(wt);D(()=>{g(se,t(J)),g(St,`llama-swap / ${t(F)??""}`)}),k("click",$e,Bt=>X(Bt.currentTarget.parentElement)),f(W,le)},Q=W=>{var J=Rc(),le=i(Xe(J),6),oe=r(le),$e=i(oe,2),Le=i(le,4),Te=r(Le),se=i(Te,2),ce=i(Le,2),wt=i(r(ce),3),St=r(wt);D(()=>{Xn(oe,t(y)),Xn(Te,t(F)),g(St,t(F))}),k("click",$e,Bt=>ve(Bt.currentTarget.previousElementSibling)),k("click",se,Bt=>ve(Bt.currentTarget.previousElementSibling)),f(W,J)},Be=W=>{const J=G(()=>xe(t(y),t(M)));var le=Fc(),oe=i(Xe(le),4),$e=r(oe),Le=i($e,2),Te=r(Le),se=r(Te),ce=i(oe,4),wt=i(r(ce)),St=r(wt);D(()=>{g(se,t(J)),g(St,`bosgame / ${t(F)??""}`)}),k("click",$e,Bt=>X(Bt.currentTarget.parentElement)),f(W,le)},ne=W=>{const J=G(()=>ke(t(y),t(M)));var le=Kc(),oe=i(Xe(le),6),$e=r(oe),Le=i($e,2),Te=r(Le),se=r(Te),ce=i(oe,2),wt=i(r(ce),3),St=r(wt);D(()=>{g(se,t(J)),g(St,`llama-swap/${t(F)??""}`)}),k("click",$e,Bt=>X(Bt.currentTarget.parentElement)),f(W,le)},he=W=>{var J=Nc(),le=i(Xe(J),4),oe=r(le),$e=i(oe,2),Le=i(le,4),Te=r(Le),se=i(Te,2);D(()=>{Xn(oe,t(y)),Xn(Te,t(F))}),k("click",$e,ce=>ve(ce.currentTarget.previousElementSibling)),k("click",se,ce=>ve(ce.currentTarget.previousElementSibling)),f(W,J)},Ne=W=>{var J=qc(),le=i(Xe(J),4),oe=r(le),$e=i(oe,2),Le=i(le,4),Te=r(Le),se=i(Te,2);D(()=>Xn(oe,t(y))),k("click",$e,ce=>ve(ce.currentTarget.previousElementSibling)),k("click",se,ce=>ve(ce.currentTarget.previousElementSibling)),f(W,J)};q(st,W=>{t(l)==="janai"?W(Ue):t(l)==="continue"?W(T,1):t(l)==="antigravity"?W(Q,2):t(l)==="zed"?W(Be,3):t(l)==="opencode"?W(ne,4):t(l)==="cline"?W(he,5):t(l)==="openwebui"&&W(Ne,6)})}var We=i(ft,2);{var Ee=W=>{const J=G(()=>`curl ${t(y)}/chat/completions \\
|
||
-H "Content-Type: application/json" \\
|
||
-d '{
|
||
"model": "${t(ye)}",
|
||
"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 le=Vc(),oe=r(le),$e=i(r(oe),2),Le=r($e);He(Le,()=>jt("check"));var Te=i(Le),se=i(oe,4),ce=r(se),wt=i(ce,2),St=r(wt),Bt=r(St);D(()=>{g(Te,` „${t(ye)??""}" bereit`),g(Bt,t(J))}),k("click",ce,hn=>X(hn.currentTarget.parentElement)),f(W,le)};q(We,W=>{t(ye)&&W(Ee)})}D(()=>g(fe,t(o).length?`${t(o).length} von ${t(s).length} ausgewählt`:"alle werden eingeschlossen")),f(x,P)},qt=x=>{var P=Gc(),N=i(r(P),2),j=i(r(N),4);k("click",j,()=>{var H;return(H=document.querySelector(".nav-item[data-view='cookbook']"))==null?void 0:H.dispatchEvent(new MouseEvent("click"))}),f(x,P)};q(zt,x=>{t(s).length?x(Wt):x(qt,-1)})}var Gt=i(zt,2),Lt=i(r(Gt),2),Ot=i(r(Lt)),U=i(Lt,2);Ye(U,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"]],lt,(x,P)=>{var N=G(()=>aa(P,3));let j=()=>t(N)[0],H=()=>t(N)[1],fe=()=>t(N)[2];var me=jc(),w=r(me),K=r(w),ee=i(w,2),we=r(ee);D(()=>{At(me,1,`card-btn${t(u)===j()?" cb-best":""}`),g(K,H()),g(we,fe())}),k("click",me,()=>c(u,j(),!0)),f(x,me)});var ae=i(U,2),A=r(ae),B=i(A,2),_e=r(B),Ce=r(_e),V=i(ae,2);{var pe=x=>{var P=Uc();f(x,P)},z=x=>{var P=Hc();f(x,P)},R=x=>{var P=Jc();f(x,P)};q(V,x=>{t(u)==="cline"?x(pe):t(u)==="opencode"?x(z,1):x(R,-1)})}D(()=>{Xn(I,t(y)),g(Ce,t(O))}),k("click",re,x=>{const P=x.currentTarget.previousElementSibling;ve(P)}),k("input",Je,$),an(Je,()=>t(p),x=>c(p,x)),k("click",Qe,Z),k("click",Ot,x=>{var P;x.preventDefault(),(P=document.querySelector(".nav-item[data-view='memory']"))==null||P.click()}),k("click",A,x=>X(x.currentTarget.parentElement)),f(e,Re),Dn()}qn(["click","input","keydown"]);var Yc=b('<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>'),Xc=b('<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>'),ev=b('<div class="empty" style="text-align:center;padding:40px">Lade News… (erstes Laden kann kurz dauern)</div>'),tv=b('<div class="alert err" style="margin:0"> </div>'),nv=b('<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>'),av=b('<span class="news-rel">für dich</span>'),iv=b('<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>'),rv=b('<div class="news-grid"></div>'),sv=b('<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 lv(e,n){Pn(n,!0);let a=L(Jt([])),s=L(Jt([])),l=L(!0),o=L("");const v=Z=>Z==="perfect"?"ok":Z==="marginal"?"warn":"bad";function d(Z){const X=Math.max(0,Date.now()/1e3-Z);return X<60?X+"s":X<3600?Math.floor(X/60)+"m":X<86400?Math.floor(X/3600)+"h":Math.floor(X/86400)+"d"}async function u(){c(l,!0),c(o,"");try{c(a,(await De("/api/news")).items||[],!0)}catch(Z){c(o,Z.message||"Fehler beim Laden",!0)}finally{c(l,!1)}}async function p(){try{c(s,(await De("/api/cookbook/upgrades")).upgrades||[],!0)}catch{c(s,[],!0)}}async function _(Z,X){var ve;X.disabled=!0,X.textContent="Starte…";try{await De("/api/cookbook/install-model",{method:"POST",body:JSON.stringify({repo:Z.repo,role:Z.role,params_b:Z.params_b,quant:Z.quant,hf_token:ci()})}),(ve=document.querySelector(".nav-item[data-view='activity']"))==null||ve.dispatchEvent(new MouseEvent("click"))}catch(ze){X.disabled=!1,X.textContent="Installieren",alert("Fehler: "+ze.message)}}function C(){u(),p()}yi(()=>{u(),p()});var m=sv(),y=Xe(m),$=i(r(y),2),O=i(y,2);{var M=Z=>{var X=Xc(),ve=r(X),ze=i(r(ve),2),Re=r(ze),je=i(ve,4);Ye(je,21,()=>t(s),lt,(ot,I)=>{var re=Yc(),be=r(re),Je=r(be),de=r(Je),Fe=r(de),ue=i(de,2),at=r(ue),Qe=i(Je,2),it=r(Qe),dt=i(be,2);D(rt=>{g(Fe,t(I).name),At(ue,1,`fit-badge ${rt??""}`),g(at,t(I).fit.text),g(it,`Ersetzt dein „${t(I).old??""}". ${t(I).why??""}`)},[()=>v(t(I).fit.level)]),k("click",dt,rt=>_(t(I),rt.currentTarget)),f(ot,re)}),D(()=>g(Re,t(s).length)),f(Z,X)};q(O,Z=>{t(s).length&&Z(M)})}var F=i(O,2);{var ye=Z=>{var X=ev();f(Z,X)},xe=Z=>{var X=tv(),ve=r(X);D(()=>g(ve,t(o))),f(Z,X)},ke=Z=>{var X=nv();f(Z,X)},Ie=Z=>{var X=rv();Ye(X,21,()=>t(a),lt,(ve,ze,Re)=>{var je=iv();At(je,1,`news-card${Re===0?" featured":""}`);var ot=r(je),I=r(ot),re=r(I),be=i(I,2);{var Je=Qe=>{var it=av();f(Qe,it)};q(be,Qe=>{t(ze).relevant&&Qe(Je)})}var de=i(be,2),Fe=r(de),ue=i(ot,2),at=r(ue);D(Qe=>{Aa(je,"href",t(ze).link),g(re,t(ze).source),g(Fe,Qe),g(at,t(ze).title)},[()=>t(ze).ts?d(t(ze).ts):""]),f(ve,je)}),f(Z,X)};q(F,Z=>{t(l)?Z(ye):t(o)?Z(xe,1):t(a).length?Z(Ie,-1):Z(ke,2)})}k("click",$,C),f(e,m),Dn()}qn(["click"]);const es=[{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>`]]}],ov=[["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 dv=b('<div class="concept"><h4> </h4> <p> </p></div>'),cv=b("<button> </button>"),vv=b('<details class="guide-acc"><summary> </summary> <div class="acc-body"></div></details>'),uv=b('<div class="card guide-card svelte-112sh7i"><div class="guide-group-hd svelte-112sh7i"> </div> <!></div>'),pv=b('<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 fv(e,n){Pn(n,!0);let a=L(0);function s(p){var _;c(a,p,!0),(_=document.getElementById(`guide-group-${p}`))==null||_.scrollIntoView({behavior:"smooth",block:"start"})}var l=pv(),o=i(Xe(l),2),v=i(r(o),2);Ye(v,21,()=>ov,lt,(p,_)=>{var C=G(()=>aa(t(_),2));let m=()=>t(C)[0],y=()=>t(C)[1];var $=dv(),O=r($),M=r(O),F=i(O,2),ye=r(F);D(()=>{g(M,m()),g(ye,y())}),f(p,$)});var d=i(o,2);Ye(d,21,()=>es,lt,(p,_,C)=>{var m=cv(),y=r(m);D(()=>{At(m,1,`guide-tab${t(a)===C?" active":""}`,"svelte-112sh7i"),g(y,t(_).label)}),k("click",m,()=>s(C)),f(p,m)});var u=i(d,2);Ye(u,17,()=>es,lt,(p,_,C)=>{var m=uv();Aa(m,"id",`guide-group-${C}`);var y=r(m),$=r(y),O=i(y,2);Ye(O,17,()=>t(_).tutorials,lt,(M,F,ye)=>{var xe=G(()=>aa(t(F),2));let ke=()=>t(xe)[0],Ie=()=>t(xe)[1];var Z=vv();Z.open=C===0&&ye===0;var X=r(Z),ve=r(X),ze=i(X,2);He(ze,Ie,!0),D(()=>g(ve,ke())),f(M,Z)}),D(()=>g($,t(_).label)),f(p,m)}),f(e,l),Dn()}qn(["click"]);var hv=b('<div class="card-sub" style="margin-bottom:10px"> </div>'),gv=b('<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=b('<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>'),bv=b('<span class="chip" role="button" tabindex="0"> <span style="color:var(--mut);margin-left:2px"> </span></span>'),_v=b('<div class="card"><div class="card-sub">Lade…</div></div>'),yv=b('<button class="primary" style="margin-top:14px">+ Ersten Eintrag anlegen</button>'),xv=b('<div class="card"><div class="empty-c" style="padding:8px 0 4px"><div class="e-t"> </div> <div class="e-s"> </div> <!></div></div>'),kv=b('<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),wv=b('<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>'),Sv=b("<div><!></div>"),Mv=b('<div class="card" style="padding:0;overflow:hidden"></div>'),Ev=b(`<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"> </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 Av(e,n){Pn(n,!0);let a=L(Jt([])),s=L(!0),l=L("all"),o=L(!1),v=L(""),d=L("stable"),u=L(null),p=L(""),_=L("stable"),C=L(!1),m=L(""),y=L("stable"),$=L("import"),O=L(!1);const M=G(()=>t(m).split(`
|
||
`).map(U=>U.trim()).filter(U=>U.length>0)),F=G(()=>t(l)==="all"?t(a):t(a).filter(U=>U.category===t(l))),ye={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 xe(U){const ae=Math.floor((Date.now()-new Date(U).getTime())/1e3);return ae<60?"gerade eben":ae<3600?`vor ${Math.floor(ae/60)} Min`:ae<86400?`vor ${Math.floor(ae/3600)} Std`:`vor ${Math.floor(ae/86400)} Tagen`}function ke(U){return t(a).filter(ae=>ae.category===U).length}async function Ie(){try{c(a,await De("/api/memory"),!0)}catch(U){ie("Laden fehlgeschlagen: "+U.message,!0)}finally{c(s,!1)}}async function Z(){if(t(v).trim())try{const U=await De("/api/memory",{method:"POST",body:JSON.stringify({content:t(v).trim(),category:t(d),source:"manual"})});c(a,[U,...t(a)],!0),c(v,""),c(d,"stable"),c(o,!1),ie("Gespeichert")}catch(U){ie("Fehler: "+U.message,!0)}}async function X(U){try{const ae=await De(`/api/memory/${U.id}`,{method:"PUT",body:JSON.stringify({content:t(p),category:t(_)})});c(a,t(a).map(A=>A.id===U.id?ae:A),!0),c(u,null),ie("Aktualisiert")}catch(ae){ie("Fehler: "+ae.message,!0)}}async function ve(U){if(await xn({title:"Eintrag löschen?",body:`„${U.content.length>80?U.content.slice(0,80)+"…":U.content}" wird dauerhaft entfernt.`,danger:!0}))try{await De(`/api/memory/${U.id}`,{method:"DELETE"}),c(a,t(a).filter(A=>A.id!==U.id),!0),ie("Gelöscht")}catch(A){ie("Fehler: "+A.message,!0)}}function ze(U){c(u,U.id,!0),c(p,U.content,!0),c(_,U.category,!0)}async function Re(){if(t(M).length===0)return;c(O,!0);let U=0;for(const ae of t(M))try{const A=await De("/api/memory",{method:"POST",body:JSON.stringify({content:ae,category:t(y),source:t($)})});c(a,[A,...t(a)],!0),U++}catch{}c(O,!1),c(C,!1),c(m,""),ie(`${U} von ${t(M).length} Einträgen importiert`)}Ga(()=>{Ie()});var je=Ev(),ot=Xe(je),I=i(r(ot),2),re=r(I),be=r(re),Je=i(re,2),de=r(Je),Fe=i(ot,2);{var ue=U=>{var ae=gv(),A=i(r(ae),6);Aa(A,"placeholder",`Tobi arbeitet am liebsten abends.
|
||
Projektsprache: Deutsch.
|
||
Bosgame M5 läuft mit Ubuntu 26.04.
|
||
...`);var B=i(A,2),_e=r(B),Ce=i(r(_e),2),V=r(Ce);V.value=V.__value="user";var pe=i(V);pe.value=pe.__value="instruction";var z=i(pe);z.value=z.__value="stable";var R=i(z);R.value=R.__value="versioned";var x=i(R);x.value=x.__value="ephemeral";var P=i(_e,2),N=i(r(P),2),j=r(N);j.value=j.__value="import";var H=i(j);H.value=H.__value="claude";var fe=i(H);fe.value=fe.__value="gemini";var me=i(fe);me.value=me.__value="chatgpt";var w=i(me);w.value=w.__value="manual";var K=i(B,2);{var ee=Ue=>{var T=hv(),Q=r(T);D(()=>g(Q,`${t(M).length??""} Eintrag/Einträge erkannt`)),f(Ue,T)};q(K,Ue=>{t(M).length>0&&Ue(ee)})}var we=i(K,2),Se=r(we),ft=r(Se),st=i(Se,2);D(()=>{Se.disabled=t(M).length===0||t(O),g(ft,t(O)?"Importiere…":`${t(M).length} Einträge speichern`)}),an(A,()=>t(m),Ue=>c(m,Ue)),Hn(Ce,()=>t(y),Ue=>c(y,Ue)),Hn(N,()=>t($),Ue=>c($,Ue)),k("click",Se,Re),k("click",st,()=>{c(C,!1),c(m,"")}),f(U,ae)};q(Fe,U=>{t(C)&&U(ue)})}var at=i(Fe,2);{var Qe=U=>{var ae=mv(),A=i(r(ae),4),B=i(A,4),_e=r(B);_e.value=_e.__value="user";var Ce=i(_e);Ce.value=Ce.__value="instruction";var V=i(Ce);V.value=V.__value="stable";var pe=i(V);pe.value=pe.__value="versioned";var z=i(pe);z.value=z.__value="ephemeral";var R=i(B,2),x=r(R),P=i(x,2);D(N=>x.disabled=N,[()=>!t(v).trim()]),k("keydown",A,N=>{N.key==="Enter"&&(N.ctrlKey||N.metaKey)&&Z()}),an(A,()=>t(v),N=>c(v,N)),Hn(B,()=>t(d),N=>c(d,N)),k("click",x,Z),k("click",P,()=>{c(o,!1),c(v,"")}),f(U,ae)};q(at,U=>{t(o)&&U(Qe)})}var it=i(at,2),dt=r(it),rt=i(r(dt),2);Ye(rt,17,()=>[["all","Alle","",t(a).length],["user","Über mich","#a78bfa",ke("user")],["instruction","Verhalten","#fb923c",ke("instruction")],["stable","Stabil","var(--accent)",ke("stable")],["versioned","Versioniert","#f59e0b",ke("versioned")],["ephemeral","Temporär","var(--mut)",ke("ephemeral")]],lt,(U,ae)=>{var A=G(()=>aa(t(ae),4));let B=()=>t(A)[0],_e=()=>t(A)[1],Ce=()=>t(A)[2],V=()=>t(A)[3];var pe=bv(),z=r(pe),R=i(z),x=r(R);D(()=>{$t(pe,`cursor:pointer;${t(l)===B()?`background:rgba(45,212,191,.12);border-color:${Ce()||"var(--accent)"};color:${Ce()||"var(--accent)"}`:""}`),g(z,`${_e()??""} `),g(x,V())}),k("click",pe,()=>c(l,B(),!0)),k("keydown",pe,P=>P.key==="Enter"&&c(l,B(),!0)),f(U,pe)});var Tt=i(it,2);{var zt=U=>{var ae=_v();f(U,ae)},Wt=U=>{var ae=xv(),A=r(ae),B=r(A),_e=r(B),Ce=i(B,2),V=r(Ce),pe=i(Ce,2);{var z=R=>{var x=yv();k("click",x,()=>c(o,!0)),f(R,x)};q(pe,R=>{t(a).length===0&&R(z)})}D(()=>{g(_e,t(a).length===0?"Noch keine Einträge":"Keine Treffer"),g(V,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.")}),f(U,ae)},qt=U=>{var ae=Mv();Ye(ae,23,()=>t(F),A=>A.id,(A,B,_e)=>{var Ce=Sv(),V=r(Ce);{var pe=R=>{var x=kv(),P=Xe(x),N=i(P,2),j=r(N);j.value=j.__value="user";var H=i(j);H.value=H.__value="instruction";var fe=i(H);fe.value=fe.__value="stable";var me=i(fe);me.value=me.__value="versioned";var w=i(me);w.value=w.__value="ephemeral";var K=i(N,2),ee=r(K),we=i(ee,2);an(P,()=>t(p),Se=>c(p,Se)),Hn(N,()=>t(_),Se=>c(_,Se)),k("click",ee,()=>X(t(B))),k("click",we,()=>c(u,null)),f(R,x)},z=R=>{var x=wv(),P=r(x),N=r(P),j=r(N),H=i(N,2),fe=r(H),me=r(fe),w=i(fe,2),K=r(w),ee=i(w,2),we=r(ee),Se=i(P,2),ft=r(Se),st=i(ft,2);D(Ue=>{var T,Q,Be;g(j,t(B).content),$t(fe,`border-color:${(((T=ye[t(B).category])==null?void 0:T.color)||"var(--mut)")??""};color:${(((Q=ye[t(B).category])==null?void 0:Q.color)||"var(--mut)")??""}`),g(me,((Be=ye[t(B).category])==null?void 0:Be.label)||t(B).category),g(K,t(B).source),g(we,Ue)},[()=>xe(t(B).updated_at)]),k("click",ft,()=>ze(t(B))),k("click",st,()=>ve(t(B))),f(R,x)};q(V,R=>{t(u)===t(B).id?R(pe):R(z,-1)})}D(()=>$t(Ce,`padding:14px 16px;${t(_e)<t(F).length-1?"border-bottom:1px solid var(--brd, rgba(255,255,255,.07))":""}`)),f(A,Ce)}),f(U,ae)};q(Tt,U=>{t(s)?U(zt):t(F).length===0?U(Wt,1):U(qt,-1)})}var Gt=i(Tt,2),Lt=i(r(Gt),2),Ot=i(r(Lt),3);D(()=>{g(be,t(C)?"Abbrechen":"⇩ Import"),g(de,t(o)?"Abbrechen":"+ Eintrag")}),k("click",re,()=>{c(C,!t(C)),c(o,!1),c(m,"")}),k("click",Je,()=>{c(o,!t(o)),c(C,!1),c(v,"")}),k("click",Ot,U=>{var ae;U.preventDefault(),(ae=document.querySelector(".nav-item[data-view='connect']"))==null||ae.click()}),f(e,je),Dn()}qn(["click","keydown"]);var Cv=b('<div class="log svelte-h40163" style="margin-top:8px"><code class="svelte-h40163">pip install faster-whisper</code></div>'),Tv=b('<div class="log svelte-h40163" style="margin-top:8px"><code class="svelte-h40163"> </code></div>'),zv=b('<div style="margin-bottom:8px" class="svelte-h40163"><div class="card-sub svelte-h40163" style="font-size:11.5px;margin-bottom:4px">4. Bosgame-Key eintragen (in Windows PowerShell):</div> <div style="position:relative" class="svelte-h40163"><button class="ghost svelte-h40163" style="position:absolute;top:6px;right:6px;font-size:11px;padding:2px 8px;z-index:1">Kopieren</button> <div class="log svelte-h40163"><code class="svelte-h40163"> </code></div></div></div>'),Pv=b('<div class="card-sub svelte-h40163" style="font-size:11.5px">SSH-Key nicht gefunden — bitte auf dem Bosgame generieren: <code style="display:block;margin-top:4px" class="svelte-h40163">ssh-keygen -t ed25519 -C "hermes-agent@bosgame" -f ~/.ssh/id_ed25519_hermes_agent -N ""</code></div>'),Dv=b('<div style="margin-top:12px" class="svelte-h40163"><div style="font-size:12.5px;font-weight:500;margin-bottom:8px" class="svelte-h40163">Einrichtung (einmalig, ~3 Minuten):</div> <div style="margin-bottom:8px" class="svelte-h40163"><div class="card-sub svelte-h40163" style="font-size:11.5px;margin-bottom:4px">1. PowerShell als Admin — OpenSSH Server installieren:</div> <div class="log svelte-h40163"><code class="svelte-h40163">Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0</code></div></div> <div style="margin-bottom:8px" class="svelte-h40163"><div class="card-sub svelte-h40163" style="font-size:11.5px;margin-bottom:4px">2. Dienst starten und dauerhaft aktivieren:</div> <div class="log svelte-h40163"><code class="svelte-h40163"></code></div></div> <div style="margin-bottom:8px" class="svelte-h40163"><div class="card-sub svelte-h40163" style="font-size:11.5px;margin-bottom:4px">3. SSH-Ordner erstellen:</div> <div class="log svelte-h40163"><code class="svelte-h40163"></code></div></div> <!> <div style="margin-bottom:8px" class="svelte-h40163"><div class="card-sub svelte-h40163" style="font-size:11.5px;margin-bottom:4px">5. Windows-IP in Mission Control Env-Var setzen:</div> <div class="log svelte-h40163"><code class="svelte-h40163">HERMES_WINDOWS_HOST=192.168.178.XXX</code></div></div> <button class="primary svelte-h40163" style="margin-top:4px">Verbindung testen</button></div>'),$v=b('<div class="card svelte-h40163" style="border-color:rgba(45,212,191,.3)"><div class="card-h svelte-h40163"><h3 class="svelte-h40163">Hermes Setup-Wizard</h3></div> <div class="tile svelte-h40163" style="margin-bottom:10px"><div style="display:flex;justify-content:space-between;align-items:center" class="svelte-h40163"><div class="svelte-h40163"><b class="svelte-h40163">Whisper (Sprache → Text)</b> <div class="card-sub svelte-h40163" style="font-size:12px">faster-whisper muss auf dem Bosgame installiert sein</div></div> <span class="chip svelte-h40163"> </span></div> <!></div> <div class="tile svelte-h40163" style="margin-bottom:10px"><div style="display:flex;justify-content:space-between;align-items:center" class="svelte-h40163"><div class="svelte-h40163"><b class="svelte-h40163">Piper TTS (Text → Sprache)</b> <div class="card-sub svelte-h40163" style="font-size:12px">Piper-Binary + deutsche Stimme</div></div> <span class="chip svelte-h40163"> </span></div> <!></div> <div class="tile svelte-h40163"><div style="display:flex;justify-content:space-between;align-items:center" class="svelte-h40163"><div class="svelte-h40163"><b class="svelte-h40163">Windows SSH-Verbindung</b> <div class="card-sub svelte-h40163" style="font-size:12px">Damit Hermes Dateien auf deinem Windows-PC ändern kann</div></div> <span class="chip svelte-h40163"> </span></div> <!></div></div>'),Iv=b('<button class="ghost svelte-h40163" style="font-size:12.5px;text-align:left"> </button>'),Lv=b('<div class="empty-c svelte-h40163" style="margin:auto"><div class="e-t svelte-h40163">Hermes ist bereit</div> <div class="e-s svelte-h40163">Stelle eine Frage oder gib einen Auftrag — per Text oder Sprache.</div> <div style="margin-top:16px;display:flex;flex-direction:column;gap:6px" class="svelte-h40163"></div></div>'),Ov=b(`<div style="display:flex;justify-content:flex-end" class="svelte-h40163"><div style="background:rgba(45,212,191,.15);border:1px solid rgba(45,212,191,.3);
|
||
border-radius:12px 12px 2px 12px;padding:10px 14px;max-width:75%;
|
||
font-size:13.5px;line-height:1.5;word-break:break-word" class="svelte-h40163"> </div></div>`),Bv=b(`<div style="display:flex;gap:8px;align-items:flex-start" class="svelte-h40163"><div style="width:28px;height:28px;border-radius:50%;background:rgba(45,212,191,.2);
|
||
border:1px solid rgba(45,212,191,.4);display:flex;align-items:center;
|
||
justify-content:center;font-size:14px;flex-shrink:0" class="svelte-h40163">H</div> <div style="background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.08);
|
||
border-radius:2px 12px 12px 12px;padding:10px 14px;max-width:80%;
|
||
font-size:13.5px;line-height:1.6;word-break:break-word;white-space:pre-wrap" class="svelte-h40163"> </div></div>`),Rv=b(`<span style="font-family:monospace;font-size:11px;opacity:.7;overflow:hidden;
|
||
text-overflow:ellipsis;white-space:nowrap;max-width:400px" class="svelte-h40163"> </span>`),Fv=b(`<div style="display:flex;align-items:center;gap:8px;color:var(--mut);font-size:11.5px;
|
||
padding:4px 8px;background:rgba(255,255,255,.02);border-radius:6px" class="svelte-h40163"><span class="svelte-h40163"> </span> <!></div>`),Kv=b('<div style="text-align:center;color:var(--mut);font-size:11px" class="svelte-h40163"> </div>'),Nv=b(`<div style="background:rgba(240,87,63,.1);border:1px solid rgba(240,87,63,.3);
|
||
border-radius:8px;padding:8px 12px;color:#ff9b95;font-size:12.5px" class="svelte-h40163"> </div>`),qv=b(`<div style="display:flex;gap:8px;align-items:center;color:var(--mut);font-size:12px" class="svelte-h40163"><div style="width:28px;height:28px;border-radius:50%;background:rgba(45,212,191,.1);
|
||
border:1px solid rgba(45,212,191,.2);display:flex;align-items:center;
|
||
justify-content:center;font-size:14px" class="svelte-h40163">H</div> <span style="animation:pulse 1.2s ease-in-out infinite" class="svelte-h40163">denkt nach…</span></div>`),Vv=b('<button class="ghost svelte-h40163" style="padding:10px 18px;flex-shrink:0;border-color:var(--err);color:var(--err)">⏹ Stopp</button>'),Wv=b('<button class="primary svelte-h40163" style="padding:10px 18px;flex-shrink:0">Senden</button>'),Gv=b('<div style="border-top:1px solid rgba(255,255,255,.04);padding:6px 16px;display:flex;justify-content:flex-end" class="svelte-h40163"><button class="ghost svelte-h40163" style="font-size:11px;padding:2px 8px;color:var(--mut)">Verlauf löschen</button></div>'),jv=b('<div class="pagehead svelte-h40163" style="display:flex;justify-content:space-between;align-items:flex-start"><div class="svelte-h40163"><h1 class="svelte-h40163">Hermes</h1> <div class="sub svelte-h40163">Dein lokaler KI-Assistent — kennt den Bosgame, lernt mit.</div></div> <div class="flex gap-2 svelte-h40163" style="flex-shrink:0;margin-top:6px;flex-wrap:wrap;align-items:center"><span class="chip svelte-h40163"> </span> <span class="chip svelte-h40163"> </span> <button class="ghost svelte-h40163"> </button> <button class="ghost svelte-h40163" style="padding:4px 10px;font-size:12px">⚙ Setup</button></div></div> <!> <div class="card svelte-h40163" style="padding:0;display:flex;flex-direction:column;min-height:420px"><div style="flex:1;overflow-y:auto;padding:16px;display:flex;flex-direction:column;gap:10px" id="hermes-msgs" class="svelte-h40163"><!> <!> <!></div> <div style="border-top:1px solid rgba(255,255,255,.07);padding:12px 16px;display:flex;gap:8px;align-items:flex-end" class="svelte-h40163"><textarea rows="2" placeholder="Frage stellen oder Aufgabe beschreiben…" style="flex:1;resize:none;font-size:13.5px;line-height:1.5;min-height:44px;max-height:160px" class="svelte-h40163"></textarea> <button class="ghost svelte-h40163"> </button> <!></div> <!></div>',1);function Uv(e,n){Pn(n,!0);const a="hermes_chat_history";let s=L(Jt((()=>{try{return JSON.parse(sessionStorage.getItem(a)||"[]")}catch{return[]}})())),l=L(""),o=L(!1),v=L(!1),d=L(!1),u=L(!1),p=L(null),_=L(!1),C=L(""),m=L(null),y=L("");Ga(()=>{try{sessionStorage.setItem(a,JSON.stringify(t(s)))}catch{}});function $(){const z=location.protocol==="https:"?"wss:":"ws:",R=localStorage.getItem("mc_token")||"",x=`${z}//${location.host}/api/hermes/chat${R?"?token="+R:""}`,P=new WebSocket(x);P.onmessage=N=>{const j=JSON.parse(N.data);if(j.type==="thinking")c(o,!0);else if(j.type!=="info")if(j.type==="token"){c(o,!1),c(y,t(y)+j.content);const H=t(s)[t(s).length-1];(H==null?void 0:H.role)==="hermes"?c(s,[...t(s).slice(0,-1),{role:"hermes",content:t(y)}],!0):c(s,[...t(s),{role:"hermes",content:t(y)}],!0)}else if(j.type==="tool_call"){c(o,!1);const H=j.args||{},fe=Object.values(H).join(" ").slice(0,60);c(s,[...t(s),{role:"tool",content:fe,tool:j.name}],!0)}else if(j.type==="tool_result"){const H=[...t(s)].reverse().find(fe=>fe.role==="tool"&&fe.tool===j.name);H&&(H.content=j.content),c(s,[...t(s)],!0)}else j.type==="error"?(c(o,!1),c(s,[...t(s),{role:"error",content:j.content}],!0)):j.type==="done"&&(c(o,!1),c(v,!1),c(y,""),t(d)&&X())},P.onclose=()=>{c(m,null),setTimeout($,3e3)},P.onerror=()=>P.close(),c(m,P,!0)}function O(){var z;c(v,!0),c(o,!1),t(y)&&c(s,[...t(s).slice(0,-1),{role:"hermes",content:t(y)+" ✋"}],!0),c(y,""),(z=t(m))==null||z.close()}async function M(){const z=t(l).trim();!z||!t(m)||t(m).readyState!==1||(c(s,[...t(s),{role:"user",content:z}],!0),c(l,""),c(y,""),c(v,!1),t(m).send(JSON.stringify({message:z})))}function F(){c(s,[],!0),c(y,"");try{sessionStorage.removeItem(a)}catch{}}let ye=null,xe=[];async function ke(){try{const z=await navigator.mediaDevices.getUserMedia({audio:!0});xe=[],ye=new MediaRecorder(z),ye.ondataavailable=R=>xe.push(R.data),ye.onstop=()=>{z.getTracks().forEach(R=>R.stop()),Z()},ye.start(),c(u,!0)}catch(z){ie("Mikrofon-Zugriff verweigert: "+z.message,!0)}}function Ie(){ye==null||ye.stop(),c(u,!1)}async function Z(){const z=new Blob(xe,{type:"audio/webm"}),R=new FormData;R.append("audio",z,"voice.webm");try{const P=await(await fetch("/api/hermes/transcribe",{method:"POST",headers:localStorage.getItem("mc_token")?{"X-MC-Token":localStorage.getItem("mc_token")}:{},body:R})).json();P.text?(c(l,P.text,!0),M()):ie("Konnte Audio nicht verstehen.",!0)}catch(x){ie("Transkription fehlgeschlagen: "+x.message,!0)}}async function X(){const z=[...t(s)].reverse().find(R=>R.role==="hermes");if(z)try{const R=await fetch("/api/hermes/tts",{method:"POST",headers:{"Content-Type":"application/json",...localStorage.getItem("mc_token")?{"X-MC-Token":localStorage.getItem("mc_token")}:{}},body:JSON.stringify({text:z.content})});if(!R.ok)return;const x=await R.blob(),P=URL.createObjectURL(x),N=new Audio(P);N.onended=()=>URL.revokeObjectURL(P),N.play()}catch{}}async function ve(){try{c(p,await De("/api/hermes/status"),!0)}catch{c(p,null)}}async function ze(){try{const z=await De("/api/hermes/pubkey");c(C,z.pubkey,!0)}catch{c(C,"")}}function Re(z){return{read_file:"📄 Lese Datei",list_directory:"📁 Liste Verzeichnis",run_command:"⚡ Befehl",get_system_status:"📊 System-Status",get_memories:"🧠 Gedächtnis",add_memory:"💾 Speichern",web_search:"🌐 Websuche"}[z]||z}function je(){var z;(z=navigator.clipboard)==null||z.writeText(t(C)),ie("SSH-Key kopiert")}Ga(()=>{$(),ve()});var ot=jv(),I=Xe(ot),re=i(r(I),2),be=r(re),Je=r(be),de=i(be,2),Fe=r(de),ue=i(de,2),at=r(ue),Qe=i(ue,2),it=i(I,2);{var dt=z=>{var R=$v(),x=i(r(R),2),P=r(x),N=i(r(P),2),j=r(N),H=i(P,2);{var fe=ne=>{var he=Cv();f(ne,he)};q(H,ne=>{var he;((he=t(p))==null?void 0:he.whisper)==="not_installed"&&ne(fe)})}var me=i(x,2),w=r(me),K=i(r(w),2),ee=r(K),we=i(w,2);{var Se=ne=>{var he=Tv(),Ne=r(he),We=r(Ne);D(Ee=>g(We,Ee),[()=>["# 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(`
|
||
`)]),f(ne,he)};q(we,ne=>{var he;((he=t(p))==null?void 0:he.piper)!=="ready"&&ne(Se)})}var ft=i(me,2),st=r(ft),Ue=i(r(st),2),T=r(Ue),Q=i(st,2);{var Be=ne=>{var he=Dv(),Ne=i(r(he),4),We=i(r(Ne),2),Ee=r(We);Ee.textContent=`Start-Service sshd
|
||
Set-Service -Name sshd -StartupType Automatic`;var W=i(Ne,2),J=i(r(W),2),le=r(J);le.textContent='New-Item -ItemType Directory -Force -Path "$env:USERPROFILE\\.ssh"';var oe=i(W,2);{var $e=se=>{var ce=zv(),wt=i(r(ce),2),St=r(wt),Bt=i(St,2),hn=r(Bt),da=r(hn);D(()=>g(da,'echo "'+t(C)+'" >> "$env:USERPROFILE\\.ssh\\authorized_keys"')),k("click",St,je),f(se,ce)},Le=se=>{var ce=Pv();f(se,ce)};q(oe,se=>{t(C)?se($e):se(Le,-1)})}var Te=i(oe,4);k("click",Te,()=>{ve(),ie("Status aktualisiert")}),f(ne,he)};q(Q,ne=>{var he;(he=t(p))!=null&&he.ssh_ok||ne(Be)})}D(()=>{var ne,he,Ne,We,Ee,W;$t(N,`font-size:11px;${((ne=t(p))==null?void 0:ne.whisper)!=="not_installed"?"color:#7ee29a":"color:#ff9b95"}`),g(j,((he=t(p))==null?void 0:he.whisper)!=="not_installed"?"✓ OK":"✗ fehlt"),$t(K,`font-size:11px;${((Ne=t(p))==null?void 0:Ne.piper)==="ready"?"color:#7ee29a":"color:#ff9b95"}`),g(ee,((We=t(p))==null?void 0:We.piper)==="ready"?"✓ OK":"✗ fehlt"),$t(Ue,`font-size:11px;${(Ee=t(p))!=null&&Ee.ssh_ok?"color:#7ee29a":"color:var(--mut)"}`),g(T,(W=t(p))!=null&&W.ssh_ok?"✓ verbunden":"optional")}),f(z,R)};q(it,z=>{t(_)&&z(dt)})}var rt=i(it,2),Tt=r(rt),zt=r(Tt);{var Wt=z=>{var R=Lv(),x=i(r(R),4);Ye(x,20,()=>["Was läuft gerade auf dem System?","Zeig mir den Inhalt von /etc/llama-swap/config.yaml","Suche nach den neuesten Qwen3-Modellen"],lt,(P,N)=>{var j=Iv(),H=r(j);D(()=>g(H,N)),k("click",j,()=>{c(l,N,!0),M()}),f(P,j)}),f(z,R)};q(zt,z=>{t(s).length===0&&z(Wt)})}var qt=i(zt,2);Ye(qt,16,()=>t(s),z=>z,(z,R)=>{var x=Ha(),P=Xe(x);{var N=w=>{var K=Ov(),ee=r(K),we=r(ee);D(()=>g(we,R.content)),f(w,K)},j=w=>{var K=Bv(),ee=i(r(K),2),we=r(ee);D(()=>g(we,R.content)),f(w,K)},H=w=>{var K=Fv(),ee=r(K),we=r(ee),Se=i(ee,2);{var ft=st=>{var Ue=Rv(),T=r(Ue);D(()=>g(T,R.content)),f(st,Ue)};q(Se,st=>{R.content&&st(ft)})}D(st=>g(we,st),[()=>Re(R.tool||"")]),f(w,K)},fe=w=>{var K=Kv(),ee=r(K);D(()=>g(ee,R.content)),f(w,K)},me=w=>{var K=Nv(),ee=r(K);D(()=>g(ee,`⚠ ${R.content??""}`)),f(w,K)};q(P,w=>{R.role==="user"?w(N):R.role==="hermes"?w(j,1):R.role==="tool"?w(H,2):R.role==="info"?w(fe,3):R.role==="error"&&w(me,4)})}f(z,x)});var Gt=i(qt,2);{var Lt=z=>{var R=qv();f(z,R)};q(Gt,z=>{t(o)&&z(Lt)})}var Ot=i(Tt,2),U=r(Ot),ae=i(U,2),A=r(ae),B=i(ae,2);{var _e=z=>{var R=Vv();k("click",R,O),f(z,R)},Ce=z=>{var R=Wv();D(x=>R.disabled=x,[()=>!t(l).trim()||!t(m)||t(m).readyState!==1]),k("click",R,M),f(z,R)};q(B,z=>{t(o)||t(v)?z(_e):z(Ce,-1)})}var V=i(Ot,2);{var pe=z=>{var R=Gv(),x=r(R);k("click",x,F),f(z,R)};q(V,z=>{t(s).length>0&&!t(o)&&z(pe)})}D(()=>{var z,R,x,P,N,j;$t(be,`font-size:11px;${((z=t(p))==null?void 0:z.whisper)==="ready"||((R=t(p))==null?void 0:R.whisper)==="installed"?"color:var(--accent);border-color:var(--accent)":"color:var(--mut)"}`),g(Je,`🎙 Whisper: ${((x=t(p))==null?void 0:x.whisper)??"…"??""}`),$t(de,`font-size:11px;${(P=t(p))!=null&&P.ssh_ok?"color:var(--accent);border-color:var(--accent)":"color:var(--mut)"}`),g(Fe,`🔑 SSH: ${(N=t(p))!=null&&N.ssh_ok?"verbunden":(j=t(p))!=null&&j.ssh_configured?"Fehler":"nicht eingerichtet"}`),$t(ue,`padding:4px 12px;font-size:12px;${t(d)?"border-color:var(--accent);color:var(--accent)":""}`),g(at,`🔊 Voice ${t(d)?"an":"aus"}`),$t(ae,`padding:10px 12px;flex-shrink:0;font-size:18px;line-height:1;
|
||
${t(u)?"border-color:var(--err);color:var(--err)":""}`),Aa(ae,"title",t(u)?"Aufnahme stoppen":"Spracheingabe"),g(A,t(u)?"⏹":"🎤")}),k("click",ue,()=>c(d,!t(d))),k("click",Qe,()=>{c(_,!t(_)),t(_)&&(ve(),ze())}),k("keydown",U,z=>{z.key==="Enter"&&!z.shiftKey&&(z.preventDefault(),M())}),an(U,()=>t(l),z=>c(l,z)),k("mousedown",ae,ke),k("mouseup",ae,Ie),k("touchstart",ae,ke),k("touchend",ae,Ie),f(e,ot),Dn()}qn(["click","keydown","mousedown","mouseup","touchstart","touchend"]);let ts={};function Hv(){const e=document.getElementById("top-active-text");e&&(e.classList.add("swap-flash"),setTimeout(()=>e.classList.remove("swap-flash"),900))}function ns(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"),as("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 v=["running","ready","loading","starting"],d=(e.models||[]).find(p=>v.includes(p.state));if(s)if(d){const p=(l=d.meta)!=null&&l.ctx?` <span style="color:var(--mut);font-size:11.5px">· ${Math.round(d.meta.ctx/1024)}k ctx</span>`:"",_=d.state==="loading"||d.state==="starting"?' <span style="color:var(--warn);font-size:11.5px">lädt…</span>':"";s.innerHTML=`<b style="color:var(--accent)">${d.name}</b>${p}${_}`}else s.innerHTML='<span style="color:var(--mut)">Kein Modell im VRAM</span>';e.swap_ok?Yv():as(`LLM-Engine nicht erreichbar unter <b>${o}</b> – läuft der llama-swap Dienst?`,!0);const u={};for(const p of e.models||[])u[p.name]=p.state;for(const[p,_]of Object.entries(u)){const C=ts[p];if(C&&C!==_&&(_==="running"||_==="loading")){Hv();break}}ts=u}Jv(e),xi.set(e)}function Jv(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 Qv(e){fa.set(e||[])}function Zv(e){Dr.set(e)}function as(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 Yv(){const e=document.getElementById("alert");e&&(e.style.display="none")}const Xv=e=>{var n;return(n=document.querySelector(`.nav-item[data-view="${e}"]`))==null?void 0:n.click()};function nr(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=()=>Xv(a),l}async function al(){try{const e=await De("/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(nr(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(nr(e.engine>0?"Engine: Update":"Engine: aktuell",e.engine>0?"warn":"ok","server")),n.appendChild(nr(e.models>0?`Modelle: ${e.models}`:"Modelle: aktuell",e.models>0?"warn":"ok","news"))}catch{}}async function Wi(){try{ns(await De("/api/status"))}catch{ns(null)}}async function il(){try{Qv(await De("/api/jobs"))}catch{}}function rl(){const e=window.location.protocol==="https:"?"wss:":"ws:",n=new WebSocket(`${e}//${window.location.host}/api/system/stream`);n.onmessage=a=>{try{Zv(JSON.parse(a.data))}catch{}},n.onclose=()=>{setTimeout(rl,3e3)},n.onerror=()=>n.close()}var ds;((ds=document.getElementById("logo"))==null?void 0:ds.innerHTML)!==void 0&&(document.getElementById("logo").innerHTML=Vi.logo);document.querySelectorAll("[data-ic]").forEach(e=>{e.innerHTML=Vi[e.dataset.ic||""]||""});const eu=[["overview",ud],["models",Ad],["activity",Rd],["server",Hd],["cookbook",zc],["connect",Zc],["news",lv],["guides",fv],["memory",Av],["hermes",Uv]];for(const[e,n]of eu){const a=document.querySelector(`.view[data-view="${e}"]`);a&&Mo(n,{target:a})}Uo("overview");const ar=document.getElementById("token");ar&&(ar.value=nl(),ar.addEventListener("change",e=>{qo(e.target.value),Wi()}));const ir=document.getElementById("hf-token");ir&&(ir.value=ci(),ir.addEventListener("change",e=>Wo(e.target.value)));const is=document.getElementById("nav-settings"),rr=document.getElementById("settings-modal"),rs=document.getElementById("sm-close");is&&rr&&rs&&(is.addEventListener("click",()=>rr.style.display="flex"),rs.addEventListener("click",()=>rr.style.display="none"));function tu(){const e=document.getElementById("clock");e&&(e.textContent=new Date().toTimeString().slice(0,5))}document.addEventListener("mc:refresh",Wi);Wi();il();rl();setInterval(tu,1e3);setInterval(Wi,3e3);setInterval(il,1500);al();setInterval(al,6e4);
|