Files
mission-control-v2/frontend/dist/assets/Auftraege-C3JDjG9Z.js
T
HitonabiandClaude Opus 5.5 5e9227c4a3 phase3+4: Homelab-Teil (Ausfuehrer, Ziele, Jetzt updaten mit Rueckweg) und Seite Homelab fuer alle Geraete
- deploy/homelab/ausfuehrer.py: laeuft als root auf dem Proxmox-Host, holt Auftraege beim Homelab-Teil
  ab (Pull, kein offener Port), feste Aktionsliste, prueft Etiketten selbst; Bericht gegen den echten
  Host erprobt (nur lesend). Kein Proxmox-Schluessel im Container noetig.
- services/homelab: Kanal mit gemeinsamem Geheimnis, App-Katalog, Inventar -> Ziele im gemeinsamen
  Modell (GitHub-Versionen, Webpruefung, alte Paketlisten = unklar), Jetzt updaten: Snapshot ->
  Update -> Pruefung -> bei Rot zurueck + dringende Meldung
- Waechter in der Rolle homelab: Ausfuehrer schweigt, Gaeste antworten nicht
- kern/github.py fuer beide Rollen (auch untagged Releases mit Version im Namen)
- Oberflaeche: Seite Homelab zeigt alle Geraete als Karten (KI-Box ueber /api/ziele, Homelab ueber
  /api/homelab/ziele) mit Stand, Rueckweg und Knopf samt Rueckfrage
- Einrichtung als Skripte (container-anlegen, ausrollen, ausfuehrer-einrichten, box-partner) — noch
  nicht ausgefuehrt, jeder Schritt braucht das User-OK
- frontend-bauen-box.sh: Frontend-Pruefung und Build auf der Box, wenn der PC keinen Speicher hat

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 18:39:59 +02:00

