084f92c661
Entschlackt die überladene Seite: statt 3 gestapelter Sektionen zwei Tabs. "Fertige Setups" = (jetzt auto-aktuelle) Bundles; "Modelle finden" bündelt Discover + Profi-Suche (Facetten) unter einem Tab. Nur eine Ansicht zur Zeit. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
666 lines
218 KiB
JavaScript
666 lines
218 KiB
JavaScript
var vl=Object.defineProperty;var Or=e=>{throw TypeError(e)};var ul=(e,n,a)=>n in e?vl(e,n,{enumerable:!0,configurable:!0,writable:!0,value:a}):e[n]=a;var en=(e,n,a)=>ul(e,typeof n!="symbol"?n+"":n,a),Qi=(e,n,a)=>n.has(e)||Or("Cannot "+a);var b=(e,n,a)=>(Qi(e,n,"read from private field"),a?a.call(e):n.get(e)),Ge=(e,n,a)=>n.has(e)?Or("Cannot add the same private member more than once"):n instanceof WeakSet?n.add(e):n.set(e,a),Fe=(e,n,a,s)=>(Qi(e,n,"write to private field"),s?s.call(e,a):n.set(e,a),a),ot=(e,n,a)=>(Qi(e,n,"access private method"),a);var wr=Array.isArray,pl=Array.prototype.indexOf,zi=Array.prototype.includes,Fi=Array.from,fl=Object.defineProperty,Ha=Object.getOwnPropertyDescriptor,hl=Object.getOwnPropertyDescriptors,gl=Object.prototype,ml=Array.prototype,fs=Object.getPrototypeOf,Br=Object.isExtensible;const bl=()=>{};function _l(e){for(var n=0;n<e.length;n++)e[n]()}function hs(){var e,n,a=new Promise((s,l)=>{e=s,n=l});return{promise:a,resolve:e,reject:n}}function En(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 Gt=2,$a=4,Ki=8,gs=1<<24,_n=16,xn=32,Qn=64,dr=128,vn=512,Ft=1024,Nt=2048,Tn=4096,Ut=8192,un=16384,Ba=32768,cr=1<<25,Pa=65536,$i=1<<17,yl=1<<18,Ra=1<<19,xl=1<<20,An=1<<25,pa=65536,Pi=1<<21,ka=1<<22,Jn=1<<23,wa=Symbol("$state"),kl=Symbol(""),Si=Symbol("attributes"),vr=Symbol("class"),ur=Symbol("style"),Ga=Symbol("text"),Mi=Symbol("form reset"),Ni=new class extends Error{constructor(){super(...arguments);en(this,"name","StaleReactionError");en(this,"message","The reaction that called `getAbortSignal()` was re-run or destroyed")}};var cs;const wl=!!((cs=globalThis.document)!=null&&cs.contentType)&&globalThis.document.contentType.includes("xml");function ms(e){throw new Error("https://svelte.dev/e/lifecycle_outside_component")}function Sl(){throw new Error("https://svelte.dev/e/async_derived_orphan")}function Ml(e,n,a){throw new Error("https://svelte.dev/e/each_key_duplicate")}function El(e){throw new Error("https://svelte.dev/e/effect_in_teardown")}function Al(){throw new Error("https://svelte.dev/e/effect_in_unowned_derived")}function Cl(e){throw new Error("https://svelte.dev/e/effect_orphan")}function Tl(){throw new Error("https://svelte.dev/e/effect_update_depth_exceeded")}function zl(){throw new Error("https://svelte.dev/e/state_descriptors_fixed")}function $l(){throw new Error("https://svelte.dev/e/state_prototype_fixed")}function Pl(){throw new Error("https://svelte.dev/e/state_unsafe_mutation")}function Dl(){throw new Error("https://svelte.dev/e/svelte_boundary_reset_onerror")}const Il=1,Ll=2,bs=4,Ol=8,Bl=16,Rl=1,Fl=2,Rt=Symbol("uninitialized"),_s="http://www.w3.org/1999/xhtml",Kl="http://www.w3.org/2000/svg",Nl="http://www.w3.org/1998/Math/MathML";function ql(){console.warn("https://svelte.dev/e/derived_inert")}function Gl(){console.warn("https://svelte.dev/e/select_multiple_invalid_value")}function Vl(){console.warn("https://svelte.dev/e/svelte_boundary_reset_noop")}function ys(e){return e===this.v}function Wl(e,n){return e!=e?n==n:e!==n||e!==null&&typeof e=="object"||typeof e=="function"}function xs(e){return!Wl(e,this.v)}let qt=null;function Da(e){qt=e}function kn(e,n=!1,a){qt={p:qt,i:!1,c:null,e:null,s:e,x:null,r:Xe,l:null}}function wn(e){var n=qt,a=n.e;if(a!==null){n.e=null;for(var s of a)Gs(s)}return n.i=!0,qt=n.p,{}}function ks(){return!0}let Xn=[];function ws(){var e=Xn;Xn=[],_l(e)}function oa(e){if(Xn.length===0&&!Qa){var n=Xn;queueMicrotask(()=>{n===Xn&&ws()})}Xn.push(e)}function jl(){for(;Xn.length>0;)ws()}function Ss(e){var n=Xe;if(n===null)return He.f|=Jn,e;if((n.f&Ba)===0&&(n.f&$a)===0)throw e;Un(e,n)}function Un(e,n){if(!(n!==null&&(n.f&un)!==0)){for(;n!==null;){if((n.f&dr)!==0){if((n.f&Ba)===0)throw e;try{n.b.error(e);return}catch(a){e=a}}n=n.parent}throw e}}const Ul=-7169;function It(e,n){e.f=e.f&Ul|n}function Sr(e){(e.f&vn)!==0||e.deps===null?It(e,Ft):It(e,Tn)}function Ms(e){if(e!==null)for(const n of e)(n.f&Gt)===0||(n.f&pa)===0||(n.f^=pa,Ms(n.deps))}function Es(e,n,a){(e.f&Nt)!==0?n.add(e):(e.f&Tn)!==0&&a.add(e),Ms(e.deps),It(e,Ft)}function Hl(e){let n=0,a=ha(0),s;return()=>{$r()&&(t(a),qi(()=>(n===0&&(s=Fa(()=>e(()=>Za(a)))),n+=1,()=>{oa(()=>{n-=1,n===0&&(s==null||s(),s=void 0,Za(a))})})))}}var Jl=Pa|Ra;function Ql(e,n,a,s){new Zl(e,n,a,s)}var ln,kr,on,aa,Jt,dn,jt,nn,Pn,ia,Wn,Sa,ai,ii,Dn,Oi,$t,Yl,Xl,eo,pr,Ei,Ai,fr,hr;class Zl{constructor(n,a,s,l){Ge(this,$t);en(this,"parent");en(this,"is_pending",!1);en(this,"transform_error");Ge(this,ln);Ge(this,kr,null);Ge(this,on);Ge(this,aa);Ge(this,Jt);Ge(this,dn,null);Ge(this,jt,null);Ge(this,nn,null);Ge(this,Pn,null);Ge(this,ia,0);Ge(this,Wn,0);Ge(this,Sa,!1);Ge(this,ai,new Set);Ge(this,ii,new Set);Ge(this,Dn,null);Ge(this,Oi,Hl(()=>(Fe(this,Dn,ha(b(this,ia))),()=>{Fe(this,Dn,null)})));var o;Fe(this,ln,n),Fe(this,on,a),Fe(this,aa,d=>{var v=Xe;v.b=this,v.f|=dr,s(d)}),this.parent=Xe.b,this.transform_error=l??((o=this.parent)==null?void 0:o.transform_error)??(d=>d),Fe(this,Jt,Pr(()=>{ot(this,$t,pr).call(this)},Jl))}defer_effect(n){Es(n,b(this,ai),b(this,ii))}is_rendered(){return!this.is_pending&&(!this.parent||this.parent.is_rendered())}has_pending_snippet(){return!!b(this,on).pending}update_pending_count(n,a){ot(this,$t,fr).call(this,n,a),Fe(this,ia,b(this,ia)+n),!(!b(this,Dn)||b(this,Sa))&&(Fe(this,Sa,!0),oa(()=>{Fe(this,Sa,!1),b(this,Dn)&&Ia(b(this,Dn),b(this,ia))}))}get_effect_pending(){return b(this,Oi).call(this),t(b(this,Dn))}error(n){if(!b(this,on).onerror&&!b(this,on).failed)throw n;be!=null&&be.is_fork?(b(this,dn)&&be.skip_effect(b(this,dn)),b(this,jt)&&be.skip_effect(b(this,jt)),b(this,nn)&&be.skip_effect(b(this,nn)),be.oncommit(()=>{ot(this,$t,hr).call(this,n)})):ot(this,$t,hr).call(this,n)}}ln=new WeakMap,kr=new WeakMap,on=new WeakMap,aa=new WeakMap,Jt=new WeakMap,dn=new WeakMap,jt=new WeakMap,nn=new WeakMap,Pn=new WeakMap,ia=new WeakMap,Wn=new WeakMap,Sa=new WeakMap,ai=new WeakMap,ii=new WeakMap,Dn=new WeakMap,Oi=new WeakMap,$t=new WeakSet,Yl=function(){try{Fe(this,dn,cn(()=>b(this,aa).call(this,b(this,ln))))}catch(n){this.error(n)}},Xl=function(n){const a=b(this,on).failed;a&&Fe(this,nn,cn(()=>{a(b(this,ln),()=>n,()=>()=>{})}))},eo=function(){const n=b(this,on).pending;n&&(this.is_pending=!0,Fe(this,jt,cn(()=>n(b(this,ln)))),oa(()=>{var a=Fe(this,Pn,document.createDocumentFragment()),s=Bn();a.append(s),Fe(this,dn,ot(this,$t,Ai).call(this,()=>cn(()=>b(this,aa).call(this,s)))),b(this,Wn)===0&&(b(this,ln).before(a),Fe(this,Pn,null),ca(b(this,jt),()=>{Fe(this,jt,null)}),ot(this,$t,Ei).call(this,be))}))},pr=function(){try{if(this.is_pending=this.has_pending_snippet(),Fe(this,Wn,0),Fe(this,ia,0),Fe(this,dn,cn(()=>{b(this,aa).call(this,b(this,ln))})),b(this,Wn)>0){var n=Fe(this,Pn,document.createDocumentFragment());Ir(b(this,dn),n);const a=b(this,on).pending;Fe(this,jt,cn(()=>a(b(this,ln))))}else ot(this,$t,Ei).call(this,be)}catch(a){this.error(a)}},Ei=function(n){this.is_pending=!1,n.transfer_effects(b(this,ai),b(this,ii))},Ai=function(n){var a=Xe,s=He,l=qt;zn(b(this,Jt)),pn(b(this,Jt)),Da(b(this,Jt).ctx);try{return fa.ensure(),n()}catch(o){return Ss(o),null}finally{zn(a),pn(s),Da(l)}},fr=function(n,a){var s;if(!this.has_pending_snippet()){this.parent&&ot(s=this.parent,$t,fr).call(s,n,a);return}Fe(this,Wn,b(this,Wn)+n),b(this,Wn)===0&&(ot(this,$t,Ei).call(this,a),b(this,jt)&&ca(b(this,jt),()=>{Fe(this,jt,null)}),b(this,Pn)&&(b(this,ln).before(b(this,Pn)),Fe(this,Pn,null)))},hr=function(n){b(this,dn)&&(Xt(b(this,dn)),Fe(this,dn,null)),b(this,jt)&&(Xt(b(this,jt)),Fe(this,jt,null)),b(this,nn)&&(Xt(b(this,nn)),Fe(this,nn,null));var a=b(this,on).onerror;let s=b(this,on).failed;var l=!1,o=!1;const d=()=>{if(l){Vl();return}l=!0,o&&Dl(),b(this,nn)!==null&&ca(b(this,nn),()=>{Fe(this,nn,null)}),ot(this,$t,Ai).call(this,()=>{ot(this,$t,pr).call(this)})},v=c=>{try{o=!0,a==null||a(c,d),o=!1}catch(f){Un(f,b(this,Jt)&&b(this,Jt).parent)}s&&Fe(this,nn,ot(this,$t,Ai).call(this,()=>{try{return cn(()=>{var f=Xe;f.b=this,f.f|=dr,s(b(this,ln),()=>c,()=>d)})}catch(f){return Un(f,b(this,Jt).parent),null}}))};oa(()=>{var c;try{c=this.transform_error(n)}catch(f){Un(f,b(this,Jt)&&b(this,Jt).parent);return}c!==null&&typeof c=="object"&&typeof c.then=="function"?c.then(v,f=>Un(f,b(this,Jt)&&b(this,Jt).parent)):v(c)})};function to(e,n,a,s){const l=Mr;var o=e.filter(k=>!k.settled),d=n.map(l);if(a.length===0&&o.length===0){s(d);return}var v=Xe,c=no(),f=o.length===1?o[0].promise:o.length>1?Promise.all(o.map(k=>k.promise)):null;function _(k){if((v.f&un)===0){c();try{s([...d,...k])}catch(I){Un(I,v)}Di()}}var T=As();if(a.length===0){f.then(()=>_([])).finally(T);return}function y(){Promise.all(a.map(k=>ao(k))).then(_).catch(k=>Un(k,v)).finally(T)}f?f.then(()=>{c(),y(),Di()}):y()}function no(){var e=Xe,n=He,a=qt,s=be;return function(o=!0){zn(e),pn(n),Da(a),o&&(e.f&un)===0&&(s==null||s.activate(),s==null||s.apply())}}function Di(e=!0){zn(null),pn(null),Da(null),e&&(be==null||be.deactivate())}function As(){var e=Xe,n=e.b,a=be,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 Mr(e){var n=Gt|Nt;return Xe!==null&&(Xe.f|=Ra),{ctx:qt,deps:null,effects:null,equals:ys,f:n,fn:e,reactions:null,rv:0,v:Rt,wv:0,parent:Xe,ac:null}}const Va=Symbol("obsolete");function ao(e,n,a){let s=Xe;s===null&&Sl();var l=void 0,o=ha(Rt),d=!He,v=new Set;return xo(()=>{var k,I;var c=Xe,f=hs();l=f.promise;try{Promise.resolve(e()).then(f.resolve,K=>{K!==Ni&&f.reject(K)}).finally(Di)}catch(K){f.reject(K),Di()}var _=be;if(d){if((c.f&Ba)!==0)var T=As();if((k=s.b)!=null&&k.is_rendered())(I=_.async_deriveds.get(c))==null||I.reject(Va);else for(const K of v.values())K.reject(Va);v.add(f),_.async_deriveds.set(c,f)}const y=(K,C=void 0)=>{T==null||T(),v.delete(f),C!==Va&&(_.activate(),C?(o.f|=Jn,Ia(o,C)):((o.f&Jn)!==0&&(o.f^=Jn),Ia(o,K)),_.deactivate())};f.promise.then(y,K=>y(null,K||"unknown"))}),qs(()=>{for(const c of v)c.reject(Va)}),new Promise(c=>{function f(_){function T(){_===l?c(o):f(l)}_.then(T,T)}f(l)})}function U(e){const n=Mr(e);return Qs(n),n}function io(e){const n=Mr(e);return n.equals=xs,n}function ro(e){var n=e.effects;if(n!==null){e.effects=null;for(var a=0;a<n.length;a+=1)Xt(n[a])}}function Er(e){var n,a=Xe,s=e.parent;if(!Zn&&s!==null&&e.v!==Rt&&(s.f&(un|Ut))!==0)return ql(),e.v;zn(s);try{e.f&=~pa,ro(e),n=el(e)}finally{zn(a)}return n}function Cs(e){var n=Er(e);if(!e.equals(n)&&(e.wv=Ys(),(!(be!=null&&be.is_fork)||e.deps===null)&&(be!==null?(be.capture(e,n,!0),Ja==null||Ja.capture(e,n,!0)):e.v=n,e.deps===null))){It(e,Ft);return}Zn||(Kt!==null?($r()||be!=null&&be.is_fork)&&Kt.set(e,n):Sr(e))}function so(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=bl),s.ac=null,ti(s,0),Dr(s))}function Ts(e){if(e.effects!==null)for(const n of e.effects)n.teardown&&n.fn!==null&&La(n)}let Zi=null,_a=null,be=null,Ja=null,Kt=null,gr=null,Qa=!1,Yi=!1,xa=null,Ci=null;var Rr=0;let lo=1;var Ma,jn,ra,Ea,Aa,Ca,In,Ta,Qt,ri,Ln,mn,Sn,za,sa,ft,mr,Wa,br,zs,$s,ya,oo,ja;const Bi=class Bi{constructor(){Ge(this,ft);en(this,"id",lo++);Ge(this,Ma,!1);en(this,"linked",!0);Ge(this,jn,null);Ge(this,ra,null);en(this,"async_deriveds",new Map);en(this,"current",new Map);en(this,"previous",new Map);Ge(this,Ea,new Set);Ge(this,Aa,new Set);Ge(this,Ca,0);Ge(this,In,new Map);Ge(this,Ta,null);Ge(this,Qt,[]);Ge(this,ri,[]);Ge(this,Ln,new Set);Ge(this,mn,new Set);Ge(this,Sn,new Map);Ge(this,za,new Set);en(this,"is_fork",!1);Ge(this,sa,!1);_a===null?Zi=_a=this:(Fe(_a,ra,this),Fe(this,jn,_a)),_a=this}skip_effect(n){b(this,Sn).has(n)||b(this,Sn).set(n,{d:[],m:[]}),b(this,za).delete(n)}unskip_effect(n,a=s=>this.schedule(s)){var s=b(this,Sn).get(n);if(s){b(this,Sn).delete(n);for(var l of s.d)It(l,Nt),a(l);for(l of s.m)It(l,Tn),a(l)}b(this,za).add(n)}capture(n,a,s=!1){n.v!==Rt&&!this.previous.has(n)&&this.previous.set(n,n.v),(n.f&Jn)===0&&(this.current.set(n,[a,s]),Kt==null||Kt.set(n,a)),this.is_fork||(n.v=a)}activate(){be=this}deactivate(){be=null,Kt=null}flush(){try{Yi=!0,be=this,ot(this,ft,Wa).call(this)}finally{Rr=0,gr=null,xa=null,Ci=null,Yi=!1,be=null,Kt=null,da.clear()}}discard(){var n;for(const a of b(this,Aa))a(this);b(this,Aa).clear();for(const a of this.async_deriveds.values())a.reject(Va);ot(this,ft,ja).call(this),(n=b(this,Ta))==null||n.resolve()}register_created_effect(n){b(this,ri).push(n)}increment(n,a){if(Fe(this,Ca,b(this,Ca)+1),n){let s=b(this,In).get(a)??0;b(this,In).set(a,s+1)}}decrement(n,a){if(Fe(this,Ca,b(this,Ca)-1),n){let s=b(this,In).get(a)??0;s===1?b(this,In).delete(a):b(this,In).set(a,s-1)}b(this,sa)||(Fe(this,sa,!0),oa(()=>{Fe(this,sa,!1),this.linked&&this.flush()}))}transfer_effects(n,a){for(const s of n)b(this,Ln).add(s);for(const s of a)b(this,mn).add(s);n.clear(),a.clear()}oncommit(n){b(this,Ea).add(n)}ondiscard(n){b(this,Aa).add(n)}settled(){return(b(this,Ta)??Fe(this,Ta,hs())).promise}static ensure(){if(be===null){const n=be=new Bi;!Yi&&!Qa&&oa(()=>{b(n,Ma)||n.flush()})}return be}apply(){{Kt=null;return}}schedule(n){var l;if(gr=n,(l=n.b)!=null&&l.is_pending&&(n.f&($a|Ki|gs))!==0&&(n.f&Ba)===0){n.b.defer_effect(n);return}for(var a=n;a.parent!==null;){a=a.parent;var s=a.f;if(xa!==null&&a===Xe&&(He===null||(He.f&Gt)===0))return;if((s&(Qn|xn))!==0){if((s&Ft)===0)return;a.f^=Ft}}b(this,Qt).push(a)}};Ma=new WeakMap,jn=new WeakMap,ra=new WeakMap,Ea=new WeakMap,Aa=new WeakMap,Ca=new WeakMap,In=new WeakMap,Ta=new WeakMap,Qt=new WeakMap,ri=new WeakMap,Ln=new WeakMap,mn=new WeakMap,Sn=new WeakMap,za=new WeakMap,sa=new WeakMap,ft=new WeakSet,mr=function(){if(this.is_fork)return!0;for(const s of b(this,In).keys()){for(var n=s,a=!1;n.parent!==null;){if(b(this,Sn).has(n)){a=!0;break}n=n.parent}if(!a)return!0}return!1},Wa=function(){var c,f,_,T;Fe(this,Ma,!0),Rr++>1e3&&(ot(this,ft,ja).call(this),vo());for(const y of b(this,Ln))b(this,mn).delete(y),It(y,Nt),this.schedule(y);for(const y of b(this,mn))It(y,Tn),this.schedule(y);const n=b(this,Qt);Fe(this,Qt,[]),this.apply();var a=xa=[],s=[],l=Ci=[];for(const y of n)try{ot(this,ft,br).call(this,y,a,s)}catch(k){throw Is(y),ot(this,ft,mr).call(this)||this.discard(),k}if(be=null,l.length>0){var o=Bi.ensure();for(const y of l)o.schedule(y)}if(xa=null,Ci=null,ot(this,ft,mr).call(this)){ot(this,ft,ya).call(this,s),ot(this,ft,ya).call(this,a);for(const[y,k]of b(this,Sn))Ds(y,k);l.length>0&&ot(c=be,ft,Wa).call(c);return}const d=ot(this,ft,zs).call(this);if(d){ot(this,ft,ya).call(this,s),ot(this,ft,ya).call(this,a),ot(f=d,ft,$s).call(f,this);return}b(this,Ln).clear(),b(this,mn).clear();for(const y of b(this,Ea))y(this);b(this,Ea).clear(),Ja=this,Fr(s),Fr(a),Ja=null,(_=b(this,Ta))==null||_.resolve();var v=be;if(b(this,Ca)===0&&(b(this,Qt).length===0||v!==null)&&ot(this,ft,ja).call(this),b(this,Qt).length>0)if(v!==null){const y=v;b(y,Qt).push(...b(this,Qt).filter(k=>!b(y,Qt).includes(k)))}else v=this;v!==null&&ot(T=v,ft,Wa).call(T)},br=function(n,a,s){n.f^=Ft;for(var l=n.first;l!==null;){var o=l.f,d=(o&(xn|Qn))!==0,v=d&&(o&Ft)!==0,c=v||(o&Ut)!==0||b(this,Sn).has(l);if(!c&&l.fn!==null){d?l.f^=Ft:(o&$a)!==0?a.push(l):ci(l)&&((o&_n)!==0&&b(this,mn).add(l),La(l));var f=l.first;if(f!==null){l=f;continue}}for(;l!==null;){var _=l.next;if(_!==null){l=_;break}l=l.parent}}},zs=function(){for(var n=b(this,jn);n!==null;){if(!n.is_fork){for(const[a,[,s]]of this.current)if(n.current.has(a)&&!s)return n}n=b(n,jn)}return null},$s=function(n){var s;for(const[l,o]of n.current)!this.previous.has(l)&&n.previous.has(l)&&this.previous.set(l,n.previous.get(l)),this.current.set(l,o);for(const[l,o]of n.async_deriveds){const d=this.async_deriveds.get(l);d&&o.promise.then(d.resolve).catch(d.reject)}n.async_deriveds.clear(),this.transfer_effects(b(n,Ln),b(n,mn));const a=l=>{var o=l.reactions;if(o!==null)for(const c of o){var d=c.f;if((d&Gt)!==0)a(c);else{var v=c;d&(ka|_n)&&!this.async_deriveds.has(v)&&(b(this,mn).delete(v),It(v,Nt),this.schedule(v))}}};for(const l of this.current.keys())a(l);this.oncommit(()=>n.discard()),ot(s=n,ft,ja).call(s),be=this,ot(this,ft,Wa).call(this)},ya=function(n){for(var a=0;a<n.length;a+=1)Es(n[a],b(this,Ln),b(this,mn))},oo=function(){var T;for(let y=Zi;y!==null;y=b(y,ra)){var n=y.id<this.id,a=[];for(const[k,[I,K]]of this.current){if(y.current.has(k)){var s=y.current.get(k)[0];if(n&&I!==s)y.current.set(k,[I,K]);else continue}a.push(k)}if(n)for(const[k,I]of this.async_deriveds){const K=y.async_deriveds.get(k);K&&I.promise.then(K.resolve).catch(K.reject)}var l=[...y.current.keys()].filter(k=>!y.current.get(k)[1]);if(!(!b(y,Ma)||l.length===0)){var o=l.filter(k=>!this.current.has(k));if(o.length===0)n&&y.discard();else if(a.length>0){if(n)for(const k of b(this,za))y.unskip_effect(k,I=>{var K;(I.f&(_n|ka))!==0?y.schedule(I):ot(K=y,ft,ya).call(K,[I])});y.activate();var d=new Set,v=new Map;for(var c of a)Ps(c,o,d,v);v=new Map;var f=[...y.current].filter(([k,I])=>{const K=this.current.get(k);return K?K[0]!==I[0]||K[1]!==I[1]:!0}).map(([k])=>k);if(f.length>0)for(const k of b(this,ri))(k.f&(un|Ut|$i))===0&&Ar(k,f,v)&&((k.f&(ka|_n))!==0?(It(k,Nt),y.schedule(k)):b(y,Ln).add(k));if(b(y,Qt).length>0&&!b(y,sa)){y.apply();for(var _ of b(y,Qt))ot(T=y,ft,br).call(T,_,[],[]);Fe(y,Qt,[])}y.deactivate()}}}},ja=function(){if(this.linked){var n=b(this,jn),a=b(this,ra);n===null?Zi=a:Fe(n,ra,a),a===null?_a=n:Fe(a,jn,n),this.linked=!1}};let fa=Bi;function co(e){var n=Qa;Qa=!0;try{for(var a;;){if(jl(),be===null)return a;be.flush()}}finally{Qa=n}}function vo(){try{Tl()}catch(e){Un(e,gr)}}let gn=null;function Fr(e){var n=e.length;if(n!==0){for(var a=0;a<n;){var s=e[a++];if((s.f&(un|Ut))===0&&ci(s)&&(gn=new Set,La(s),s.deps===null&&s.first===null&&s.nodes===null&&s.teardown===null&&s.ac===null&&Us(s),(gn==null?void 0:gn.size)>0)){da.clear();for(const l of gn){if((l.f&(un|Ut))!==0)continue;const o=[l];let d=l.parent;for(;d!==null;)gn.has(d)&&(gn.delete(d),o.push(d)),d=d.parent;for(let v=o.length-1;v>=0;v--){const c=o[v];(c.f&(un|Ut))===0&&La(c)}}gn.clear()}}gn=null}}function Ps(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&Gt)!==0?Ps(l,n,a,s):(o&(ka|_n))!==0&&(o&Nt)===0&&Ar(l,n,s)&&(It(l,Nt),Cr(l))}}function Ar(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&Gt)!==0&&Ar(l,n,a))return a.set(l,!0),!0}return a.set(e,!1),!1}function Cr(e){be.schedule(e)}function Ds(e,n){if(!((e.f&xn)!==0&&(e.f&Ft)!==0)){(e.f&Nt)!==0?n.d.push(e):(e.f&Tn)!==0&&n.m.push(e),It(e,Ft);for(var a=e.first;a!==null;)Ds(a,n),a=a.next}}function Is(e){It(e,Ft);for(var n=e.first;n!==null;)Is(n),n=n.next}let Ii=new Set;const da=new Map;let Ls=!1;function ha(e,n){var a={f:0,v:e,reactions:null,equals:ys,rv:0,wv:0};return a}function F(e,n){const a=ha(e);return Qs(a),a}function uo(e,n=!1,a=!0){const s=ha(e);return n||(s.equals=xs),s}function u(e,n,a=!1){He!==null&&(!yn||(He.f&$i)!==0)&&ks()&&(He.f&(Gt|_n|ka|$i))!==0&&(Cn===null||!Cn.has(e))&&Pl();let s=a?Lt(n):n;return Ia(e,s,Ci)}function Ia(e,n,a=null){if(!e.equals(n)){da.set(e,Zn?n:e.v);var s=fa.ensure();if(s.capture(e,n),(e.f&Gt)!==0){const l=e;(e.f&Nt)!==0&&Er(l),Kt===null&&Sr(l)}e.wv=Ys(),Os(e,Nt,a),Xe!==null&&(Xe.f&Ft)!==0&&(Xe.f&(xn|Qn))===0&&(sn===null?wo([e]):sn.push(e)),!s.is_fork&&Ii.size>0&&!Ls&&po()}return n}function po(){Ls=!1;for(const e of Ii){(e.f&Ft)!==0&&It(e,Tn);let n;try{n=ci(e)}catch{n=!0}n&&La(e)}Ii.clear()}function Za(e){u(e,e.v+1)}function Os(e,n,a){var s=e.reactions;if(s!==null)for(var l=s.length,o=0;o<l;o++){var d=s[o],v=d.f,c=(v&Nt)===0;if(c&&It(d,n),(v&$i)!==0)Ii.add(d);else if((v&Gt)!==0){var f=d;Kt==null||Kt.delete(f),(v&pa)===0&&(v&vn&&(Xe===null||(Xe.f&Pi)===0)&&(d.f|=pa),Os(f,Tn,a))}else if(c){var _=d;(v&_n)!==0&&gn!==null&&gn.add(_),a!==null?a.push(_):Cr(_)}}}function Lt(e){if(typeof e!="object"||e===null||wa in e)return e;const n=fs(e);if(n!==gl&&n!==ml)return e;var a=new Map,s=wr(e),l=F(0),o=va,d=v=>{if(va===o)return v();var c=He,f=va;pn(null),Vr(o);var _=v();return pn(c),Vr(f),_};return s&&a.set("length",F(e.length)),new Proxy(e,{defineProperty(v,c,f){(!("value"in f)||f.configurable===!1||f.enumerable===!1||f.writable===!1)&&zl();var _=a.get(c);return _===void 0?d(()=>{var T=F(f.value);return a.set(c,T),T}):u(_,f.value,!0),!0},deleteProperty(v,c){var f=a.get(c);if(f===void 0){if(c in v){const _=d(()=>F(Rt));a.set(c,_),Za(l)}}else u(f,Rt),Za(l);return!0},get(v,c,f){var k;if(c===wa)return e;var _=a.get(c),T=c in v;if(_===void 0&&(!T||(k=Ha(v,c))!=null&&k.writable)&&(_=d(()=>{var I=Lt(T?v[c]:Rt),K=F(I);return K}),a.set(c,_)),_!==void 0){var y=t(_);return y===Rt?void 0:y}return Reflect.get(v,c,f)},getOwnPropertyDescriptor(v,c){var f=Reflect.getOwnPropertyDescriptor(v,c);if(f&&"value"in f){var _=a.get(c);_&&(f.value=t(_))}else if(f===void 0){var T=a.get(c),y=T==null?void 0:T.v;if(T!==void 0&&y!==Rt)return{enumerable:!0,configurable:!0,value:y,writable:!0}}return f},has(v,c){var y;if(c===wa)return!0;var f=a.get(c),_=f!==void 0&&f.v!==Rt||Reflect.has(v,c);if(f!==void 0||Xe!==null&&(!_||(y=Ha(v,c))!=null&&y.writable)){f===void 0&&(f=d(()=>{var k=_?Lt(v[c]):Rt,I=F(k);return I}),a.set(c,f));var T=t(f);if(T===Rt)return!1}return _},set(v,c,f,_){var Ce;var T=a.get(c),y=c in v;if(s&&c==="length")for(var k=f;k<T.v;k+=1){var I=a.get(k+"");I!==void 0?u(I,Rt):k in v&&(I=d(()=>F(Rt)),a.set(k+"",I))}if(T===void 0)(!y||(Ce=Ha(v,c))!=null&&Ce.writable)&&(T=d(()=>F(void 0)),u(T,Lt(f)),a.set(c,T));else{y=T.v!==Rt;var K=d(()=>Lt(f));u(T,K)}var C=Reflect.getOwnPropertyDescriptor(v,c);if(C!=null&&C.set&&C.set.call(_,f),!y){if(s&&typeof c=="string"){var V=a.get("length"),Ae=Number(c);Number.isInteger(Ae)&&Ae>=V.v&&u(V,Ae+1)}Za(l)}return!0},ownKeys(v){t(l);var c=Reflect.ownKeys(v).filter(T=>{var y=a.get(T);return y===void 0||y.v!==Rt});for(var[f,_]of a)_.v!==Rt&&!(f in v)&&c.push(f);return c},setPrototypeOf(){$l()}})}function Kr(e){try{if(e!==null&&typeof e=="object"&&wa in e)return e[wa]}catch{}return e}function fo(e,n){return Object.is(Kr(e),Kr(n))}var Nr,Bs,Rs,Fs;function ho(){if(Nr===void 0){Nr=window,Bs=/Firefox/.test(navigator.userAgent);var e=Element.prototype,n=Node.prototype,a=Text.prototype;Rs=Ha(n,"firstChild").get,Fs=Ha(n,"nextSibling").get,Br(e)&&(e[vr]=void 0,e[Si]=null,e[ur]=void 0,e.__e=void 0),Br(a)&&(a[Ga]=void 0)}}function Bn(e=""){return document.createTextNode(e)}function Hn(e){return Rs.call(e)}function oi(e){return Fs.call(e)}function r(e,n){return Hn(e)}function Ye(e,n=!1){{var a=Hn(e);return a instanceof Comment&&a.data===""?oi(a):a}}function i(e,n=1,a=!1){let s=e;for(;n--;)s=oi(s);return s}function go(e){e.textContent=""}function Ks(){return!1}function Ns(e,n,a){return n==null||n===_s?a?document.createElement(e,{is:a}):document.createElement(e):a?document.createElementNS(n,e,{is:a}):document.createElementNS(n,e)}let qr=!1;function mo(){qr||(qr=!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 Tr(e){var n=He,a=Xe;pn(null),zn(null);try{return e()}finally{pn(n),zn(a)}}function zr(e,n,a,s=a){e.addEventListener(n,()=>Tr(a));const l=e[Mi];l?e[Mi]=()=>{l(),s(!0)}:e[Mi]=()=>s(!0),mo()}function bo(e){Xe===null&&(He===null&&Cl(),Al()),Zn&&El()}function _o(e,n){var a=n.last;a===null?n.last=n.first=e:(a.next=e,e.prev=a,n.last=e)}function Fn(e,n){var a=Xe;a!==null&&(a.f&Ut)!==0&&(e|=Ut);var s={ctx:qt,deps:null,nodes:null,f:e|Nt|vn,first:null,fn:n,last:null,next:null,parent:a,b:a&&a.b,prev:null,teardown:null,wv:0,ac:null};be==null||be.register_created_effect(s);var l=s;if((e&$a)!==0)xa!==null?xa.push(s):fa.ensure().schedule(s);else if(n!==null){try{La(s)}catch(d){throw Xt(s),d}l.deps===null&&l.teardown===null&&l.nodes===null&&l.first===l.last&&(l.f&Ra)===0&&(l=l.first,(e&_n)!==0&&(e&Pa)!==0&&l!==null&&(l.f|=Pa))}if(l!==null&&(l.parent=a,a!==null&&_o(l,a),He!==null&&(He.f&Gt)!==0&&(e&Qn)===0)){var o=He;(o.effects??(o.effects=[])).push(l)}return s}function $r(){return He!==null&&!yn}function qs(e){const n=Fn(Ki,null);return It(n,Ft),n.teardown=e,n}function di(e){bo();var n=Xe.f,a=!He&&(n&xn)!==0&&qt!==null&&!qt.i;if(a){var s=qt;(s.e??(s.e=[])).push(e)}else return Gs(e)}function Gs(e){return Fn($a|xl,e)}function yo(e){fa.ensure();const n=Fn(Qn|Ra,e);return(a={})=>new Promise(s=>{a.outro?ca(n,()=>{Xt(n),s(void 0)}):(Xt(n),s(void 0))})}function Vs(e){return Fn($a,e)}function xo(e){return Fn(ka|Ra,e)}function qi(e,n=0){return Fn(Ki|n,e)}function $(e,n=[],a=[],s=[]){to(s,n,a,l=>{Fn(Ki,()=>{e(...l.map(t))})})}function Pr(e,n=0){var a=Fn(_n|n,e);return a}function cn(e){return Fn(xn|Ra,e)}function Ws(e){var n=e.teardown;if(n!==null){const a=Zn,s=He;Gr(!0),pn(null);try{n.call(null)}finally{Gr(a),pn(s)}}}function Dr(e,n=!1){var a=e.first;for(e.first=e.last=null;a!==null;){const l=a.ac;l!==null&&Tr(()=>{l.abort(Ni)});var s=a.next;(a.f&Qn)!==0?a.parent=null:Xt(a,n),a=s}}function ko(e){for(var n=e.first;n!==null;){var a=n.next;(n.f&xn)===0&&Xt(n),n=a}}function Xt(e,n=!0){var a=!1;(n||(e.f&yl)!==0)&&e.nodes!==null&&e.nodes.end!==null&&(js(e.nodes.start,e.nodes.end),a=!0),e.f|=cr,Dr(e,n&&!a),ti(e,0);var s=e.nodes&&e.nodes.t;if(s!==null)for(const o of s)o.stop();Ws(e),e.f^=cr,e.f|=un;var l=e.parent;l!==null&&l.first!==null&&Us(e),e.next=e.prev=e.teardown=e.ctx=e.deps=e.fn=e.nodes=e.ac=e.b=null}function js(e,n){for(;e!==null;){var a=e===n?null:oi(e);e.remove(),e=a}}function Us(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 ca(e,n,a=!0){var s=[];Hs(e,s,!0);var l=()=>{a&&Xt(e),n&&n()},o=s.length;if(o>0){var d=()=>--o||l();for(var v of s)v.out(d)}else l()}function Hs(e,n,a){if((e.f&Ut)===0){e.f^=Ut;var s=e.nodes&&e.nodes.t;if(s!==null)for(const v of s)(v.is_global||a)&&n.push(v);for(var l=e.first;l!==null;){var o=l.next;if((l.f&Qn)===0){var d=(l.f&Pa)!==0||(l.f&xn)!==0&&(e.f&_n)!==0;Hs(l,n,d?a:!1)}l=o}}}function Li(e){Js(e,!0)}function Js(e,n){if((e.f&Ut)!==0){e.f^=Ut,(e.f&Ft)===0&&(It(e,Nt),fa.ensure().schedule(e));for(var a=e.first;a!==null;){var s=a.next,l=(a.f&Pa)!==0||(a.f&xn)!==0;Js(a,l?n:!1),a=s}var o=e.nodes&&e.nodes.t;if(o!==null)for(const d of o)(d.is_global||n)&&d.in()}}function Ir(e,n){if(e.nodes)for(var a=e.nodes.start,s=e.nodes.end;a!==null;){var l=a===s?null:oi(a);n.append(a),a=l}}let Ti=!1,Zn=!1;function Gr(e){Zn=e}let He=null,yn=!1;function pn(e){He=e}let Xe=null;function zn(e){Xe=e}let Cn=null;function Qs(e){He!==null&&(Cn??(Cn=new Set)).add(e)}let Zt=null,tn=0,sn=null;function wo(e){sn=e}let Zs=1,ea=0,va=ea;function Vr(e){va=e}function Ys(){return++Zs}function ci(e){var n=e.f;if((n&Nt)!==0)return!0;if(n&Gt&&(e.f&=~pa),(n&Tn)!==0){for(var a=e.deps,s=a.length,l=0;l<s;l++){var o=a[l];if(ci(o)&&Cs(o),o.wv>e.wv)return!0}(n&vn)!==0&&Kt===null&&It(e,Ft)}return!1}function Xs(e,n,a=!0){var s=e.reactions;if(s!==null&&!(Cn!==null&&Cn.has(e)))for(var l=0;l<s.length;l++){var o=s[l];(o.f&Gt)!==0?Xs(o,n,!1):n===o&&(a?It(o,Nt):(o.f&Ft)!==0&&It(o,Tn),Cr(o))}}function el(e){var K;var n=Zt,a=tn,s=sn,l=He,o=Cn,d=qt,v=yn,c=va,f=e.f;Zt=null,tn=0,sn=null,He=(f&(xn|Qn))===0?e:null,Cn=null,Da(e.ctx),yn=!1,va=++ea,e.ac!==null&&(Tr(()=>{e.ac.abort(Ni)}),e.ac=null);try{e.f|=Pi;var _=e.fn,T=_();e.f|=Ba;var y=e.deps,k=be==null?void 0:be.is_fork;if(Zt!==null){var I;if(k||ti(e,tn),y!==null&&tn>0)for(y.length=tn+Zt.length,I=0;I<Zt.length;I++)y[tn+I]=Zt[I];else e.deps=y=Zt;if($r()&&(e.f&vn)!==0)for(I=tn;I<y.length;I++)((K=y[I]).reactions??(K.reactions=[])).push(e)}else!k&&y!==null&&tn<y.length&&(ti(e,tn),y.length=tn);if(ks()&&sn!==null&&!yn&&y!==null&&(e.f&(Gt|Tn|Nt))===0)for(I=0;I<sn.length;I++)Xs(sn[I],e);if(l!==null&&l!==e){if(ea++,l.deps!==null)for(let C=0;C<a;C+=1)l.deps[C].rv=ea;if(n!==null)for(const C of n)C.rv=ea;sn!==null&&(s===null?s=sn:s.push(...sn))}return(e.f&Jn)!==0&&(e.f^=Jn),T}catch(C){return Ss(C)}finally{e.f^=Pi,Zt=n,tn=a,sn=s,He=l,Cn=o,Da(d),yn=v,va=c}}function So(e,n){let a=n.reactions;if(a!==null){var s=pl.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&Gt)!==0&&(Zt===null||!zi.call(Zt,n))){var o=n;(o.f&vn)!==0&&(o.f^=vn,o.f&=~pa),o.v!==Rt&&Sr(o),so(o),ti(o,0)}}function ti(e,n){var a=e.deps;if(a!==null)for(var s=n;s<a.length;s++)So(e,a[s])}function La(e){var n=e.f;if((n&un)===0){It(e,Ft);var a=Xe,s=Ti;Xe=e,Ti=!0;try{(n&(_n|gs))!==0?ko(e):Dr(e),Ws(e);var l=el(e);e.teardown=typeof l=="function"?l:null,e.wv=Zs;var o}finally{Ti=s,Xe=a}}}async function Mo(){await Promise.resolve(),co()}function t(e){var n=e.f,a=(n&Gt)!==0;if(He!==null&&!yn){var s=Xe!==null&&(Xe.f&un)!==0;if(!s&&(Cn===null||!Cn.has(e))){var l=He.deps;if((He.f&Pi)!==0)e.rv<ea&&(e.rv=ea,Zt===null&&l!==null&&l[tn]===e?tn++:Zt===null?Zt=[e]:Zt.push(e));else{He.deps??(He.deps=[]),zi.call(He.deps,e)||He.deps.push(e);var o=e.reactions;o===null?e.reactions=[He]:zi.call(o,He)||o.push(He)}}}if(Zn&&da.has(e))return da.get(e);if(a){var d=e;if(Zn){var v=d.v;return((d.f&Ft)===0&&d.reactions!==null||nl(d))&&(v=Er(d)),da.set(d,v),v}var c=(d.f&vn)===0&&!yn&&He!==null&&(Ti||(He.f&vn)!==0),f=(d.f&Ba)===0;ci(d)&&(c&&(d.f|=vn),Cs(d)),c&&!f&&(Ts(d),tl(d))}if(Kt!=null&&Kt.has(e))return Kt.get(e);if((e.f&Jn)!==0)throw e.v;return e.v}function tl(e){if(e.f|=vn,e.deps!==null)for(const n of e.deps)(n.reactions??(n.reactions=[])).push(e),(n.f&Gt)!==0&&(n.f&vn)===0&&(Ts(n),tl(n))}function nl(e){if(e.v===Rt)return!0;if(e.deps===null)return!1;for(const n of e.deps)if(da.has(n)||(n.f&Gt)!==0&&nl(n))return!0;return!1}function Fa(e){var n=yn;try{return yn=!0,e()}finally{yn=n}}const Eo=["touchstart","touchmove"];function Ao(e){return Eo.includes(e)}const ta=Symbol("events"),al=new Set,_r=new Set;function S(e,n,a){(n[ta]??(n[ta]={}))[e]=a}function $n(e){for(var n=0;n<e.length;n++)al.add(e[n]);for(var a of _r)a(e)}let Wr=null;function jr(e){var K,C;var n=this,a=n.ownerDocument,s=e.type,l=((K=e.composedPath)==null?void 0:K.call(e))||[],o=l[0]||e.target;Wr=e;var d=0,v=Wr===e&&e[ta];if(v){var c=l.indexOf(v);if(c!==-1&&(n===document||n===window)){e[ta]=n;return}var f=l.indexOf(n);if(f===-1)return;c<=f&&(d=c)}if(o=l[d]||e.target,o!==n){fl(e,"currentTarget",{configurable:!0,get(){return o||a}});var _=He,T=Xe;pn(null),zn(null);try{for(var y,k=[];o!==null&&o!==n;){try{var I=(C=o[ta])==null?void 0:C[s];I!=null&&(!o.disabled||e.target===o)&&I.call(o,e)}catch(V){y?k.push(V):y=V}if(e.cancelBubble)break;d++,o=d<l.length?l[d]:null}if(y){for(let V of k)queueMicrotask(()=>{throw V});throw y}}finally{e[ta]=n,delete e.currentTarget,pn(_),zn(T)}}}var vs;const Xi=((vs=globalThis==null?void 0:globalThis.window)==null?void 0:vs.trustedTypes)&&globalThis.window.trustedTypes.createPolicy("svelte-trusted-html",{createHTML:e=>e});function Co(e){return(Xi==null?void 0:Xi.createHTML(e))??e}function To(e){var n=Ns("template");return n.innerHTML=Co(e.replaceAll("<!>","<!---->")),n.content}function Oa(e,n){var a=Xe;a.nodes===null&&(a.nodes={start:e,end:n,a:null,t:null})}function g(e,n){var a=(n&Rl)!==0,s=(n&Fl)!==0,l,o=!e.startsWith("<!>");return()=>{l===void 0&&(l=To(o?e:"<!>"+e),a||(l=Hn(l)));var d=s||Bs?document.importNode(l,!0):l.cloneNode(!0);if(a){var v=Hn(d),c=d.lastChild;Oa(v,c)}else Oa(d,d);return d}}function Ya(e=""){{var n=Bn(e+"");return Oa(n,n),n}}function ua(){var e=document.createDocumentFragment(),n=document.createComment(""),a=Bn();return e.append(n,a),Oa(n,a),e}function p(e,n){e!==null&&e.before(n)}function h(e,n){var a=n==null?"":typeof n=="object"?`${n}`:n;a!==(e[Ga]??(e[Ga]=e.nodeValue))&&(e[Ga]=a,e.nodeValue=`${a}`)}function zo(e,n){return $o(e,n)}const wi=new Map;function $o(e,{target:n,anchor:a,props:s={},events:l,context:o,intro:d=!0,transformError:v}){ho();var c=void 0,f=yo(()=>{var _=a??n.appendChild(Bn());Ql(_,{pending:()=>{}},k=>{kn({});var I=qt;o&&(I.c=o),l&&(s.$$events=l),c=e(k,s)||{},wn()},v);var T=new Set,y=k=>{for(var I=0;I<k.length;I++){var K=k[I];if(!T.has(K)){T.add(K);var C=Ao(K);for(const Ce of[n,document]){var V=wi.get(Ce);V===void 0&&(V=new Map,wi.set(Ce,V));var Ae=V.get(K);Ae===void 0?(Ce.addEventListener(K,jr,{passive:C}),V.set(K,1)):V.set(K,Ae+1)}}}};return y(Fi(al)),_r.add(y),()=>{var C;for(var k of T)for(const V of[n,document]){var I=wi.get(V),K=I.get(k);--K==0?(V.removeEventListener(k,jr),I.delete(k),I.size===0&&wi.delete(V)):I.set(k,K)}_r.delete(y),_!==a&&((C=_.parentNode)==null||C.removeChild(_))}});return Po.set(c,f),c}let Po=new WeakMap;var bn,Mn,an,la,si,li,Ri;class Do{constructor(n,a=!0){en(this,"anchor");Ge(this,bn,new Map);Ge(this,Mn,new Map);Ge(this,an,new Map);Ge(this,la,new Set);Ge(this,si,!0);Ge(this,li,n=>{if(b(this,bn).has(n)){var a=b(this,bn).get(n),s=b(this,Mn).get(a);if(s)Li(s),b(this,la).delete(a);else{var l=b(this,an).get(a);l&&(Li(l.effect),b(this,Mn).set(a,l.effect),b(this,an).delete(a),l.fragment.lastChild.remove(),this.anchor.before(l.fragment),s=l.effect)}for(const[o,d]of b(this,bn)){if(b(this,bn).delete(o),o===n)break;const v=b(this,an).get(d);v&&(Xt(v.effect),b(this,an).delete(d))}for(const[o,d]of b(this,Mn)){if(o===a||b(this,la).has(o))continue;const v=()=>{if(Array.from(b(this,bn).values()).includes(o)){var f=document.createDocumentFragment();Ir(d,f),f.append(Bn()),b(this,an).set(o,{effect:d,fragment:f})}else Xt(d);b(this,la).delete(o),b(this,Mn).delete(o)};b(this,si)||!s?(b(this,la).add(o),ca(d,v,!1)):v()}}});Ge(this,Ri,n=>{b(this,bn).delete(n);const a=Array.from(b(this,bn).values());for(const[s,l]of b(this,an))a.includes(s)||(Xt(l.effect),b(this,an).delete(s))});this.anchor=n,Fe(this,si,a)}ensure(n,a){var s=be,l=Ks();if(a&&!b(this,Mn).has(n)&&!b(this,an).has(n))if(l){var o=document.createDocumentFragment(),d=Bn();o.append(d),b(this,an).set(n,{effect:cn(()=>a(d)),fragment:o})}else b(this,Mn).set(n,cn(()=>a(this.anchor)));if(b(this,bn).set(s,n),l){for(const[v,c]of b(this,Mn))v===n?s.unskip_effect(c):s.skip_effect(c);for(const[v,c]of b(this,an))v===n?s.unskip_effect(c.effect):s.skip_effect(c.effect);s.oncommit(b(this,li)),s.ondiscard(b(this,Ri))}else b(this,li).call(this,s)}}bn=new WeakMap,Mn=new WeakMap,an=new WeakMap,la=new WeakMap,si=new WeakMap,li=new WeakMap,Ri=new WeakMap;function O(e,n,a=!1){var s=new Do(e),l=a?Pa:0;function o(d,v){s.ensure(d,v)}Pr(()=>{var d=!1;n((v,c=0)=>{d=!0,o(c,v)}),d||o(-1,null)},l)}function nt(e,n){return n}function Io(e,n,a){for(var s=[],l=n.length,o,d=n.length,v=0;v<l;v++){let T=n[v];ca(T,()=>{if(o){if(o.pending.delete(T),o.done.add(T),o.pending.size===0){var y=e.outrogroups;yr(e,Fi(o.done)),y.delete(o),y.size===0&&(e.outrogroups=null)}}else d-=1},!1)}if(d===0){var c=s.length===0&&a!==null;if(c){var f=a,_=f.parentNode;go(_),_.append(f),e.items.clear()}yr(e,n,!c)}else o={pending:new Set(n),done:new Set},(e.outrogroups??(e.outrogroups=new Set)).add(o)}function yr(e,n,a=!0){var s;if(e.pending.size>0){s=new Set;for(const d of e.pending.values())for(const v of d)s.add(e.items.get(v).e)}for(var l=0;l<n.length;l++){var o=n[l];if(s!=null&&s.has(o)){o.f|=An;const d=document.createDocumentFragment();Ir(o,d)}else Xt(n[l],a)}}var Ur;function Ze(e,n,a,s,l,o=null){var d=e,v=new Map,c=(n&bs)!==0;if(c){var f=e;d=f.appendChild(Bn())}var _=null,T=io(()=>{var Ce=a();return wr(Ce)?Ce:Ce==null?[]:Fi(Ce)}),y,k=new Map,I=!0;function K(Ce){(Ae.effect.f&un)===0&&(Ae.pending.delete(Ce),Ae.fallback=_,Lo(Ae,y,d,n,s),_!==null&&(y.length===0?(_.f&An)===0?Li(_):(_.f^=An,Ua(_,null,d)):ca(_,()=>{_=null})))}function C(Ce){Ae.pending.delete(Ce)}var V=Pr(()=>{y=t(T);for(var Ce=y.length,Be=new Set,De=be,se=Ks(),le=0;le<Ce;le+=1){var $e=y[le],Te=s($e,le),We=I?null:v.get(Te);We?(We.v&&Ia(We.v,$e),We.i&&Ia(We.i,le),se&&De.unskip_effect(We.e)):(We=Oo(v,I?d:Ur??(Ur=Bn()),$e,Te,le,l,n,a),I||(We.e.f|=An),v.set(Te,We)),Be.add(Te)}if(Ce===0&&o&&!_&&(I?_=cn(()=>o(d)):(_=cn(()=>o(Ur??(Ur=Bn()))),_.f|=An)),Ce>Be.size&&Ml(),!I)if(k.set(De,Be),se){for(const[rt,Je]of v)Be.has(rt)||De.skip_effect(Je.e);De.oncommit(K),De.ondiscard(C)}else K(De);t(T)}),Ae={effect:V,items:v,pending:k,outrogroups:null,fallback:_};I=!1}function qa(e){for(;e!==null&&(e.f&xn)===0;)e=e.next;return e}function Lo(e,n,a,s,l){var We,rt,Je,R,_e,Re,at,Q,de;var o=(s&Ol)!==0,d=n.length,v=e.items,c=qa(e.effect.first),f,_=null,T,y=[],k=[],I,K,C,V;if(o)for(V=0;V<d;V+=1)I=n[V],K=l(I,V),C=v.get(K).e,(C.f&An)===0&&((rt=(We=C.nodes)==null?void 0:We.a)==null||rt.measure(),(T??(T=new Set)).add(C));for(V=0;V<d;V+=1){if(I=n[V],K=l(I,V),C=v.get(K).e,e.outrogroups!==null)for(const xe of e.outrogroups)xe.pending.delete(C),xe.done.delete(C);if((C.f&Ut)!==0&&(Li(C),o&&((R=(Je=C.nodes)==null?void 0:Je.a)==null||R.unfix(),(T??(T=new Set)).delete(C))),(C.f&An)!==0)if(C.f^=An,C===c)Ua(C,null,a);else{var Ae=_?_.next:c;C===e.effect.last&&(e.effect.last=C.prev),C.prev&&(C.prev.next=C.next),C.next&&(C.next.prev=C.prev),qn(e,_,C),qn(e,C,Ae),Ua(C,Ae,a),_=C,y=[],k=[],c=qa(_.next);continue}if(C!==c){if(f!==void 0&&f.has(C)){if(y.length<k.length){var Ce=k[0],Be;_=Ce.prev;var De=y[0],se=y[y.length-1];for(Be=0;Be<y.length;Be+=1)Ua(y[Be],Ce,a);for(Be=0;Be<k.length;Be+=1)f.delete(k[Be]);qn(e,De.prev,se.next),qn(e,_,De),qn(e,se,Ce),c=Ce,_=se,V-=1,y=[],k=[]}else f.delete(C),Ua(C,c,a),qn(e,C.prev,C.next),qn(e,C,_===null?e.effect.first:_.next),qn(e,_,C),_=C;continue}for(y=[],k=[];c!==null&&c!==C;)(f??(f=new Set)).add(c),k.push(c),c=qa(c.next);if(c===null)continue}(C.f&An)===0&&y.push(C),_=C,c=qa(C.next)}if(e.outrogroups!==null){for(const xe of e.outrogroups)xe.pending.size===0&&(yr(e,Fi(xe.done)),(_e=e.outrogroups)==null||_e.delete(xe));e.outrogroups.size===0&&(e.outrogroups=null)}if(c!==null||f!==void 0){var le=[];if(f!==void 0)for(C of f)(C.f&Ut)===0&&le.push(C);for(;c!==null;)(c.f&Ut)===0&&c!==e.fallback&&le.push(c),c=qa(c.next);var $e=le.length;if($e>0){var Te=(s&bs)!==0&&d===0?a:null;if(o){for(V=0;V<$e;V+=1)(at=(Re=le[V].nodes)==null?void 0:Re.a)==null||at.measure();for(V=0;V<$e;V+=1)(de=(Q=le[V].nodes)==null?void 0:Q.a)==null||de.fix()}Io(e,le,Te)}}o&&oa(()=>{var xe,et;if(T!==void 0)for(C of T)(et=(xe=C.nodes)==null?void 0:xe.a)==null||et.apply()})}function Oo(e,n,a,s,l,o,d,v){var c=(d&Il)!==0?(d&Bl)===0?uo(a,!1,!1):ha(a):null,f=(d&Ll)!==0?ha(l):null;return{v:c,i:f,e:cn(()=>(o(n,c??a,f??l,v),()=>{e.delete(s)}))}}function Ua(e,n,a){if(e.nodes)for(var s=e.nodes.start,l=e.nodes.end,o=n&&(n.f&An)===0?n.nodes.start:a;s!==null;){var d=oi(s);if(o.before(s),s===l)return;s=d}}function qn(e,n,a){n===null?e.effect.first=a:n.next=a,a===null?e.effect.last=n:a.prev=n}function lt(e,n,a=!1,s=!1,l=!1,o=!1){var d=e,v="";if(a)var c=e;$(()=>{var f=Xe;if(v!==(v=n()??"")){if(a){f.nodes=null,c.innerHTML=v,v!==""&&Oa(Hn(c),c.lastChild);return}if(f.nodes!==null&&(js(f.nodes.start,f.nodes.end),f.nodes=null),v!==""){var _=s?Kl:l?Nl:void 0,T=Ns(s?"svg":l?"math":"template",_);T.innerHTML=v;var y=s||l?T:T.content;if(Oa(Hn(y),y.lastChild),s||l)for(;Hn(y);)d.before(Hn(y));else d.before(y)}}})}function Bo(e,n,a){var s=e==null?"":""+e;return n&&(s=s?s+" "+n:n),s===""?null:s}function Ro(e,n){return e==null?null:String(e)}function bt(e,n,a,s,l,o){var d=e[vr];if(d!==a||d===void 0){var v=Bo(a,s);v==null?e.removeAttribute("class"):e.className=v,e[vr]=a}return o}function St(e,n,a,s){var l=e[ur];if(l!==n){var o=Ro(n);o==null?e.removeAttribute("style"):e.style.cssText=o,e[ur]=n}return s}function il(e,n,a=!1){if(e.multiple){if(n==null)return;if(!wr(n))return Gl();for(var s of e.options)s.selected=n.includes(Xa(s));return}for(s of e.options){var l=Xa(s);if(fo(l,n)){s.selected=!0;return}}(!a||n!==void 0)&&(e.selectedIndex=-1)}function Fo(e){var n=new MutationObserver(()=>{il(e,e.__value)});n.observe(e,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["value"]}),qs(()=>{n.disconnect()})}function On(e,n,a=n){var s=new WeakSet,l=!0;zr(e,"change",o=>{var d=o?"[selected]":":checked",v;if(e.multiple)v=[].map.call(e.querySelectorAll(d),Xa);else{var c=e.querySelector(d)??e.querySelector("option:not([disabled])");v=c&&Xa(c)}a(v),e.__value=v,be!==null&&s.add(be)}),Vs(()=>{var o=n();if(e===document.activeElement){var d=be;if(s.has(d))return}if(il(e,o,l),l&&o===void 0){var v=e.querySelector(":checked");v!==null&&(o=Xa(v),a(o))}e.__value=o,l=!1}),Fo(e)}function Xa(e){return"__value"in e?e.__value:e.value}const Ko=Symbol("is custom element"),No=Symbol("is html"),qo=wl?"progress":"PROGRESS";function Gn(e,n){var a=rl(e);a.value===(a.value=n??void 0)||e.value===n&&(n!==0||e.nodeName!==qo)||(e.value=n??"")}function ga(e,n,a,s){var l=rl(e);l[n]!==(l[n]=a)&&(n==="loading"&&(e[kl]=a),a==null?e.removeAttribute(n):typeof a!="string"&&Go(e).includes(n)?e[n]=a:e.setAttribute(n,a))}function rl(e){return e[Si]??(e[Si]={[Ko]:e.nodeName.includes("-"),[No]:e.namespaceURI===_s})}var Hr=new Map;function Go(e){var n=e.getAttribute("is")||e.nodeName,a=Hr.get(n);if(a)return a;Hr.set(n,a=[]);for(var s,l=e,o=Element.prototype;o!==l;){s=hl(l);for(var d in s)s[d].set&&d!=="innerHTML"&&d!=="textContent"&&d!=="innerText"&&a.push(d);l=fs(l)}return a}function Yt(e,n,a=n){var s=new WeakSet;zr(e,"input",async l=>{var o=l?e.defaultValue:e.value;if(o=er(e)?tr(o):o,a(o),be!==null&&s.add(be),await Mo(),o!==(o=n())){var d=e.selectionStart,v=e.selectionEnd,c=e.value.length;if(e.value=o??"",v!==null){var f=e.value.length;d===v&&v===c&&f>c?(e.selectionStart=f,e.selectionEnd=f):(e.selectionStart=d,e.selectionEnd=Math.min(v,f))}}}),Fa(n)==null&&e.value&&(a(er(e)?tr(e.value):e.value),be!==null&&s.add(be)),qi(()=>{var l=n();if(e===document.activeElement){var o=be;if(s.has(o))return}er(e)&&l===tr(e.value)||e.type==="date"&&!l&&!e.value||l!==e.value&&(e.value=l??"")})}function Vo(e,n,a=n){zr(e,"change",s=>{var l=s?e.defaultChecked:e.checked;a(l)}),Fa(n)==null&&a(e.checked),qi(()=>{var s=n();e.checked=!!s})}function er(e){var n=e.type;return n==="number"||n==="range"}function tr(e){return e===""?null:+e}function nr(e,n){return e===n||(e==null?void 0:e[wa])===n}function Wo(e={},n,a,s){var l=qt.r,o=Xe;return Vs(()=>{var d,v;return qi(()=>{d=v,v=[],Fa(()=>{nr(a(...v),e)||(n(e,...v),d&&nr(a(...d),e)&&n(null,...d))})}),()=>{let c=o;for(;c!==l&&c.parent!==null&&c.parent.f&cr;)c=c.parent;const f=()=>{v&&nr(a(...v),e)&&n(null,...v)},_=c.teardown;c.teardown=()=>{f(),_==null||_()}}}),e}function vi(e){qt===null&&ms(),di(()=>{const n=Fa(e);if(typeof n=="function")return n})}function jo(e){qt===null&&ms(),vi(()=>()=>Fa(e))}let ni=localStorage.getItem("mc_token")||"";function sl(){return ni}function Uo(e){ni=(e||"").trim(),localStorage.setItem("mc_token",ni)}function Ho(){const e={"Content-Type":"application/json"};return ni&&(e["X-MC-Token"]=ni),e}function ei(){return localStorage.getItem("mc_hf_token")||""}function Jo(e){localStorage.setItem("mc_hf_token",(e||"").trim())}async function Se(e,n={}){const a=await fetch(e,{headers:Ho(),...n}),s=await a.json().catch(()=>({}));if(!a.ok)throw new Error(s.error||"HTTP "+a.status);return s}const Qo=(e,n=document)=>n.querySelector(e),Jr=(e,n=document)=>[...n.querySelectorAll(e)];function Rn(e){return String(e??"").replace(/[&<>]/g,n=>({"&":"&","<":"<",">":">"})[n])}let Qr;function he(e,n=!1){const a=Qo("#toast");a&&(a.textContent=e,a.className="toast show"+(n?" err":""),clearTimeout(Qr),Qr=setTimeout(()=>a.className="toast",3200))}function Zo(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 pt=e=>`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round">${e}</svg>`,Gi={logo:pt('<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:pt('<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:pt('<rect x="6" y="6" width="12" height="12" rx="2"/><path d="M9 1v3M15 1v3M9 20v3M15 20v3M1 9h3M1 15h3M20 9h3M20 15h3"/>'),pulse:pt('<path d="M3 12h4l2 6 4-14 2 8h6"/>'),server:pt('<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:pt('<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:pt('<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:pt('<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:pt('<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:pt('<rect x="3" y="4" width="18" height="12" rx="2"/><path d="M8 20h8M12 16v4"/>'),layers:pt('<path d="m12 2 9 5-9 5-9-5z"/><path d="m3 12 9 5 9-5M3 17l9 5 9-5"/>'),alert:pt('<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:pt('<path d="M12 14 16 9"/><circle cx="12" cy="13" r="9"/><path d="M12 4v2M21 13h-2M5 13H3"/>'),search:pt('<circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/>'),compass:pt('<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:pt('<polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/>'),eye:pt('<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:pt('<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:pt('<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:pt('<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:pt('<path d="M14 14.76V5a2 2 0 0 0-4 0v9.76a4 4 0 1 0 4 0z"/>'),shield:pt('<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:pt('<circle cx="12" cy="12" r="9"/><path d="M12 16v-4M12 8h.01"/>'),chevron:pt('<path d="m9 6 6 6-6 6"/>'),bolt:pt('<path d="M13 2 3 14h7l-1 8 10-12h-7z"/>'),x:pt('<path d="M18 6 6 18M6 6l12 12"/>'),check:pt('<path d="M20 6 9 17l-5-5"/>'),download:pt('<path d="M12 3v12M7 10l5 5 5-5"/><path d="M5 21h14"/>'),clock:pt('<circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/>')};function Bt(e){return Gi[e]||""}function xr(e){return`<span class="info-dot" tabindex="0" title="${Rn(e)}" aria-label="${Rn(e)}">${Gi.info}</span>`}function Yn(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 rn({title:e,body:n,confirmLabel:a="Bestätigen",cancelLabel:s="Abbrechen",danger:l=!1}){return new Promise(o=>{const d=document.createElement("div");d.className="modal-overlay",d.innerHTML=`<div class="modal-card" role="dialog" aria-modal="true">
|
||
<h3>${Rn(e)}</h3>
|
||
<p>${n}</p>
|
||
<div class="modal-actions">
|
||
<button data-x="0">${Rn(s)}</button>
|
||
<button class="${l?"danger":"primary"}" data-x="1">${Rn(a)}</button>
|
||
</div></div>`;const v=c=>{d.remove(),o(c)};d.addEventListener("click",c=>{if(c.target===d)return v(!1);const f=c.target.closest("[data-x]");f&&v(f.getAttribute("data-x")==="1")}),document.body.appendChild(d),d.querySelector('[data-x="1"]').focus()})}function ar({title:e,body:n="",placeholder:a="",password:s=!1,confirmLabel:l="Weiter",danger:o=!1}){return new Promise(d=>{const v=document.createElement("div");v.className="modal-overlay",v.innerHTML=`<div class="modal-card" role="dialog" aria-modal="true">
|
||
<h3>${Rn(e)}</h3>
|
||
${n?`<p>${n}</p>`:""}
|
||
<input type="${s?"password":"text"}" placeholder="${Rn(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">${Rn(l)}</button>
|
||
</div></div>`;const c=v.querySelector("input"),f=_=>{v.remove(),d(_)};v.addEventListener("click",_=>{if(_.target===v)return f(null);const T=_.target.closest("[data-x]");T&&f(T.getAttribute("data-x")==="1"?c.value||"":null)}),c.addEventListener("keydown",_=>{_.key==="Enter"&&f(c.value||""),_.key==="Escape"&&f(null)}),document.body.appendChild(v),c.focus()})}function Yo(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(d=>d.hidden=d.dataset.view!==o),n.forEach(d=>d.classList.toggle("active",d.dataset.view===o)),location.hash!=="#/"+o&&(location.hash="#/"+o)}return n.forEach(o=>o.addEventListener("click",d=>{d.preventDefault(),l(o.dataset.view)})),window.addEventListener("hashchange",()=>l(location.hash.replace("#/",""))),l(location.hash.replace("#/","")||e),{show:l}}let Zr=F(null);const ui={get value(){return t(Zr)},set(e){u(Zr,e,!0)}};let Yr=F(Lt([])),Vn=F(Lt([]));const na={get value(){return t(Yr)},set(e){u(Yr,e||[],!0)},get tracked(){return t(Vn)},track(e){t(Vn).includes(e)||u(Vn,[...t(Vn),e],!0)},toggle(e){u(Vn,t(Vn).includes(e)?t(Vn).filter(n=>n!==e):[...t(Vn),e],!0)}};let Xr=F(null);const Lr={get value(){return t(Xr)},set(e){u(Xr,e,!0)}},Xo="5";var us;typeof window<"u"&&((us=window.__svelte??(window.__svelte={})).v??(us.v=new Set)).add(Xo);var ed=g('<span style="font-size:13px;font-weight:400;color:var(--mut)">— bereit für Anfragen</span>'),td=g('<div><div class="k-h"><span class="k-t">Temperatur (GPU)</span><span class="k-ic"></span></div> <div class="k-v"> </div> <div class="k-s"> </div></div> <div><div class="k-h"><span class="k-t">Freier Speicher</span><span class="k-ic"></span></div> <div class="k-v"> <small>GB</small></div> <div class="k-s"> </div></div>',1),nd=g('<div class="kpi muted"><div class="k-h"><span class="k-t">Temperatur</span></div><div class="k-v">–</div><div class="k-s">messe…</div></div> <div class="kpi muted"><div class="k-h"><span class="k-t">Freier Speicher</span></div><div class="k-v">–</div><div class="k-s">messe…</div></div>',1),ad=g('<div class="meter"><div class="meter-h"><span class="mk"> </span><span class="mv"> </span></div> <div><i></i></div></div>'),id=g('<div class="empty">Warte auf Messwerte…</div>'),rd=g('<div class="card-sub">Noch kein Modell eingerichtet — starte hier:</div> <button class="qa"><span class="qa-ic teal"></span> <span class="qa-main"><span class="qa-t">Schritt 1 · Modell holen</span><span class="qa-s">Cookbook → passendes Setup installieren</span></span> <span class="qa-arrow"></span></button> <button class="qa" style="opacity:.55;pointer-events:none"><span class="qa-ic teal"></span> <span class="qa-main"><span class="qa-t">Schritt 2 · Tools verbinden</span><span class="qa-s">Erst nach dem Download verfügbar</span></span> <span class="qa-arrow"></span></button> <button class="qa"><span class="qa-ic blue"></span> <span class="qa-main"><span class="qa-t">Einsteiger-Guide lesen</span><span class="qa-s">Alle Begriffe erklärt, ohne Vorwissen</span></span> <span class="qa-arrow"></span></button>',1),sd=g('<div class="card-sub">Die häufigsten Aufgaben — ein Klick.</div> <button class="qa"><span class="qa-ic teal"></span> <span class="qa-main"><span class="qa-t">Modell finden</span><span class="qa-s">Passend zu deiner Hardware</span></span> <span class="qa-arrow"></span></button> <button class="qa"><span class="qa-ic amber"></span> <span class="qa-main"><span class="qa-t">Speicher freigeben</span><span class="qa-s">Alle Modelle entladen</span></span> <span class="qa-arrow"></span></button> <button class="qa"><span class="qa-ic blue"></span> <span class="qa-main"><span class="qa-t">Logs ansehen</span><span class="qa-s">Live mitlesen, was läuft</span></span> <span class="qa-arrow"></span></button> <button class="qa"><span class="qa-ic teal"></span> <span class="qa-main"><span class="qa-t">Tools verbinden</span><span class="qa-s">Zed, OpenCode, Cline einrichten</span></span> <span class="qa-arrow"></span></button>',1),ld=g('<span class="tag img">Bild</span>'),od=g('<span class="tag code">Code</span>'),dd=g('<span class="tag text">Text</span>'),cd=g('<span class="chip" style="padding:2px 7px;font-size:11px">∞ aktiv</span>'),vd=g('<button class="ghost"> </button>'),ud=g('<div class="li" style="padding:10px 4px"><span></span> <div class="li-main"><div class="flex items-center gap-2" style="flex-wrap:wrap"><span class="li-id"> </span> <!> <!></div> <div class="li-sub mono-sm"> </div></div> <div class="flex items-center gap-2"><span class="li-meta"> </span> <!></div></div>'),es=g('<div class="list"></div>'),pd=g('<div class="empty-c"><div class="e-t">Noch keine Modelle</div> <div class="e-s">Hol dir unter „Cookbook" ein Modell, das auf deine Hardware passt.</div> <button class="primary" style="margin-top:12px">Zum Cookbook →</button></div>'),fd=g('<a class="li" target="_blank" rel="noopener" style="text-decoration:none;color:inherit"><div class="li-main"><div style="font-size:13px;line-height:1.4"> </div> <div class="li-sub"> </div></div></a>'),hd=g('<div class="empty">News gerade nicht ladbar.</div>'),gd=g('<div class="pagehead" style="margin-bottom:10px"><div><h1 style="display:flex;align-items:center;gap:10px"> <!></h1> <div class="sub"> </div></div></div> <div class="tiles"><div><div class="k-h"><span class="k-t">LLM-Engine</span> <span class="k-ic"></span></div> <div class="k-v"> </div> <div class="k-s"> </div></div> <div><div class="k-h"><span class="k-t">Aktives Modell</span> <span class="k-ic"></span></div> <div class="k-v" style="font-size:16px;word-break:break-word"> </div> <div class="k-s"><!></div></div> <!></div> <div class="split"><div class="card"><div class="card-h"><h3>System-Gesundheit</h3></div> <div class="card-sub">Auslastung in Echtzeit.</div> <!></div> <div class="card"><div class="card-h"><h3>Schnellstart</h3></div> <!></div></div> <div class="grid grid-2"><div class="card"><div class="card-h"><h3>Dein Stack</h3> <span class="meta"> </span></div> <!></div> <div class="card"><div class="card-h"><h3>Top-News</h3> <span class="meta" style="cursor:pointer" role="button" tabindex="0">Alle →</span></div> <!></div></div>',1);function md(e,n){kn(n,!0);const a=U(()=>ui.value),s=U(()=>Lr.value),l=U(()=>{var w;return((w=t(a))==null?void 0:w.models)||[]}),o=U(()=>{var w;return((w=t(a))==null?void 0:w.swap_ok)??!1}),d=["running","ready","loading","starting"],v=U(()=>t(l).find(w=>d.includes(w.state))),c=U(()=>t(l).filter(w=>!w.incomplete)),f=U(()=>t(a)?t(o)?t(s)&&t(s).ram.percent>=90?"Achtung: Speicher wird knapp.":"Alles läuft rund.":"LLM-Engine offline":"Verbinde…"),_=U(()=>t(a)?t(o)?t(s)&&t(s).ram.percent>=90?`Arbeitsspeicher bei ${Math.round(t(s).ram.percent)} % — eventuell Speicher freigeben.`:`${t(c).length} ${t(c).length===1?"Modell":"Modelle"} konfiguriert · ${t(v)?`„${t(v).name}" geladen`:"keines geladen"} · keine Warnungen.`:"Der llama-swap-Dienst antwortet gerade nicht.":""),T=U(()=>()=>{var ee;const w=(ee=t(s))==null?void 0:ee.gpu;return w&&w.vram.total+w.gtt.total>0?(w.vram.used+w.gtt.used)/(w.vram.total+w.gtt.total)*100:0});let y=F(Lt([])),k=F(null);vi(async()=>{try{u(y,((await Se("/api/news")).items||[]).slice(0,4),!0)}catch{}});async function I(){await rn({title:"Speicher freigeben?",body:"Alle aktuell geladenen Modelle werden aus dem Grafikspeicher geworfen. Sie laden beim nächsten Aufruf automatisch neu.",confirmLabel:"Speicher freigeben"})&&(await Se("/api/unload",{method:"POST"}),C())}async function K(w){u(k,w,!0);try{await Se("/api/preload?model="+encodeURIComponent(w),{method:"POST"})}catch(ee){he("Laden fehlgeschlagen: "+(ee.message||"Engine nicht erreichbar?"),!0)}u(k,null),C()}function C(){document.dispatchEvent(new Event("mc:refresh"))}function V(w){var ee;(ee=document.querySelector(`.nav-item[data-view="${w}"]`))==null||ee.dispatchEvent(new MouseEvent("click"))}function Ae(w){return w>=90?"red":w>=75?"":"green"}function Ce(w){return w==null?"":w>=75?"red":w>=55?"":"green"}function Be(w){return w>=90?"red":w>=70?"":"green"}var De=gd(),se=Ye(De),le=r(se),$e=r(le),Te=r($e),We=i(Te);{var rt=w=>{var ee=ed();p(w,ee)};O(We,w=>{t(o)&&!t(v)&&w(rt)})}var Je=i($e,2),R=r(Je),_e=i(se,2),Re=r(_e),at=r(Re),Q=i(r(at),2);lt(Q,()=>Bt("server"),!0);var de=i(at,2),xe=r(de),et=i(de,2),Ve=r(et),tt=i(Re,2),Ke=r(tt),it=i(r(Ke),2);lt(it,()=>Bt("cpu"),!0);var dt=i(Ke,2),ht=r(dt),ct=i(dt,2),_t=r(ct);{var At=w=>{var ee=Ya();$(ge=>h(ee,`${ge??""} · ${t(v).state??""}`),[()=>{var ge;return(ge=t(v).meta)!=null&&ge.ctx?Math.round(t(v).meta.ctx/1024)+"k ctx":""}]),p(w,ee)},xt=w=>{var ee=Ya("lädt bei erster Anfrage");p(w,ee)};O(_t,w=>{t(v)?w(At):w(xt,-1)})}var Pt=i(tt,2);{var Ct=w=>{const ee=U(()=>{var Ne;return t(s).gpu_temp??((Ne=t(s).cpu)==null?void 0:Ne.temp)??null}),ge=U(()=>Ce(t(ee))),m=U(()=>t(s).ram.total-t(s).ram.used),x=U(()=>100-t(s).ram.percent);var A=td(),q=Ye(A),H=r(q),G=i(r(H));lt(G,()=>Bt("thermo"),!0);var P=i(H,2),W=r(P),L=i(P,2),X=r(L),ae=i(q,2),ue=r(ae),j=i(r(ue));lt(j,()=>Bt("database"),!0);var te=i(ue,2),Le=r(te),Qe=i(te,2),Oe=r(Qe);$((Ne,yt,Mt,wt)=>{bt(q,1,`kpi ${t(ge)??""}`),h(W,Ne),h(X,t(ee)==null?"messe…":t(ee)<55?"kühl":t(ee)<75?"normal":"⚠ heiß"),bt(ae,1,`kpi ${t(x)<15?"red":t(x)<30?"":"green"}`),h(Le,yt),h(Oe,`von ${Mt??""} GB · ${wt??""} % frei`)},[()=>t(ee)!=null?`${Math.round(t(ee))}°C`:"–",()=>Math.round(t(m)/1073741824),()=>Math.round(t(s).ram.total/1073741824),()=>Math.round(t(x))]),p(w,A)},kt=w=>{var ee=nd();p(w,ee)};O(Pt,w=>{t(s)?w(Ct):w(kt,-1)})}var B=i(_e,2),Z=r(B),D=i(r(Z),4);{var J=w=>{const ee=U(()=>t(T)());var ge=ua(),m=Ye(ge);Ze(m,17,()=>{var x;return[["Prozessor (CPU)",((x=t(s).cpu)==null?void 0:x.percent)??0,""],["Arbeitsspeicher (RAM)",t(s).ram.percent,Ae(t(s).ram.percent)],["Grafikspeicher (VRAM)",t(ee),Be(t(ee))]]},nt,(x,A)=>{var q=U(()=>En(t(A),3));let H=()=>t(q)[0],G=()=>t(q)[1];const P=U(()=>Math.max(0,Math.min(100,G()||0)));var W=ad(),L=r(W),X=r(L),ae=r(X),ue=i(X),j=r(ue),te=i(L,2),Le=r(te);$((Qe,Oe)=>{h(ae,H()),h(j,`${Qe??""} %`),bt(te,1,`bar ${t(P)>=90?"bad":t(P)>=75?"warn":""}`),St(Le,`width:${Oe??""}%`)},[()=>Math.round(t(P)),()=>Math.max(2,t(P))]),p(x,W)}),p(w,ge)},M=w=>{var ee=id();p(w,ee)};O(D,w=>{t(s)?w(J):w(M,-1)})}var ie=i(Z,2),ke=i(r(ie),2);{var Ie=w=>{var ee=rd(),ge=i(Ye(ee),2),m=r(ge);lt(m,()=>Bt("search"),!0);var x=i(m,4);lt(x,()=>Bt("chevron"),!0);var A=i(ge,2),q=r(A);lt(q,()=>Bt("swap"),!0);var H=i(q,4);lt(H,()=>Bt("chevron"),!0);var G=i(A,2),P=r(G);lt(P,()=>Bt("file"),!0);var W=i(P,4);lt(W,()=>Bt("chevron"),!0),S("click",ge,()=>V("cookbook")),S("click",A,()=>V("connect")),S("click",G,()=>V("guides")),p(w,ee)},z=w=>{var ee=sd(),ge=i(Ye(ee),2),m=r(ge);lt(m,()=>Bt("search"),!0);var x=i(m,4);lt(x,()=>Bt("chevron"),!0);var A=i(ge,2),q=r(A);lt(q,()=>Bt("refresh"),!0);var H=i(q,4);lt(H,()=>Bt("chevron"),!0);var G=i(A,2),P=r(G);lt(P,()=>Bt("file"),!0);var W=i(P,4);lt(W,()=>Bt("chevron"),!0);var L=i(G,2),X=r(L);lt(X,()=>Bt("swap"),!0);var ae=i(X,4);lt(ae,()=>Bt("chevron"),!0),S("click",ge,()=>V("cookbook")),S("click",A,I),S("click",G,()=>V("server")),S("click",L,()=>V("connect")),p(w,ee)};O(ke,w=>{t(c).length?w(z,-1):w(Ie)})}var N=i(B,2),ve=r(N),oe=r(ve),re=i(r(oe),2),we=r(re),pe=i(oe,2);{var E=w=>{var ee=es();Ze(ee,21,()=>t(c),nt,(ge,m)=>{const x=U(()=>d.includes(t(m).state)),A=U(()=>t(m).state==="downloading"),q=U(()=>t(m).state==="loading"||t(m).state==="starting"||t(A)?"load":t(x)?"on":""),H=U(()=>t(A)?`↓ ${t(m).download_progress!=null?Math.round(t(m).download_progress)+"%":"..."}`:t(m).state==="loading"||t(m).state==="starting"?"lädt…":t(x)?"geladen ✓":"bereit");var G=ud(),P=r(G),W=i(P,2),L=r(W),X=r(L),ae=r(X),ue=i(X,2);{var j=qe=>{var ut=ld();p(qe,ut)},te=U(()=>{var qe,ut;return(ut=(qe=t(m).meta)==null?void 0:qe.caps)==null?void 0:ut.includes("Bild")}),Le=qe=>{var ut=od();p(qe,ut)},Qe=U(()=>{var qe,ut;return(ut=(qe=t(m).meta)==null?void 0:qe.caps)==null?void 0:ut.includes("Code")}),Oe=qe=>{var ut=dd();p(qe,ut)};O(ue,qe=>{t(te)?qe(j):t(Qe)?qe(Le,1):qe(Oe,-1)})}var Ne=i(ue,2);{var yt=qe=>{var ut=cd();p(qe,ut)};O(Ne,qe=>{t(m).ttl>=99999&&qe(yt)})}var Mt=i(L,2),wt=r(Mt),vt=i(W,2),Et=r(vt),Wt=r(Et),Vt=i(Et,2);{var fn=qe=>{var ut=vd(),me=r(ut);$(()=>{St(ut,`padding:3px 9px;font-size:12px;opacity:${t(k)===t(m).name?".5":"1"}`),ut.disabled=t(k)===t(m).name,h(me,t(k)===t(m).name?"…":"Laden")}),S("click",ut,()=>K(t(m).name)),p(qe,ut)};O(Vt,qe=>{!t(x)&&!t(A)&&t(o)&&qe(fn)})}$((qe,ut)=>{var me;bt(P,1,`li-dot ${t(q)??""}`),St(X,t(x)?"color:var(--accent)":""),h(ae,t(m).name),h(wt,`${qe??""}
|
||
${(me=t(m).meta)!=null&&me.quant?" · "+t(m).meta.quant:""}
|
||
${ut??""}`),St(Et,`white-space:nowrap;color:${t(x)?"var(--on)":"var(--mut)"}`),h(Wt,t(H))},[()=>{var qe;return(qe=t(m).meta)!=null&&qe.ctx?Math.round(t(m).meta.ctx/1024)+"k ctx":""},()=>{var qe;return(qe=t(m).meta)!=null&&qe.size_bytes?" · "+(t(m).meta.size_bytes/1073741824).toFixed(1)+" GB":""}]),p(ge,G)}),p(w,ee)},Y=w=>{var ee=pd(),ge=i(r(ee),4);S("click",ge,()=>V("cookbook")),p(w,ee)};O(pe,w=>{t(c).length?w(E):w(Y,-1)})}var fe=i(ve,2),Me=r(fe),ne=i(r(Me),2),ce=i(Me,2);{var ze=w=>{var ee=es();Ze(ee,21,()=>t(y),nt,(ge,m)=>{var x=fd(),A=r(x),q=r(A),H=r(q),G=i(q,2),P=r(G);$(()=>{ga(x,"href",t(m).link),h(H,t(m).title),h(P,`${t(m).source??""}${t(m).relevant?" · für dich":""}`)}),p(ge,x)}),p(w,ee)},Pe=w=>{var ee=hd();p(w,ee)};O(ce,w=>{t(y).length?w(ze):w(Pe,-1)})}$(w=>{h(Te,`${t(f)??""} `),h(R,t(_)),bt(Re,1,`kpi ${t(o)?"green":"red"}`),h(xe,t(o)?"Online":"Offline"),h(Ve,w),bt(tt,1,`kpi ${t(v)?"blue":"muted"}`),h(ht,t(v)?t(v).name:"Keins"),h(we,t(c).length?t(c).length+" konfiguriert":"")},[()=>{var w,ee;return((ee=(w=t(a))==null?void 0:w.swap_url)==null?void 0:ee.replace(/^https?:\/\//,""))??"—"}]),S("click",ne,()=>V("news")),S("keydown",ne,w=>w.key==="Enter"&&V("news")),p(e,De),wn()}$n(["click","keydown"]);var bd=g("<option> </option>"),_d=g('<div class="reply" style="margin-top:12px"> </div>'),yd=g('<div class="empty-c"><div class="e-t">Noch keine Modelle konfiguriert</div> <div class="e-s">Hol dir unter „Cookbook" ein passendes Modell.</div></div>'),xd=g('<tr style="opacity:.9"><td class="mid" style="font-weight:500"> <div class="li-sub mono-sm" style="color:var(--warn)">kein Modell hinterlegt</div></td><td>—</td><td><span class="mono-sm text-mut">leere Rolle</span></td><td><span class="badge">leer</span></td><td class="port">—</td><td style="text-align:right;white-space:nowrap"><button class="ghost">Modell zuweisen</button> <button class="ghost del">Löschen</button></td></tr>'),kd=g('<span class="tag" style="background:rgba(45,212,191,.14);color:var(--accent);border-color:rgba(45,212,191,.3)"> </span>'),wd=g('<div class="li-sub mono-sm"> </div>'),Sd=g('<code style="cursor:pointer" title="Klicken zum Kopieren"> </code>'),Md=g('<tr><td class="mid"><div style="font-weight:500;display:flex;align-items:center;gap:7px;flex-wrap:wrap"> <!></div> <!> <div class="li-sub mono-sm" style="margin-top:3px;display:flex;align-items:center;gap:6px;flex-wrap:wrap"><span class="text-mut">API-Name:</span> <!></div></td><td></td><td></td><td></td><td class="port"> </td><td style="text-align:right;white-space:nowrap"><button class="ghost">Rolle</button> <button class="ghost">Konfigurieren</button> <button class="ghost">Entladen</button> <button class="ghost del">Löschen</button></td></tr>'),Ed=g('<table><thead><tr><th>Modell</th><th>Kann</th><th>Details</th><th>Status</th><th>Port</th><th style="text-align:right">Aktionen</th></tr></thead><tbody></tbody></table>'),Ad=g('<div class="tile" style="display:flex;justify-content:space-between;align-items:center;margin:8px 0 10px"><div style="flex:1"><div style="font-size:13px">Empfohlen für deine Hardware</div> <div class="hint" style="margin:4px 0 0"> <br/> </div></div> <button class="ghost">Optimal übernehmen</button></div>'),Cd=g('<div class="modal-overlay" role="dialog"><div class="modal-card"><button class="ghost" style="position:absolute;top:14px;right:14px">Schließen</button> <h3>Modell konfigurieren</h3> <p class="mono-sm" style="margin:-4px 0 16px"> </p> <label>Kontext-Größe (Tokens) <!></label> <input type="number"/> <!> <div class="hint" style="margin-bottom:14px">Es läuft immer nur <b>ein</b> Modell gleichzeitig — ein größerer Kontext hier beeinflusst deine anderen Modelle nicht.</div> <div class="tile" style="display:flex;justify-content:space-between;align-items:center;margin:0 0 14px"><div style="flex:1"><div style="font-size:13px;font-weight:500">Immer aktiv halten</div> <div class="hint" style="margin:3px 0 0">Modell bleibt dauerhaft im RAM — nie automatisch entladen. Ideal für den kleinen Scout (~5 GB), der immer schnell antworten soll.</div></div> <label style="display:flex;align-items:center;gap:8px;margin:0;cursor:pointer;flex:0 0 auto"><input type="checkbox" style="width:18px;height:18px;accent-color:var(--accent);cursor:pointer"/> <span class="mono-sm"> </span></label></div> <button class="primary" style="width:100%;margin-top:6px">Speichern</button></div></div>'),Td=g('<button style="border-radius:999px"> </button>'),zd=g('<div class="modal-overlay" role="dialog"><div class="modal-card"><button class="ghost" style="position:absolute;top:14px;right:14px">Schließen</button> <h3>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>'),$d=g('<div id="m-head"><div class="pagehead"><div><h1>Modelle</h1> <div class="sub">Deine konfigurierten Modelle — testen, Kontext anpassen oder aus dem Speicher werfen.</div></div></div></div> <div class="card"><div class="card-h"><h3>Schnelltest</h3></div> <div class="card-sub">Schreib eine Nachricht — das gewählte Modell wird automatisch geweckt.</div> <label>Modell</label> <select></select> <label>Nachricht</label> <textarea placeholder="z.B. „Erklär mir kurz, was du kannst.""></textarea> <button class="primary"> </button> <!></div> <div class="card"><div class="card-h"><h3>Modelle & Ports</h3><span class="meta"> </span></div> <div class="card-sub">Modelle laden automatisch, sobald eine Anfrage kommt — du musst nichts manuell starten.</div> <!></div> <!> <!>',1);function Pd(e,n){kn(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=U(()=>{var B;return((B=ui.value)==null?void 0:B.models)||[]});function d(){document.dispatchEvent(new Event("mc:refresh"))}let v=F(""),c=F(""),f=F(""),_=F(!1);const T=U(()=>t(o).filter(B=>!B.incomplete));async function y(){var Z;const B=t(v)||((Z=t(T)[0])==null?void 0:Z.name);if(!(!B||!t(c).trim())){u(_,!0),u(f,"(wecke Modell, kann beim Laden kurz dauern…)");try{const D=await Se("/api/chat",{method:"POST",body:JSON.stringify({model:B,message:t(c)})});u(f,D.reply,!0)}catch(D){u(f,"Fehler: "+D.message)}u(_,!1),d()}}const k=300;let I=F(!1),K=F(null),C=F(8192),V=F(!1);function Ae(B){var Z;u(K,t(o).find(D=>D.name===B),!0),t(K)&&(u(C,((Z=t(K).meta)==null?void 0:Z.ctx)||8192,!0),u(V,(t(K).ttl??k)>=99999),u(I,!0))}async function Ce(){const B=t(V)?99999:k;try{await Se("/api/update_model",{method:"POST",body:JSON.stringify({alias:t(K).name,ctx:t(C),ttl:B})}),he("Gespeichert — aktiv beim nächsten Modell-Start."),u(I,!1),d()}catch(Z){he(Z.message,!0)}}let Be=F(!1),De=F(""),se=F(""),le=F("");function $e(B){const Z=t(o).find(D=>D.name===B);u(De,B,!0),u(le,(Z==null?void 0:Z.role)||"",!0),u(se,""),u(Be,!0)}async function Te(B){try{await Se("/api/set_role",{method:"POST",body:JSON.stringify({alias:t(De),role:B})}),he(B?`Rolle gesetzt: ${B}`:"Rolle entfernt."),u(Be,!1),d()}catch(Z){he(Z.message,!0)}}async function We(B){if(await rn({title:`„${B}" entladen?`,body:"Das Modell wird aus dem Grafikspeicher geworfen und lädt beim nächsten Aufruf automatisch neu.",confirmLabel:"Entladen"}))try{await Se("/api/unload?model="+encodeURIComponent(B),{method:"POST"}),he("Entladen: "+B),setTimeout(d,600)}catch(Z){he(Z.message,!0)}}async function rt(B){if(await rn({title:`„${B}" 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 Z=await Se("/api/delete_model",{method:"POST",body:JSON.stringify({alias:B})});he(Z.note||"Gelöscht: "+B),setTimeout(d,600)}catch(Z){he(Z.message,!0)}}function Je(B){if(!B)return"–";const Z=[];return B.coder&&Z.push('<span class="tag code">Code</span>'),B.vision&&Z.push('<span class="tag img">Bild</span>'),B.reasoning&&Z.push('<span class="tag" style="border-color:#a78bfa;color:#a78bfa">🧠 Reason</span>'),B.moe&&Z.push(`<span class="tag" style="border-color:#f59e0b;color:#f59e0b">🧩 MoE${B.active_b?" ·"+B.active_b+"B":""}</span>`),B.tools==="yes"?Z.push('<span class="tag" style="border-color:var(--accent);color:var(--accent)" title="Tool-Calling vom Template/Flag unterstützt">🛠 Tools</span>'):B.tools==="likely"&&Z.push('<span class="tag" style="opacity:.55" title="laut Modell-Familie wahrscheinlich tool-fähig">🛠 Tools?</span>'),B.embedding&&Z.push('<span class="tag" style="opacity:.7">🔢 Embed</span>'),!B.coder&&!B.vision&&!B.embedding&&Z.unshift('<span class="tag text">Text</span>'),Z.length?Z.join(" "):"–"}function R(B){if(!B)return"–";const Z=B.quant||"?",D=B.ctx?Math.round(B.ctx/1024)+"K":"?",J=B.size_bytes?(B.size_bytes/1024**3).toFixed(1)+" GB":"?";return`<span class="mono-sm">${Z} · ${D} · ${J}</span>`}function _e(B){var Z;(Z=navigator.clipboard)==null||Z.writeText(B),he("Kopiert: "+B)}var Re=$d(),at=i(Ye(Re),2),Q=i(r(at),6);Ze(Q,21,()=>t(T),nt,(B,Z)=>{var D=bd(),J=r(D),M={};$(()=>{h(J,t(Z).name),M!==(M=t(Z).name)&&(D.value=(D.__value=t(Z).name)??"")}),p(B,D)});var de=i(Q,4),xe=i(de,2),et=r(xe),Ve=i(xe,2);{var tt=B=>{var Z=_d(),D=r(Z);$(()=>h(D,t(f))),p(B,Z)};O(Ve,B=>{t(f)&&B(tt)})}var Ke=i(at,2),it=r(Ke),dt=i(r(it)),ht=r(dt),ct=i(it,4);{var _t=B=>{var Z=yd();p(B,Z)},At=B=>{var Z=Ed(),D=i(r(Z));Ze(D,21,()=>t(o),nt,(J,M)=>{var ie=ua(),ke=Ye(ie);{var Ie=N=>{var ve=xd(),oe=r(ve),re=r(oe),we=i(oe,5),pe=r(we),E=i(pe,2);$(()=>h(re,t(M).name)),S("click",pe,()=>{var Y;he("Lade im Cookbook ein Modell und setze den Alias auf: "+t(M).name),(Y=document.querySelector(".nav-item[data-view='cookbook']"))==null||Y.dispatchEvent(new MouseEvent("click"))}),S("click",E,()=>rt(t(M).name)),p(N,ve)},z=N=>{var ve=Md(),oe=r(ve),re=r(oe),we=r(re),pe=i(we);{var E=H=>{var G=kd(),P=r(G);$(()=>h(P,t(M).role)),p(H,G)};O(pe,H=>{t(M).role&&H(E)})}var Y=i(re,2);{var fe=H=>{var G=wd(),P=r(G);$(()=>h(P,t(M).meta.filename)),p(H,G)};O(Y,H=>{var G;(G=t(M).meta)!=null&&G.filename&&H(fe)})}var Me=i(Y,2),ne=i(r(Me),2);Ze(ne,17,()=>{var H;return(H=t(M).api_ids)!=null&&H.length?t(M).api_ids:[t(M).name]},nt,(H,G)=>{var P=Sd(),W=r(P);$(()=>h(W,t(G))),S("click",P,()=>_e(t(G))),p(H,P)});var ce=i(oe);lt(ce,()=>{var H;return Je((H=t(M).meta)==null?void 0:H.capabilities)},!0);var ze=i(ce);lt(ze,()=>R(t(M).meta),!0);var Pe=i(ze);lt(Pe,()=>Zo(t(M).state,t(M).download_progress),!0);var w=i(Pe),ee=r(w),ge=i(w),m=r(ge),x=i(m,2),A=i(x,2),q=i(A,2);$(()=>{h(we,`${t(M).name??""} `),h(ee,t(M).port??"auto")}),S("click",m,()=>$e(t(M).name)),S("click",x,()=>Ae(t(M).name)),S("click",A,()=>We(t(M).name)),S("click",q,()=>rt(t(M).name)),p(N,ve)};O(ke,N=>{t(M).incomplete?N(Ie):N(z,-1)})}p(J,ie)}),p(B,Z)};O(ct,B=>{t(o).length?B(At,-1):B(_t)})}var xt=i(Ke,2);{var Pt=B=>{var Z=Cd(),D=r(Z),J=r(D),M=i(J,4),ie=r(M),ke=i(M,2),Ie=i(r(ke));lt(Ie,()=>xr(a));var z=i(ke,2),N=i(z,2);{var ve=fe=>{var Me=Ad(),ne=r(Me),ce=i(r(ne),2),ze=r(ce),Pe=i(ze,2),w=i(ne,2);$((ee,ge)=>{h(ze,`Optimal ~${ee??""}k → ~${t(K).meta.peak_ram_optimal_gb??""} GB Spitzenbedarf.`),h(Pe,` Aktuell ~${ge??""}k → ~${t(K).meta.peak_ram_gb??""} GB.`)},[()=>Math.round(t(K).meta.optimal_ctx/1024),()=>Math.round((t(K).meta.ctx||0)/1024)]),S("click",w,()=>u(C,t(K).meta.optimal_ctx,!0)),p(fe,Me)};O(N,fe=>{var Me;(Me=t(K).meta)!=null&&Me.optimal_ctx&&fe(ve)})}var oe=i(N,4),re=i(r(oe),2),we=r(re),pe=i(we,2),E=r(pe),Y=i(oe,2);$(()=>{h(ie,t(K).name),St(pe,`color:${t(V)?"var(--accent)":"var(--mut)"}`),h(E,t(V)?"An (TTL = ∞)":"Aus (TTL = 5 min)")}),S("click",Z,fe=>{fe.target.classList.contains("modal-overlay")&&u(I,!1)}),S("click",J,()=>u(I,!1)),Yt(z,()=>t(C),fe=>u(C,fe)),Vo(we,()=>t(V),fe=>u(V,fe)),S("click",Y,Ce),p(B,Z)};O(xt,B=>{t(I)&&t(K)&&B(Pt)})}var Ct=i(xt,2);{var kt=B=>{var Z=zd(),D=r(Z),J=r(D),M=i(J,2),ie=i(r(M));lt(ie,()=>xr(s));var ke=i(M,2),Ie=r(ke),z=i(ke,4);Ze(z,21,()=>l,nt,(we,pe)=>{var E=Td(),Y=r(E);$(()=>{bt(E,1,t(le)===t(pe).id?"primary":"ghost"),ga(E,"title",t(pe).desc),h(Y,t(pe).label)}),S("click",E,()=>Te(t(pe).id)),p(we,E)});var N=i(z,4),ve=i(N,2),oe=r(ve),re=i(oe,2);$(()=>h(Ie,t(De))),S("click",Z,we=>{we.target.classList.contains("modal-overlay")&&u(Be,!1)}),S("click",J,()=>u(Be,!1)),Yt(N,()=>t(se),we=>u(se,we)),S("click",oe,()=>Te("")),S("click",re,()=>Te(t(se).trim().toLowerCase())),p(B,Z)};O(Ct,B=>{t(Be)&&B(kt)})}$(()=>{xe.disabled=t(_),h(et,t(_)?"…":"Senden"),h(ht,t(o).length?t(o).length+" konfiguriert":"")}),On(Q,()=>t(v),B=>u(v,B)),Yt(de,()=>t(c),B=>u(c,B)),S("click",xe,y),p(e,Re),wn()}$n(["click"]);var Dd=g('<div class="tiles"><div class="tile"><div class="t-l">Prozessor (CPU)</div> <div class="t-v"> <small>%</small></div> <div class="t-s"> </div></div> <div class="tile"><div class="t-l">Arbeitsspeicher</div> <div class="t-v"> <small>%</small></div> <div class="t-s"> </div></div> <div class="tile"><div class="t-l">Grafikspeicher</div> <div class="t-v"> <small>%</small></div> <div class="t-s"> </div></div></div> <div class="card"><div class="card-h"><h3>System-Metriken (Bosgame)</h3></div> <div class="card-sub">Live-Auslastung deines Mini-PCs, alle 0,5 Sekunden.</div> <div class="kv" style="margin-bottom:6px"><div class="kv-row"><span class="kv-k">Arbeitsspeicher (RAM)</span><span class="kv-v"> </span></div> <div class="kv-row"><span class="kv-k">Grafikspeicher (VRAM + GTT)</span> <span class="kv-v"> </span></div> <div class="kv-row"><span class="kv-k">Speicherplatz (Disk)</span><span class="kv-v"> </span></div> <div class="kv-row"><span class="kv-k">Temperatur (GPU / CPU)</span> <span class="kv-v"> </span></div></div> <div class="grid grid-3" style="margin-top:14px"><div><div class="meta text-xs">CPU-Verlauf</div><div style="display:flex;align-items:flex-end;gap:2px;height:38px;margin-top:10px"></div></div> <div><div class="meta text-xs">RAM-Verlauf</div><div style="display:flex;align-items:flex-end;gap:2px;height:38px;margin-top:10px"></div></div> <div><div class="meta text-xs">VRAM-Verlauf</div><div style="display:flex;align-items:flex-end;gap:2px;height:38px;margin-top:10px"></div></div></div></div>',1),Id=g('<button class="ghost" style="margin-left:auto;padding:4px 11px;font-size:12px">Verlauf leeren</button>'),Ld=g('<div class="empty-c"><div class="e-t">Gerade nichts los.</div> <div class="e-s">Alles ruhig — keine laufenden Aufgaben.</div></div>'),Od=g('<span class="mono-sm" style="margin-left:auto"> </span>'),Bd=g('<button class="ghost">Abbrechen</button>'),Rd=g('<button class="ghost" title="Aus Verlauf entfernen" style="margin-left:auto;margin-right:2px;padding:2px 9px;font-size:14px;line-height:1">×</button>'),Fd=g('<div class="bar" style="margin-top:8px"><i></i></div>'),Kd=g('<div class="log"> </div>'),Nd=g('<div class="job"><div class="job-h" role="button" tabindex="0"><span></span> <span class="mid"> </span> <!> <!> <!></div> <!> <!></div>'),qd=g('<div class="pagehead"><div><h1>Aktivität</h1> <div class="sub">Live-Auslastung und laufende Aufgaben (Downloads, Updates) mit Protokoll.</div></div></div> <!> <div class="card"><div class="card-h"><h3>Hintergrund-Aufgaben</h3> <span class="meta"> </span> <!></div> <div class="card-sub">Downloads & Updates erscheinen hier mit Live-Protokoll — zum Aufklappen klicken.</div> <!></div>',1);function Gd(e,n){kn(n,!0);const a=U(()=>na.value),s=U(()=>na.tracked),l=U(()=>Lr.value);let o=Lt({cpu:[],ram:[],gpu:[]});di(()=>{var Re;if(!t(l))return;const R=t(l).gpu,_e=R&&R.vram.total+R.gtt.total>0?(R.vram.used+R.gtt.used)/(R.vram.total+R.gtt.total)*100:0;o.cpu=[...o.cpu,((Re=t(l).cpu)==null?void 0:Re.percent)??0].slice(-60),o.ram=[...o.ram,t(l).ram.percent].slice(-60),o.gpu=[...o.gpu,_e].slice(-60)});const d=U(()=>()=>{var _e;const R=(_e=t(l))==null?void 0:_e.gpu;return R&&R.vram.total+R.gtt.total>0?(R.vram.used+R.gtt.used)/(R.vram.total+R.gtt.total)*100:0}),v=U(()=>t(a).filter(R=>R.state!=="running"&&R.state!=="queued").length),c=U(()=>t(a).filter(R=>R.state==="failed").length);function f(R){if(R.state!=="running")return null;if(typeof R.progress=="number")return Math.min(100,R.progress);const Re=((R.log||[]).at(-1)||"").match(/(\d+(?:\.\d+)?)\s*%/);return Re?Math.min(100,parseFloat(Re[1])):null}function _(R){return R==null||R<0?"":R>=90?`noch ~${Math.round(R/60)} min`:`noch ~${Math.max(1,Math.round(R))} s`}function T(R){return R==="done"?'<span class="badge b-run">fertig</span>':R==="failed"?'<span class="badge b-err">fehler</span>':R==="canceled"?'<span class="badge">abgebrochen</span>':'<span class="badge b-load">läuft…</span>'}function y(R){return R==="done"?"on":R==="failed"||R==="canceled"?"":"load"}async function k(R){try{await Se(`/api/jobs/${R}/cancel`,{method:"POST"}),he("Abbruch angefordert…")}catch(_e){he(_e.message,!0)}}async function I(R){try{await Se(`/api/jobs/${R}`,{method:"DELETE"})}catch(_e){he(_e.message,!0)}}async function K(){try{const R=await Se("/api/jobs/clear",{method:"POST"});he(`${R.removed} Einträge entfernt.`)}catch(R){he(R.message,!0)}}function C(R,_e){return R.map(Re=>`<div style="width:4px;background:var(${_e});opacity:.55;height:${Math.max(2,Re)}%;border-radius:2px"></div>`).join("")}var V=qd(),Ae=i(Ye(V),2);{var Ce=R=>{const _e=U(()=>t(d)());var Re=Dd(),at=Ye(Re),Q=r(at),de=i(r(Q),2),xe=r(de),et=i(de,2),Ve=r(et),tt=i(Q,2),Ke=i(r(tt),2),it=r(Ke),dt=i(Ke,2),ht=r(dt),ct=i(tt,2),_t=i(r(ct),2),At=r(_t),xt=i(_t,2),Pt=r(xt),Ct=i(at,2),kt=i(r(Ct),4),B=r(kt),Z=i(r(B)),D=r(Z),J=i(B,2),M=i(r(J),2),ie=r(M),ke=i(J,2),Ie=i(r(ke)),z=r(Ie),N=i(ke,2),ve=i(r(N),2),oe=r(ve),re=i(kt,2),we=r(re),pe=i(r(we));lt(pe,()=>C(o.cpu,"--accent"),!0);var E=i(we,2),Y=i(r(E));lt(Y,()=>C(o.ram,"--purple"),!0);var fe=i(E,2),Me=i(r(fe));lt(Me,()=>C(o.gpu,"--on"),!0),$((ne,ce,ze,Pe,w,ee,ge,m,x,A,q,H,G)=>{h(xe,ne),h(Ve,ce),h(it,ze),h(ht,`${Pe??""} / ${w??""}`),h(At,ee),h(Pt,ge),h(D,`${m??""} / ${x??""}`),h(ie,A),h(z,`${q??""} % belegt`),h(oe,`${H??""} / ${G??""}`)},[()=>{var ne;return Math.round(((ne=t(l).cpu)==null?void 0:ne.percent)??0)},()=>{var ne;return((ne=t(l).cpu)==null?void 0:ne.temp)!=null?`${Math.round(t(l).cpu.temp)}° CPU-Temp`:"Auslastung"},()=>Math.round(t(l).ram.percent),()=>Yn(t(l).ram.used),()=>Yn(t(l).ram.total),()=>Math.round(t(_e)),()=>t(l).gpu_temp!=null?`${Math.round(t(l).gpu_temp)}° GPU-Temp`:"VRAM + GTT",()=>Yn(t(l).ram.used),()=>Yn(t(l).ram.total),()=>t(l).gpu?`${Yn(t(l).gpu.vram.used+t(l).gpu.gtt.used)} / ${Yn(t(l).gpu.vram.total+t(l).gpu.gtt.total)}`:"–",()=>{var ne;return Math.round(((ne=t(l).disk)==null?void 0:ne.percent)??0)},()=>t(l).gpu_temp!=null?Math.round(t(l).gpu_temp)+"°":"–",()=>{var ne;return((ne=t(l).cpu)==null?void 0:ne.temp)!=null?Math.round(t(l).cpu.temp)+"°":"–"}]),p(R,Re)};O(Ae,R=>{t(l)&&R(Ce)})}var Be=i(Ae,2),De=r(Be),se=i(r(De),2),le=r(se),$e=i(se,2);{var Te=R=>{var _e=Id();S("click",_e,K),p(R,_e)};O($e,R=>{t(v)&&R(Te)})}var We=i(De,4);{var rt=R=>{var _e=Ld();p(R,_e)},Je=R=>{var _e=ua(),Re=Ye(_e);Ze(Re,17,()=>t(a),nt,(at,Q)=>{const de=U(()=>f(t(Q))),xe=U(()=>t(Q).state==="running"?_(t(Q).eta_s):""),et=U(()=>t(Q).state==="running"&&t(Q).rate_bps?Yn(t(Q).rate_bps)+"/s":""),Ve=U(()=>[t(xe),t(et)].filter(Boolean).join(" · ")),tt=U(()=>t(s).includes(t(Q).id));var Ke=Nd(),it=r(Ke),dt=r(it),ht=i(dt,2),ct=r(ht),_t=i(ht,2);{var At=M=>{var ie=Od(),ke=r(ie);$(Ie=>h(ke,`${Ie??""} %${t(Ve)?` · ${t(Ve)}`:""}`),[()=>Math.round(t(de))]),p(M,ie)};O(_t,M=>{t(de)!=null&&M(At)})}var xt=i(_t,2);{var Pt=M=>{var ie=Bd();$(()=>St(ie,`${t(de)==null?"margin-left:auto;":""}margin-right:2px;padding:2px 9px;font-size:12px`)),S("click",ie,ke=>{ke.stopPropagation(),k(t(Q).id)}),p(M,ie)},Ct=M=>{var ie=Rd();S("click",ie,ke=>{ke.stopPropagation(),I(t(Q).id)}),p(M,ie)};O(xt,M=>{t(Q).state==="running"?M(Pt):M(Ct,-1)})}var kt=i(xt,2);lt(kt,()=>T(t(Q).state));var B=i(it,2);{var Z=M=>{var ie=Fd(),ke=r(ie);$(()=>St(ke,`width:${t(de)??""}%`)),p(M,ie)};O(B,M=>{t(de)!=null&&t(Q).state==="running"&&M(Z)})}var D=i(B,2);{var J=M=>{var ie=Kd(),ke=r(ie);$(Ie=>h(ke,Ie),[()=>(t(Q).log||[]).join(`
|
||
`)]),p(M,ie)};O(D,M=>{t(tt)&&M(J)})}$(M=>{bt(dt,1,`li-dot ${M??""}`),h(ct,t(Q).label)},[()=>y(t(Q).state)]),S("click",it,()=>na.toggle(t(Q).id)),S("keydown",it,M=>M.key==="Enter"&&na.toggle(t(Q).id)),p(at,Ke)}),p(R,_e)};O(We,R=>{t(a).length?R(Je,-1):R(rt)})}$(()=>h(le,t(a).length?t(c)?t(c)+" Fehler":t(a).length+" gesamt":"")),p(e,V),wn()}$n(["click","keydown"]);var Vd=g('<span class="mono-sm"> </span>'),Wd=g('<button class="ghost" style="margin-left:auto;padding:3px 12px">Abbrechen</button>'),jd=g('<span class="badge b-run">✓ fertig</span>'),Ud=g('<span class="badge b-err">✗ fehlgeschlagen</span>'),Hd=g('<span class="badge">abgebrochen</span>'),Jd=g('<span class="badge b-load">läuft…</span>'),Qd=g('<div class="bar" style="margin-bottom:10px"><i></i></div>'),Zd=g('<div class="card"><div class="card-h"><h3>Aktueller Vorgang</h3> <!> <span style="margin-left:10px"><!></span></div> <div class="card-sub"> </div> <!> <div class="log" style="max-height:280px"> </div></div>'),Yd=g('<div class="pagehead"><div><h1>Server & Wartung</h1> <div class="sub">Dienste steuern, Updates einspielen und live mitlesen — ganz ohne SSH oder Terminal.</div></div></div> <div class="card"><div class="card-h"><h3>LLM-Engine (llama-swap)</h3> <span class="chip"> </span></div> <div class="card-sub">Das Herzstück: lädt bei jeder Anfrage automatisch das passende Modell.</div> <div class="kv" style="margin-bottom:6px"><div class="kv-row"><span class="kv-k">Adresse (für deine Tools)</span><span class="kv-v mono-sm"> </span></div> <div class="kv-row"><span class="kv-k">Aktuell geladen</span> <span class="kv-v"> </span></div> <div class="kv-row"><span class="kv-k">Konfigurierte Modelle</span> <span class="kv-v"> </span></div></div> <div class="btn-row" style="display:flex;align-items:center;gap:10px"><button class="ghost">Verbindung prüfen</button> <!></div></div> <div class="card"><div class="card-h"><h3>Dienste & Applikation</h3></div> <div class="card-sub">Diese Aktionen sind harmlos und passwortlos — es geht nichts dabei verloren.</div> <button class="qa"><span class="qa-ic teal">↻</span> <span class="qa-main"><span class="qa-t">LLM-Engine neustarten</span><span class="qa-s">Startet llama-swap neu. Geladene Modelle laden danach automatisch wieder.</span></span> <span class="qa-arrow">›</span></button> <button class="qa"><span class="qa-ic blue">↻</span> <span class="qa-main"><span class="qa-t">Dashboard neustarten</span><span class="qa-s">Startet diese Oberfläche neu (~5 Sek).</span></span> <span class="qa-arrow">›</span></button> <button class="qa"><span class="qa-ic teal">⬇</span> <span class="qa-main"><span class="qa-t">Mission Control aktualisieren</span><span class="qa-s">Holt die neueste Version aus Gitea und startet automatisch neu (~10 Sek).</span></span> <span class="qa-arrow">›</span></button> <button class="qa"><span class="qa-ic blue">⚡</span> <span class="qa-main"><span class="qa-t">LLM-Engine aktualisieren</span><span class="qa-s">Lädt die neueste llama.cpp-Version (ROCm) für deine GPU.</span></span> <span class="qa-arrow">›</span></button> <button class="qa"><span class="qa-ic amber">🗄</span> <span class="qa-main"><span class="qa-t">Grafikspeicher leeren</span><span class="qa-s">Wirft alle aktuell geladenen Modelle aus dem VRAM. Fragt vorher nach.</span></span> <span class="qa-arrow">›</span></button></div> <div class="card"><div class="card-h"><h3>Betriebssystem (Bosgame)</h3></div> <div class="card-sub">Tiefe Eingriffe — das Dashboard fragt einmalig nach deinem sudo-Passwort.</div> <button class="qa"><span class="qa-ic amber">↻</span> <span class="qa-main"><span class="qa-t">OS-Updates installieren</span><span class="qa-s">Führt apt update & upgrade aus. Kann ein paar Minuten dauern.</span></span> <span class="qa-arrow">›</span></button> <button class="qa qa-danger"><span class="qa-ic red">⚡</span> <span class="qa-main"><span class="qa-t">Server neustarten (Reboot)</span><span class="qa-s">Bootet den ganzen Bosgame neu. Alles ist für ~1 Minute offline.</span></span> <span class="qa-arrow">›</span></button></div> <!> <div class="card"><div class="card-h"><h3>Live-Konsole</h3> <select style="margin:0 0 0 auto;width:240px"><option>LLM-Engine (llama-swap)</option><option>Dashboard (mission-control)</option><option>System (ganzer Server)</option></select></div> <div class="card-sub">Live mitlesen, was der Dienst gerade tut.</div> <div class="console"> </div></div>',1);function Xd(e,n){kn(n,!0);const a=U(()=>ui.value),s=U(()=>na.value);let l=null,o=F(`Verbinde…
|
||
`),d=F("llama-swap"),v,c=F(null),f=F("");const _=new Set,T=U(()=>t(c)?t(s).find(E=>E.id===t(c)):null);di(()=>{if(!t(T))return;const E=t(T),Y=E.state==="done",fe=E.state==="failed",Me=E.state==="canceled";(Y||fe||Me)&&!_.has(E.id)&&(_.add(E.id),he(Y?`✓ ${t(f)} abgeschlossen.`:Me?`${t(f)} abgebrochen.`:`✗ ${t(f)} fehlgeschlagen.`,fe),Y&&setTimeout(()=>document.dispatchEvent(new Event("mc:refresh")),800))});function y(E,Y){u(c,E,!0),u(f,Y,!0),na.track(E)}vi(()=>{k()}),jo(()=>{l==null||l.close()});function k(){l==null||l.close();const E=t(d);u(o,`Verbinde mit ${E}…
|
||
`);const Y=location.protocol==="https:"?"wss:":"ws:";l=new WebSocket(`${Y}//${location.host}/api/logs/${E}?token=${encodeURIComponent(sl())}`),l.onmessage=fe=>{u(o,t(o)+fe.data),v&&(v.scrollTop=v.scrollHeight)},l.onclose=()=>{u(o,t(o)+`
|
||
— Verbindung getrennt —`)},l.onerror=()=>l==null?void 0:l.close()}async function I(E,Y,fe){if(await rn({title:Y,body:fe,confirmLabel:"Neustarten"}))try{await Se(`/api/service/${E}/restart`,{method:"POST"}),he("Neustart ausgelöst: "+E),setTimeout(()=>document.dispatchEvent(new Event("mc:refresh")),2e3)}catch(Me){he(Me.message,!0)}}async function K(){if(await rn({title:"Mission Control aktualisieren?",body:"Holt die neueste Dashboard-Version aus Gitea und startet automatisch neu. Die Seite trennt kurz und verbindet von selbst wieder (~10 Sek)."}))try{const E=await Se("/api/self-update",{method:"POST"});he("Update läuft — Dashboard startet gleich neu."),y(E.job_id,"Mission Control Update")}catch(E){he(E.message,!0)}}async function C(){if(!await rn({title:"LLM-Engine aktualisieren?",body:"Lädt die neueste llama.cpp-ROCm-Version und installiert sie. Die Engine ist während des Updates kurz nicht erreichbar."}))return;const E=await ar({title:"sudo-Passwort",body:"Für das Engine-Update wird einmalig dein sudo-Passwort gebraucht (für den Update-Befehl).",placeholder:"sudo-Passwort",password:!0,confirmLabel:"Update starten"});if(E!==null)try{const Y=await Se("/api/update",{method:"POST",body:JSON.stringify({password:E})});he("LLM-Engine-Update läuft."),y(Y.job_id,"LLM-Engine-Update")}catch(Y){he(Y.message,!0)}}async function V(){if(await rn({title:"Grafikspeicher leeren?",body:"Alle geladenen Modelle werden entladen. Sie laden beim nächsten Aufruf automatisch neu — es geht nichts verloren.",confirmLabel:"Leeren"}))try{await Se("/api/unload",{method:"POST"}),he("Grafikspeicher geleert."),setTimeout(()=>document.dispatchEvent(new Event("mc:refresh")),600)}catch(E){he(E.message,!0)}}async function Ae(){if(!await rn({title:"OS-Updates installieren?",body:"Führt <code>apt update & upgrade</code> aus. Das kann ein paar Minuten dauern; der Fortschritt erscheint in der Aktivität."}))return;const E=await ar({title:"sudo-Passwort",body:"Für die System-Updates wird einmalig dein sudo-Passwort gebraucht.",placeholder:"sudo-Passwort",password:!0,confirmLabel:"Installieren"});if(E)try{const Y=await Se("/api/os-update",{method:"POST",body:JSON.stringify({password:E})});he("OS-Update gestartet."),y(Y.job_id,"OS-Update")}catch(Y){he(Y.message,!0)}}async function Ce(){if(!await rn({title:"Server wirklich neu starten?",body:"Der ganze Bosgame startet physisch neu. Alles ist für ~1 Minute offline — auch dieses Dashboard.",confirmLabel:"Reboot",danger:!0}))return;const E=await ar({title:"sudo-Passwort",body:"Für den Reboot wird einmalig dein sudo-Passwort gebraucht.",placeholder:"sudo-Passwort",password:!0,confirmLabel:"Jetzt neustarten",danger:!0});if(E)try{await Se("/api/reboot",{method:"POST",body:JSON.stringify({password:E})}),he("Reboot ausgelöst — bis gleich.")}catch(Y){he(Y.message,!0)}}async function Be(){u(De,"prüfe…");try{const E=await Se("/api/integration/test");u(De,E.ok?`✓ Engine antwortet — ${E.models.length} Modell(e): ${E.models.join(", ")}`:`✗ keine Verbindung: ${E.error}`,!0),u(se,E.ok,!0)}catch(E){u(De,"✗ "+E.message),u(se,!1)}}let De=F(""),se=F(!1);const le=U(()=>{var E;return((E=t(a))==null?void 0:E.models)||[]}),$e=["running","ready","loading","starting"],Te=U(()=>t(le).find(E=>$e.includes(E.state)));function We(E){if(!E||E.state!=="running")return null;if(typeof E.progress=="number")return Math.min(100,E.progress);const fe=((E.log||[]).at(-1)||"").match(/(\d+(?:\.\d+)?)\s*%/);return fe?Math.min(100,parseFloat(fe[1])):null}var rt=Yd(),Je=i(Ye(rt),2),R=r(Je),_e=i(r(R),2),Re=r(_e),at=i(R,4),Q=r(at),de=i(r(Q)),xe=r(de),et=i(Q,2),Ve=i(r(et),2),tt=r(Ve),Ke=i(et,2),it=i(r(Ke),2),dt=r(it),ht=i(at,2),ct=r(ht),_t=i(ct,2);{var At=E=>{var Y=Vd(),fe=r(Y);$(()=>{St(Y,`color:${t(se)?"#7ee29a":"#ff9b95"}`),h(fe,t(De))}),p(E,Y)};O(_t,E=>{t(De)&&E(At)})}var xt=i(Je,2),Pt=i(r(xt),4),Ct=i(Pt,2),kt=i(Ct,2),B=i(kt,2),Z=i(B,2),D=i(xt,2),J=i(r(D),4),M=i(J,2),ie=i(D,2);{var ke=E=>{const Y=U(()=>t(T)),fe=U(()=>t(Y).state==="done"),Me=U(()=>t(Y).state==="failed"),ne=U(()=>t(Y).state==="canceled"),ce=U(()=>t(fe)||t(Me)||t(ne)),ze=U(()=>We(t(Y)));var Pe=Zd(),w=r(Pe),ee=i(r(w),2);{var ge=j=>{var te=Wd();S("click",te,async()=>{await rn({title:t(f)+" abbrechen?",body:"Der laufende Vorgang wird gestoppt.",confirmLabel:"Abbrechen",danger:!0})&&Se(`/api/jobs/${t(Y).id}/cancel`,{method:"POST"})}),p(j,te)};O(ee,j=>{t(ce)||j(ge)})}var m=i(ee,2),x=r(m);{var A=j=>{var te=jd();p(j,te)},q=j=>{var te=Ud();p(j,te)},H=j=>{var te=Hd();p(j,te)},G=j=>{var te=Jd();p(j,te)};O(x,j=>{t(fe)?j(A):t(Me)?j(q,1):t(ne)?j(H,2):j(G,-1)})}var P=i(w,2),W=r(P),L=i(P,2);{var X=j=>{var te=Qd(),Le=r(te);$(()=>St(Le,`width:${t(ze)??""}%`)),p(j,te)};O(L,j=>{t(ze)!=null&&!t(ce)&&j(X)})}var ae=i(L,2),ue=r(ae);$(j=>{h(W,`${t(f)??""}${t(ce)?t(fe)?" — erfolgreich.":t(ne)?" — abgebrochen.":" — fehlgeschlagen.":" läuft…"}`),h(ue,j)},[()=>(t(Y).log||[]).join(`
|
||
`)]),p(E,Pe)};O(ie,E=>{t(T)&&E(ke)})}var Ie=i(ie,2),z=r(Ie),N=i(r(z),2),ve=r(N);ve.value=ve.__value="llama-swap";var oe=i(ve);oe.value=oe.__value="mission-control";var re=i(oe);re.value=re.__value="system";var we=i(z,4),pe=r(we);Wo(we,E=>v=E,()=>v),$(E=>{var Y,fe,Me;St(_e,`margin-left:auto;${(Y=t(a))!=null&&Y.swap_ok?"background:rgba(63,185,80,.12);border-color:rgba(63,185,80,.25);color:#7ee29a":"background:rgba(248,81,73,.12);border-color:rgba(248,81,73,.3);color:#ff9b95"}`),h(Re,(fe=t(a))!=null&&fe.swap_ok?"● erreichbar":"● offline"),h(xe,(((Me=t(a))==null?void 0:Me.swap_url)||"—")+"/v1"),h(tt,t(Te)?t(Te).name+` (${t(Te).state})`:"nichts geladen — lädt bei der nächsten Anfrage"),h(dt,E),h(pe,t(o))},[()=>t(le).filter(E=>!E.incomplete).length||"keine"]),S("click",ct,Be),S("click",Pt,()=>I("llama-swap","LLM-Engine neustarten?","Die Engine startet neu. Geladene Modelle werden kurz entladen (~5 Sekunden), laden danach automatisch wieder.")),S("click",Ct,()=>I("mission-control","Dashboard neustarten?","Diese Oberfläche trennt sich kurz und verbindet automatisch wieder.")),S("click",kt,K),S("click",B,C),S("click",Z,V),S("click",J,Ae),S("click",M,Ce),S("change",N,k),On(N,()=>t(d),E=>u(d,E)),p(e,rt),wn()}$n(["click","change"]);var ec=g('<div class="empty" style="text-align:center;padding:30px">Lade Setups…</div>'),tc=g('<span title="Setup bearbeiten" style="position:absolute;top:10px;right:36px;color:var(--accent);cursor:pointer;font-size:14px;line-height:1" role="button" tabindex="0">✎</span> <span title="Setup löschen" style="position:absolute;top:9px;right:12px;color:var(--err);cursor:pointer;font-size:18px;line-height:1" role="button" tabindex="0">×</span>',1),ir=g('<div class="cb-best-tag">★ Beste Wahl für dein System</div>'),nc=g('<div class="cb-best-tag" style="background:var(--act);color:#fff">Dein Setup</div>'),ac=g('<button style="text-align:left;position:relative"><!> <!> <div class="flex justify-between items-center"><span class="flex items-center gap-2"><h3 style="margin:0;font-size:15px"> </h3></span> <span> </span></div> <p> </p> <div class="text-xs text-mut"> </div></button>'),ic=g('<div id="cb-recipes" class="grid grid-3" style="gap:10px;margin-top:6px"></div>'),rc=g('<div class="card"><div class="card-h"><h3>Fertige Setups — automatisch aktuell für deine Hardware</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>'),sc=g('<span style="color:var(--warn)">· ⚠ Cache veraltet</span>'),lc=g("<!> <!>",1),oc=g('<div class="empty" style="text-align:center;padding:30px">Frage Quellen ab…</div>'),dc=g('<div class="li-sub" style="color:var(--warn);margin-top:3px"> </div>'),cc=g('<span class="fit-badge ok">✓ installiert</span>'),vc=g('<button class="primary" style="padding:6px 12px;font-size:12.5px">Installieren</button>'),uc=g('<div style="display:flex;flex-direction:column;position:relative"><!> <div class="flex justify-between" style="align-items:flex-start;gap:8px"><div style="min-width:0"><h3 style="margin:0;font-size:14px;font-weight:500;word-break:break-word"> </h3> <div class="text-xs text-mut" style="margin-top:3px"> </div></div> <span> </span></div> <div class="flex gap-2" style="flex-wrap:wrap;margin-top:7px"></div> <div class="mono-sm text-mut" style="margin-top:8px;font-size:11.5px"> </div> <!> <div style="flex:1;min-height:8px"></div> <div class="flex justify-end" style="margin-top:10px"><!></div></div>'),pc=g('<div style="margin-bottom:8px"><div class="flex items-center gap-2" style="margin:6px 0 8px"><h4 style="margin:0;font-size:13.5px;font-weight:600"> </h4></div> <div class="grid grid-3"></div></div>'),fc=g('<button style="padding:4px 10px;border-radius:999px;font-size:12px"> </button>'),hc=g('<button class="ghost" style="padding:4px 10px;border-radius:999px;font-size:12px;color:var(--mut)">✕ zurücksetzen</button>'),gc=g('<div style="display:flex;flex-direction:column;cursor:pointer"><!> <div class="flex justify-between" style="align-items:flex-start;gap:8px"><div style="min-width:0"><h3 style="margin:0;font-size:14.5px;font-weight:500;word-break:break-word"> </h3> <div class="text-xs text-mut" style="margin-top:3px"> </div></div> <span> </span></div> <div class="flex gap-2" style="flex-wrap:wrap;margin-top:7px"></div> <div style="flex:1;margin-top:12px"></div> <div class="flex justify-between items-center text-xs text-mut" style="border-top:1px solid var(--line);padding-top:11px"><span class="mono-sm"> </span> <span class="mono-sm"> </span></div></div>'),mc=g('<div class="grid grid-3" id="cb-grid"></div>'),bc=g('<div class="card"><div class="card-h"><h3>Aktuell die besten Modelle für dein System</h3> <span class="meta" style="margin-left:auto"><!></span> <button class="ghost" style="margin-left:8px"> </button></div> <div class="card-sub">Top-Modelle je Kategorie von HuggingFace — Hardware-Fit wird live für dein System berechnet.</div> <!></div> <div class="card"><div class="card-h"><h3>Profi-Suche (HuggingFace)</h3></div> <div class="card-sub">Direkt HuggingFace durchsuchen — oder eine Modell-URL einfügen für den direkten Sprung.</div> <div class="flex gap-2" style="align-items:stretch;margin-bottom:10px"><input placeholder="Suchbegriff oder HuggingFace-URL…" style="flex:1;margin:0"/> <select style="width:auto;margin:0"><option>Downloads</option><option>Trending</option><option>Neu</option></select> <button class="primary"> </button></div> <div class="flex gap-2" style="flex-wrap:wrap;margin-bottom:12px;align-items:center"><span class="text-xs text-mut" style="margin-right:2px">Filter:</span> <!> <!></div> <!></div>',1),_c=g('<div class="li-sub"> </div>'),yc=g('<div class="li-sub mono-sm"> </div>'),xc=g("<span> </span>"),kc=g('<div class="li" style="align-items:flex-start"><div class="li-main"><div class="flex items-center gap-2" style="flex-wrap:wrap"><span class="li-id"> </span> <span class="tag text"> </span> <!></div> <!> <!></div> <!></div>'),wc=g('<div class="hint" style="margin:12px 0">Größter Spitzenbedarf: <b> </b>. Es läuft immer nur <b>ein</b> Modell gleichzeitig — das größte bestimmt, ob das Setup passt.</div>'),Sc=g('Alternative: <a href="#" style="color:var(--accent)"> </a> — passt auf dein System.',1),Mc=g('<div class="hint" style="color:var(--warn);margin-bottom:10px;border-left:2px solid var(--warn);padding-left:10px">⚠ Dieses Setup übersteigt deinen verfügbaren Speicher. <!></div>'),Ec=g('<div class="modal-overlay" role="dialog"><div class="modal-card" style="max-width:560px"><button class="ghost" style="position:absolute;top:14px;right:14px">Schließen</button> <h3> </h3> <p class="text-mut text-sm" style="margin:-4px 0 16px"> </p> <div class="list"></div> <!> <!> <button id="cb-r-install-btn" style="width:100%"> </button></div></div>'),Ac=g('<div class="hint">Lade Dateien von HuggingFace…</div>'),ts=g("<option> </option>"),Cc=g('<div class="hint" style="margin:-6px 0 14px">Empfohlener Kontext für deine Hardware: <b> </b> — <a href="#">übernehmen</a></div>'),Tc=g('<div class="tile" style="display:flex;justify-content:space-between;align-items:center;margin:8px 0 18px"><div><div style="font-size:13px">Ressourcen-Check</div> <div class="hint" style="margin:4px 0 0"> </div></div> <span> </span></div>'),zc=g('<div class="hint" style="color:var(--warn);margin:-8px 0 14px;border-left:2px solid var(--warn);padding-left:10px">⚠ Diese Datei ist zu groß für deinen Speicher. Kleinere Alternative: <a href="#" style="color:var(--accent)"> </a> — einfach auswählen.</div>'),$c=g('<div class="hint" style="color:var(--warn);margin:-8px 0 14px;border-left:2px solid var(--warn);padding-left:10px">⚠ Alle Varianten dieses Modells sind zu groß für deinen Speicher. Ein kleineres Modell aus den Empfehlungen wäre die bessere Wahl.</div>'),Pc=g('<label>Quantisierung (GGUF-Datei) wählen</label> <select></select> <div class="row" style="margin-top:4px"><div><label>Rolle (optional)</label> <input placeholder="z.B. coder, vision, scout"/></div> <div><label>Kontext-Größe <!></label> <input type="number"/></div></div> <!> <!> <!> <button style="width:100%"> </button>',1),Dc=g('<div class="hint">Keine GGUF-Dateien im Repo gefunden.</div>'),Ic=g('<div class="modal-overlay" role="dialog"><div class="modal-card" style="max-width:560px"><button class="ghost" style="position:absolute;top:14px;right:14px">Schließen</button> <h3> </h3> <p class="mono-sm" style="margin:-4px 0 16px"> </p> <!></div></div>'),Lc=g('<div class="flex gap-2" style="margin-bottom:8px;align-items:center"><input placeholder="Repo, z.B. unsloth/Qwen3-8B-GGUF" style="flex:2;margin:0"/> <input placeholder="Rolle (z.B. coder)" style="flex:1;margin:0"/> <select style="width:auto;margin:0"></select> <button class="ghost del" style="margin:0;padding:6px 10px">×</button></div>'),Oc=g('<div class="modal-overlay" role="dialog"><div class="modal-card" style="max-width:640px"><button class="ghost" style="position:absolute;top:14px;right:14px">Schließen</button> <h3> </h3> <p class="text-mut text-sm" style="margin:-4px 0 16px">Stell dir aus beliebigen Modellen ein eigenes Setup zusammen.</p> <label>Titel</label> <input placeholder="z.B. Mein Schreib-Stack"/> <label>Kurzbeschreibung (optional)</label> <input placeholder="Wofür ist dieses Setup gut?"/> <label style="margin-top:10px">Modelle</label> <!> <button class="ghost" style="margin-top:8px">+ Modell hinzufügen</button> <div class="hint" style="margin-top:10px">Die <b>Repo-ID</b> findest du über die <b>Profi-Suche</b> weiter unten (z.B. <code>unsloth/Qwen3-8B-GGUF</code>).</div> <button class="primary" style="width:100%;margin-top:14px"> </button></div></div>'),Bc=g('<div class="pagehead"><div><h1>Cookbook</h1><div class="sub">Modelle finden, installieren und eigene Setups zusammenstellen.</div></div></div> <div class="flex gap-2" style="margin-bottom:14px"><button style="padding:7px 16px">📦 Fertige Setups</button> <button style="padding:7px 16px">🔍 Modelle finden</button></div> <!> <!> <!> <!> <!>',1);function Rc(e,n){kn(n,!0);const a="Kontext = das Kurzzeitgedächtnis des Modells. Größer = merkt sich mehr, braucht aber mehr Speicher und wird etwas langsamer.",s="MoE (Mixture of Experts): viele Parameter fürs Wissen, aber pro Wort ist nur ein kleiner Teil aktiv → fast große-Modell-Qualität bei hohem Tempo. Ideal für deine APU.",l={perfect:0,marginal:1,too_tight:2},o=["qwen2.5","qwen3","qwen2","hermes","mistral","mixtral","devstral","command-r","command_r","llama-3.1","llama3.1","llama-3.3","llama-4","llama4","functionary","watt","firefunction","granite","glm-4","ministral","gemma-3","gemma3"],d=["-r1","deepseek-r1","qwq","magistral","-think","thinking","-o1","gpt-oss","reasoning","exaone-deep","phi-4-reasoning"];function v(m,x=[]){const A=(m||"").toLowerCase(),q=(x||[]).map(P=>String(P).toLowerCase()),H=q.some(P=>P.includes("function-calling")||P.includes("tool-use")||P.includes("tools")),G=o.some(P=>A.includes(P));return{moe:y(A),active_b:k(A),vision:["-vl","vision","llava","pixtral","multimodal","-mm-"].some(P=>A.includes(P))||q.includes("image-text-to-text"),coder:["coder","-code","code-","codestral","starcoder"].some(P=>A.includes(P)),reasoning:d.some(P=>A.includes(P))||q.includes("reasoning"),tools:H?"yes":G?"likely":"no"}}let c=F(Lt({tools:!1,moe:!1,reasoning:!1,vision:!1,coder:!1}));const f=[["tools","🛠 Tools"],["moe","🧩 MoE"],["reasoning","🧠 Logik"],["vision","👁 Bild"],["coder","💻 Code"]];function _(m,x=[]){const A=Object.keys(t(c)).filter(H=>t(c)[H]);if(!A.length)return!0;const q=v(m,x);return A.every(H=>H==="tools"?q.tools!=="no":q[H])}function T(m,x=[]){const A=v(m,x),q=[];return A.coder&&q.push('<span class="chip">💻 Code</span>'),A.vision&&q.push('<span class="chip">👁 Bild</span>'),A.reasoning&&q.push('<span class="chip">🧠 Logik</span>'),A.moe&&q.push(`<span class="chip" title="${Rn(s)}">🧩 MoE${A.active_b?` · ~${A.active_b}B`:""}</span>`),A.tools==="yes"?q.push('<span class="chip" title="Tool-Calling unterstützt">🛠 Tools</span>'):A.tools==="likely"&&q.push('<span class="chip" style="opacity:.55" title="laut Modell-Familie wahrscheinlich tool-fähig">🛠 Tools?</span>'),!A.coder&&!A.vision&&q.unshift('<span class="chip">💬 Chat</span>'),q.join(" ")}function y(m=""){const x=m.toLowerCase();return/\d+x\d+(\.\d+)?b/.test(x)||new RegExp("(?<![a-z])a\\d+(\\.\\d+)?b\\b").test(x)||x.includes("mixtral")||/\bmoe\b/.test(x)}function k(m=""){const x=m.toLowerCase().match(new RegExp("(?<![a-z])a(\\d+(?:\\.\\d+)?)b\\b"));return x?x[1]:null}function I(m){return m==="perfect"?"ok":m==="marginal"?"warn":"bad"}function K(m){return m==="perfect"?"Passt":m==="marginal"?"Knapp":"Zu groß"}function C(m){return`~${(m.req_gb??0).toFixed(1)} GB · ~${Math.round(m.tps??0)} Tok/s`}let V=F("setups"),Ae=F(Lt([])),Ce=F(null),Be=F(!0),De=F(null),se=F(!1),le=F(!1),$e=F(""),Te=F(Lt([])),We=F(!1),rt=F("downloads"),Je=F(Lt([])),R=F(-1),_e=F(null),Re=F(!1),at=F(""),Q=F(""),de=F(null),xe=F(""),et=F(""),Ve=F(8192),tt=F(!1),Ke=F(null),it=F(!1),dt=F(""),ht=F(""),ct=F(Lt([{repo:"",role:"",quant:"Q4_K_M"}])),_t=F(null);function At(m){var x;(x=document.querySelector(`.nav-item[data-view="${m}"]`))==null||x.dispatchEvent(new MouseEvent("click"))}vi(()=>{xt(),Pt()});async function xt(){u(Be,!0);try{const m=await Se("/api/cookbook/recipes");u(Ae,m.recipes||[],!0),u(Ce,m.recommended_id||null,!0)}catch(m){he(m.message,!0)}u(Be,!1)}async function Pt(m=!1){u(se,!0);try{const x=await Se("/api/cookbook/discover"+(m?"?force=true":""));u(De,x,!0),u(le,x.stale,!0)}catch(x){he("Empfehlungen nicht ladbar: "+x.message,!0)}u(se,!1)}function Ct(m){m=m.trim();const x=m.match(/huggingface\.co\/([^\s/]+\/[^\s/?#]+)/i);return x?x[1]:/^[\w.-]+\/[\w.-]+$/.test(m)?m:null}async function kt(){const m=t($e).trim(),x=Ct(m),A=m;if(!A&&!x){u(Te,[],!0);return}u(We,!0),u(Je,[],!0),u(R,-1);try{if(x)u(Te,[{id:x,author:x.split("/")[0],downloads:0}],!0);else{const q=`https://huggingface.co/api/models?search=${encodeURIComponent(A)}&filter=gguf&full=true&sort=${encodeURIComponent(t(rt))}&direction=-1&limit=40`,H=await fetch(q);u(Te,await H.json(),!0)}t(Te).forEach((q,H)=>B(H,q.id))}catch(q){he(q.message,!0),u(Te,[],!0)}u(We,!1)}async function B(m,x){var A;try{const q=await Se("/api/cookbook/analyze",{method:"POST",body:JSON.stringify({repo_id:x,ctx:8192})});if(!((A=q.files)!=null&&A.length)){t(Je)[m]=null,Z();return}const H=q.files.find(G=>{var P;return(P=G.quant)==null?void 0:P.includes("Q4_K_M")})||q.files[0];t(Je)[m]=H.fit.level,Z()}catch{t(Je)[m]=null,Z()}}function Z(){let m=-1,x=99;t(Je).forEach((A,q)=>{if(A==null)return;const H=l[A]??99;H<x&&(x=H,m=q)}),u(R,m>=0&&x<=1?m:-1,!0)}function D(m){u(_e,t(Ae).find(x=>x.id===m),!0)}async function J(m){const x=document.getElementById("cb-r-install-btn");x&&(x.disabled=!0,x.textContent="Starte…");try{const A=await Se("/api/cookbook/install-recipe",{method:"POST",body:JSON.stringify({recipe_id:m,hf_token:ei()})});he(`${A.count} Download${A.count!==1?"s":""} läuft — Modelle erscheinen danach automatisch im Modelle-Tab.`),u(_e,null),At("activity")}catch(A){he(A.message,!0),x&&(x.disabled=!1,x.textContent="Installieren")}}async function M(m,x){var A,q;u(Re,!0),u(at,x,!0),u(Q,m,!0),u(et,""),u(Ve,8192),u(de,null),u(Ke,null),u(xe,""),u(tt,!0);try{if(u(de,await Se("/api/cookbook/analyze",{method:"POST",body:JSON.stringify({repo_id:m,ctx:8192})}),!0),(q=(A=t(de))==null?void 0:A.files)!=null&&q.length){const H=t(de).files.find(G=>{var P;return(P=G.quant)==null?void 0:P.includes("Q4_K_M")})||t(de).files[0];u(xe,H.filename,!0),H.optimal_ctx&&t(Ve)===8192&&u(Ve,H.optimal_ctx,!0),ie()}}catch(H){he(H.message,!0)}u(tt,!1)}function ie(){var m,x,A;!((x=(m=t(de))==null?void 0:m.files)!=null&&x.length)||!t(xe)||(u(Ke,t(de).files.find(q=>q.filename===t(xe))||null,!0),(A=t(Ke))!=null&&A.optimal_ctx&&t(Ve)===8192&&u(Ve,t(Ke).optimal_ctx,!0))}async function ke(){var m,x;if(!t(Q)||!t(xe))return he("Bitte eine GGUF-Datei wählen.",!0);u(tt,!0);try{const A=((m=t(de))==null?void 0:m.params_b)??7,q=((x=t(Ke))==null?void 0:x.quant)??"Q4_K_M";await Se("/api/cookbook/install-model",{method:"POST",body:JSON.stringify({repo:t(Q),role:t(et),params_b:A,quant:q,file:t(xe),ctx:t(Ve),hf_token:ei()})}),he("Download läuft — Modell erscheint danach automatisch im Modelle-Tab."),u(Re,!1),At("activity")}catch(A){he("Fehler: "+A.message,!0)}u(tt,!1)}async function Ie(m,x,A,q){q.disabled=!0,q.textContent="Starte…";try{await Se("/api/cookbook/install-model",{method:"POST",body:JSON.stringify({repo:m,role:x,params_b:A,quant:"Q4_K_M",hf_token:ei()})}),he("Download läuft — Modell erscheint danach automatisch im Modelle-Tab."),At("activity")}catch(H){he(H.message,!0),q.disabled=!1,q.textContent="Installieren"}}function z(){u(_t,null),u(dt,""),u(ht,""),u(ct,[{repo:"",role:"",quant:"Q4_K_M"}],!0),u(it,!0)}function N(m){const x=t(Ae).find(A=>A.id===m);x&&(u(_t,m,!0),u(dt,x.title,!0),u(ht,x.desc||"",!0),u(ct,x.models.map(A=>({repo:A.repo,role:A.role,quant:A.quant||"Q4_K_M"})),!0),u(it,!0))}async function ve(){if(!t(dt).trim())return he("Bitte einen Titel angeben.",!0);const m=t(ct).filter(x=>x.repo.trim());if(!m.length)return he("Mindestens ein Modell (Repo) angeben.",!0);try{t(_t)?(await Se("/api/cookbook/user-recipe/"+encodeURIComponent(t(_t)),{method:"PUT",body:JSON.stringify({title:t(dt),desc:t(ht),models:m})}),he("Setup aktualisiert.")):(await Se("/api/cookbook/user-recipe",{method:"POST",body:JSON.stringify({title:t(dt),desc:t(ht),models:m})}),he("Setup gespeichert.")),u(it,!1),xt()}catch(x){he(x.message,!0)}}async function oe(m){const x=t(Ae).find(A=>A.id===m);if(await rn({title:`„${(x==null?void 0:x.title)||m}" löschen?`,body:"Dein eigenes Setup wird aus dem Cookbook entfernt. Bereits installierte Modelle bleiben unangetastet.",confirmLabel:"Löschen",danger:!0}))try{await Se("/api/cookbook/user-recipe/"+encodeURIComponent(m),{method:"DELETE"}),he("Setup gelöscht."),xt()}catch(A){he(A.message,!0)}}var re=Bc(),we=i(Ye(re),2),pe=r(we),E=i(pe,2),Y=i(we,2);{var fe=m=>{var x=rc(),A=r(x),q=i(r(A),2),H=i(A,4);{var G=W=>{var L=ec();p(W,L)},P=W=>{var L=ic();Ze(L,21,()=>t(Ae),nt,(X,ae)=>{const ue=U(()=>t(ae).id===t(Ce));var j=ac(),te=r(j);{var Le=me=>{var Ue=tc(),je=Ye(Ue),Ee=i(je,2);S("click",je,ye=>{ye.stopPropagation(),N(t(ae).id)}),S("keydown",je,ye=>{ye.key==="Enter"&&(ye.stopPropagation(),N(t(ae).id))}),S("click",Ee,ye=>{ye.stopPropagation(),oe(t(ae).id)}),S("keydown",Ee,ye=>{ye.key==="Enter"&&(ye.stopPropagation(),oe(t(ae).id))}),p(me,Ue)};O(te,me=>{t(ae).user&&me(Le)})}var Qe=i(te,2);{var Oe=me=>{var Ue=ir();p(me,Ue)},Ne=me=>{var Ue=nc();p(me,Ue)};O(Qe,me=>{t(ue)?me(Oe):t(ae).user&&me(Ne,1)})}var yt=i(Qe,2),Mt=r(yt),wt=r(Mt),vt=r(wt),Et=i(Mt,2),Wt=r(Et),Vt=i(yt,2),fn=r(Vt),qe=i(Vt,2),ut=r(qe);$((me,Ue)=>{bt(j,1,`card-btn${t(ue)?" cb-best":""}`),h(vt,t(ae).title),bt(Et,1,`fit-badge ${me??""}`),h(Wt,Ue),h(fn,t(ae).desc),h(ut,`${t(ae).models.length??""} Modell${t(ae).models.length>1?"e":""} im Setup`)},[()=>I(t(ae).fit_level),()=>K(t(ae).fit_level)]),S("click",j,()=>D(t(ae).id)),p(X,j)}),p(W,L)};O(H,W=>{t(Be)?W(G):W(P,-1)})}S("click",q,z),p(m,x)};O(Y,m=>{t(V)==="setups"&&m(fe)})}var Me=i(Y,2);{var ne=m=>{var x=bc(),A=Ye(x),q=r(A),H=i(r(q),2),G=r(H);{var P=me=>{const Ue=U(()=>Math.round((Date.now()/1e3-t(De).updated)/60));var je=lc(),Ee=Ye(je);{var ye=gt=>{var zt=Ya();$(()=>h(zt,`Quellen befragt vor ${t(Ue)??""} min`)),p(gt,zt)},st=gt=>{var zt=Ya();$(mt=>h(zt,`Quellen befragt vor ${mt??""} h`),[()=>Math.round(t(Ue)/60)]),p(gt,zt)},Tt=gt=>{var zt=Ya();$(mt=>h(zt,`Quellen befragt vor ${mt??""} Tg.`),[()=>Math.round(t(Ue)/1440)]),p(gt,zt)};O(Ee,gt=>{t(Ue)<60?gt(ye):t(Ue)<1440?gt(st,1):gt(Tt,-1)})}var Dt=i(Ee,2);{var Ot=gt=>{var zt=sc();p(gt,zt)};O(Dt,gt=>{t(le)&>(Ot)})}p(me,je)};O(G,me=>{var Ue;(Ue=t(De))!=null&&Ue.updated&&me(P)})}var W=i(H,2),L=r(W),X=i(q,4);{var ae=me=>{var Ue=oc();p(me,Ue)},ue=me=>{var Ue=ua(),je=Ye(Ue);Ze(je,17,()=>t(De).categories,nt,(Ee,ye)=>{var st=pc(),Tt=r(st),Dt=r(Tt),Ot=r(Dt),gt=i(Tt,2);Ze(gt,21,()=>t(ye).models,nt,(zt,mt)=>{const Kn=U(()=>t(ye).recommended&&t(mt).repo===t(ye).recommended);var ma=uc(),Ka=r(ma);{var pi=Ht=>{var hn=ir();p(Ht,hn)};O(Ka,Ht=>{t(Kn)&&Ht(pi)})}var fi=i(Ka,2),hi=r(fi),gi=r(hi),mi=r(gi),Wi=i(gi,2),bi=r(Wi),_i=i(hi,2),yi=r(_i),xi=i(fi,2);lt(xi,()=>T(t(mt).repo,t(mt).tags),!0);var ki=i(xi,2),ji=r(ki),Nn=i(ki,2);Ze(Nn,17,()=>t(mt).requirements||[],nt,(Ht,hn)=>{var ba=dc(),cl=r(ba);$(()=>h(cl,`⚠ ${t(hn)??""}`)),p(Ht,ba)});var Na=i(Nn,4),Ui=r(Na);{var Hi=Ht=>{var hn=cc();$(()=>ga(hn,"title",`bereits eingerichtet als ${t(mt).installed??""}`)),p(Ht,hn)},Ji=Ht=>{var hn=vc();S("click",hn,ba=>Ie(t(mt).repo,t(mt).role,t(mt).params_b,ba.currentTarget)),p(Ht,hn)};O(Ui,Ht=>{t(mt).installed?Ht(Hi):Ht(Ji,-1)})}$((Ht,hn,ba)=>{bt(ma,1,`card${t(Kn)?" res-best":""}`),h(mi,t(mt).name),h(bi,`${t(mt).author??""} · ${t(mt).params_b??""}B`),bt(_i,1,`fit-badge ${Ht??""}`),h(yi,t(mt).fit.text),h(ji,`${hn??""} · ⬇ ${ba??""}`)},[()=>I(t(mt).fit.level),()=>C(t(mt).fit),()=>(t(mt).downloads||0).toLocaleString()]),p(zt,ma)}),$(()=>h(Ot,t(ye).title)),p(Ee,st)}),p(me,Ue)};O(X,me=>{var Ue;t(se)&&!t(De)?me(ae):(Ue=t(De))!=null&&Ue.categories&&me(ue,1)})}var j=i(A,2),te=i(r(j),4),Le=r(te),Qe=i(Le,2),Oe=r(Qe);Oe.value=Oe.__value="downloads";var Ne=i(Oe);Ne.value=Ne.__value="trending";var yt=i(Ne);yt.value=yt.__value="created_at";var Mt=i(Qe,2),wt=r(Mt),vt=i(te,2),Et=i(r(vt),2);Ze(Et,17,()=>f,nt,(me,Ue)=>{var je=U(()=>En(t(Ue),2));let Ee=()=>t(je)[0],ye=()=>t(je)[1];var st=fc(),Tt=r(st);$(()=>{bt(st,1,t(c)[Ee()]?"primary":"ghost"),h(Tt,ye())}),S("click",st,()=>t(c)[Ee()]=!t(c)[Ee()]),p(me,st)});var Wt=i(Et,2);{var Vt=me=>{var Ue=hc();S("click",Ue,()=>u(c,{tools:!1,moe:!1,reasoning:!1,vision:!1,coder:!1},!0)),p(me,Ue)},fn=U(()=>Object.values(t(c)).some(me=>me));O(Wt,me=>{t(fn)&&me(Vt)})}var qe=i(vt,2);{var ut=me=>{var Ue=mc();Ze(Ue,21,()=>t(Te),nt,(je,Ee,ye)=>{var st=ua(),Tt=Ye(st);{var Dt=gt=>{var zt=gc(),mt=r(zt);{var Kn=Nn=>{var Na=ir();p(Nn,Na)};O(mt,Nn=>{ye===t(R)&&Nn(Kn)})}var ma=i(mt,2),Ka=r(ma),pi=r(Ka),fi=r(pi),hi=i(pi,2),gi=r(hi),mi=i(Ka,2),Wi=r(mi),bi=i(ma,2);lt(bi,()=>T(t(Ee).id,t(Ee).tags),!0);var _i=i(bi,4),yi=r(_i),xi=r(yi),ki=i(yi,2),ji=r(ki);$((Nn,Na,Ui,Hi,Ji)=>{bt(zt,1,`card${ye===t(R)?" res-best":""}`),h(fi,Nn),h(gi,t(Ee).author||""),bt(mi,1,`fit-badge ${Na??""}`),h(Wi,Ui),h(xi,Hi),h(ji,`⬇ ${Ji??""}`)},[()=>t(Ee).id.split("/").pop(),()=>t(Je)[ye]?I(t(Je)[ye]):"warn",()=>t(Je)[ye]?K(t(Je)[ye]):"prüfe…",()=>t(Je)[ye]?C({req_gb:0,tps:0}):"Hardware-Fit…",()=>(t(Ee).downloads||0).toLocaleString()]),S("click",zt,()=>M(t(Ee).id,t(Ee).id.split("/").pop())),p(gt,zt)},Ot=U(()=>_(t(Ee).id,t(Ee).tags));O(Tt,gt=>{t(Ot)&>(Dt)})}p(je,st)}),p(me,Ue)};O(qe,me=>{t(Te).length&&me(ut)})}$(()=>{W.disabled=t(se),h(L,t(se)?"Suche…":"Aktualisieren"),Mt.disabled=t(We),h(wt,t(We)?"Lade…":"Suchen")}),S("click",W,()=>Pt(!0)),S("keydown",Le,me=>me.key==="Enter"&&kt()),Yt(Le,()=>t($e),me=>u($e,me)),On(Qe,()=>t(rt),me=>u(rt,me)),S("click",Mt,kt),p(m,x)};O(Me,m=>{t(V)==="find"&&m(ne)})}var ce=i(Me,2);{var ze=m=>{const x=U(()=>t(_e));var A=Ec(),q=r(A),H=r(q),G=i(H,2),P=r(G),W=i(G,2),L=r(W),X=i(W,2);Ze(X,21,()=>t(x).models,nt,(Oe,Ne)=>{var yt=kc(),Mt=r(yt),wt=r(Mt),vt=r(wt),Et=r(vt),Wt=i(vt,2),Vt=r(Wt),fn=i(Wt,2);lt(fn,()=>T(t(Ne).repo,t(Ne).tags));var qe=i(wt,2);{var ut=ye=>{var st=_c(),Tt=r(st);$(()=>h(Tt,t(Ne).why)),p(ye,st)};O(qe,ye=>{t(Ne).why&&ye(ut)})}var me=i(qe,2);{var Ue=ye=>{var st=yc(),Tt=r(st);$((Dt,Ot,gt)=>h(Tt,`~${Dt??""} GB · ~${Ot??""} Tok/s · optimal ~${gt??""}k Kontext`),[()=>(t(Ne).fit.req_gb??0).toFixed(1),()=>Math.round(t(Ne).fit.tps??0),()=>Math.round((t(Ne).optimal_ctx||8192)/1024)]),p(ye,st)};O(me,ye=>{t(Ne).fit&&ye(Ue)})}var je=i(Mt,2);{var Ee=ye=>{var st=xc(),Tt=r(st);$(Dt=>{bt(st,1,`fit-badge ${Dt??""}`),h(Tt,t(Ne).fit.text)},[()=>I(t(Ne).fit.level)]),p(ye,st)};O(je,ye=>{t(Ne).fit&&ye(Ee)})}$(()=>{h(Et,t(Ne).name),h(Vt,t(Ne).role)}),p(Oe,yt)});var ae=i(X,2);{var ue=Oe=>{const Ne=U(()=>Math.max(...t(x).models.map(vt=>{var Et;return((Et=vt.fit)==null?void 0:Et.req_gb)??0})));var yt=wc(),Mt=i(r(yt)),wt=r(Mt);$(vt=>h(wt,`~${vt??""} GB`),[()=>t(Ne).toFixed(1)]),p(Oe,yt)};O(ae,Oe=>{t(x).models.length&&t(x).models[0].fit&&Oe(ue)})}var j=i(ae,2);{var te=Oe=>{const Ne=U(()=>t(Ae).find(vt=>!vt.user&&vt.fit_level!=="too_tight"&&vt.id!==t(x).id));var yt=Mc(),Mt=i(r(yt));{var wt=vt=>{var Et=Sc(),Wt=i(Ye(Et)),Vt=r(Wt);$(()=>h(Vt,`„${t(Ne).title??""}" ansehen`)),S("click",Wt,fn=>{fn.preventDefault(),u(_e,null),setTimeout(()=>D(t(Ne).id),50)}),p(vt,Et)};O(Mt,vt=>{t(Ne)&&vt(wt)})}p(Oe,yt)};O(j,Oe=>{t(x).fit_level==="too_tight"&&Oe(te)})}var Le=i(j,2),Qe=r(Le);$(()=>{h(P,t(x).title),h(L,t(x).desc),bt(Le,1,`primary${t(x).fit_level==="too_tight"?" warn":""}`),h(Qe,t(x).fit_level==="too_tight"?"Trotzdem installieren (nicht empfohlen)":"Komplettes Setup installieren")}),S("click",A,Oe=>{Oe.target.classList.contains("modal-overlay")&&u(_e,null)}),S("click",H,()=>u(_e,null)),S("click",Le,()=>J(t(x).id)),p(m,A)};O(ce,m=>{t(_e)&&m(ze)})}var Pe=i(ce,2);{var w=m=>{var x=Ic(),A=r(x),q=r(A),H=i(q,2),G=r(H),P=i(H,2),W=r(P),L=i(P,2);{var X=j=>{var te=Ac();p(j,te)},ae=j=>{var te=Pc(),Le=i(Ye(te),2);Ze(Le,21,()=>t(de).files,nt,(je,Ee)=>{const ye=U(()=>t(Ee).fit.level==="perfect"?"●":t(Ee).fit.level==="marginal"?"◐":"○");var st=ts(),Tt=r(st),Dt={};$(()=>{h(Tt,`${t(ye)??""} ${t(Ee).filename??""}`),Dt!==(Dt=t(Ee).filename)&&(st.value=(st.__value=t(Ee).filename)??"")}),p(je,st)});var Qe=i(Le,2),Oe=r(Qe),Ne=i(r(Oe),2),yt=i(Oe,2),Mt=r(yt),wt=i(r(Mt));lt(wt,()=>xr(a));var vt=i(Mt,2),Et=i(Qe,2);{var Wt=je=>{var Ee=Cc(),ye=i(r(Ee)),st=r(ye),Tt=i(ye,2);$(Dt=>h(st,`~${Dt??""}k`),[()=>Math.round(t(Ke).optimal_ctx/1024)]),S("click",Tt,Dt=>{Dt.preventDefault(),u(Ve,t(Ke).optimal_ctx,!0)}),p(je,Ee)};O(Et,je=>{var Ee;(Ee=t(Ke))!=null&&Ee.optimal_ctx&&je(Wt)})}var Vt=i(Et,2);{var fn=je=>{var Ee=Tc(),ye=r(Ee),st=i(r(ye),2),Tt=r(st),Dt=i(ye,2),Ot=r(Dt);$((gt,zt,mt)=>{h(Tt,`~${gt??""} GB · ~${zt??""} Tok/s · ${(t(Ke).quant||"GGUF")??""}`),bt(Dt,1,`fit-badge ${mt??""}`),h(Ot,t(Ke).fit.text)},[()=>(t(Ke).fit.req_gb??0).toFixed(1),()=>Math.round(t(Ke).fit.tps??0),()=>I(t(Ke).fit.level)]),p(je,Ee)};O(Vt,je=>{t(Ke)&&je(fn)})}var qe=i(Vt,2);{var ut=je=>{const Ee=U(()=>t(de).files.find(Ot=>Ot.fit.level!=="too_tight"&&Ot.filename!==t(xe)));var ye=ua(),st=Ye(ye);{var Tt=Ot=>{var gt=zc(),zt=i(r(gt)),mt=r(zt);$(Kn=>h(mt,`${t(Ee).filename??""} (${Kn??""})`),[()=>K(t(Ee).fit.level)]),S("click",zt,Kn=>{Kn.preventDefault(),u(xe,t(Ee).filename,!0),ie()}),p(Ot,gt)},Dt=Ot=>{var gt=$c();p(Ot,gt)};O(st,Ot=>{t(Ee)?Ot(Tt):Ot(Dt,-1)})}p(je,ye)};O(qe,je=>{var Ee,ye;((Ee=t(Ke))==null?void 0:Ee.fit.level)==="too_tight"&&((ye=t(de))!=null&&ye.files)&&je(ut)})}var me=i(qe,2),Ue=r(me);$(()=>{var je,Ee;bt(me,1,`primary${((je=t(Ke))==null?void 0:je.fit.level)==="too_tight"?" warn":""}`),me.disabled=t(tt),h(Ue,t(tt)?"Starte…":((Ee=t(Ke))==null?void 0:Ee.fit.level)==="too_tight"?"Trotzdem holen (zu groß — nicht empfohlen)":"Herunterladen & Einpflegen")}),S("change",Le,ie),On(Le,()=>t(xe),je=>u(xe,je)),Yt(Ne,()=>t(et),je=>u(et,je)),Yt(vt,()=>t(Ve),je=>u(Ve,je)),S("click",me,ke),p(j,te)},ue=j=>{var te=Dc();p(j,te)};O(L,j=>{var te,Le;t(tt)&&!t(de)?j(X):(Le=(te=t(de))==null?void 0:te.files)!=null&&Le.length?j(ae,1):t(tt)||j(ue,2)})}$(()=>{h(G,t(at)),h(W,t(Q))}),S("click",x,j=>{j.target.classList.contains("modal-overlay")&&u(Re,!1)}),S("click",q,()=>u(Re,!1)),p(m,x)};O(Pe,m=>{t(Re)&&m(w)})}var ee=i(Pe,2);{var ge=m=>{var x=Oc(),A=r(x),q=r(A),H=i(q,2),G=r(H),P=i(H,6),W=i(P,4),L=i(W,4);Ze(L,17,()=>t(ct),nt,(j,te,Le)=>{var Qe=Lc(),Oe=r(Qe),Ne=i(Oe,2),yt=i(Ne,2);Ze(yt,20,()=>["Q4_K_M","Q5_K_M","Q6_K","Q8_0","Q3_K_M"],nt,(wt,vt)=>{var Et=ts(),Wt=r(Et),Vt={};$(()=>{h(Wt,vt),Vt!==(Vt=vt)&&(Et.__value=vt)}),p(wt,Et)});var Mt=i(yt,2);Yt(Oe,()=>t(te).repo,wt=>t(te).repo=wt),Yt(Ne,()=>t(te).role,wt=>t(te).role=wt),On(yt,()=>t(te).quant,wt=>t(te).quant=wt),S("click",Mt,()=>u(ct,t(ct).filter((wt,vt)=>vt!==Le),!0)),p(j,Qe)});var X=i(L,2),ae=i(X,4),ue=r(ae);$(()=>{h(G,t(_t)?"Setup bearbeiten":"Eigenes Setup erstellen"),h(ue,t(_t)?"Änderungen speichern":"Setup speichern")}),S("click",x,j=>{j.target.classList.contains("modal-overlay")&&u(it,!1)}),S("click",q,()=>u(it,!1)),Yt(P,()=>t(dt),j=>u(dt,j)),Yt(W,()=>t(ht),j=>u(ht,j)),S("click",X,()=>u(ct,[...t(ct),{repo:"",role:"",quant:"Q4_K_M"}],!0)),S("click",ae,ve),p(m,x)};O(ee,m=>{t(it)&&m(ge)})}$(()=>{bt(pe,1,t(V)==="setups"?"primary":"ghost"),bt(E,1,t(V)==="find"?"primary":"ghost")}),S("click",pe,()=>u(V,"setups")),S("click",E,()=>u(V,"find")),p(e,re),wn()}$n(["click","keydown","change"]);var Fc=g(`<div class="alert warn" style="margin:0 0 12px"><span class="a-dot"></span> <span>Du öffnest Mission Control über einen <b>Proxy/Namen</b>. Die Engine läuft auf <b>Port 8080 ohne HTTPS</b> direkt am Bosgame.
|
||
Trag in deinen Tools die <b>LAN-IP</b> ein: <code>http://192.168.178.151:8080/v1</code> — nicht den Proxy-Namen.</span></div>`),Kc=g('<span class="mono-sm"> </span>'),Nc=g('<div class="tile" style="display:flex;gap:12px;align-items:flex-start"><span style="font-size:20px;line-height:1;flex:0 0 auto"> </span> <div><div style="font-weight:500;font-size:13.5px"> </div> <div class="card-sub" style="margin:4px 0 0"> </div></div></div>'),qc=g('<span class="chip" role="button" tabindex="0"> </span>'),Gc=g('<div style="margin-top:10px"><a href="#" style="color:var(--mut);font-size:12.5px">Auswahl aufheben (alle)</a></div>'),ns=g('<button style="text-align:left;padding:12px 16px"><div style="font-weight:500;font-size:13.5px"> </div> <div class="card-sub" style="margin:3px 0 0"> </div></button>'),Vc=g('<p><b>Jan AI</b> ist eine Desktop-App — kein Browser, kein Server, kein Admin-Panel. Einfach installieren und loslegen.</p> <p>Jan AI öffnen → linke Leiste → <b>Remote-Modelle</b> → <b>+ Modell hinzufügen</b>:</p> <label>Basis-URL (kopieren und in Jan AI einfügen)</label> <div class="flex gap-2" style="align-items:stretch;margin-bottom:12px"><input class="mono-sm" readonly="" style="flex:1;margin:0"/> <button class="ghost">Kopieren</button></div> <label>Modell-ID (in Jan AI als „Model name" eintragen)</label> <div class="flex gap-2" style="align-items:stretch;margin-bottom:12px"><input class="mono-sm" readonly="" style="flex:1;margin:0"/> <button class="ghost">Kopieren</button></div> <div class="hint">API-Key: ein beliebiger Wert (z.B. <code>local</code>). Jan AI fragt danach beim Einrichten.</div> <div class="hint" style="margin-top:8px">Jan AI herunterladen: <a href="https://jan.ai" target="_blank" rel="noopener">jan.ai</a> — kostenlos, open source, Windows/macOS/Linux.</div>',1),Wc=g('<p>Datei anlegen oder öffnen: <code>~/.continue/config.json</code></p> <div class="alert warn" style="margin:8px 0 12px;padding:10px 14px"><span class="a-dot"></span><span>Falls bereits eine <code>config.json</code> vorhanden: nur den <code>"models"</code>-Eintrag ergänzen, nicht die ganze Datei ersetzen.</span></div> <div style="position:relative"><button class="ghost" style="position:absolute;top:8px;right:8px;z-index:1">Kopieren</button> <div class="log" style="max-height:none"><code> </code></div></div> <p style="margin-top:12px">Danach Continue in VS Code neu starten → im Chat-Panel das Modell <b> </b> wählen.</p> <div class="hint">Continue: <a href="https://continue.dev" target="_blank" rel="noopener">continue.dev</a> — kostenlose VS Code / JetBrains Extension. Hinweis: 2026 von Cursor akquiriert — aktuell weiter aktiv und kostenlos.</div>',1),jc=g('<p><b>Antigravity</b> (Googles agentic IDE, VS Code-basiert) unterstützt OpenAI-kompatible Endpoints direkt:</p> <p>Settings → Models → <b>Custom Endpoint</b> → <b>+ hinzufügen</b>:</p> <label>Basis-URL</label> <div class="flex gap-2" style="align-items:stretch;margin-bottom:12px"><input class="mono-sm" readonly="" style="flex:1;margin:0"/> <button class="ghost">Kopieren</button></div> <label>Modell-ID</label> <div class="flex gap-2" style="align-items:stretch;margin-bottom:12px"><input class="mono-sm" readonly="" style="flex:1;margin:0"/> <button class="ghost">Kopieren</button></div> <div class="hint">API-Key: ein beliebiger Wert (z.B. <code>local</code>). Danach das Modell <b> </b> in der Model-Liste auswählen.</div> <div class="hint" style="margin-top:8px">Antigravity herunterladen: <a href="https://antigravityide.net" target="_blank" rel="noopener">antigravityide.net</a> — kostenlose Einzelperson-Tier, VS Code-basiert.</div>',1),Uc=g('<p>Öffne die Zed-Settings mit <code>Cmd/Strg + ,</code> und <b>füge diesen Block</b> in deine bestehende <code>settings.json</code> ein. Falls bereits ein <code>"bosgame"</code>-Eintrag existiert: vorher löschen.</p> <div class="alert warn" style="margin-bottom:12px;padding:10px 14px"><span class="a-dot"></span><span>Nur diesen Block einfügen, <b>nicht die ganze Datei ersetzen</b> — sonst gehen andere Einstellungen verloren.</span></div> <div style="position:relative"><button class="ghost" style="position:absolute;top:8px;right:8px;z-index:1">Kopieren</button> <div class="log" style="max-height:none"><code> </code></div></div> <p style="margin-top:12px"><b>API-Key:</b> Öffne den Agent-Panel → Anbieter <b>bosgame</b> → trag irgendeinen Wert ein (z.B. <code>local</code>).</p> <div class="hint">Danach im Agent-Panel das Modell <b> </b> auswählen.</div> <div class="hint" style="margin-top:4px">Zed herunterladen: <a href="https://zed.dev" target="_blank" rel="noopener">zed.dev</a> — kostenlos, native Performance, Windows/macOS/Linux.</div>',1),Hc=g('<p>Datei anlegen oder öffnen (OpenCode Desktop nutzt <b>.jsonc</b> — JSON mit Kommentaren):</p> <p class="mono-sm" style="line-height:1.6">Windows: <code>%USERPROFILE%\\.config\\opencode\\opencode.jsonc</code></p> <div class="alert warn" style="margin:8px 0 12px;padding:10px 14px"><span class="a-dot"></span><span>Den <code>"providers"</code>-Block in die bestehende <code>opencode.jsonc</code> einfügen (nicht die ganze Datei ersetzen). Falls bereits ein <code>"llama-swap"</code>-Eintrag existiert: <b>vorher löschen</b>.</span></div> <div style="position:relative"><button class="ghost" style="position:absolute;top:8px;right:8px;z-index:1">Kopieren</button> <div class="log" style="max-height:none"><code> </code></div></div> <p style="margin-top:12px">Danach in OpenCode <code>/models</code> → <b> </b> wählen.</p> <div class="hint">OpenCode Desktop: <a href="https://opencode.ai" target="_blank" rel="noopener">opencode.ai</a></div>',1),Jc=g('<p>In Cline/Cursor den Provider <b>„OpenAI Compatible"</b> wählen:</p> <label>Basis-URL</label> <div class="flex gap-2" style="align-items:stretch;margin-bottom:12px"><input class="mono-sm" readonly="" style="flex:1;margin:0"/> <button class="ghost">Kopieren</button></div> <label>Modell-ID</label> <div class="flex gap-2" style="align-items:stretch;margin-bottom:12px"><input class="mono-sm" readonly="" style="flex:1;margin:0"/> <button class="ghost">Kopieren</button></div> <div class="hint">API-Key: ein beliebiger Wert (z.B. <code>local</code>).</div> <div class="hint" style="margin-top:4px">Cline für VS Code: <a href="https://marketplace.visualstudio.com/items?itemName=saoudrizwan.claude-dev" target="_blank" rel="noopener">VS Code Marketplace</a> · für JetBrains: <a href="https://plugins.jetbrains.com/plugin/24604-cline" target="_blank" rel="noopener">JetBrains Marketplace</a></div>',1),Qc=g('<p>Settings → Admin Panel → Connections → neue OpenAI-Verbindung:</p> <label>Basis-URL</label> <div class="flex gap-2" style="align-items:stretch;margin-bottom:12px"><input class="mono-sm" readonly="" style="flex:1;margin:0"/> <button class="ghost">Kopieren</button></div> <label>API-Key</label> <div class="flex gap-2" style="align-items:stretch"><input class="mono-sm" readonly="" value="dummy-key" style="flex:1;margin:0"/> <button class="ghost">Kopieren</button></div>',1),Zc=g('<div class="card"><div class="card-h"><h3>Bilder einbinden (Vision)</h3> <span class="chip" style="background:rgba(63,185,80,.12);border-color:rgba(63,185,80,.25);color:#7ee29a"><!> </span></div> <div class="card-sub">Mit Vision-Modellen kannst du Screenshots oder Fehlerbilder direkt mitschicken.</div> <div style="position:relative;margin-top:8px"><button class="ghost" style="position:absolute;top:8px;right:8px;z-index:1">Kopieren</button> <div class="log" style="max-height:none"><code> </code></div></div></div>'),Yc=g('<div class="card"><div class="card-h"><h3>2 · Modelle auswählen</h3> <span class="meta"> </span></div> <div class="card-sub">Wähle, welche Modelle im Config-Snippet erscheinen sollen.</div> <div class="flex gap-2" style="flex-wrap:wrap"></div> <!></div> <div class="card"><div class="card-h"><h3>3 · Tool wählen</h3></div> <div class="card-sub" style="margin-bottom:8px">Für welches Werkzeug brauchst du die Konfiguration?</div> <div style="font-size:10.5px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--accent);margin-bottom:6px">Chat</div> <div class="grid grid-3" style="gap:8px;margin-bottom:14px"></div> <div style="font-size:10.5px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--accent);margin-bottom:6px">Coding-Assistenten</div> <div class="grid grid-3" style="gap:8px"></div></div> <div class="card"><div class="card-h"><h3>4 · Config-Snippet</h3></div> <!></div> <!>',1),Xc=g('<div class="card"><div class="card-h"><h3>2 · Erst ein Modell installieren</h3></div> <div class="empty-c" style="padding:8px 0 4px"><div class="e-t">Noch kein Modell eingerichtet</div> <div class="e-s">Bevor du ein Tool verbinden kannst, braucht die Engine mindestens ein Modell. Das Config-Snippet wird dann automatisch mit deinen echten Modellnamen befüllt.</div> <button class="primary" style="margin-top:14px">→ Zum Cookbook (Modell holen)</button></div></div>'),ev=g('<button style="text-align:left;padding:10px 14px"><div style="font-weight:500;font-size:13px"> </div> <div class="card-sub" style="margin:2px 0 0;font-size:11.5px"> </div></button>'),tv=g('<p style="margin-top:12px">In <b>Cline</b>: MCP-Einstellungen öffnen (Stecker-Icon in der Cline-Sidebar) → „Add MCP Server" → diesen Block einfügen.</p> <p>In <b>Claude Code</b>: Block in <code>~/.claude/settings.json</code> unter <code>"mcpServers"</code> einfügen.</p> <div class="alert warn" style="margin-top:8px;padding:10px 14px"><span class="a-dot"></span> <span>Einmalig auf dem Windows-PC: <code>pip install mcp httpx</code> ausführen — danach <code>mcp_memory.py</code> aus dem Repo-Ordner erreichbar machen (Pfad im Snippet anpassen).</span></div>',1),nv=g('<p style="margin-top:12px">Block in <code>~/.config/opencode/opencode.json</code> unter <code>"mcpServers"</code> einfügen.</p> <div class="alert warn" style="margin-top:8px;padding:10px 14px"><span class="a-dot"></span> <span>Einmalig: <code>pip install mcp httpx</code> — und Pfad zu <code>mcp_memory.py</code> im Snippet anpassen.</span></div>',1),av=g('<p style="margin-top:12px">Block in die MCP-Config des jeweiligen Tools einfügen. Der Bosgame-Pfad <code>/opt/mission-control/mcp_memory.py</code> ist bereits korrekt — kein weiteres Setup nötig.</p>'),iv=g(`<div class="pagehead"><div><h1>Verbinden</h1> <div class="sub">Schritt für Schritt: KI-Modelle in deine Tools einbinden — getestet, erklärt, mit Copy-Paste-Config.</div></div></div> <div class="card"><div class="card-h"><h3>1 · Verbindung prüfen</h3></div> <div class="card-sub">Stelle sicher, dass die LLM-Engine erreichbar ist, bevor du Tools konfigurierst.</div> <label>Engine-Adresse (für alle Tools)</label> <div class="flex gap-2" style="align-items:stretch;margin-bottom:4px"><input class="mono-sm" readonly="" style="flex:1;margin:0"/> <button class="ghost">Kopieren</button></div> <div class="flex gap-2" style="align-items:stretch;margin-bottom:12px"><input class="mono-sm" placeholder="LAN-IP überschreiben, z.B. 192.168.178.151 (leer = auto)" style="flex:1;margin:0;font-size:12px;opacity:.7"/></div> <!> <div class="btn-row" style="display:flex;align-items:center;gap:10px"><button class="primary">Verbindung testen</button> <!></div></div> <div class="card"><div class="card-h"><h3>Wie funktioniert das Auto-Swap?</h3></div> <div style="display:flex;flex-direction:column;gap:10px"></div></div> <!> <div class="card"><div class="card-h"><h3>Gedächtnis-MCP</h3> <span class="chip" style="background:rgba(45,212,191,.1);border-color:rgba(45,212,191,.3);color:var(--accent)">Neu in v7</span></div> <div class="card-sub" style="margin-bottom:14px">Damit Cline, OpenCode und Claude Code sich Projektfakten, Entscheidungen und Präferenzen
|
||
über Sessions hinweg merken — geteilt über alle Tools, verwaltet im <a href="#" style="color:var(--accent)">Gedächtnis-Tab</a>.</div> <div class="flex gap-2" style="margin-bottom:14px;flex-wrap:wrap"></div> <div style="position:relative"><button class="ghost" style="position:absolute;top:8px;right:8px;z-index:1">Kopieren</button> <div class="log" style="max-height:none"><code> </code></div></div> <!></div>`,1);function rv(e,n){kn(n,!0);const a=U(()=>ui.value),s=U(()=>{var z;return(((z=t(a))==null?void 0:z.models)||[]).filter(N=>!N.incomplete)});let l=F("zed"),o=F(Lt([])),d=F(""),v=F(!1),c=F("cline"),f=F(Lt(localStorage.getItem("mc_ip_override")||""));function _(z){return/^\d{1,3}(\.\d{1,3}){3}$/.test(z)}function T(){return location.protocol==="https:"||!_(location.hostname)}function y(){return`http://${t(f).trim()||location.hostname}:8080/v1`}const k=U(y);function I(){const z=t(f).trim();z?localStorage.setItem("mc_ip_override",z):localStorage.removeItem("mc_ip_override")}const K=U(()=>Te(t(c))),C=U(()=>t(o).length?t(o):t(s).map(z=>z.name)),V=U(()=>t(C)[0]||"coder"),Ae=U(()=>{var z;return(z=t(s).find(N=>{var ve,oe;return(oe=(ve=N.meta)==null?void 0:ve.caps)==null?void 0:oe.includes("Bild")}))==null?void 0:z.name});function Ce(z,N){const oe=(N.length?t(s).filter(re=>N.includes(re.name)):t(s).length?t(s):[{name:"coder",meta:{}}]).map(re=>{var E,Y;const we=(((E=re.meta)==null?void 0:E.caps)||[]).some(fe=>/Bild|Vision/i.test(fe)),pe=((Y=re.meta)==null?void 0:Y.ctx)||131072;return` { "name": "${re.name}", "display_name": "${re.name}", "max_tokens": ${pe}${we?', "capabilities": { "tools": true, "images": true }':""} }`}).join(`,
|
||
`);return`"language_models": {
|
||
"openai_compatible": {
|
||
"bosgame": {
|
||
"api_url": "${z}",
|
||
"available_models": [
|
||
${oe}
|
||
]
|
||
}
|
||
}
|
||
}`}function Be(z,N){const oe=(N.length?t(s).filter(re=>N.includes(re.name)):t(s).length?t(s):[{name:"coder",meta:{}}]).map(re=>{var pe;const we=((pe=re.meta)==null?void 0:pe.ctx)||131072;return` "${re.name}": { "name": "${re.name}", "contextWindowSize": ${we} }`}).join(`,
|
||
`);return`"providers": {
|
||
"llama-swap": {
|
||
"npm": "@ai-sdk/openai-compatible",
|
||
"name": "Bosgame (llama-swap)",
|
||
"options": {
|
||
"baseURL": "${z}",
|
||
"apiKey": "local"
|
||
},
|
||
"models": {
|
||
${oe}
|
||
}
|
||
}
|
||
}`}function De(z,N){return`{
|
||
"models": [
|
||
${(N.length?t(s).filter(re=>N.includes(re.name)):t(s).length?t(s):[{name:"coder",meta:{}}]).map(re=>` {
|
||
"title": "llama-swap / ${re.name}",
|
||
"provider": "openai",
|
||
"model": "${re.name}",
|
||
"apiBase": "${z}",
|
||
"apiKey": "local"
|
||
}`).join(`,
|
||
`)}
|
||
]
|
||
}`}async function se(){u(d,"Teste…");try{const z=await Se("/api/integration/test");u(v,z.ok,!0),u(d,z.ok?`✓ Verbunden — ${z.models.length} Modell(e): ${z.models.join(", ")}`:`✗ Keine Verbindung: ${z.error}`,!0)}catch(z){u(v,!1),u(d,"✗ "+z.message)}}function le(z){var ve;const N=z.querySelector("code");N&&((ve=navigator.clipboard)==null||ve.writeText(N.textContent||""))}function $e(z){var N;(N=navigator.clipboard)==null||N.writeText(z.value)}function Te(z){return`{
|
||
"mcpServers": {
|
||
"mission-control-memory": {
|
||
"command": "${z==="bosgame"?"/opt/mission-control/.venv/bin/python":"python"}",
|
||
"args": ["${z==="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 We=iv(),rt=i(Ye(We),2),Je=i(r(rt),6),R=r(Je),_e=i(R,2),Re=i(Je,2),at=r(Re),Q=i(Re,2);{var de=z=>{var N=Fc();p(z,N)},xe=U(()=>T());O(Q,z=>{t(xe)&&z(de)})}var et=i(Q,2),Ve=r(et),tt=i(Ve,2);{var Ke=z=>{var N=Kc(),ve=r(N);$(()=>{St(N,`color:${t(v)?"#7ee29a":"#ff9b95"}`),h(ve,t(d))}),p(z,N)};O(tt,z=>{t(d)&&z(Ke)})}var it=i(rt,2),dt=i(r(it),2);Ze(dt,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."]],nt,(z,N)=>{var ve=U(()=>En(N,3));let oe=()=>t(ve)[0],re=()=>t(ve)[1],we=()=>t(ve)[2];var pe=Nc(),E=r(pe),Y=r(E),fe=i(E,2),Me=r(fe),ne=r(Me),ce=i(Me,2),ze=r(ce);$(()=>{h(Y,oe()),h(ne,re()),h(ze,we())}),p(z,pe)});var ht=i(it,2);{var ct=z=>{var N=Yc(),ve=Ye(N),oe=r(ve),re=i(r(oe),2),we=r(re),pe=i(oe,4);Ze(pe,21,()=>t(s),nt,(G,P)=>{const W=U(()=>t(o).includes(t(P).name));var L=qc(),X=r(L);$(()=>{St(L,`cursor:pointer;${t(W)?"background:rgba(45,212,191,.2);border-color:var(--accent);color:var(--accent)":""}`),h(X,t(P).name)}),S("click",L,()=>u(o,t(W)?t(o).filter(ae=>ae!==t(P).name):[...t(o),t(P).name],!0)),S("keydown",L,ae=>ae.key==="Enter"&&u(o,t(W)?t(o).filter(ue=>ue!==t(P).name):[...t(o),t(P).name],!0)),p(G,L)});var E=i(pe,2);{var Y=G=>{var P=Gc(),W=r(P);S("click",W,L=>{L.preventDefault(),u(o,[],!0)}),p(G,P)};O(E,G=>{t(o).length&&G(Y)})}var fe=i(ve,2),Me=i(r(fe),6);Ze(Me,20,()=>[["janai","Jan AI","Einfachstes Chat-Interface — Desktop-App, kein Setup"],["openwebui","OpenWebUI","Browser-Chat für Teams — mehr Features, mehr Setup"]],nt,(G,P)=>{var W=U(()=>En(P,3));let L=()=>t(W)[0],X=()=>t(W)[1],ae=()=>t(W)[2];var ue=ns(),j=r(ue),te=r(j),Le=i(j,2),Qe=r(Le);$(()=>{bt(ue,1,`card-btn${t(l)===L()?" cb-best":""}`),h(te,X()),h(Qe,ae())}),S("click",ue,()=>u(l,L(),!0)),p(G,ue)});var ne=i(Me,4);Ze(ne,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"]],nt,(G,P)=>{var W=U(()=>En(P,3));let L=()=>t(W)[0],X=()=>t(W)[1],ae=()=>t(W)[2];var ue=ns(),j=r(ue),te=r(j),Le=i(j,2),Qe=r(Le);$(()=>{bt(ue,1,`card-btn${t(l)===L()?" cb-best":""}`),h(te,X()),h(Qe,ae())}),S("click",ue,()=>u(l,L(),!0)),p(G,ue)});var ce=i(fe,2),ze=i(r(ce),2);{var Pe=G=>{var P=Vc(),W=i(Ye(P),6),L=r(W),X=i(L,2),ae=i(W,4),ue=r(ae),j=i(ue,2);$(()=>{Gn(L,t(k)),Gn(ue,t(V))}),S("click",X,te=>$e(te.currentTarget.previousElementSibling)),S("click",j,te=>$e(te.currentTarget.previousElementSibling)),p(G,P)},w=G=>{const P=U(()=>De(t(k),t(C)));var W=Wc(),L=i(Ye(W),4),X=r(L),ae=i(X,2),ue=r(ae),j=r(ue),te=i(L,2),Le=i(r(te)),Qe=r(Le);$(()=>{h(j,t(P)),h(Qe,`llama-swap / ${t(V)??""}`)}),S("click",X,Oe=>le(Oe.currentTarget.parentElement)),p(G,W)},ee=G=>{var P=jc(),W=i(Ye(P),6),L=r(W),X=i(L,2),ae=i(W,4),ue=r(ae),j=i(ue,2),te=i(ae,2),Le=i(r(te),3),Qe=r(Le);$(()=>{Gn(L,t(k)),Gn(ue,t(V)),h(Qe,t(V))}),S("click",X,Oe=>$e(Oe.currentTarget.previousElementSibling)),S("click",j,Oe=>$e(Oe.currentTarget.previousElementSibling)),p(G,P)},ge=G=>{const P=U(()=>Ce(t(k),t(C)));var W=Uc(),L=i(Ye(W),4),X=r(L),ae=i(X,2),ue=r(ae),j=r(ue),te=i(L,4),Le=i(r(te)),Qe=r(Le);$(()=>{h(j,t(P)),h(Qe,`bosgame / ${t(V)??""}`)}),S("click",X,Oe=>le(Oe.currentTarget.parentElement)),p(G,W)},m=G=>{const P=U(()=>Be(t(k),t(C)));var W=Hc(),L=i(Ye(W),6),X=r(L),ae=i(X,2),ue=r(ae),j=r(ue),te=i(L,2),Le=i(r(te),3),Qe=r(Le);$(()=>{h(j,t(P)),h(Qe,`llama-swap/${t(V)??""}`)}),S("click",X,Oe=>le(Oe.currentTarget.parentElement)),p(G,W)},x=G=>{var P=Jc(),W=i(Ye(P),4),L=r(W),X=i(L,2),ae=i(W,4),ue=r(ae),j=i(ue,2);$(()=>{Gn(L,t(k)),Gn(ue,t(V))}),S("click",X,te=>$e(te.currentTarget.previousElementSibling)),S("click",j,te=>$e(te.currentTarget.previousElementSibling)),p(G,P)},A=G=>{var P=Qc(),W=i(Ye(P),4),L=r(W),X=i(L,2),ae=i(W,4),ue=r(ae),j=i(ue,2);$(()=>Gn(L,t(k))),S("click",X,te=>$e(te.currentTarget.previousElementSibling)),S("click",j,te=>$e(te.currentTarget.previousElementSibling)),p(G,P)};O(ze,G=>{t(l)==="janai"?G(Pe):t(l)==="continue"?G(w,1):t(l)==="antigravity"?G(ee,2):t(l)==="zed"?G(ge,3):t(l)==="opencode"?G(m,4):t(l)==="cline"?G(x,5):t(l)==="openwebui"&&G(A,6)})}var q=i(ce,2);{var H=G=>{const P=U(()=>`curl ${t(k)}/chat/completions \\
|
||
-H "Content-Type: application/json" \\
|
||
-d '{
|
||
"model": "${t(Ae)}",
|
||
"messages": [{"role":"user","content":[{"type":"text","text":"Was ist auf dem Bild falsch?"},{"type":"image_url","image_url":{"url":"data:image/png;base64,<DEIN_BILD>"}}]}]
|
||
}'`);var W=Zc(),L=r(W),X=i(r(L),2),ae=r(X);lt(ae,()=>Bt("check"));var ue=i(ae),j=i(L,4),te=r(j),Le=i(te,2),Qe=r(Le),Oe=r(Qe);$(()=>{h(ue,` „${t(Ae)??""}" bereit`),h(Oe,t(P))}),S("click",te,Ne=>le(Ne.currentTarget.parentElement)),p(G,W)};O(q,G=>{t(Ae)&&G(H)})}$(()=>h(we,t(o).length?`${t(o).length} von ${t(s).length} ausgewählt`:"alle werden eingeschlossen")),p(z,N)},_t=z=>{var N=Xc(),ve=i(r(N),2),oe=i(r(ve),4);S("click",oe,()=>{var re;return(re=document.querySelector(".nav-item[data-view='cookbook']"))==null?void 0:re.dispatchEvent(new MouseEvent("click"))}),p(z,N)};O(ht,z=>{t(s).length?z(ct):z(_t,-1)})}var At=i(ht,2),xt=i(r(At),2),Pt=i(r(xt)),Ct=i(xt,2);Ze(Ct,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"]],nt,(z,N)=>{var ve=U(()=>En(N,3));let oe=()=>t(ve)[0],re=()=>t(ve)[1],we=()=>t(ve)[2];var pe=ev(),E=r(pe),Y=r(E),fe=i(E,2),Me=r(fe);$(()=>{bt(pe,1,`card-btn${t(c)===oe()?" cb-best":""}`),h(Y,re()),h(Me,we())}),S("click",pe,()=>u(c,oe(),!0)),p(z,pe)});var kt=i(Ct,2),B=r(kt),Z=i(B,2),D=r(Z),J=r(D),M=i(kt,2);{var ie=z=>{var N=tv();p(z,N)},ke=z=>{var N=nv();p(z,N)},Ie=z=>{var N=av();p(z,N)};O(M,z=>{t(c)==="cline"?z(ie):t(c)==="opencode"?z(ke,1):z(Ie,-1)})}$(()=>{Gn(R,t(k)),h(J,t(K))}),S("click",_e,z=>{const N=z.currentTarget.previousElementSibling;$e(N)}),S("input",at,I),Yt(at,()=>t(f),z=>u(f,z)),S("click",Ve,se),S("click",Pt,z=>{var N;z.preventDefault(),(N=document.querySelector(".nav-item[data-view='memory']"))==null||N.click()}),S("click",B,z=>le(z.currentTarget.parentElement)),p(e,We),wn()}$n(["click","input","keydown"]);var sv=g('<div class="li" style="align-items:flex-start"><div class="li-main"><div class="flex items-center gap-2" style="flex-wrap:wrap"><span class="li-id" style="font-family:var(--sans);font-weight:500"> </span> <span> </span></div> <div class="li-sub"> </div></div> <button class="primary">Installieren</button></div>'),lv=g('<div class="card" style="margin-bottom:18px;border-color:rgba(45,212,191,.25)"><div class="card-h"><h3>Für dich: Upgrades</h3> <span class="meta"> </span></div> <div class="card-sub">Neuere Modelle, die ein installiertes ersetzen können.</div> <div class="list"></div></div>'),ov=g('<div class="empty" style="text-align:center;padding:40px">Lade News… (erstes Laden kann kurz dauern)</div>'),dv=g('<div class="alert err" style="margin:0"> </div>'),cv=g('<div class="empty-c"><div class="e-t">Keine News geladen</div> <div class="e-s">Die Quellen sind gerade nicht erreichbar — später nochmal probieren.</div></div>'),vv=g('<span class="news-rel">für dich</span>'),uv=g('<a target="_blank" rel="noopener"><div class="news-meta"><span class="news-src"> </span> <!> <span class="news-date"> </span></div> <div class="news-title"> </div></a>'),pv=g('<div class="news-grid"></div>'),fv=g('<div class="pagehead"><div><h1>News</h1> <div class="sub">Aktuelles aus der Local-LLM-Welt — aus kuratierten Quellen.</div></div> <button class="ghost">Aktualisieren</button></div> <!> <!>',1);function hv(e,n){kn(n,!0);let a=F(Lt([])),s=F(Lt([])),l=F(!0),o=F("");const d=se=>se==="perfect"?"ok":se==="marginal"?"warn":"bad";function v(se){const le=Math.max(0,Date.now()/1e3-se);return le<60?le+"s":le<3600?Math.floor(le/60)+"m":le<86400?Math.floor(le/3600)+"h":Math.floor(le/86400)+"d"}async function c(){u(l,!0),u(o,"");try{u(a,(await Se("/api/news")).items||[],!0)}catch(se){u(o,se.message||"Fehler beim Laden",!0)}finally{u(l,!1)}}async function f(){try{u(s,(await Se("/api/cookbook/upgrades")).upgrades||[],!0)}catch{u(s,[],!0)}}async function _(se,le){var $e;le.disabled=!0,le.textContent="Starte…";try{await Se("/api/cookbook/install-model",{method:"POST",body:JSON.stringify({repo:se.repo,role:se.role,params_b:se.params_b,quant:se.quant,hf_token:ei()})}),($e=document.querySelector(".nav-item[data-view='activity']"))==null||$e.dispatchEvent(new MouseEvent("click"))}catch(Te){le.disabled=!1,le.textContent="Installieren",alert("Fehler: "+Te.message)}}function T(){c(),f()}vi(()=>{c(),f()});var y=fv(),k=Ye(y),I=i(r(k),2),K=i(k,2);{var C=se=>{var le=lv(),$e=r(le),Te=i(r($e),2),We=r(Te),rt=i($e,4);Ze(rt,21,()=>t(s),nt,(Je,R)=>{var _e=sv(),Re=r(_e),at=r(Re),Q=r(at),de=r(Q),xe=i(Q,2),et=r(xe),Ve=i(at,2),tt=r(Ve),Ke=i(Re,2);$(it=>{h(de,t(R).name),bt(xe,1,`fit-badge ${it??""}`),h(et,t(R).fit.text),h(tt,`Ersetzt dein „${t(R).old??""}". ${t(R).why??""}`)},[()=>d(t(R).fit.level)]),S("click",Ke,it=>_(t(R),it.currentTarget)),p(Je,_e)}),$(()=>h(We,t(s).length)),p(se,le)};O(K,se=>{t(s).length&&se(C)})}var V=i(K,2);{var Ae=se=>{var le=ov();p(se,le)},Ce=se=>{var le=dv(),$e=r(le);$(()=>h($e,t(o))),p(se,le)},Be=se=>{var le=cv();p(se,le)},De=se=>{var le=pv();Ze(le,21,()=>t(a),nt,($e,Te,We)=>{var rt=uv();bt(rt,1,`news-card${We===0?" featured":""}`);var Je=r(rt),R=r(Je),_e=r(R),Re=i(R,2);{var at=Ve=>{var tt=vv();p(Ve,tt)};O(Re,Ve=>{t(Te).relevant&&Ve(at)})}var Q=i(Re,2),de=r(Q),xe=i(Je,2),et=r(xe);$(Ve=>{ga(rt,"href",t(Te).link),h(_e,t(Te).source),h(de,Ve),h(et,t(Te).title)},[()=>t(Te).ts?v(t(Te).ts):""]),p($e,rt)}),p(se,le)};O(V,se=>{t(l)?se(Ae):t(o)?se(Ce,1):t(a).length?se(De,-1):se(Be,2)})}S("click",I,T),p(e,y),wn()}$n(["click"]);const as=[{label:"Einstieg",tutorials:[["Dein erster Workflow — in 3 Schritten",`
|
||
<ol class="tut-steps">
|
||
<li><b>Modell holen:</b> Tab <b>Cookbook</b> → Anwendungsfall wählen (z.B. „Coden & Programmieren") →
|
||
<b>Komplettes Setup installieren</b>. Der Download läuft im Tab <b>Aktivität</b> — einfach warten bis der Job grün wird.</li>
|
||
<li><b>Verbinden:</b> Tab <b>Verbinden</b> → Tool wählen → Config-Snippet kopieren und einfügen.
|
||
<b>Verbindung testen</b> bestätigt, dass alles klappt.</li>
|
||
<li><b>Arbeiten:</b> Im Tool das gewünschte Modell auswählen und loslegen.
|
||
Das Modell wird <b>automatisch geladen</b> — du musst nichts manuell starten.</li>
|
||
</ol>
|
||
<p style="margin-top:10px"><b>Nicht sicher welches Tool du nehmen sollst?</b>
|
||
Lies den Abschnitt „Welches Tool ist das richtige für mich?" weiter unten.</p>`],["Kontext — das Kurzzeitgedächtnis des Modells",`
|
||
<p>Der Kontext ist wie ein Blatt Papier: alles was du mit dem Modell besprochen hast,
|
||
steht darauf. Wird es voll, fallen die ältesten Nachrichten raus.</p>
|
||
<p><b>Was du meist nicht tun musst:</b> Tools wie OpenCode, Cline und OpenWebUI
|
||
verwalten das Kontextfenster automatisch. Ein neuer Chat = leeres Blatt.</p>
|
||
<p><b>Wenn der Kontext volläuft</b> (Fehler „context length exceeded" oder das Modell vergisst den Anfang):</p>
|
||
<ol class="tut-steps">
|
||
<li><b>Neuen Chat starten</b> — der einfachste Reset.</li>
|
||
<li>Vorher: <em>„Fasse kurz zusammen was wir bisher erreicht haben"</em> — dann diesen Stand in den neuen Chat einfügen.</li>
|
||
<li><b>Kontext vergrößern:</b> Tab <b>Modelle</b> → <b>Konfigurieren</b> → Empfehlung für deine Hardware übernehmen.</li>
|
||
</ol>
|
||
<p><b>Wichtig:</b> „Grafikspeicher leeren" (Tab <b>Server</b>) ist etwas anderes —
|
||
das wirft das <em>Modell</em> aus dem Speicher, nicht den Gesprächsverlauf.</p>`],["Auto-Swap — Modelle laden sich von selbst",`
|
||
<p>llama-swap lädt automatisch das Modell, das gerade angefragt wird —
|
||
und entlädt es nach einer Leerlaufzeit wieder. <b>Es läuft immer nur eines gleichzeitig.</b></p>
|
||
<p>Du richtest beliebig viele Modelle ein und wählst im Tool das passende.
|
||
Das Laden und Entladen passiert unsichtbar im Hintergrund.</p>
|
||
<p><b>Warum dauert die erste Antwort manchmal 5–15 Sekunden?</b><br>
|
||
Das Modell wird gerade geladen — danach geht es normal weiter.
|
||
Die Topbar zeigt <em>„[Modellname] lädt…"</em> während das passiert.</p>
|
||
<p><b>Scout immer sofort verfügbar halten:</b> Tab <b>Modelle</b> → Konfigurieren →
|
||
<em>Immer aktiv halten</em> aktivieren (TTL = ∞). Das Modell bleibt dann dauerhaft im RAM
|
||
und antwortet ohne Wartezeit — ideal für den kleinen, schnellen Allrounder.</p>`]]},{label:"Tools einrichten",tutorials:[["Welches Tool ist das richtige für mich?",`
|
||
<p><b>Chat — ich will einfach reden, schreiben, fragen:</b></p>
|
||
<div class="tut-table">
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">Einfachster Einstieg</div>
|
||
<div class="tut-cell-bd">→ <b>Jan AI</b> — Desktop-App, Doppelklick-Installer, sofort loslegen.
|
||
Vertraut wie ChatGPT, läuft komplett lokal. Kein Admin-Panel, kein Docker.</div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">Teams / Power-User</div>
|
||
<div class="tut-cell-bd">→ <b>OpenWebUI</b> — viele Features (RAG, Bilder, Plugins, Mehrbenutzer).
|
||
Mehr Setup-Aufwand, aber der mächtigste Chat-Client.</div>
|
||
</div>
|
||
</div>
|
||
<p style="margin-top:12px"><b>Coding — ich will KI beim Programmieren:</b></p>
|
||
<div class="tut-table">
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">Simpler Einstieg in VS Code</div>
|
||
<div class="tut-cell-bd">→ <b>Continue</b> — Chat + Autocomplete direkt im Editor, kein Agent-Overhead.
|
||
Macht keinen Schritt ohne dich.</div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">Voller Coding-Agent im Editor</div>
|
||
<div class="tut-cell-bd">→ <b>Cline</b> — liest Dateien, schreibt Code, fragt vor jeder Änderung.
|
||
VS Code, JetBrains, Zed u.a.</div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">Agent-IDE mit VS Code-Feeling</div>
|
||
<div class="tut-cell-bd">→ <b>Antigravity</b> — Googles agentic IDE (VS Code-Fork), kostenlos.
|
||
Multi-Agent, planen + coden + testen in einem.</div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">Autonomer Terminal-Agent</div>
|
||
<div class="tut-cell-bd">→ <b>OpenCode</b> — mächtigster lokaler Agent, lebt im Terminal.
|
||
Ideal für „bau mir Feature X komplett fertig".</div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">Schneller Editor, minimalistisch</div>
|
||
<div class="tut-cell-bd">→ <b>Zed</b> — nativer Editor (Rust), eingebautes KI-Panel.
|
||
Für Leute die Performance über Features stellen.</div>
|
||
</div>
|
||
</div>
|
||
<p style="margin-top:10px"><b>Faustregel:</b> Fang mit <b>Jan AI</b> zum Chatten an.
|
||
Für Coding: <b>Continue</b> als sanfter Einstieg oder gleich <b>Cline/Antigravity</b>
|
||
wenn du bereit bist, dem Agenten mehr Kontrolle zu geben.</p>`],["OpenCode verbinden und die ersten Schritte",`
|
||
<p>OpenCode ist installiert? Dann in vier Schritten verbinden:</p>
|
||
<ol class="tut-steps">
|
||
<li><b>Config-Snippet holen:</b> Tab <b>Verbinden</b> → <em>OpenCode</em> auswählen →
|
||
Snippet kopieren und in <code>~/.config/opencode/opencode.json</code> einfügen.</li>
|
||
<li><b>OpenCode starten:</b> Terminal öffnen, <code>opencode</code> eintippen —
|
||
immer im Projektordner starten, damit der Agent deine Dateien sieht.</li>
|
||
<li><b>Modell wählen:</b> <code>/models</code> eintippen → <em>llama-swap/coder</em> auswählen.</li>
|
||
<li><b>Erste Aufgabe geben</b> — z.B.:
|
||
<em>„Lies die Datei README.md und erkläre mir kurz was dieses Projekt macht."</em></li>
|
||
</ol>
|
||
<p><b>Die wichtigsten Slash-Commands:</b></p>
|
||
<div class="tut-table">
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd"><code>/model</code></div>
|
||
<div class="tut-cell-bd">Modell wechseln — z.B. mitten im Gespräch auf <em>scout</em> für kurze Fragen</div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd"><code>/compact</code> · <code>/summarize</code></div>
|
||
<div class="tut-cell-bd">Kontext komprimieren wenn er voll wird — fasst die Session zusammen und setzt fort</div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd"><code>/clear</code> · <code>/new</code></div>
|
||
<div class="tut-cell-bd">Neue Session starten — komplett leerer Kontext</div>
|
||
</div>
|
||
</div>
|
||
<p>Bevor OpenCode eine Datei ändert, fragt es nach — mit <b>y</b> bestätigen oder <b>n</b> ablehnen.</p>
|
||
<p><b>Terminal oder Desktop-App?</b> Die Anleitung gilt für beide —
|
||
der Config-Snippet landet in derselben Datei (<code>~/.config/opencode/opencode.json</code>),
|
||
und alle Slash-Commands funktionieren in beiden Versionen gleich.
|
||
Unterschied: Im Terminal startest du mit <code>cd ~/mein-projekt && opencode</code>;
|
||
in der Desktop-App öffnest du einfach die App und wählst den Projektordner über die GUI.</p>
|
||
<p><b>Multi-Agenten (2026):</b> Du kannst in OpenCode mehrere spezialisierte Agenten definieren
|
||
— z.B. einen <em>review</em>-Agent und einen <em>coder</em>-Agent.
|
||
Mit <b>Tab</b> wechselst du zwischen primären Agenten; mit <b>@review</b> rufst du einen Subagenten direkt im Chat auf.
|
||
Agenten werden als Markdown-Dateien angelegt: eine Datei <code>review.md</code> im
|
||
<code>~/.config/opencode/</code>-Ordner erstellt automatisch den Agenten <em>review</em>.</p>
|
||
<p class="tut-sources">Weitere Infos: <a href="https://opencode.ai/docs" target="_blank" rel="noopener">opencode.ai/docs</a> · <a href="https://opencode.ai/docs/agents/" target="_blank" rel="noopener">Agenten-Docs</a></p>`],["Cline verbinden und nutzen",`
|
||
<p>Cline (v3.81, Stand Juni 2026) läuft in: <b>VS Code, JetBrains, Cursor, Windsurf, Zed, Neovim</b>
|
||
und als CLI auf macOS/Linux. Verbinden funktioniert überall gleich:</p>
|
||
<ol class="tut-steps">
|
||
<li>Das Cline-Panel öffnen (Roboter-Icon in der Seitenleiste).</li>
|
||
<li>Provider <b>„OpenAI Compatible"</b> wählen.</li>
|
||
<li>Tab <b>Verbinden</b> → <em>Cline / Cursor</em> → Basis-URL und Modell-ID kopieren und eintragen.</li>
|
||
<li>API-Key: irgendeinen beliebigen Text eingeben (z.B. <code>local</code>) — wird nicht geprüft.</li>
|
||
</ol>
|
||
<p><b>Plan-Modus vs. Act-Modus:</b></p>
|
||
<div class="tut-table">
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">Plan</div>
|
||
<div class="tut-cell-bd">Cline liest und denkt nach — erklärt den Plan bevor es handelt.
|
||
Billiger (weniger Tokens) und ideal für Anfänger.</div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">Act</div>
|
||
<div class="tut-cell-bd">Cline handelt sofort, fragt aber vor jeder Dateiänderung um Erlaubnis.
|
||
Schneller für klare Aufgaben.</div>
|
||
</div>
|
||
</div>
|
||
<p><b>Memory Bank (empfohlen):</b> Lege eine Datei <code>projectbrief.md</code> im Projektordner an —
|
||
Cline liest sie zu Beginn jeder Aufgabe automatisch. Sie ist das Fundament: Projektziel, Tech-Stack,
|
||
wichtigste Regeln. Ergänzend: <code>activeContext.md</code> für den aktuellen Fokus,
|
||
<code>progress.md</code> für den Stand.</p>
|
||
<p><b>.clinerules:</b> Für größere Projekte kannst du statt einer einzelnen Datei ein ganzes
|
||
Verzeichnis <code>.clinerules/</code> anlegen — jede Datei darin gilt als separate Regel.
|
||
Achtung: Jedes Zeichen in .clinerules verbraucht Kontext — kurze, präzise Regeln schlagen lange Listen.</p>
|
||
<p><b>Ausgaben-Limit (seit April 2026):</b> In Settings → Spending Limits kannst du ein
|
||
Tages- oder Monats-Budget setzen — verhindert dass ein laufender Agent unbemerkt viel Token verbraucht.</p>
|
||
<p class="tut-sources">Weitere Infos: <a href="https://cline.bot" target="_blank" rel="noopener">cline.bot</a> · <a href="https://docs.cline.bot/best-practices/memory-bank" target="_blank" rel="noopener">Memory Bank Docs</a></p>`],["Jan AI — einfachstes Chat-Interface",`
|
||
<p><b>Jan AI</b> ist die einfachste Art, lokal mit KI zu chatten —
|
||
Desktop-App, kein Terminal, kein Docker, kein Admin-Panel.</p>
|
||
<ol class="tut-steps">
|
||
<li><b>Jan AI installieren:</b> <a href="https://jan.ai" target="_blank" rel="noopener">jan.ai</a>
|
||
→ Download → Doppelklick-Installer (Windows/macOS/Linux).</li>
|
||
<li><b>Remote-Modell hinzufügen:</b> In der linken Leiste auf das Hub-Icon →
|
||
oben rechts <b>+ Remote-Modell</b>.</li>
|
||
<li><b>Verbindung eintragen:</b> Tab <b>Verbinden</b> → <em>Jan AI</em> auswählen →
|
||
Basis-URL und Modell-ID kopieren und in Jan einfügen.</li>
|
||
<li>API-Key: irgendeinen Text (z.B. <code>local</code>). Speichern.</li>
|
||
</ol>
|
||
<p>Danach erscheint das Modell in der Modell-Liste — auswählen und loslegen.</p>
|
||
<p><b>Gut für:</b> Chatten, Texte schreiben, übersetzen, Fragen stellen —
|
||
genauso wie ChatGPT, aber 100% lokal und privat. Bilder mitschicken klappt auch
|
||
sobald ein Vision-Modell eingetragen ist.</p>
|
||
<p class="tut-sources">Download & Docs: <a href="https://jan.ai" target="_blank" rel="noopener">jan.ai</a> · <a href="https://www.jan.ai/docs" target="_blank" rel="noopener">jan.ai/docs</a></p>`],["Continue — Coding-Hilfe in VS Code ohne Agent-Overhead",`
|
||
<p><b>Continue</b> ist die einfachste Coding-Erweiterung für VS Code und JetBrains —
|
||
kein autonomer Agent, sondern ein KI-Assistent der nur auf Anfrage handelt.</p>
|
||
<ol class="tut-steps">
|
||
<li><b>Extension installieren:</b> VS Code → Extensions → „Continue" suchen → Installieren.<br>
|
||
Oder: <a href="https://continue.dev" target="_blank" rel="noopener">continue.dev</a></li>
|
||
<li><b>Config holen:</b> Tab <b>Verbinden</b> → <em>Continue</em> auswählen →
|
||
Snippet kopieren und in <code>~/.continue/config.json</code> einfügen.</li>
|
||
<li>Continue in VS Code neu starten → im Chat-Panel Modell wählen → loslegen.</li>
|
||
</ol>
|
||
<p><b>Was Continue kann:</b></p>
|
||
<ul class="tut-steps" style="list-style:disc">
|
||
<li><b>Chat:</b> Frage direkt im Editor — markiere Code und drücke <code>Strg+L</code></li>
|
||
<li><b>Autocomplete:</b> Ergänzt Code während du tippst (wie Copilot)</li>
|
||
<li><b>Inline-Edit:</b> Markieren → <code>Strg+I</code> → „Refactore das zu TypeScript"</li>
|
||
</ul>
|
||
<p><b>Unterschied zu Cline:</b> Continue macht nichts von alleine — du steuerst jeden Schritt.
|
||
Ideal als erster Einstieg bevor man mit vollen Agenten arbeitet.</p>
|
||
<p class="tut-sources">Weitere Infos: <a href="https://continue.dev" target="_blank" rel="noopener">continue.dev</a>
|
||
— Hinweis: 2026 von Cursor akquiriert, weiterhin kostenlos & open source.</p>`],["Antigravity — Googles agentic IDE",`
|
||
<p><b>Antigravity</b> ist Googles agent-first IDE — ein Fork von VS Code, der Planung,
|
||
Coding, Testing und Deployment in einem Workflow zusammenführt. Kostenlos für Einzelpersonen.</p>
|
||
<ol class="tut-steps">
|
||
<li><b>Antigravity installieren:</b>
|
||
<a href="https://antigravityide.net" target="_blank" rel="noopener">antigravityide.net</a>
|
||
→ Download → läuft wie VS Code.</li>
|
||
<li><b>Eigenen Endpoint einrichten:</b> Settings → Models → <b>Custom Endpoint</b> → + hinzufügen.</li>
|
||
<li><b>Verbindung eintragen:</b> Tab <b>Verbinden</b> → <em>Antigravity</em> auswählen →
|
||
Basis-URL und Modell-ID kopieren und eintragen.</li>
|
||
<li>API-Key: beliebiger Text (z.B. <code>local</code>). Danach das Modell aus der Liste wählen.</li>
|
||
</ol>
|
||
<p><b>Was Antigravity besonders macht:</b></p>
|
||
<ul class="tut-steps" style="list-style:disc">
|
||
<li><b>Agent-First:</b> Statt Code-Completion steht der Agent im Mittelpunkt —
|
||
du beschreibst, er plant und setzt um</li>
|
||
<li><b>Multi-Agent:</b> Mehrere Agenten arbeiten parallel an verschiedenen Teilen</li>
|
||
<li><b>Manager-Oberfläche:</b> Übersicht über alle laufenden Agenten-Sessions</li>
|
||
<li><b>VS Code-kompatibel:</b> Extensions und Keybindings funktionieren wie gewohnt</li>
|
||
</ul>
|
||
<p><b>Wann Antigravity statt OpenCode?</b> Wenn du lieber eine grafische IDE als ein Terminal magst
|
||
und trotzdem volle Agenten-Kontrolle willst. OpenCode ist mächtiger im Terminal-Flow;
|
||
Antigravity ist komfortabler für Umsteiger aus VS Code.</p>
|
||
<p class="tut-sources">Weitere Infos: <a href="https://antigravityide.net" target="_blank" rel="noopener">antigravityide.net</a> ·
|
||
<a href="https://developers.googleblog.com/build-with-google-antigravity-our-new-agentic-development-platform/" target="_blank" rel="noopener">Google Dev Blog</a></p>`],["OpenWebUI — für Teams und Power-User",`
|
||
<p>OpenWebUI ist der mächtigste lokale Chat-Client — aber auch der komplexeste.
|
||
Empfohlen wenn du mehr als ein einfaches Chat-Interface brauchst.</p>
|
||
<p><b>Was OpenWebUI besonders kann (gegenüber Jan AI):</b></p>
|
||
<ul class="tut-steps" style="list-style:disc">
|
||
<li>RAG: eigene Dokumente hochladen, KI liest und beantwortet Fragen dazu</li>
|
||
<li>Mehrbenutzer: eigene Accounts für verschiedene Personen im Heimnetz</li>
|
||
<li>Plugins und Agenten: erweiterbar mit Tools und Custom-Pipelines</li>
|
||
<li>Bilder generieren (mit Stable Diffusion), Sprachausgabe, Web-Suche</li>
|
||
</ul>
|
||
<p><b>Verbinden</b> (braucht Docker oder eine lokale Installation):</p>
|
||
<ol class="tut-steps">
|
||
<li>OpenWebUI im Browser öffnen → <b>Admin Panel</b> → <b>Connections</b>.</li>
|
||
<li><b>+ OpenAI-Verbindung</b> → Tab <b>Verbinden</b> → <em>OpenWebUI</em> → Basis-URL kopieren.</li>
|
||
<li>API-Key: <code>dummy-key</code>. Speichern.</li>
|
||
</ol>
|
||
<p>Danach Modell auswählen und loslegen. Für einfaches Chatten: <b>Jan AI</b> ist einfacher.
|
||
OpenWebUI lohnt sich ab dem Moment, wo du mehr als nur Chat willst.</p>
|
||
<p class="tut-sources">Weitere Infos: <a href="https://openwebui.com" target="_blank" rel="noopener">openwebui.com</a></p>`]]},{label:"Agenten meistern",tutorials:[["Was ein Agent tut — und was er nicht kann",`
|
||
<p>Ein nacktes Modell antwortet auf Text — das war's.
|
||
Ein <b>Agent</b> ist das Programm drumherum, das das Modell in eine <b>Handlungsschleife</b> bringt:</p>
|
||
<p style="text-align:center;padding:8px 0;font-family:monospace;font-size:12.5px;color:var(--accent)">
|
||
Planen → Werkzeug nutzen → Ergebnis prüfen → nächsten Schritt planen → …
|
||
</p>
|
||
<p>Konkret: Datei lesen → Code verstehen → Änderung schreiben → Test ausführen → Fehler beheben —
|
||
ohne dass du jeden Schritt anstoßen musst.</p>
|
||
<p><b>Was Agenten gut können:</b></p>
|
||
<ul class="tut-steps" style="list-style:disc">
|
||
<li>Features über mehrere Dateien implementieren</li>
|
||
<li>Bugs finden und in ihrem Kontext beheben</li>
|
||
<li>Code refactoren, Dokumentation schreiben, Tests ergänzen</li>
|
||
<li>Recherchieren und das Ergebnis direkt umsetzen (mit MCP)</li>
|
||
<li>Parallele Teilaufgaben an Subagenten delegieren (OpenCode 2026)</li>
|
||
</ul>
|
||
<p><b>Was Agenten schlecht können:</b></p>
|
||
<ul class="tut-steps" style="list-style:disc">
|
||
<li>Kreative Richtungsentscheidungen ohne klare Vorgabe treffen</li>
|
||
<li>Sehr komplexe, undokumentierte Systeme ohne Kontext verstehen</li>
|
||
<li>Fehler in externer Hardware oder fremden APIs beheben</li>
|
||
</ul>
|
||
<p><b>Faustregel:</b> Je klarer die Aufgabe, desto besser das Ergebnis. Unklarer Auftrag → unklares Ergebnis.</p>`],["Einen Agenten richtig briefen",`
|
||
<p>Der Unterschied zwischen „es passiert nichts Sinnvolles" und „es funktioniert auf Anhieb"
|
||
ist meistens die Qualität des Auftrags.</p>
|
||
<p><b>Schlecht → Gut:</b></p>
|
||
<div class="tut-table">
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd bad">„Mach meine App besser."</div>
|
||
<div class="tut-cell-bd">→ <em>„Die Login-Seite in <code>src/pages/Login.tsx</code> zeigt
|
||
bei falschem Passwort gar keinen Fehler an. Füge unter dem Passwortfeld eine rote Fehlermeldung
|
||
ein wenn die API 401 zurückgibt."</em></div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd bad">„Erkläre mir Python."</div>
|
||
<div class="tut-cell-bd">→ <em>„Ich bin Anfänger. Erkläre mir in 5 Schritten wie ich eine CSV-Datei
|
||
in Python einlese und die Summe einer Spalte berechne — mit echtem Code-Beispiel."</em></div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd bad">„Mach das schneller."</div>
|
||
<div class="tut-cell-bd">→ <em>„Die Funktion <code>loadUsers()</code> in <code>src/api/users.ts</code>
|
||
braucht 3 Sekunden. Die Daten kommen vom Backend. Prüfe ob Caching helfen würde und schlage eine
|
||
konkrete Lösung vor."</em></div>
|
||
</div>
|
||
</div>
|
||
<p style="margin-top:12px"><b>Die 3 Zutaten für einen guten Auftrag:</b></p>
|
||
<ol class="tut-steps">
|
||
<li><b>WO:</b> Welche Datei / welcher Ordner / welches Feature</li>
|
||
<li><b>WAS:</b> Was ist das genaue Problem oder Ziel</li>
|
||
<li><b>WIE:</b> Welches Ergebnis erwartest du</li>
|
||
</ol>
|
||
<p><b>Trick:</b> Wenn du nicht sicher bist ob der Auftrag klar genug ist, frag den Agenten:
|
||
<em>„Hast du alles was du brauchst, oder fehlt dir etwas?"</em></p>`],["MCP — deinem Agenten echte Werkzeuge geben",`
|
||
<p><b>MCP</b> (Model Context Protocol) ist ein einheitlicher „Stecker", über den ein Agent
|
||
zusätzliche <b>Werkzeuge</b> bekommt. Ohne MCP kann er nur Text lesen und schreiben.
|
||
Mit MCP kann er z.B.:</p>
|
||
<ul class="tut-steps" style="list-style:disc">
|
||
<li>Im Web suchen (Brave Search, Tavily)</li>
|
||
<li>GitHub Issues lesen und kommentieren</li>
|
||
<li>Deine Datenbank abfragen</li>
|
||
<li>Screenshots machen, E-Mails lesen, Kalender verwalten</li>
|
||
</ul>
|
||
<p><b>Wie MCPs eingebunden werden</b> (Beispiel für OpenCode):</p>
|
||
<p>In der Konfigurationsdatei (<code>~/.config/opencode/opencode.json</code>) einen
|
||
<code>"mcp"</code>-Block hinzufügen:</p>
|
||
<pre class="tut-code">{
|
||
"mcp": {
|
||
"brave-search": {
|
||
"command": "npx",
|
||
"args": ["-y", "@modelcontextprotocol/server-brave-search"],
|
||
"env": { "BRAVE_API_KEY": "dein-key" }
|
||
}
|
||
}
|
||
}</pre>
|
||
<p>Danach OpenCode neu starten — der Agent nutzt das Werkzeug automatisch wenn er es braucht.</p>
|
||
<p><b>Empfohlene MCPs 2026 — nach Anwendungsfall:</b></p>
|
||
<div class="tut-table">
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">Web-Suche</div>
|
||
<div class="tut-cell-bd"><b>brave-search</b> oder <b>tavily</b> — recherchieren, aktuelle Infos holen</div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">GitHub</div>
|
||
<div class="tut-cell-bd"><b>github</b> — meistinstallierter MCP überhaupt. Issues, PRs, Commits, Repos direkt im Chat verwalten</div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">Lokale Dateien</div>
|
||
<div class="tut-cell-bd"><b>filesystem</b> — meistgenutzter MCP überhaupt. Sichere Dateizugriffe auf beliebige Ordner</div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">Browser</div>
|
||
<div class="tut-cell-bd"><b>playwright</b> — Browser-Automatisierung und UI-Tests. Agent öffnet Seiten, klickt, prüft</div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">Gedächtnis</div>
|
||
<div class="tut-cell-bd"><b>memory / mem0</b> — persistentes Gedächtnis über Sessions hinweg. Agent erinnert sich an deine Präferenzen und Projekt-Kontext auch in neuen Chats</div>
|
||
</div>
|
||
</div>
|
||
<p style="margin-top:8px">Über <b>36.000 MCPs</b> sind mittlerweile verfügbar (Stand Juni 2026).
|
||
Fang mit filesystem + github an — die decken 80% der täglichen Arbeit ab.</p>
|
||
<p class="tut-sources"><b>Wo MCPs finden:</b>
|
||
<a href="https://mcp.run" target="_blank" rel="noopener">mcp.run</a> ·
|
||
<a href="https://smithery.ai" target="_blank" rel="noopener">smithery.ai</a> ·
|
||
<a href="https://modelcontextprotocol.io/servers" target="_blank" rel="noopener">modelcontextprotocol.io/servers</a>
|
||
— oder fragen: <em>„Welche MCPs gibt es für [dein Werkzeug]?"</em></p>
|
||
<p><b>Merksatz:</b> Fehlt dem Agenten eine <em>Fähigkeit</em> → MCP.
|
||
Soll er etwas nur <em>besser machen</em> → Skill (nächster Abschnitt).</p>`],["Skills & Rules — Agenten Gewohnheiten beibringen",`
|
||
<p><b>Skills</b> (auch <em>Rules</em>, <em>AGENTS.md</em> oder <em>Instructions</em> genannt)
|
||
sind kurze Texte, die dem Agenten beibringen wie er in deinem Projekt arbeiten soll —
|
||
immer, ohne dass du es jedes Mal neu sagen musst.</p>
|
||
<p><b>Beispiel</b> — eine einfache AGENTS.md:</p>
|
||
<pre class="tut-code">Schreib alle Variablen in camelCase.
|
||
Kommentare immer auf Deutsch.
|
||
Tests immer mit describe/it-Blöcken (Jest).
|
||
Importiere nichts was nicht schon in package.json steht.
|
||
Bevor du Dateien änderst: erkläre kurz was du vorhast.</pre>
|
||
<p>Der Agent liest das vor jeder Aufgabe und hält sich daran.</p>
|
||
<p><b>Wo die Datei ablegen:</b></p>
|
||
<div class="tut-table">
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">OpenCode</div>
|
||
<div class="tut-cell-bd"><code>AGENTS.md</code> im Projektordner (pro Projekt)<br>
|
||
<code>~/.config/opencode/AGENTS.md</code> (global, gilt überall)</div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">Cline</div>
|
||
<div class="tut-cell-bd"><code>.clinerules</code> im Projektordner<br>
|
||
<code>~/.clinerules</code> (global)</div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">Zed</div>
|
||
<div class="tut-cell-bd">Zed Settings → Assistant → System Prompt</div>
|
||
</div>
|
||
</div>
|
||
<p style="margin-top:10px"><b>Fertige Skills finden:</b></p>
|
||
<div class="tut-table">
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd"><a href="https://skills.sh" target="_blank" rel="noopener">skills.sh</a></div>
|
||
<div class="tut-cell-bd">Von Vercel gestartet (Jan 2026) — das npm für Agent-Skills. Funktioniert mit Claude Code, OpenCode, Cursor u.v.m. One-Command-Installer.
|
||
<b>Hinweis:</b> Community-Inhalte ohne formale Prüfung — Skill vor dem Einsatz kurz lesen.</div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd"><a href="https://skillhub.ai" target="_blank" rel="noopener">SkillHub</a></div>
|
||
<div class="tut-cell-bd">KI-bewertete Skills (S/A/B-Ranking nach Qualität, Klarheit, Wirkung). Kleinerer Katalog, höhere Signal-Qualität.</div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd"><a href="https://cursor.directory" target="_blank" rel="noopener">cursor.directory</a></div>
|
||
<div class="tut-cell-bd">Vorgefertigte Rules für React, Vue, Python, Go etc. — direkt als .clinerules oder AGENTS.md nutzbar.</div>
|
||
</div>
|
||
</div>
|
||
<p style="margin-top:8px"><b>Sicherheitshinweis:</b> Ein Snyk-Audit (2026) fand in 13,4% der Community-Skills
|
||
kritische Probleme (Prompt Injection, exponierte Secrets). Regel: Skill-Datei kurz lesen bevor du sie einsetzt.</p>
|
||
<p style="margin-top:8px">Oder einfach fragen: <em>„Schreib mir eine AGENTS.md für ein React + TypeScript Projekt mit Tailwind."</em></p>`],["Die Persona — Rolle, Beziehung & Onboarding",`
|
||
<p>Eine Persona hat <b>zwei Dimensionen</b> — beide sind wichtig:</p>
|
||
<div class="tut-table">
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">Was der Agent tut</div>
|
||
<div class="tut-cell-bd">Fokus, Fachgebiet, Grenzen — die klassische Rollenbeschreibung.</div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">Wie er mit dir umgeht</div>
|
||
<div class="tut-cell-bd">Ton, Proaktivität, Feedback-Stil — antwortet er kurz oder ausführlich?
|
||
Hakt er nach oder liefert er einfach? Spricht er Fehler direkt an oder verpackt er sie?</div>
|
||
</div>
|
||
</div>
|
||
<p style="margin-top:10px">Ein Agent der technisch gleich konfiguriert ist, verhält sich komplett anders
|
||
wenn er weiß: <em>Du willst kurze Antworten ohne Erklärung.</em> Oder: <em>Du lernst noch —
|
||
ermutige mich und erkläre immer warum.</em></p>
|
||
|
||
<p><b>Das vollständige Persona-Template:</b></p>
|
||
<pre class="tut-code">Du bist [Name], [Rolle].
|
||
|
||
Fokus: [Was du hauptsächlich tust]
|
||
Wie du kommunizierst: [Stil — direkt/erklärend/ermutigend, kurze oder ausführliche Antworten]
|
||
Wie du mit mir umgehst: [Proaktivität, Rückfragen, Feedback-Stil, Fehlerkultur]
|
||
Sprache: Immer auf Deutsch. Code-Kommentare auf Englisch.
|
||
Grenzen: [Was du nicht tust, was du nachfragst statt zu raten]</pre>
|
||
|
||
<p><b>Beispiel 1 — Coding-Assistent (direkt, erfahren):</b></p>
|
||
<pre class="tut-code">Du bist Alex, ein erfahrener Senior-Entwickler spezialisiert auf TypeScript und React.
|
||
|
||
Fokus: Code schreiben, reviewen, erklären — immer mit konkreten Beispielen.
|
||
Wie du kommunizierst: direkt, pragmatisch. Keine Erklärung wenn der Code für sich spricht.
|
||
Wie du mit mir umgehst: Du fragst nach bevor du loslegst wenn die Aufgabe unklar ist.
|
||
Fehler sprichst du klar an — aber ohne Schuldzuweisungen. Du machst Gegenvorschläge
|
||
wenn du eine bessere Lösung siehst, aber respektierst meine Entscheidung.
|
||
Sprache: Deutsch. Code-Kommentare auf Englisch.
|
||
Grenzen: Kein Code ohne Datei-Kontext. Keine neuen Dependencies ohne Rückfrage.</pre>
|
||
|
||
<p><b>Beispiel 2 — Lernbegleiter (geduldig, ermutigend):</b></p>
|
||
<pre class="tut-code">Du bist Sam, eine geduldige Lernbegleiterin für Programmier-Anfänger.
|
||
|
||
Fokus: Konzepte erklären, Fehler korrigieren, Schritt für Schritt führen.
|
||
Wie du kommunizierst: freundlich, mit Analogien aus dem Alltag. Fachbegriffe sofort erklären.
|
||
Wie du mit mir umgehst: Du lobst Fortschritte, auch kleine. Fehler sind Lernchancen —
|
||
du zeigst was falsch war und warum, ohne zu urteilen. Du fragst ob ich es verstanden
|
||
habe bevor du weitermachst.
|
||
Sprache: Immer auf Deutsch. Niemals Englisch ohne Übersetzung.</pre>
|
||
|
||
<hr style="border:none;border-top:1px solid var(--line);margin:18px 0">
|
||
<p><b>Der schnellste Weg: Onboarding-Interview</b></p>
|
||
<p>Statt die Persona selbst auszufüllen — lass den Agenten <em>dich</em> befragen.
|
||
Starte einen frischen Chat und gib ihm diesen Prompt:</p>
|
||
<pre class="tut-code">Ich möchte dich in mein Projekt und meinen Arbeitsstil einarbeiten.
|
||
Führe mit mir ein kurzes Interview durch — stelle mir 6–8 Fragen,
|
||
eine nach der anderen — um zu verstehen:
|
||
|
||
1. Wer ich bin und wie ich am liebsten kommuniziere
|
||
2. Was unser Projekt ist und welches Ziel es hat
|
||
3. Was ich gut kann und wobei ich Unterstützung brauche
|
||
4. Meine Arbeitsgewohnheiten und Präferenzen
|
||
5. Was mir wichtig ist und was mich stört
|
||
|
||
Wenn du alle Antworten hast, erstelle daraus:
|
||
- Eine vollständige AGENTS.md als dauerhaftes Fundament
|
||
- Einen Satz der zusammenfasst wer ich für dich bin</pre>
|
||
<p>Das Ergebnis: eine maßgeschneiderte Persona die <em>wirklich</em> zu dir passt —
|
||
weil du sie nicht selbst formulieren musstest, sondern im Gespräch entstanden ist.</p>
|
||
|
||
<p><b>Wo eintragen:</b></p>
|
||
<div class="tut-table">
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">Für ein Projekt</div>
|
||
<div class="tut-cell-bd">Erste Zeilen der <code>AGENTS.md</code> im Projektordner.</div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">Global (überall)</div>
|
||
<div class="tut-cell-bd"><code>~/.config/opencode/AGENTS.md</code> (OpenCode) ·
|
||
Settings → System Prompt (OpenWebUI)</div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">Nur dieser Chat</div>
|
||
<div class="tut-cell-bd"><em>„Ab jetzt bist du …"</em> direkt eintippen.</div>
|
||
</div>
|
||
</div>
|
||
<p class="tut-sources" style="margin-top:10px">Fertige Personas: <a href="https://skills.sh" target="_blank" rel="noopener">skills.sh</a> · <a href="https://cursor.directory" target="_blank" rel="noopener">cursor.directory</a></p>`],["AGENTS.MD & SAVEPOINT.MD — Gedächtnis für den Agenten",`
|
||
<p>Jedes Mal wenn du einen neuen Chat startest, weiß der Agent <b>nichts</b> über dein Projekt.
|
||
Diese zwei Dateien lösen das Problem.</p>
|
||
<p><b>AGENTS.md ist 2026 der plattformübergreifende Standard</b> — nativ gelesen von:
|
||
OpenCode, Claude Code, Codex CLI, Cursor, Aider, Devin, GitHub Copilot, Gemini CLI, Windsurf, Amazon Q.
|
||
Eine Datei, alle Tools.</p>
|
||
<div class="tut-table">
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">AGENTS.md</div>
|
||
<div class="tut-cell-bd"><b>Was das Projekt ist</b> — Tech-Stack, Konventionen,
|
||
Struktur. Wird vor jeder Aufgabe gelesen. Einmal schreiben, immer wirksam.</div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">SAVEPOINT.md</div>
|
||
<div class="tut-cell-bd"><b>Wo wir gerade stehen</b> — aktueller Stand, offene Punkte,
|
||
nächste Schritte. Wird am Ende einer Session aktualisiert und zu Beginn der nächsten gelesen.</div>
|
||
</div>
|
||
</div>
|
||
|
||
<p style="margin-top:14px"><b>AGENTS.MD — Vorlage:</b></p>
|
||
<pre class="tut-code"># Projekt: [Name]
|
||
|
||
## Persona
|
||
Du bist [Name], [Rolle]. [Stil, Sprache, Grenzen]
|
||
|
||
## Tech-Stack
|
||
- Frontend: [z.B. React 18, TypeScript, Tailwind CSS]
|
||
- Backend: [z.B. FastAPI, Python 3.12]
|
||
- Datenbank:[z.B. PostgreSQL via Prisma]
|
||
|
||
## Konventionen
|
||
- Variablen: camelCase (JS) / snake_case (Python)
|
||
- Kommentare: auf Deutsch
|
||
- Commits: konventionell (feat/fix/chore/docs)
|
||
- Tests: immer mit describe/it-Blöcken
|
||
|
||
## Projektstruktur
|
||
src/
|
||
components/ → UI-Komponenten (eine Datei = eine Komponente)
|
||
pages/ → Seiten / Routes
|
||
api/ → Backend-Calls und Typen
|
||
|
||
## Regeln
|
||
- Vor jeder Dateiänderung kurz erklären was geplant ist
|
||
- Keine neuen Dependencies ohne Rückfrage hinzufügen
|
||
- Bei Unklarheiten fragen, nicht raten
|
||
|
||
<!-- Ziel: 200–500 Zeilen. AGENTS.md wird in jeden Kontext geladen —
|
||
kürzer = mehr Platz für Code und Gespräch. --></pre>
|
||
<p style="color:var(--mut);font-size:12px;margin:4px 0 8px">
|
||
<b>Größe:</b> 200–500 Zeilen sind der empfohlene Sweet Spot (Stand 2026).
|
||
AGENTS.md wird in jeden Kontext geladen — je kürzer, desto mehr Platz bleibt für Code und Gespräch.</p>
|
||
|
||
<p><b>SAVEPOINT.MD — Vorlage:</b></p>
|
||
<pre class="tut-code"># Savepoint — [Datum / Uhrzeit]
|
||
|
||
## Aktueller Stand
|
||
[1–2 Sätze: wo steht das Projekt gerade?]
|
||
|
||
## Zuletzt erledigt
|
||
- [Aufgabe] ✓
|
||
- [Aufgabe] ✓
|
||
|
||
## In Arbeit / halbfertig
|
||
- [Was noch offen ist — welche Datei, welcher Schritt fehlt noch]
|
||
|
||
## Als nächstes
|
||
1. [Konkrete nächste Aufgabe]
|
||
2. [Übernächste Aufgabe]
|
||
|
||
## Wichtige Entscheidungen
|
||
- [Was entschieden wurde]: [Warum]
|
||
|
||
## Bekannte Probleme
|
||
- [Problem]: [Was bekannt ist, noch nicht gelöst]</pre>
|
||
|
||
<p><b>Workflow:</b></p>
|
||
<ol class="tut-steps">
|
||
<li><b>Session starten:</b> <em>„Lies AGENTS.md und SAVEPOINT.md und mach weiter."</em></li>
|
||
<li><b>Session beenden:</b> <em>„Aktualisiere SAVEPOINT.md mit dem aktuellen Stand."</em></li>
|
||
</ol>
|
||
<p><b>Tipp:</b> Lass den Agenten die SAVEPOINT.md selbst schreiben — er sieht was er getan hat.
|
||
Du prüfst nur ob der Stand stimmt und ergänzt bei Bedarf.</p>
|
||
<p class="tut-sources">Vorlagen & Inspiration: <a href="https://skills.sh" target="_blank" rel="noopener">skills.sh</a> · <a href="https://opencode.ai/docs" target="_blank" rel="noopener">opencode.ai/docs</a></p>`]]},{label:"Wenn etwas nicht klappt",tutorials:[["Häufige Probleme & Lösungen",`
|
||
<div class="tut-table">
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">🔴 Engine offline, rotes Licht in der Topbar</div>
|
||
<div class="tut-cell-bd">Tab <b>Server</b> → LLM-Engine-Karte → <b>Neustart</b>.
|
||
Warte 10–15 Sekunden — danach sollte die Verbindung wieder grün sein.</div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">⏳ Modell lädt länger als 5 Minuten</div>
|
||
<div class="tut-cell-bd">Tab <b>Aktivität</b> prüfen: läuft ein Download-Job?
|
||
Der muss erst abgeschlossen sein bevor das Modell ladbar ist.
|
||
Bei Fehler → Job-Zeile aufklappen, Log lesen.</div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">💬 „context length exceeded" Fehler im Tool</div>
|
||
<div class="tut-cell-bd">Neuen Chat starten. Vorher: <em>„Fasse kurz zusammen was wir
|
||
erreicht haben"</em> eingeben und diesen Text in den neuen Chat mitnehmen.</div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">🌐 Modell antwortet immer auf Englisch</div>
|
||
<div class="tut-cell-bd">Am Anfang der Unterhaltung schreiben: <em>„Antworte immer auf Deutsch."</em>
|
||
Für dauerhaft: eine <code>AGENTS.md</code> / <code>.clinerules</code> mit dieser Anweisung anlegen
|
||
(siehe Abschnitt Skills & Rules).</div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">🔌 Tool findet keine Modelle / Verbindung schlägt fehl</div>
|
||
<div class="tut-cell-bd">Tab <b>Verbinden</b> → <b>Verbindung testen</b>. Wenn Fehler:
|
||
läuft llama-swap? (Tab Server). URL korrekt? Muss <code>http://</code> (nicht https) sein,
|
||
Port <b>8080</b>. Über Proxy? → LAN-IP direkt nutzen: <code>http://192.168.178.151:8080/v1</code></div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">⬇ Download schlägt fehl / bricht ab</div>
|
||
<div class="tut-cell-bd">Tab <b>Aktivität</b> → Job-Zeile aufklappen → Log lesen.
|
||
Häufigste Ursache: HuggingFace braucht einen Token für dieses Modell (gated model).
|
||
→ Einstellungen (Zahnrad-Icon oben) → <b>HuggingFace-Token</b> eintragen.</div>
|
||
</div>
|
||
<div class="tut-row">
|
||
<div class="tut-cell-hd">🔄 Seite lädt / Dashboard hängt komplett</div>
|
||
<div class="tut-cell-bd">Strg+Shift+R (Hard Reload). Wenn das nicht hilft:
|
||
Tab <b>Server</b> → Mission Control → <b>Neu starten</b>.</div>
|
||
</div>
|
||
</div>`]]}],gv=[["LLM / Modell","Die KI selbst — versteht und schreibt Text (wie ChatGPT, nur lokal auf deinem PC). Ein Modell ist eine konkrete Datei, oft auf etwas spezialisiert (Code, Bilder, Chat)."],["GGUF","Das lokal lauffähige Dateiformat. llama-swap lädt nur GGUF — Repos ohne GGUF kann die Engine nicht nutzen."],["Quantisierung (Q4_K_M)","Verkleinert ein Modell (16-Bit → 4-Bit), damit es in den Speicher passt — bei kaum Qualitätsverlust. Q4_K_M ist der bewährte Sweetspot. Für Coding/Reasoning: Q8_0 (nahezu verlustfrei). Wenn Q4_K_M 1 GB zu groß ist: IQ4_XS als Alternative (ähnliche Qualität, etwas kleiner)."],["Kontextfenster","Das Kurzzeitgedächtnis: wie viel Text sich das Modell gleichzeitig merken kann. Größer = mehr Überblick, mehr Speicher, etwas langsamer."],["Token","Die kleinste Einheit die ein Modell verarbeitet — meist 3–4 Zeichen oder ein kurzes Wort. 1 000 Tokens ≈ 750 Wörter. Kontextfenster, Geschwindigkeit und Kosten werden in Tokens gemessen."],["Auto-Swap","llama-swap lädt/entlädt Modelle automatisch — immer nur eins gleichzeitig. Du managst nichts."],["TTL (Time to Live)","Wie lange ein Modell nach der letzten Anfrage im RAM bleibt bevor es entladen wird. Standard: 5 Minuten. ∞ = bleibt dauerhaft geladen (sinnvoll für den Scout)."],["Agent","Ein Programm (OpenCode, Cline, Continue), das das Modell in einer Handlungsschleife laufen lässt — Dateien lesen/ändern, Befehle ausführen, planen, bis die Aufgabe erledigt ist."],["MCP","Model Context Protocol — der Stecker, über den ein Agent zusätzliche Werkzeuge bekommt (Web, Datenbank, GitHub …). MCP = neue Fähigkeiten."],["Skills / Rules","Kurze Textdatei (AGENTS.md, .clinerules …) mit Anweisungen wie der Agent in deinem Projekt arbeiten soll — einmal geschrieben, immer befolgt. Seit 2026 plattformübergreifender Standard: AGENTS.md wird von über 10 Tools nativ gelesen."],["Memory Bank","Clines Konzept für dauerhaften Projekt-Kontext: projectbrief.md (Ziel & Scope), activeContext.md (aktueller Fokus), progress.md (Stand). Wird zu Beginn jeder Aufgabe automatisch gelesen — ähnlich wie AGENTS.md, aber aufgeteilt nach Zweck."],["System-Prompt","Eine unsichtbare Anweisung die vor deiner Nachricht steht und das Verhalten des Modells grundlegend prägt (Sprache, Ton, Rolle). Skills nutzen oft den System-Prompt."],["Vision","Modelle mit Vision-Fähigkeit können Bilder verstehen — Screenshots, Diagramme, Fehlerfotos. Erkennbar am mmproj-Projektor der mitgeladen wird."]];var mv=g('<div class="concept"><h4> </h4> <p> </p></div>'),bv=g("<button> </button>"),_v=g('<details class="guide-acc"><summary> </summary> <div class="acc-body"></div></details>'),yv=g('<div class="card guide-card svelte-112sh7i"><div class="guide-group-hd svelte-112sh7i"> </div> <!></div>'),xv=g('<div class="pagehead"><div><h1>Guide</h1> <div class="sub">Schritt für Schritt erklärt — von der ersten Einrichtung bis zu echten Agenten-Workflows.</div></div></div> <div class="card"><div class="card-h"><h3>Begriffe kurz erklärt</h3></div> <div class="concept-grid" style="margin-top:8px"></div></div> <div class="guide-tabs svelte-112sh7i"></div> <!>',1);function kv(e,n){kn(n,!0);let a=F(0);function s(f){var _;u(a,f,!0),(_=document.getElementById(`guide-group-${f}`))==null||_.scrollIntoView({behavior:"smooth",block:"start"})}var l=xv(),o=i(Ye(l),2),d=i(r(o),2);Ze(d,21,()=>gv,nt,(f,_)=>{var T=U(()=>En(t(_),2));let y=()=>t(T)[0],k=()=>t(T)[1];var I=mv(),K=r(I),C=r(K),V=i(K,2),Ae=r(V);$(()=>{h(C,y()),h(Ae,k())}),p(f,I)});var v=i(o,2);Ze(v,21,()=>as,nt,(f,_,T)=>{var y=bv(),k=r(y);$(()=>{bt(y,1,`guide-tab${t(a)===T?" active":""}`,"svelte-112sh7i"),h(k,t(_).label)}),S("click",y,()=>s(T)),p(f,y)});var c=i(v,2);Ze(c,17,()=>as,nt,(f,_,T)=>{var y=yv();ga(y,"id",`guide-group-${T}`);var k=r(y),I=r(k),K=i(k,2);Ze(K,17,()=>t(_).tutorials,nt,(C,V,Ae)=>{var Ce=U(()=>En(t(V),2));let Be=()=>t(Ce)[0],De=()=>t(Ce)[1];var se=_v();se.open=T===0&&Ae===0;var le=r(se),$e=r(le),Te=i(le,2);lt(Te,De,!0),$(()=>h($e,Be())),p(C,se)}),$(()=>h(I,t(_).label)),p(f,y)}),p(e,l),wn()}$n(["click"]);var wv=g('<div class="card-sub" style="margin-bottom:10px"> </div>'),Sv=g('<div class="card" style="border-color:rgba(45,212,191,.25)"><div class="card-h"><h3>Import aus Claude / Gemini / ChatGPT</h3></div> <div class="card-sub" style="margin-bottom:10px">Füge Erkenntnisse aus anderen KI-Sessions ein — jede Zeile wird ein eigener Eintrag.</div> <label>Einträge (eine Zeile = ein Eintrag)</label> <textarea rows="8" style="width:100%;box-sizing:border-box;resize:vertical;margin-bottom:10px;font-family:var(--mono);font-size:12.5px"></textarea> <div style="display:flex;gap:12px;flex-wrap:wrap;margin-bottom:14px"><div style="flex:1;min-width:160px"><label>Kategorie für alle Einträge</label> <select style="margin-bottom:0"><option>Über mich — Wer du bist, Präferenzen</option><option>Verhalten — Regeln für alle KI-Tools</option><option>Stabil — Projektfakten</option><option>Versioniert — Tech-Versionen</option><option>Temporär — 7 Tage, dann weg</option></select></div> <div style="flex:1;min-width:120px"><label>Quelle</label> <select style="margin-bottom:0"><option>import</option><option>claude</option><option>gemini</option><option>chatgpt</option><option>manual</option></select></div></div> <!> <div class="btn-row"><button class="primary"> </button> <button class="ghost">Abbrechen</button></div></div>'),Mv=g('<div class="card"><div class="card-h"><h3>Neuer Eintrag</h3></div> <label>Inhalt</label> <textarea rows="3" placeholder="z.B.: Mission Control läuft auf Port 9000 — oder: Wir nutzen SQLite statt Qdrant" style="width:100%;box-sizing:border-box;resize:vertical;margin-bottom:10px"></textarea> <label>Kategorie</label> <select style="margin-bottom:14px"><option>Über mich — Wer du bist, Präferenzen, Arbeitsweise</option><option>Verhalten — Wie alle KI-Tools sich verhalten sollen</option><option>Stabil — Projektfakten, die sich selten ändern</option><option>Versioniert — Tech-Versionen (bei Updates überschreiben)</option><option>Temporär — Aktuelle Aufgabe (nach 7 Tagen gelöscht)</option></select> <div class="btn-row"><button class="primary">Speichern</button> <button class="ghost">Abbrechen</button> <span class="card-sub" style="font-size:11.5px;margin-left:4px">Strg+Enter zum Speichern</span></div></div>'),Ev=g('<span class="chip" role="button" tabindex="0"> <span style="color:var(--mut);margin-left:2px"> </span></span>'),Av=g('<div class="card"><div class="card-sub">Lade…</div></div>'),Cv=g('<button class="primary" style="margin-top:14px">+ Ersten Eintrag anlegen</button>'),Tv=g('<div class="card"><div class="empty-c" style="padding:8px 0 4px"><div class="e-t"> </div> <div class="e-s"> </div> <!></div></div>'),zv=g('<textarea rows="3" style="width:100%;box-sizing:border-box;resize:vertical;margin-bottom:8px"></textarea> <select style="margin-bottom:10px"><option>Über mich</option><option>Verhalten</option><option>Stabil</option><option>Versioniert</option><option>Temporär</option></select> <div class="btn-row"><button class="primary">Speichern</button> <button class="ghost">Abbrechen</button></div>',1),$v=g('<div style="display:flex;gap:10px;align-items:flex-start"><div style="flex:1;min-width:0"><div style="font-size:13.5px;line-height:1.55;word-break:break-word"> </div> <div class="flex gap-2" style="margin-top:8px;flex-wrap:wrap;align-items:center"><span class="chip"> </span> <span class="chip"> </span> <span style="font-size:11px;color:var(--mut)"> </span></div></div> <div class="flex gap-2" style="flex-shrink:0;margin-top:2px"><button class="ghost" style="padding:4px 10px;font-size:12px">Bearbeiten</button> <button class="ghost" style="padding:4px 10px;font-size:12px;color:var(--err)">Löschen</button></div></div>'),Pv=g("<div><!></div>"),Dv=g('<div class="card" style="padding:0;overflow:hidden"></div>'),Iv=g(`<div class="pagehead" style="display:flex;justify-content:space-between;align-items:flex-start"><div><h1>Gedächtnis</h1> <div class="sub">Fakten, Entscheidungen und Kontext — geteilt von allen KI-Tools via MCP.</div></div> <div class="flex gap-2" style="flex-shrink:0;margin-top:4px"><button class="ghost" title="Doppelte Einträge zusammenführen"> </button> <button class="ghost"> </button> <button class="primary"> </button></div></div> <!> <!> <div class="card" style="padding:10px 16px"><div class="flex gap-2" style="flex-wrap:wrap;align-items:center"><span style="font-size:11.5px;color:var(--mut);margin-right:4px">Filter:</span> <!></div></div> <!> <div class="card" style="background:rgba(45,212,191,.04);border-color:rgba(45,212,191,.2)"><div class="card-h"><h3 style="font-size:13px;font-weight:500">Wie KI-Tools dieses Gedächtnis nutzen</h3></div> <div class="card-sub" style="line-height:1.6">Cline, OpenCode und Claude Code greifen über den <b>Memory MCP-Server</b> auf diese Einträge zu.
|
||
Beim Start einer Session lädt der Agent automatisch alle Einträge — er kennt dann deinen Stack,
|
||
deine Präferenzen und frühere Entscheidungen. Den Setup-Guide findest du unter <a href="#" style="color:var(--accent)">Verbinden → Gedächtnis-MCP</a>.</div> <div class="card-sub" style="margin-top:8px;font-size:11.5px"><b style="color:#a78bfa">Über mich</b> = wer du bist, Präferenzen · <b style="color:#fb923c">Verhalten</b> = Regeln für alle KI-Tools · <b style="color:var(--accent)">Stabil</b> = Projektfakten · <b style="color:#f59e0b">Versioniert</b> = Tech-Versionen · <b style="color:var(--mut)">Temporär</b> = 7 Tage, dann weg</div></div>`,1);function Lv(e,n){kn(n,!0);let a=F(Lt([])),s=F(!0),l=F("all"),o=F(!1),d=F(""),v=F("stable"),c=F(null),f=F(""),_=F("stable"),T=F(!1),y=F(""),k=F("stable"),I=F("import"),K=F(!1);const C=U(()=>t(y).split(`
|
||
`).map(D=>D.trim()).filter(D=>D.length>0)),V=U(()=>t(l)==="all"?t(a):t(a).filter(D=>D.category===t(l))),Ae={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 Ce(D){const J=Math.floor((Date.now()-new Date(D).getTime())/1e3);return J<60?"gerade eben":J<3600?`vor ${Math.floor(J/60)} Min`:J<86400?`vor ${Math.floor(J/3600)} Std`:`vor ${Math.floor(J/86400)} Tagen`}function Be(D){return t(a).filter(J=>J.category===D).length}async function De(){try{u(a,await Se("/api/memory"),!0)}catch(D){he("Laden fehlgeschlagen: "+D.message,!0)}finally{u(s,!1)}}async function se(){if(t(d).trim())try{const D=await Se("/api/memory",{method:"POST",body:JSON.stringify({content:t(d).trim(),category:t(v),source:"manual"})});u(a,[D,...t(a)],!0),u(d,""),u(v,"stable"),u(o,!1),he("Gespeichert")}catch(D){he("Fehler: "+D.message,!0)}}async function le(D){try{const J=await Se(`/api/memory/${D.id}`,{method:"PUT",body:JSON.stringify({content:t(f),category:t(_)})});u(a,t(a).map(M=>M.id===D.id?J:M),!0),u(c,null),he("Aktualisiert")}catch(J){he("Fehler: "+J.message,!0)}}async function $e(D){if(await rn({title:"Eintrag löschen?",body:`„${D.content.length>80?D.content.slice(0,80)+"…":D.content}" wird dauerhaft entfernt.`,danger:!0}))try{await Se(`/api/memory/${D.id}`,{method:"DELETE"}),u(a,t(a).filter(M=>M.id!==D.id),!0),he("Gelöscht")}catch(M){he("Fehler: "+M.message,!0)}}function Te(D){u(c,D.id,!0),u(f,D.content,!0),u(_,D.category,!0)}let We=F(!1);async function rt(){u(We,!0);try{const D=await Se("/api/memory/dedupe",{method:"POST",body:JSON.stringify({apply:!1})});if(D.duplicate_count===0){he("Keine Dubletten gefunden 🎉");return}if(!await rn({title:`${D.duplicate_count} Dubletten entfernen?`,body:`${D.duplicate_count} doppelte Einträge werden gelöscht; die ${D.groups.length} vollständigeren bleiben erhalten. Nur exakte/enthaltene/sehr ähnliche Einträge derselben Kategorie.`,danger:!0}))return;const M=await Se("/api/memory/dedupe",{method:"POST",body:JSON.stringify({apply:!0})});he(`${M.removed} Dubletten entfernt`),await De()}catch(D){he("Fehler: "+D.message,!0)}finally{u(We,!1)}}async function Je(){if(t(C).length===0)return;u(K,!0);let D=0;for(const J of t(C))try{const M=await Se("/api/memory",{method:"POST",body:JSON.stringify({content:J,category:t(k),source:t(I)})});u(a,[M,...t(a)],!0),D++}catch{}u(K,!1),u(T,!1),u(y,""),he(`${D} von ${t(C).length} Einträgen importiert`)}di(()=>{De()});var R=Iv(),_e=Ye(R),Re=i(r(_e),2),at=r(Re),Q=r(at),de=i(at,2),xe=r(de),et=i(de,2),Ve=r(et),tt=i(_e,2);{var Ke=D=>{var J=Sv(),M=i(r(J),6);ga(M,"placeholder",`Tobi arbeitet am liebsten abends.
|
||
Projektsprache: Deutsch.
|
||
Bosgame M5 läuft mit Ubuntu 26.04.
|
||
...`);var ie=i(M,2),ke=r(ie),Ie=i(r(ke),2),z=r(Ie);z.value=z.__value="user";var N=i(z);N.value=N.__value="instruction";var ve=i(N);ve.value=ve.__value="stable";var oe=i(ve);oe.value=oe.__value="versioned";var re=i(oe);re.value=re.__value="ephemeral";var we=i(ke,2),pe=i(r(we),2),E=r(pe);E.value=E.__value="import";var Y=i(E);Y.value=Y.__value="claude";var fe=i(Y);fe.value=fe.__value="gemini";var Me=i(fe);Me.value=Me.__value="chatgpt";var ne=i(Me);ne.value=ne.__value="manual";var ce=i(ie,2);{var ze=m=>{var x=wv(),A=r(x);$(()=>h(A,`${t(C).length??""} Eintrag/Einträge erkannt`)),p(m,x)};O(ce,m=>{t(C).length>0&&m(ze)})}var Pe=i(ce,2),w=r(Pe),ee=r(w),ge=i(w,2);$(()=>{w.disabled=t(C).length===0||t(K),h(ee,t(K)?"Importiere…":`${t(C).length} Einträge speichern`)}),Yt(M,()=>t(y),m=>u(y,m)),On(Ie,()=>t(k),m=>u(k,m)),On(pe,()=>t(I),m=>u(I,m)),S("click",w,Je),S("click",ge,()=>{u(T,!1),u(y,"")}),p(D,J)};O(tt,D=>{t(T)&&D(Ke)})}var it=i(tt,2);{var dt=D=>{var J=Mv(),M=i(r(J),4),ie=i(M,4),ke=r(ie);ke.value=ke.__value="user";var Ie=i(ke);Ie.value=Ie.__value="instruction";var z=i(Ie);z.value=z.__value="stable";var N=i(z);N.value=N.__value="versioned";var ve=i(N);ve.value=ve.__value="ephemeral";var oe=i(ie,2),re=r(oe),we=i(re,2);$(pe=>re.disabled=pe,[()=>!t(d).trim()]),S("keydown",M,pe=>{pe.key==="Enter"&&(pe.ctrlKey||pe.metaKey)&&se()}),Yt(M,()=>t(d),pe=>u(d,pe)),On(ie,()=>t(v),pe=>u(v,pe)),S("click",re,se),S("click",we,()=>{u(o,!1),u(d,"")}),p(D,J)};O(it,D=>{t(o)&&D(dt)})}var ht=i(it,2),ct=r(ht),_t=i(r(ct),2);Ze(_t,17,()=>[["all","Alle","",t(a).length],["user","Über mich","#a78bfa",Be("user")],["instruction","Verhalten","#fb923c",Be("instruction")],["stable","Stabil","var(--accent)",Be("stable")],["versioned","Versioniert","#f59e0b",Be("versioned")],["ephemeral","Temporär","var(--mut)",Be("ephemeral")]],nt,(D,J)=>{var M=U(()=>En(t(J),4));let ie=()=>t(M)[0],ke=()=>t(M)[1],Ie=()=>t(M)[2],z=()=>t(M)[3];var N=Ev(),ve=r(N),oe=i(ve),re=r(oe);$(()=>{St(N,`cursor:pointer;${t(l)===ie()?`background:rgba(45,212,191,.12);border-color:${Ie()||"var(--accent)"};color:${Ie()||"var(--accent)"}`:""}`),h(ve,`${ke()??""} `),h(re,z())}),S("click",N,()=>u(l,ie(),!0)),S("keydown",N,we=>we.key==="Enter"&&u(l,ie(),!0)),p(D,N)});var At=i(ht,2);{var xt=D=>{var J=Av();p(D,J)},Pt=D=>{var J=Tv(),M=r(J),ie=r(M),ke=r(ie),Ie=i(ie,2),z=r(Ie),N=i(Ie,2);{var ve=oe=>{var re=Cv();S("click",re,()=>u(o,!0)),p(oe,re)};O(N,oe=>{t(a).length===0&&oe(ve)})}$(()=>{h(ke,t(a).length===0?"Noch keine Einträge":"Keine Treffer"),h(z,t(a).length===0?'Klicke „+ Eintrag" um manuell etwas zu speichern, oder verbinde ein KI-Tool via MCP.':"Andere Kategorie wählen oder Eintrag anlegen.")}),p(D,J)},Ct=D=>{var J=Dv();Ze(J,23,()=>t(V),M=>M.id,(M,ie,ke)=>{var Ie=Pv(),z=r(Ie);{var N=oe=>{var re=zv(),we=Ye(re),pe=i(we,2),E=r(pe);E.value=E.__value="user";var Y=i(E);Y.value=Y.__value="instruction";var fe=i(Y);fe.value=fe.__value="stable";var Me=i(fe);Me.value=Me.__value="versioned";var ne=i(Me);ne.value=ne.__value="ephemeral";var ce=i(pe,2),ze=r(ce),Pe=i(ze,2);Yt(we,()=>t(f),w=>u(f,w)),On(pe,()=>t(_),w=>u(_,w)),S("click",ze,()=>le(t(ie))),S("click",Pe,()=>u(c,null)),p(oe,re)},ve=oe=>{var re=$v(),we=r(re),pe=r(we),E=r(pe),Y=i(pe,2),fe=r(Y),Me=r(fe),ne=i(fe,2),ce=r(ne),ze=i(ne,2),Pe=r(ze),w=i(we,2),ee=r(w),ge=i(ee,2);$(m=>{var x,A,q;h(E,t(ie).content),St(fe,`border-color:${(((x=Ae[t(ie).category])==null?void 0:x.color)||"var(--mut)")??""};color:${(((A=Ae[t(ie).category])==null?void 0:A.color)||"var(--mut)")??""}`),h(Me,((q=Ae[t(ie).category])==null?void 0:q.label)||t(ie).category),h(ce,t(ie).source),h(Pe,m)},[()=>Ce(t(ie).updated_at)]),S("click",ee,()=>Te(t(ie))),S("click",ge,()=>$e(t(ie))),p(oe,re)};O(z,oe=>{t(c)===t(ie).id?oe(N):oe(ve,-1)})}$(()=>St(Ie,`padding:14px 16px;${t(ke)<t(V).length-1?"border-bottom:1px solid var(--brd, rgba(255,255,255,.07))":""}`)),p(M,Ie)}),p(D,J)};O(At,D=>{t(s)?D(xt):t(V).length===0?D(Pt,1):D(Ct,-1)})}var kt=i(At,2),B=i(r(kt),2),Z=i(r(B),3);$(()=>{at.disabled=t(We),h(Q,t(We)?"…":"🧹 Aufräumen"),h(xe,t(T)?"Abbrechen":"⇩ Import"),h(Ve,t(o)?"Abbrechen":"+ Eintrag")}),S("click",at,rt),S("click",de,()=>{u(T,!t(T)),u(o,!1),u(y,"")}),S("click",et,()=>{u(o,!t(o)),u(T,!1),u(d,"")}),S("click",Z,D=>{var J;D.preventDefault(),(J=document.querySelector(".nav-item[data-view='connect']"))==null||J.click()}),p(e,R),wn()}$n(["click","keydown"]);var is=g('<span class="chip" style="font-size:11px;color:var(--mut)"> </span>'),Ov=g('<span><b style="color:var(--accent)"> </b> <span class="card-sub">Sessions</span></span>'),Bv=g('<span><b style="color:var(--accent)"> </b> <span class="card-sub">Nachrichten</span></span>'),Rv=g('<span><b style="color:var(--accent)"> </b> <span class="card-sub">Tool-Calls</span></span>'),Fv=g('<span><b style="color:var(--accent)"> </b> <span class="card-sub">Tokens</span></span>'),Kv=g('<span><b style="color:var(--accent)"> </b> <span class="card-sub">aktiv</span></span>'),Nv=g('<div style="display:flex;align-items:center;gap:8px;font-size:12px"><span style="min-width:230px"> </span> <span style="flex:1;height:6px;background:rgba(255,255,255,.05);border-radius:3px;overflow:hidden"><span></span></span> <span class="card-sub" style="font-size:11px;min-width:64px;text-align:right"> </span></div>'),qv=g('<div class="card-sub" style="font-size:11px;margin-bottom:4px">Meistgenutzte Tools</div> <div style="display:flex;flex-direction:column;gap:3px"></div>',1),Gv=g('<div class="tile" style="margin-bottom:10px"><div style="margin-bottom:8px"><b>Aktivität</b> <span class="card-sub" style="font-size:11px">(letzte 30 Tage)</span></div> <div style="display:flex;gap:18px;flex-wrap:wrap;font-size:12.5px;margin-bottom:8px"><!> <!> <!> <!> <!></div> <!></div>'),Vv=g('<li style="font-size:12.5px;line-height:1.45"> </li>'),Wv=g('<ul style="margin:0 0 6px;padding-left:18px;display:flex;flex-direction:column;gap:3px"></ul>'),jv=g('<div class="card-sub" style="font-size:11.5px;border-top:1px solid rgba(255,255,255,.06);padding-top:6px;margin-top:2px"> </div>'),Uv=g('<div class="tile" style="margin-bottom:10px"><div style="margin-bottom:6px"><b>Was Hermes über dich gelernt hat</b> <span class="card-sub" style="font-size:11px">(automatisches Profil)</span></div> <!> <!></div>'),Hv=g(`<div class="card-sub" style="font-size:12px">Keine geplanten Jobs. Hermes kann selbst welche anlegen — sag ihm z. B.
|
||
„Erinnere mich jeden Morgen um 9 Uhr an die offenen Modell-Upgrades".</div>`),Jv=g('<span style="color:var(--mut)"><span style="opacity:.6"> </span> </span>'),Qv=g(`<div style="display:flex;align-items:center;gap:8px;font-size:12.5px;
|
||
padding:6px 8px;background:rgba(255,255,255,.02);border-radius:6px"></div>`),Zv=g('<div style="display:flex;flex-direction:column;gap:6px"></div>'),Yv=g('<div class="card-sub" style="font-size:12px">Keine Skills geladen (oder Agent offline).</div>'),Xv=g('<span class="card-sub" style="font-size:11px"> </span>'),eu=g('<span class="chip" style="font-size:10px;color:var(--accent);border-color:rgba(45,212,191,.3)"> </span>'),tu=g('<div><span></span> <span style="font-weight:500"> </span> <!> <span style="flex:1"></span> <!> <span class="card-sub" style="font-size:10px"> </span></div>'),nu=g('<div style="max-height:260px;overflow-y:auto;display:flex;flex-direction:column;gap:3px"></div>'),au=g('<div class="card" style="border-color:rgba(45,212,191,.3)"><div class="card-h" style="display:flex;justify-content:space-between;align-items:center"><h3>Agent-Cockpit</h3> <button class="ghost" style="font-size:11px;padding:2px 10px"> </button></div> <div class="tile" style="margin-bottom:10px"><div style="display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:8px"><div><b>Status</b> <div class="card-sub" style="font-size:12px">Hermes-Gateway-Dienst (:8642) auf dem Bosgame</div></div> <div class="flex gap-2" style="flex-wrap:wrap;align-items:center"><span class="chip"> </span> <span class="chip"> </span> <!> <!></div></div></div> <!> <!> <div class="tile" style="margin-bottom:10px"><div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:6px"><b>Geplante Aufgaben <span class="card-sub" style="font-size:11px"> </span></b></div> <!></div> <div class="tile"><div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:6px"><b>Skills <span class="card-sub" style="font-size:11px"> </span></b></div> <!></div></div>'),iu=g('<div class="log" style="margin-top:8px"><code>pip install faster-whisper</code></div>'),ru=g('<div class="log" style="margin-top:8px"><code> </code></div>'),su=g('<div style="margin-bottom:8px"><div class="card-sub" style="font-size:11.5px;margin-bottom:4px">4. Bosgame-Key eintragen (in Windows PowerShell):</div> <div style="position:relative"><button class="ghost" style="position:absolute;top:6px;right:6px;font-size:11px;padding:2px 8px;z-index:1">Kopieren</button> <div class="log"><code> </code></div></div></div>'),lu=g('<div class="card-sub" style="font-size:11.5px">SSH-Key nicht gefunden — bitte auf dem Bosgame generieren: <code style="display:block;margin-top:4px">ssh-keygen -t ed25519 -C "hermes-agent@bosgame" -f ~/.ssh/id_ed25519_hermes_agent -N ""</code></div>'),ou=g('<div style="margin-top:12px"><div style="font-size:12.5px;font-weight:500;margin-bottom:8px">Einrichtung (einmalig, ~3 Minuten):</div> <div style="margin-bottom:8px"><div class="card-sub" style="font-size:11.5px;margin-bottom:4px">1. PowerShell als Admin — OpenSSH Server installieren:</div> <div class="log"><code>Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0</code></div></div> <div style="margin-bottom:8px"><div class="card-sub" style="font-size:11.5px;margin-bottom:4px">2. Dienst starten und dauerhaft aktivieren:</div> <div class="log"><code></code></div></div> <div style="margin-bottom:8px"><div class="card-sub" style="font-size:11.5px;margin-bottom:4px">3. SSH-Ordner erstellen:</div> <div class="log"><code></code></div></div> <!> <div style="margin-bottom:8px"><div class="card-sub" style="font-size:11.5px;margin-bottom:4px">5. Windows-IP in Mission Control Env-Var setzen:</div> <div class="log"><code>HERMES_WINDOWS_HOST=192.168.178.XXX</code></div></div> <button class="primary" style="margin-top:4px">Verbindung testen</button></div>'),du=g('<div class="card" style="border-color:rgba(45,212,191,.3)"><div class="card-h"><h3>Hermes Setup-Wizard</h3></div> <div class="tile" style="margin-bottom:10px"><div style="display:flex;justify-content:space-between;align-items:center"><div><b>Whisper (Sprache → Text)</b> <div class="card-sub" style="font-size:12px">faster-whisper muss auf dem Bosgame installiert sein</div></div> <span class="chip"> </span></div> <!></div> <div class="tile" style="margin-bottom:10px"><div style="display:flex;justify-content:space-between;align-items:center"><div><b>Piper TTS (Text → Sprache)</b> <div class="card-sub" style="font-size:12px">Piper-Binary + deutsche Stimme</div></div> <span class="chip"> </span></div> <!></div> <div class="tile"><div style="display:flex;justify-content:space-between;align-items:center"><div><b>Windows SSH-Verbindung</b> <div class="card-sub" style="font-size:12px">Damit Hermes Dateien auf deinem Windows-PC ändern kann</div></div> <span class="chip"> </span></div> <!></div></div>'),cu=g('<iframe title="Hermes Chat" src="/hermes-ui/chat" style="width:100%;height:calc(100dvh - 116px);min-height:520px;border:0;display:block;background:#0f1720"></iframe>'),vu=g(`<div class="empty-c" style="padding:48px 24px"><div class="e-t">Hermes-Agent offline</div> <div class="e-s">Der Hermes-Gateway (:8642) bzw. das Dashboard (:9119) ist nicht erreichbar.
|
||
Status im Cockpit prüfen oder den Dienst neu starten.</div></div>`),uu=g('<div class="pagehead" style="display:flex;justify-content:space-between;align-items:center;margin-bottom:10px"><h1 style="margin:0;font-size:20px">Hermes</h1> <div class="flex gap-2" style="flex-shrink:0;flex-wrap:wrap;align-items:center"><span class="chip"> </span> <button class="ghost">📡 Cockpit</button> <button class="ghost" style="padding:4px 10px;font-size:12px">⚙ Setup</button></div></div> <!> <!> <div class="card" style="padding:0;overflow:hidden;border-radius:12px"><!></div>',1);function pu(e,n){kn(n,!0);let a=F(null),s=F(!1),l=F(!1),o=F(!1),d=F(null),v=F(Lt([])),c=F(Lt([])),f=F(null),_=F(null),T=F("");async function y(){try{u(a,await Se("/api/hermes/status"),!0)}catch{u(a,null)}}async function k(){try{const Q=await Se("/api/hermes/pubkey");u(T,Q.pubkey,!0)}catch{u(T,"")}}async function I(){u(o,!0);try{const[Q,de,xe,et,Ve]=await Promise.all([Se("/api/hermes/agent"),Se("/api/hermes/cron"),Se("/api/hermes/skills"),Se("/api/hermes/learned"),Se("/api/hermes/insights")]);u(d,Q,!0),u(v,de.jobs||[],!0),u(c,xe.skills||[],!0),u(f,et,!0),u(_,Ve,!0)}catch{u(d,null)}u(o,!1)}let K=U(()=>[...t(c)].sort((Q,de)=>(de.use_count||0)-(Q.use_count||0)||(Q.name||"").localeCompare(de.name||""))),C=U(()=>t(c).filter(Q=>(Q.status||"").includes("enabled")).length);function V(){var Q;(Q=navigator.clipboard)==null||Q.writeText(t(T)),he("SSH-Key kopiert")}di(()=>{y()});var Ae=uu(),Ce=Ye(Ae),Be=i(r(Ce),2),De=r(Be),se=r(De),le=i(De,2),$e=i(le,2),Te=i(Ce,2);{var We=Q=>{var de=au(),xe=r(de),et=i(r(xe),2),Ve=r(et),tt=i(xe,2),Ke=r(tt),it=i(r(Ke),2),dt=r(it),ht=r(dt),ct=i(dt,2),_t=r(ct),At=i(ct,2);{var xt=ne=>{var ce=is(),ze=r(ce);$(()=>h(ze,`Ticker vor ${t(d).heartbeat_age_s??""}s`)),p(ne,ce)};O(At,ne=>{var ce;((ce=t(d))==null?void 0:ce.heartbeat_age_s)!=null&&ne(xt)})}var Pt=i(At,2);{var Ct=ne=>{var ce=is(),ze=r(ce);$(Pe=>{ga(ce,"title",t(d).version),h(ze,Pe)},[()=>t(d).version.split(" · ")[0]]),p(ne,ce)};O(Pt,ne=>{var ce;(ce=t(d))!=null&&ce.version&&ne(Ct)})}var kt=i(tt,2);{var B=ne=>{var ce=Gv(),ze=i(r(ce),2),Pe=r(ze);{var w=L=>{var X=Ov(),ae=r(X),ue=r(ae);$(()=>h(ue,t(_).sessions)),p(L,X)};O(Pe,L=>{t(_).sessions&&L(w)})}var ee=i(Pe,2);{var ge=L=>{var X=Bv(),ae=r(X),ue=r(ae);$(()=>h(ue,t(_).messages)),p(L,X)};O(ee,L=>{t(_).messages&&L(ge)})}var m=i(ee,2);{var x=L=>{var X=Rv(),ae=r(X),ue=r(ae);$(()=>h(ue,t(_).tool_calls)),p(L,X)};O(m,L=>{t(_).tool_calls&&L(x)})}var A=i(m,2);{var q=L=>{var X=Fv(),ae=r(X),ue=r(ae);$(()=>h(ue,t(_).total_tokens)),p(L,X)};O(A,L=>{t(_).total_tokens&&L(q)})}var H=i(A,2);{var G=L=>{var X=Kv(),ae=r(X),ue=r(ae);$(()=>h(ue,t(_).active_time)),p(L,X)};O(H,L=>{t(_).active_time&&L(G)})}var P=i(ze,2);{var W=L=>{var X=qv(),ae=i(Ye(X),2);Ze(ae,21,()=>t(_).top_tools.slice(0,6),nt,(ue,j)=>{var te=Nv(),Le=r(te),Qe=r(Le),Oe=i(Le,2),Ne=r(Oe),yt=i(Oe,2),Mt=r(yt);$(()=>{h(Qe,t(j).name),St(Ne,`display:block;height:100%;width:${t(j).pct??""}%;background:var(--accent)`),h(Mt,`${t(j).calls??""}× · ${t(j).pct??""}%`)}),p(ue,te)}),p(L,X)};O(P,L=>{var X;(X=t(_).top_tools)!=null&&X.length&&L(W)})}p(ne,ce)};O(kt,ne=>{t(_)&&(t(_).sessions||t(_).total_tokens)&&ne(B)})}var Z=i(kt,2);{var D=ne=>{var ce=Uv(),ze=i(r(ce),2);{var Pe=ge=>{var m=Wv();Ze(m,21,()=>t(f).user_facts,nt,(x,A)=>{var q=Vv(),H=r(q);$(()=>h(H,t(A))),p(x,q)}),p(ge,m)};O(ze,ge=>{var m;(m=t(f).user_facts)!=null&&m.length&&ge(Pe)})}var w=i(ze,2);{var ee=ge=>{var m=jv(),x=r(m);$(()=>h(x,t(f).memory)),p(ge,m)};O(w,ge=>{t(f).memory&&ge(ee)})}p(ne,ce)};O(Z,ne=>{var ce,ze,Pe;((ze=(ce=t(f))==null?void 0:ce.user_facts)!=null&&ze.length||(Pe=t(f))!=null&&Pe.memory)&&ne(D)})}var J=i(Z,2),M=r(J),ie=r(M),ke=i(r(ie)),Ie=r(ke),z=i(M,2);{var N=ne=>{var ce=Hv();p(ne,ce)},ve=ne=>{var ce=Zv();Ze(ce,21,()=>t(v),nt,(ze,Pe)=>{var w=Qv();Ze(w,21,()=>Object.entries(t(Pe)),nt,(ee,ge)=>{var m=U(()=>En(t(ge),2));let x=()=>t(m)[0],A=()=>t(m)[1];var q=ua(),H=Ye(q);{var G=P=>{var W=Jv(),L=r(W),X=r(L),ae=i(L);$(()=>{h(X,`${x()??""}:`),h(ae,` ${A()??""}`)}),p(P,W)};O(H,P=>{A()&&P(G)})}p(ee,q)}),p(ze,w)}),p(ne,ce)};O(z,ne=>{t(v).length===0?ne(N):ne(ve,-1)})}var oe=i(J,2),re=r(oe),we=r(re),pe=i(r(we)),E=r(pe),Y=i(re,2);{var fe=ne=>{var ce=Yv();p(ne,ce)},Me=ne=>{var ce=nu();Ze(ce,21,()=>t(K),nt,(ze,Pe)=>{var w=tu(),ee=r(w),ge=i(ee,2),m=r(ge),x=i(ge,2);{var A=W=>{var L=Xv(),X=r(L);$(()=>h(X,t(Pe).category)),p(W,L)};O(x,W=>{t(Pe).category&&W(A)})}var q=i(x,4);{var H=W=>{var L=eu(),X=r(L);$(()=>h(X,`${t(Pe).use_count??""}× genutzt`)),p(W,L)};O(q,W=>{t(Pe).use_count>0&&W(H)})}var G=i(q,2),P=r(G);$((W,L)=>{St(w,`display:flex;align-items:center;gap:8px;font-size:12.5px;padding:4px 8px;
|
||
border-radius:6px;${W??""}`),St(ee,`width:7px;height:7px;border-radius:50%;flex-shrink:0;
|
||
background:${L??""}`),h(m,t(Pe).name),h(P,t(Pe).source)},[()=>(t(Pe).status||"").includes("enabled")?"":"opacity:.45",()=>(t(Pe).status||"").includes("enabled")?"var(--accent)":"var(--mut)"]),p(ze,w)}),p(ne,ce)};O(Y,ne=>{t(c).length===0?ne(fe):ne(Me,-1)})}$(()=>{var ne,ce,ze,Pe;h(Ve,t(o)?"…":"↻ Aktualisieren"),St(dt,`font-size:11px;${((ne=t(d))==null?void 0:ne.gateway_state)==="running"?"color:#7ee29a;border-color:rgba(126,226,154,.4)":"color:#ff9b95;border-color:rgba(255,155,149,.4)"}`),h(ht,`● ${((ce=t(d))==null?void 0:ce.gateway_state)??"offline"??""}`),St(ct,`font-size:11px;${(ze=t(d))!=null&&ze.cron_running?"color:var(--accent);border-color:var(--accent)":"color:var(--mut)"}`),h(_t,`⏱ Scheduler ${(Pe=t(d))!=null&&Pe.cron_running?"läuft":"inaktiv"}`),h(Ie,`(${t(v).length??""})`),h(E,`(${t(C)??""} aktiv von ${t(c).length??""})`)}),S("click",et,I),p(Q,de)};O(Te,Q=>{t(l)&&Q(We)})}var rt=i(Te,2);{var Je=Q=>{var de=du(),xe=i(r(de),2),et=r(xe),Ve=i(r(et),2),tt=r(Ve),Ke=i(et,2);{var it=J=>{var M=iu();p(J,M)};O(Ke,J=>{var M;((M=t(a))==null?void 0:M.whisper)==="not_installed"&&J(it)})}var dt=i(xe,2),ht=r(dt),ct=i(r(ht),2),_t=r(ct),At=i(ht,2);{var xt=J=>{var M=ru(),ie=r(M),ke=r(ie);$(Ie=>h(ke,Ie),[()=>["# 1. Piper Binary (Linux x86_64)","mkdir -p /opt/mission-control/piper/voices","cd /tmp && wget -q https://github.com/rhasspy/piper/releases/download/2023.11.14-2/piper_linux_x86_64.tar.gz","tar -xzf piper_linux_x86_64.tar.gz -C /opt/mission-control/piper/ --strip-components=1","","# 2. Deutsche Stimme — Kerstin (weiblich, ~25 MB)","wget -q -O /opt/mission-control/piper/voices/de_DE-kerstin-low.onnx \\",' "https://huggingface.co/rhasspy/piper-voices/resolve/v1.0.0/de/de_DE/kerstin/low/de_DE-kerstin-low.onnx"',"wget -q -O /opt/mission-control/piper/voices/de_DE-kerstin-low.onnx.json \\",' "https://huggingface.co/rhasspy/piper-voices/resolve/v1.0.0/de/de_DE/kerstin/low/de_DE-kerstin-low.onnx.json"'].join(`
|
||
`)]),p(J,M)};O(At,J=>{var M;((M=t(a))==null?void 0:M.piper)!=="ready"&&J(xt)})}var Pt=i(dt,2),Ct=r(Pt),kt=i(r(Ct),2),B=r(kt),Z=i(Ct,2);{var D=J=>{var M=ou(),ie=i(r(M),4),ke=i(r(ie),2),Ie=r(ke);Ie.textContent=`Start-Service sshd
|
||
Set-Service -Name sshd -StartupType Automatic`;var z=i(ie,2),N=i(r(z),2),ve=r(N);ve.textContent='New-Item -ItemType Directory -Force -Path "$env:USERPROFILE\\.ssh"';var oe=i(z,2);{var re=E=>{var Y=su(),fe=i(r(Y),2),Me=r(fe),ne=i(Me,2),ce=r(ne),ze=r(ce);$(()=>h(ze,'echo "'+t(T)+'" >> "$env:USERPROFILE\\.ssh\\authorized_keys"')),S("click",Me,V),p(E,Y)},we=E=>{var Y=lu();p(E,Y)};O(oe,E=>{t(T)?E(re):E(we,-1)})}var pe=i(oe,4);S("click",pe,()=>{y(),he("Status aktualisiert")}),p(J,M)};O(Z,J=>{var M;(M=t(a))!=null&&M.ssh_ok||J(D)})}$(()=>{var J,M,ie,ke,Ie,z;St(Ve,`font-size:11px;${((J=t(a))==null?void 0:J.whisper)!=="not_installed"?"color:#7ee29a":"color:#ff9b95"}`),h(tt,((M=t(a))==null?void 0:M.whisper)!=="not_installed"?"✓ OK":"✗ fehlt"),St(ct,`font-size:11px;${((ie=t(a))==null?void 0:ie.piper)==="ready"?"color:#7ee29a":"color:#ff9b95"}`),h(_t,((ke=t(a))==null?void 0:ke.piper)==="ready"?"✓ OK":"✗ fehlt"),St(kt,`font-size:11px;${(Ie=t(a))!=null&&Ie.ssh_ok?"color:#7ee29a":"color:var(--mut)"}`),h(B,(z=t(a))!=null&&z.ssh_ok?"✓ verbunden":"optional")}),p(Q,de)};O(rt,Q=>{t(s)&&Q(Je)})}var R=i(rt,2),_e=r(R);{var Re=Q=>{var de=cu();p(Q,de)},at=Q=>{var de=vu();p(Q,de)};O(_e,Q=>{var de;((de=t(a))==null?void 0:de.hermes)==="ready"?Q(Re):Q(at,-1)})}$(()=>{var Q,de;St(De,`font-size:11px;${((Q=t(a))==null?void 0:Q.hermes)==="ready"?"color:#7ee29a;border-color:rgba(126,226,154,.4)":"color:#ff9b95;border-color:rgba(255,155,149,.4)"}`),h(se,`● Agent: ${((de=t(a))==null?void 0:de.hermes)==="ready"?"online":"offline"}`),St(le,`padding:4px 10px;font-size:12px;${t(l)?"border-color:var(--accent);color:var(--accent)":""}`)}),S("click",le,()=>{u(l,!t(l)),t(l)&&I()}),S("click",$e,()=>{u(s,!t(s)),t(s)&&(y(),k())}),p(e,Ae),wn()}$n(["click"]);let rs={};function fu(){const e=document.getElementById("top-active-text");e&&(e.classList.add("swap-flash"),setTimeout(()=>e.classList.remove("swap-flash"),900))}function ss(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"),ls("Backend nicht erreichbar – läuft uvicorn?",!1);else{const o=(e.swap_url||"").replace(/^https?:\/\//,"");n&&(n.className="dot "+(e.swap_ok?"on":"off")),a&&(a.textContent=(e.swap_ok?"LLM-Engine: Online – ":"LLM-Engine: Offline – ")+o);const d=["running","ready","loading","starting"],v=(e.models||[]).find(f=>d.includes(f.state));if(s)if(v){const f=(l=v.meta)!=null&&l.ctx?` <span style="color:var(--mut);font-size:11.5px">· ${Math.round(v.meta.ctx/1024)}k ctx</span>`:"",_=v.state==="loading"||v.state==="starting"?' <span style="color:var(--warn);font-size:11.5px">lädt…</span>':"";s.innerHTML=`<b style="color:var(--accent)">${v.name}</b>${f}${_}`}else s.innerHTML='<span style="color:var(--mut)">Kein Modell im VRAM</span>';e.swap_ok?bu():ls(`LLM-Engine nicht erreichbar unter <b>${o}</b> – läuft der llama-swap Dienst?`,!0);const c={};for(const f of e.models||[])c[f.name]=f.state;for(const[f,_]of Object.entries(c)){const T=rs[f];if(T&&T!==_&&(_==="running"||_==="loading")){fu();break}}rs=c}hu(e),ui.set(e)}function hu(e){const n=document.getElementById("sec-chip"),a=document.getElementById("sec-chip-tx");!n||!a||(n.classList.toggle("ok",!!(e!=null&&e.secured)),a.textContent=e!=null&&e.secured?"Geschützt · Heimnetz":"Nur im Heimnetz (offen)")}function gu(e){na.set(e||[])}function mu(e){Lr.set(e)}function ls(e,n){const a=document.getElementById("alert");a.className="alert"+(n?" warn":""),a.innerHTML=`<span class="a-dot"></span><span>${e}</span>`,a.style.display="flex"}function bu(){const e=document.getElementById("alert");e&&(e.style.display="none")}const _u=e=>{var n;return(n=document.querySelector(`.nav-item[data-view="${e}"]`))==null?void 0:n.click()};function rr(e,n,a,s){const l=document.createElement("span");return l.className="upd-badge"+(n?" "+n:""),l.textContent=e,s&&(l.title=s),l.onclick=()=>_u(a),l}async function ll(){try{const e=await Se("/api/updates"),n=document.getElementById("update-badges");if(!n)return;const a=e.apt_cache_age_h,s=a!=null&&a>24,l=a!=null?` · apt-Cache: vor ${a}h`:"";n.innerHTML="",n.appendChild(rr(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(rr(e.engine>0?"Engine: Update":"Engine: aktuell",e.engine>0?"warn":"ok","server")),n.appendChild(rr(e.models>0?`Modelle: ${e.models}`:"Modelle: aktuell",e.models>0?"warn":"ok","news"))}catch{}}async function Vi(){try{ss(await Se("/api/status"))}catch{ss(null)}}async function ol(){try{gu(await Se("/api/jobs"))}catch{}}function dl(){const e=window.location.protocol==="https:"?"wss:":"ws:",n=new WebSocket(`${e}//${window.location.host}/api/system/stream`);n.onmessage=a=>{try{mu(JSON.parse(a.data))}catch{}},n.onclose=()=>{setTimeout(dl,3e3)},n.onerror=()=>n.close()}var ps;((ps=document.getElementById("logo"))==null?void 0:ps.innerHTML)!==void 0&&(document.getElementById("logo").innerHTML=Gi.logo);document.querySelectorAll("[data-ic]").forEach(e=>{e.innerHTML=Gi[e.dataset.ic||""]||""});const yu=[["overview",md],["models",Pd],["activity",Gd],["server",Xd],["cookbook",Rc],["connect",rv],["news",hv],["guides",kv],["memory",Lv],["hermes",pu]];for(const[e,n]of yu){const a=document.querySelector(`.view[data-view="${e}"]`);a&&zo(n,{target:a})}Yo("overview");const sr=document.getElementById("token");sr&&(sr.value=sl(),sr.addEventListener("change",e=>{Uo(e.target.value),Vi()}));const lr=document.getElementById("hf-token");lr&&(lr.value=ei(),lr.addEventListener("change",e=>Jo(e.target.value)));const os=document.getElementById("nav-settings"),or=document.getElementById("settings-modal"),ds=document.getElementById("sm-close");os&&or&&ds&&(os.addEventListener("click",()=>or.style.display="flex"),ds.addEventListener("click",()=>or.style.display="none"));function xu(){const e=document.getElementById("clock");e&&(e.textContent=new Date().toTimeString().slice(0,5))}document.addEventListener("mc:refresh",Vi);Vi();ol();dl();setInterval(xu,1e3);setInterval(Vi,3e3);setInterval(ol,1500);ll();setInterval(ll,6e4);
|