This repository has been archived on 2026-07-22. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
mission-control/static/dist/main.js
T
Hitonabi 40d9efee18 docs(v9): Phase 4 (Agent-Cockpit) dokumentiert + Versions-Chip-Fix
- HermesPanel: version-Chip zeigt PINNED_VERSION ohne doppeltes "v".
- ROADMAP/CLAUDE.md: Phase 4 als live markiert, HERMES_HOME/BIN ergänzt.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 16:20:19 +02:00

677 lines
222 KiB
JavaScript
Raw Blame History

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