2 lines
9.3 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.
import{c as e,i as t,p as n,s as r,t as i,u as a}from"./button-BheHBEml.js";import{L as o,N as s,h as c,j as l,m as u,n as d,t as f}from"./index-SRwQwEnh.js";import{t as p}from"./Bestaetigen-CE_3b0PK.js";var m=r();function h(e,t){if(e===`os`)return{laeuft:`Ubuntu`,neu:t.count?`${t.count} ${t.count===1?`Paket`:`Pakete`}`:null};if(e===`hermes`)return{laeuft:t.installed_version?`v${t.installed_version}`:`–`,neu:t.behind?`+${t.behind.toLocaleString(`de-DE`)} Änderungen`:null};let n=e===`engine`?`b`:`v`;return{laeuft:t.installed_build==null?`–`:`${n}${t.installed_build}`,neu:t.latest_build!=null&&t.installed_build!=null&&t.latest_build>t.installed_build?`${n}${t.latest_build}`:null}}function g(e,t){return!t||t.error?null:e===`os`?typeof t.count==`number`?t.count>0:null:e===`hermes`?typeof t.behind==`number`?t.behind>0:null:t.latest_build==null||t.installed_build==null?null:t.latest_build>t.installed_build}function _(e){let t=e.trim();return/timed out|timeout|zeitüberschreitung/i.test(t)?`Konnte nicht prüfen: Die Gegenstelle hat nicht rechtzeitig geantwortet. Später klappt es meist wieder.`:/name resolution|name or service not known|network is unreachable|connection (refused|reset)|nicht erreichbar/i.test(t)?`Konnte nicht prüfen: Die Box kommt gerade nicht ins Internet.`:`Konnte nicht prüfen: ${t.length>160?`${t.slice(0,157)}…`:t}`}var v=e=>e.group===`download`||/^download\s/i.test(e.label),y=e=>e.group===`pruefen`||e.label===`Nach Updates suchen`,b=e=>o(e)&&v(e),x=[[/^download\s+(.+)$/i,`Download $1`],[/^OS-Update \(apt\)$/,`Update Betriebssystem`],[/^Engine-Update \(llama\.cpp Vulkan\)$/,`Update Motor (llama.cpp)`],[/^Router-Update \(llama-swap\)$/,`Update llama-swap`],[/^Hermes-Agent-Update$/,`Update Hermes`]],S=[[`Engine (llama.cpp)`,`Motor`],[`Router (llama-swap)`,`llama-swap`],[`Hermes-Agent`,`Hermes`],[`OS (apt)`,`Betriebssystem`]];function C(e){for(let[t,n]of x)if(t.test(e.label))return e.label.replace(t,n);return e.label.startsWith(`Alle aktualisieren`)?S.reduce((e,[t,n])=>e.split(t).join(n),e.label):e.label}function w(e){if(e<60)return`noch unter einer Minute`;let t=Math.round(e/60);if(t<60)return`noch etwa ${t} min`;let n=Math.floor(t/60),r=t%60;return r?`noch etwa ${n} h ${r} min`:`noch etwa ${n} h`}function T(e,t=Date.now()/1e3){let n=Math.max(0,t-e.started_at),r=Math.floor(n/60),i=n<60?`ein paar Sekunden`:r<60?`${r} min`:`${Math.floor(r/60)} h ${r%60} min`;return`${e.state===`queued`?`Wartet`:`Läuft`} seit ${i}`}function E(e){if(e.progress==null)return null;let t=[`${Math.round(e.progress)} %`];return e.total_bytes&&t.push(`${s(e.done_bytes??0,1)} von ${s(e.total_bytes,1)}`),e.eta_s!=null&&o(e)&&t.push(w(e.eta_s)),t.join(` · `)}function D(e){for(let t=(e.log?.length??0)-1;t>=0;t--){let n=e.log[t].trim();if(n&&!n.startsWith(`$ `))return n}return null}function O(e,t=Date.now()/1e3){let n=e.filter(o).sort((e,t)=>e.started_at-t.started_at),r=e.filter(e=>!o(e)&&t-(e.finished_at??e.started_at)<86400).sort((e,t)=>(t.finished_at??t.started_at)-(e.finished_at??e.started_at)).slice(0,3);return[...n,...r]}function k(e,t,n){if(!n)return`Nach dem Download übernimmt ${e} die Rolle „${t}“.`;let r=n.weitere.length?` Die Rolle${n.weitere.length===1?``:`n`} „${n.weitere.join(`“, „`)}“ behält es.`:``;return`Achtung: Nach dem Download übernimmt ${e} die Rolle „${t}“ und ersetzt damit ${n.name}. Das bisherige Modell bleibt auf der Platte.${r}`+(n.zwilling?` Bilder liest vorerst weiter sein Bild-Zwilling, also noch das bisherige Modell.`:``)}function A(e){return`Kurze Unterbrechung: Beim Eintragen lädt llama-swap sofort neu. Was Lucy oder OpenChamber gerade schreiben, bricht ab, und die Modelle werden neu geladen.`+(e?` Mit Rolle passiert das nach dem Download noch einmal.`:``)}var j=n(a(),1),M=e(),N={queued:{text:`Wartet`,art:`cyan`},running:{text:`Läuft`,art:`cyan`},done:{text:`Fertig`,art:`gruen`},failed:{text:`Fehler`,art:`rot`},canceled:{text:`Abgebrochen`,art:`grau`}},P={queued:`bg-cyan`,running:`bg-cyan`,done:`bg-gruen`,failed:`bg-rot`,canceled:`bg-text-3`},F=e=>l(new Date(e*1e3).toISOString());function I(e){let t=(0,m.c)(3),[n,r]=(0,j.useState)(L),i,a;return t[0]===e?(i=t[1],a=t[2]):(i=()=>{if(!e)return;let t=window.setInterval(()=>r(Date.now()/1e3),3e4);return()=>window.clearInterval(t)},a=[e],t[0]=e,t[1]=i,t[2]=a),(0,j.useEffect)(i,a),n}function L(){return Date.now()/1e3}function R(e){let n=(0,m.c)(75),{job:r,onAbbrechen:a,abbrechenGesperrt:s,ebene:c}=e,l=c===void 0?4:c,[u,f]=(0,j.useState)(!1),[h,g]=(0,j.useState)(!1),_;n[0]===r.state?_=n[1]:(_=N[r.state]??{text:r.state,art:`grau`},n[0]=r.state,n[1]=_);let y=_,x;n[2]===r?x=n[3]:(x=C(r),n[2]=r,n[3]=x);let S=x,w;n[4]===r?w=n[5]:(w=E(r),n[4]=r,n[5]=w);let O=w,k;n[6]===r?k=n[7]:(k=D(r),n[6]=r,n[7]=k);let A=k,L;n[8]===r?L=n[9]:(L=o(r),n[8]=r,n[9]=L);let R=L,z=I(R),B;n[10]!==r||n[11]!==a?(B=!!a&&b(r),n[10]=r,n[11]=a,n[12]=B):B=n[12];let V=B,H,U,W,G,K,q,J,Y;if(n[13]!==s||n[14]!==V||n[15]!==l||n[16]!==O||n[17]!==z||n[18]!==r||n[19]!==R||n[20]!==A||n[21]!==h||n[22]!==S||n[23]!==y.art||n[24]!==y.text){let e=(r.log??[]).slice(-12),a=l===3?`h3`:`h4`;J=`Auftrag: ${S}`,Y=`flex flex-col gap-2.5 rounded-xl border border-linie bg-erhaben/50 p-3.5`;let o;n[33]!==a||n[34]!==S?(o=(0,M.jsx)(a,{className:`m-0 min-w-0 text-[15px] leading-snug font-semibold break-words`,children:S}),n[33]=a,n[34]=S,n[35]=o):o=n[35];let c;n[36]!==y.art||n[37]!==y.text?(c=(0,M.jsx)(d,{art:y.art,children:y.text}),n[36]=y.art,n[37]=y.text,n[38]=c):c=n[38],n[39]!==o||n[40]!==c?(H=(0,M.jsxs)(`div`,{className:`flex items-start justify-between gap-3`,children:[o,c]}),n[39]=o,n[40]=c,n[41]=H):H=n[41],n[42]!==r.progress||n[43]!==r.state||n[44]!==S?(U=r.progress!=null&&(0,M.jsx)(`div`,{role:`progressbar`,"aria-label":`Fortschritt: ${S}`,"aria-valuemin":0,"aria-valuemax":100,"aria-valuenow":Math.round(r.progress),className:`h-2 overflow-hidden rounded-full bg-linie`,children:(0,M.jsx)(`div`,{className:t(`h-full`,P[r.state]??`bg-cyan`),style:{width:`${Math.max(2,Math.min(100,r.progress))}%`}})}),n[42]=r.progress,n[43]=r.state,n[44]=S,n[45]=U):U=n[45];let u;n[46]!==O||n[47]!==z||n[48]!==r||n[49]!==R||n[50]!==y.text?(u=R?O??T(r,z):`${y.text} · ${F(r.finished_at??r.started_at)}`,n[46]=O,n[47]=z,n[48]=r,n[49]=R,n[50]=y.text,n[51]=u):u=n[51],n[52]===u?W=n[53]:(W=(0,M.jsx)(`p`,{className:`ziffern m-0 text-sm text-text-2`,children:u}),n[52]=u,n[53]=W),n[54]!==r.progress||n[55]!==r.state||n[56]!==R||n[57]!==A?(G=A&&(r.state===`failed`||R&&r.progress==null)&&(0,M.jsx)(`p`,{className:r.state===`failed`?`m-0 text-sm break-words text-rot-text`:`ziffern m-0 line-clamp-2 text-xs break-all text-text-3`,children:r.state===`failed`?`Letzte Meldung: ${A}`:A}),n[54]=r.progress,n[55]=r.state,n[56]=R,n[57]=A,n[58]=G):G=n[58],K=(V||e.length>1)&&(0,M.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[V&&(0,M.jsx)(i,{variant:`outline`,size:`sm`,disabled:s,onClick:()=>f(!0),children:`Abbrechen`}),e.length>1&&(0,M.jsx)(i,{variant:`ghost`,size:`sm`,"aria-expanded":h,onClick:()=>g(!h),children:h?`Protokoll zu`:`Protokoll`})]}),q=h&&(0,M.jsx)(`pre`,{className:`ziffern m-0 max-h-56 overflow-auto rounded-md bg-[#0b0d0f] p-2 text-xs whitespace-pre-wrap break-all text-text-2`,children:e.join(`
`)}),n[13]=s,n[14]=V,n[15]=l,n[16]=O,n[17]=z,n[18]=r,n[19]=R,n[20]=A,n[21]=h,n[22]=S,n[23]=y.art,n[24]=y.text,n[25]=H,n[26]=U,n[27]=W,n[28]=G,n[29]=K,n[30]=q,n[31]=J,n[32]=Y}else H=n[25],U=n[26],W=n[27],G=n[28],K=n[29],q=n[30],J=n[31],Y=n[32];let X;n[59]!==V||n[60]!==u||n[61]!==r||n[62]!==a||n[63]!==S?(X=V&&(0,M.jsx)(p,{offen:u,gefahr:!0,titel:`Auftrag abbrechen?`,text:v(r)?`Der ${S} stoppt. Du kannst ihn später über „Modelle selbst suchen“ neu starten.`:`„${S}“ wird abgebrochen.`,knopf:`Ja, abbrechen`,neinKnopf:`Weiterlaufen lassen`,onNein:()=>f(!1),onJa:()=>{u&&(f(!1),a?.(r))}}),n[59]=V,n[60]=u,n[61]=r,n[62]=a,n[63]=S,n[64]=X):X=n[64];let Z;return n[65]!==H||n[66]!==U||n[67]!==W||n[68]!==G||n[69]!==K||n[70]!==q||n[71]!==X||n[72]!==J||n[73]!==Y?(Z=(0,M.jsxs)(`article`,{"aria-label":J,className:Y,children:[H,U,W,G,K,q,X]}),n[65]=H,n[66]=U,n[67]=W,n[68]=G,n[69]=K,n[70]=q,n[71]=X,n[72]=J,n[73]=Y,n[74]=Z):Z=n[74],Z}function z(e){let t=(0,m.c)(17),{alsPanel:n}=e,r=n!==void 0&&n,i=c(),a=u(),o,s;if(t[0]!==a||t[1]!==r||t[2]!==i.data||t[3]!==i.error||t[4]!==i.isError){s=Symbol.for(`react.early_return_sentinel`);bb0:{let e=O(i.data?.jobs??[]);if(e.length>0){let n;t[7]!==a||t[8]!==r?(n=e=>(0,M.jsx)(R,{job:e,ebene:r?3:4,abbrechenGesperrt:a.isPending,onAbbrechen:e=>a.mutate({id:e.id,titel:C(e)})},e.id),t[7]=a,t[8]=r,t[9]=n):n=t[9],o=(0,M.jsx)(`div`,{className:`grid items-start gap-2.5 lg:grid-cols-2`,children:e.map(n)})}else if(i.isError&&!i.data){let e;t[10]===i.error.message?e=t[11]:(e=(0,M.jsxs)(`p`,{role:`alert`,className:`text-sm text-rot-text`,children:[`Die Aufträge lassen sich gerade nicht lesen: `,i.error.message]}),t[10]=i.error.message,t[11]=e),o=e}else{s=null;break bb0}}t[0]=a,t[1]=r,t[2]=i.data,t[3]=i.error,t[4]=i.isError,t[5]=o,t[6]=s}else o=t[5],s=t[6];if(s!==Symbol.for(`react.early_return_sentinel`))return s;if(r){let e;return t[12]===o?e=t[13]:(e=(0,M.jsx)(f,{titel:`Aufträge`,children:o}),t[12]=o,t[13]=e),e}let l;t[14]===Symbol.for(`react.memo_cache_sentinel`)?(l=(0,M.jsx)(`h3`,{className:`schild m-0 text-sm text-text-3`,children:`Aufträge`}),t[14]=l):l=t[14];let d;return t[15]===o?d=t[16]:(d=(0,M.jsxs)(`section`,{"aria-label":`Aufträge`,className:`flex flex-col gap-2.5`,children:[l,o]}),t[15]=o,t[16]=d),d}export{_ as a,y as i,g as n,k as o,A as r,h as s,z as t};