fix(stack): Mem0 restlos ausgebaut + vier stille Defekte behoben
Systemaudit vom 27.08.2026. Alle Befunde gemessen, nicht vermutet.
VIER STILLE DEFEKTE
1. mc2-steward startete seit Wochen nicht (live: 207.609 Neustarts).
steward.py importierte services.memory, das beim Mem0-Ausbau geloescht
wurde -> ImportError bei jedem Start. Re-Warm- und Health-Waechter
waren damit tot.
2. Jedes Hermes-Update wurde automatisch zurueckgerollt.
hermes-postcheck.sh prueft vier Dinge, die es seit dem 07.08. nicht mehr
gibt (Sidecar :8765, /api/memory, memory.provider, mc2-memory-Plugin).
Die Checks konnten nicht gruen werden -> autoupdate.sh wertete jedes
Update als rot und rollte es zurueck. Checks ersatzlos entfernt; der
Tool-Smoke laeuft ohnehin durch den echten Agenten.
3. 7 von 12 Skills waren per Knopfdruck nicht startbar.
deploy.sh kopiert Skills mit tr '-' '_' nach ~/.hermes/skills/,
routers/skills.py gab Hermes aber den Ordnernamen MIT Bindestrich.
Der Knopf meldete Erfolg, ausgefuehrt wurde nichts. Neu: _hermes_name().
4. deploy.sh warf bei jedem Deploy die Live-Modellkonfiguration weg.
MC2 schreibt /etc/llama-swap/config.yaml selbst; die Repo-Datei ist nur
ein Abzug (ihm fehlt u.a. kritiker/Devstral). Jetzt: erst sichern, Diff
zeigen, dann kopieren. MC_DEPLOY_SKIP_SWAP_CONFIG=1 ueberspringt.
MEM0-AUSBAU VOLLENDET (Kriterium 3: 17 -> 0 Dateien)
- mem0_service/, mcp/mcp_memory.py und hermes/plugins/mc2-memory entfernt;
das Plugin schickte bei JEDEM Turn zwei 404-Requests an tote Routen.
- MEMORY_DB/MEM0_SERVICE_URL, _mem0_reachable(), MC_MEMORY_DB und
MC_MEM_DEDUPE_ENABLED aus Config/Router/Unit entfernt.
- mem0_ms war strukturell tot (park("retrieve") wird nirgends mehr
aufgerufen) -> aus Backend, API-Typ und Latenzkarte entfernt.
- Verbinden-Tab: tote Gedaechtnis-MCP-Leitung raus, Status-Kachel bleibt.
- AGENTS.md beschrieb Mem0 noch als aktiv - korrigiert.
GATEWAY-ROBUSTHEIT
- _proxy gab bei ungueltigen Payloads HTTP 500 (gemessen 5/5: Rohtext,
leerer Body, JSON-Liste, JSON-String, null) -> jetzt 5/5 HTTP 400.
- Bild-Weiche ohne Deckel: 10 Bilder x 2 Versuche x 240 s hielten den
Client bis zu 80 min. Neu: MC_CODER_IMAGE_MAX (4), Rueckfall auf die
Vision-Umleitung.
- /v1/models: nicht-JSON von der Engine gab 500 -> jetzt 502.
UNITS UND DEPLOY
- mc2-steward.service, dessen warmset-Drop-in und voice-service.service
fehlten im Repo, obwohl maintenance.py und stack-postcheck.sh sie
voraussetzen. 1:1 von der laufenden Box uebernommen.
- deploy.sh startete mc2-steward nie neu; restore.sh liess mc2-gateway und
mc2-steward mit alter Config weiterlaufen. Beide ergaenzt.
FRONTEND
- useEigenleben rief /api/eigenleben - existiert im Backend nicht und wurde
nirgends genutzt. Samt Typen entfernt.
- Anleitung beschrieb einen Gedaechtnis-Tab, den es nicht gibt.
- Abgeglichen: alle uebrigen 63 Frontend-Aufrufe treffen echte Routen, alle
5 SSE-Invalidation-Keys sind gemappt, keine ungefangenen Promises.
Gates: compileall gruen - ruff "All checks passed" - tsc gruen - vite build
gruen (dist aktualisiert) - Importe app/steward/gateway_app gruen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
34a9862591
commit
84dc34c0a3
+1
-1
@@ -1,4 +1,4 @@
|
||||
import{c as A,I as P,f as M,k as B,u as D,r as z,j as e,J as T,b as a,K as g,M as b,N as W,t as f,W as j,O as G,X as I,C as N,n as y,q as i}from"./index-CCbyojll.js";/**
|
||||
import{c as A,I as P,f as M,k as B,u as D,r as z,j as e,J as T,b as a,K as g,M as b,N as W,t as f,W as j,O as G,X as I,C as N,n as y,q as i}from"./index-DNt66je4.js";/**
|
||||
* @license lucide-react v0.460.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import{c as W,a1 as H,a2 as F,u as G,k as T,r as b,j as e,R as _,b as y,L as m,C as E,_ as O,D as P,a0 as z,a3 as R,a4 as V,X as D,T as C,F as K,n as $,a5 as q,q as U}from"./index-CCbyojll.js";import{S,H as Q}from"./SectionLabel-BfFwUeZU.js";import{C as M}from"./chevron-down-SPeGIim5.js";/**
|
||||
import{c as W,a1 as H,a2 as F,u as G,k as T,r as b,j as e,R as _,b as y,L as m,C as E,_ as O,D as P,a0 as z,a3 as R,a4 as V,X as D,T as C,F as K,n as $,a5 as q,q as U}from"./index-DNt66je4.js";import{S,H as Q}from"./SectionLabel-DKDWJ8hi.js";import{C as M}from"./chevron-down-BTSzJRag.js";/**
|
||||
* @license lucide-react v0.460.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
||||
import{c as d,aj as S,r as h,j as e,ak as M,L as p,a0 as z,a5 as C,al as D,am as A,b as B,an as Z,u as E,k as L,n as k,q}from"./index-CCbyojll.js";import{R as j}from"./rotate-ccw-DuKtbjZS.js";/**
|
||||
import{c as d,aj as S,r as h,j as e,ak as M,L as p,a0 as z,a5 as C,al as D,am as A,b as B,an as Z,u as E,k as L,n as k,q}from"./index-DNt66je4.js";import{R as j}from"./rotate-ccw-CGv9dXzB.js";/**
|
||||
* @license lucide-react v0.460.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
-26
File diff suppressed because one or more lines are too long
+26
File diff suppressed because one or more lines are too long
+4
-4
File diff suppressed because one or more lines are too long
+1
-1
@@ -1,4 +1,4 @@
|
||||
import{c as $,j as e,b as S,a2 as ve,u as Se,k as De,r as d,n as z,a6 as Ke,_ as O,L as D,X as Q,a7 as xe,F as T,a3 as he,C as Ce,T as ze,a4 as Ee,a8 as pe,q as Ae,R as fe}from"./index-CCbyojll.js";import{S as Le,H as X}from"./SectionLabel-BfFwUeZU.js";import{C as ee}from"./code-xml-AZtn6xxf.js";import{L as Pe}from"./layers-Dpl2QlP2.js";import{C as U}from"./chevron-down-SPeGIim5.js";import{R as We}from"./rotate-ccw-DuKtbjZS.js";/**
|
||||
import{c as $,j as e,b as S,a2 as ve,u as Se,k as De,r as d,n as z,a6 as Ke,_ as O,L as D,X as Q,a7 as xe,F as T,a3 as he,C as Ce,T as ze,a4 as Ee,a8 as pe,q as Ae,R as fe}from"./index-DNt66je4.js";import{S as Le,H as X}from"./SectionLabel-DKDWJ8hi.js";import{C as ee}from"./code-xml-BiSOeCkP.js";import{L as Pe}from"./layers-BakyhGhx.js";import{C as U}from"./chevron-down-BTSzJRag.js";import{R as We}from"./rotate-ccw-CGv9dXzB.js";/**
|
||||
* @license lucide-react v0.460.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
+1
-1
@@ -1 +1 @@
|
||||
import{u,ah as m,k as x,j as s,y as n,ai as b,b as p,n as f,q as h}from"./index-CCbyojll.js";function y(){const d=u(),{data:t=[]}=m(),{showAlert:l,dialogElement:o}=x();async function i(e){try{await f(`/api/jobs/${e}/cancel`,{method:"POST"}),d.invalidateQueries({queryKey:h.jobs})}catch(c){l("Fehler",c.message)}}const a=t.filter(e=>e.state==="running"||e.state==="queued"),r=t.filter(e=>e.state!=="running"&&e.state!=="queued").slice(-3);return a.length===0&&r.length===0?null:s.jsxs("div",{className:"space-y-3 mc-card p-4",children:[s.jsx("div",{className:"text-[11px] font-semibold text-muted-foreground uppercase tracking-wider",children:"Aktive Downloads"}),a.map(e=>s.jsxs("div",{className:"space-y-1.5 p-3 rounded-xl bg-background/20 border border-border/40",children:[s.jsxs("div",{className:"flex justify-between items-center text-xs",children:[s.jsx("span",{className:"font-semibold truncate max-w-[250px]",children:e.label}),s.jsxs("div",{className:"flex items-center gap-3",children:[s.jsxs("span",{className:"text-muted-foreground font-mono",children:[e.progress??0,"% • ",n(e.done_bytes),"/",n(e.total_bytes),e.eta_s?` • ETA ${b(e.eta_s)}`:""]}),s.jsx("button",{onClick:()=>i(e.id),className:"text-[10px] text-red-400 hover:text-red-300 font-semibold border border-red-500/25 bg-red-500/5 px-2 py-0.5 rounded transition-all cursor-pointer",children:"Abbrechen"})]})]}),s.jsx("div",{className:"h-1.5 overflow-hidden rounded-full bg-muted",children:s.jsx("div",{className:"h-full rounded-full bg-primary transition-all duration-500",style:{width:`${e.progress??0}%`}})})]},e.id)),r.map(e=>s.jsxs("div",{className:"flex justify-between items-center text-xs text-muted-foreground px-1",children:[s.jsx("span",{className:"truncate",children:e.label}),s.jsx("span",{className:p("font-semibold text-[10px] px-1.5 py-0.5 rounded uppercase font-mono",e.state==="done"?"bg-emerald-500/10 text-emerald-400":"bg-amber-500/10 text-amber-400"),children:e.state})]},e.id)),o]})}export{y as J};
|
||||
import{u,ah as m,k as x,j as s,y as n,ai as b,b as p,n as f,q as h}from"./index-DNt66je4.js";function y(){const d=u(),{data:t=[]}=m(),{showAlert:l,dialogElement:o}=x();async function i(e){try{await f(`/api/jobs/${e}/cancel`,{method:"POST"}),d.invalidateQueries({queryKey:h.jobs})}catch(c){l("Fehler",c.message)}}const a=t.filter(e=>e.state==="running"||e.state==="queued"),r=t.filter(e=>e.state!=="running"&&e.state!=="queued").slice(-3);return a.length===0&&r.length===0?null:s.jsxs("div",{className:"space-y-3 mc-card p-4",children:[s.jsx("div",{className:"text-[11px] font-semibold text-muted-foreground uppercase tracking-wider",children:"Aktive Downloads"}),a.map(e=>s.jsxs("div",{className:"space-y-1.5 p-3 rounded-xl bg-background/20 border border-border/40",children:[s.jsxs("div",{className:"flex justify-between items-center text-xs",children:[s.jsx("span",{className:"font-semibold truncate max-w-[250px]",children:e.label}),s.jsxs("div",{className:"flex items-center gap-3",children:[s.jsxs("span",{className:"text-muted-foreground font-mono",children:[e.progress??0,"% • ",n(e.done_bytes),"/",n(e.total_bytes),e.eta_s?` • ETA ${b(e.eta_s)}`:""]}),s.jsx("button",{onClick:()=>i(e.id),className:"text-[10px] text-red-400 hover:text-red-300 font-semibold border border-red-500/25 bg-red-500/5 px-2 py-0.5 rounded transition-all cursor-pointer",children:"Abbrechen"})]})]}),s.jsx("div",{className:"h-1.5 overflow-hidden rounded-full bg-muted",children:s.jsx("div",{className:"h-full rounded-full bg-primary transition-all duration-500",style:{width:`${e.progress??0}%`}})})]},e.id)),r.map(e=>s.jsxs("div",{className:"flex justify-between items-center text-xs text-muted-foreground px-1",children:[s.jsx("span",{className:"truncate",children:e.label}),s.jsx("span",{className:p("font-semibold text-[10px] px-1.5 py-0.5 rounded uppercase font-mono",e.state==="done"?"bg-emerald-500/10 text-emerald-400":"bg-amber-500/10 text-amber-400"),children:e.state})]},e.id)),o]})}export{y as J};
|
||||
Vendored
+1
-1
@@ -1 +1 @@
|
||||
import{I as b,u as f,K as h,r as d,j as e,b as c,J as g,T as p,R as j,Q as N,n as v,U as w,q as x}from"./index-CCbyojll.js";function y(){const{data:s}=b(),m=f(),r=s!=null&&s.box_console_url?h(s.box_console_url):void 0,a=s==null?void 0:s.box_console_reachable,[l,o]=d.useState(!1),[i,n]=d.useState("");async function u(){o(!0),n("");try{const t=await v("/api/maintenance/restart",{method:"POST",body:JSON.stringify({service:"box-console"})});n(t.ok?"Neu gestartet — einen Moment, dann lädt das Terminal.":`Fehlgeschlagen: ${t.err||"Unbekannter Fehler"}`),w(m,x.agentStatus,x.services)}catch(t){n(`Fehlgeschlagen: ${(t==null?void 0:t.message)||t}`)}finally{o(!1)}}return e.jsxs("div",{className:"flex h-full flex-col gap-4",children:[e.jsxs("div",{className:"flex flex-wrap items-end justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"bg-gradient-to-r from-foreground via-foreground to-primary bg-clip-text font-space text-2xl font-bold tracking-tight text-transparent",children:"Konsole"}),e.jsx("p",{className:"flex items-center gap-2 text-sm text-muted-foreground",children:"Direkte Shell auf der Box — wie ein SSH-Fenster, mitten im Browser."})]}),e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsxs("span",{className:"flex items-center gap-1.5 text-[11px] font-medium text-muted-foreground",children:[e.jsx("span",{className:c("h-2 w-2 rounded-full",a?"bg-emerald-500 animate-pulse":"bg-amber-500")}),a?"online":"offline"]}),r&&e.jsxs("a",{href:r,target:"_blank",rel:"noopener",className:"flex h-8 items-center gap-1.5 rounded-lg border border-border/60 bg-background/20 px-3 text-xs font-semibold text-muted-foreground transition-all hover:border-primary/50 hover:text-foreground",children:[e.jsx(g,{className:"h-3.5 w-3.5"})," In neuem Tab"]})]})]}),r?e.jsxs("div",{className:"relative min-h-[58vh] flex-1 overflow-hidden rounded-2xl border border-border/60 bg-black/50 shadow-lg shadow-black/25",children:[a===!1&&e.jsxs("div",{className:"absolute inset-0 z-10 flex flex-col items-center justify-center gap-3 bg-black/70 text-center",children:[e.jsx(p,{className:"h-8 w-8 text-amber-400"}),e.jsx("div",{className:"text-sm font-semibold text-amber-300",children:"Konsole nicht erreichbar"}),e.jsxs("p",{className:"max-w-sm text-[11px] leading-normal text-muted-foreground",children:["Der Terminal-Dienst (",e.jsx("code",{className:"font-mono text-primary",children:"box-console"}),") läuft gerade nicht."]}),e.jsxs("button",{onClick:u,disabled:l,className:"flex h-9 items-center gap-1.5 rounded-lg border border-amber-500/40 bg-amber-500/10 px-4 text-[11px] font-bold uppercase tracking-wide text-amber-300 transition-all hover:bg-amber-500/20 cursor-pointer disabled:opacity-50",children:[e.jsx(j,{className:c("h-3.5 w-3.5",l&&"animate-spin")})," Dienst neu starten"]}),i&&e.jsx("p",{className:"max-w-sm text-[11px] text-muted-foreground",children:i})]}),e.jsx("iframe",{src:r,title:"Box-Konsole",className:"h-full w-full border-0",style:{minHeight:"58vh"}})]}):e.jsxs("div",{className:"flex min-h-[58vh] flex-1 items-center justify-center rounded-2xl border border-border/60 bg-background/20 text-xs text-muted-foreground",children:[e.jsx(N,{className:"mr-2 h-4 w-4"})," Lade Konsole…"]})]})}export{y as KonsoleView};
|
||||
import{I as b,u as f,K as h,r as d,j as e,b as c,J as g,T as p,R as j,Q as N,n as v,U as w,q as x}from"./index-DNt66je4.js";function y(){const{data:s}=b(),m=f(),r=s!=null&&s.box_console_url?h(s.box_console_url):void 0,a=s==null?void 0:s.box_console_reachable,[l,o]=d.useState(!1),[i,n]=d.useState("");async function u(){o(!0),n("");try{const t=await v("/api/maintenance/restart",{method:"POST",body:JSON.stringify({service:"box-console"})});n(t.ok?"Neu gestartet — einen Moment, dann lädt das Terminal.":`Fehlgeschlagen: ${t.err||"Unbekannter Fehler"}`),w(m,x.agentStatus,x.services)}catch(t){n(`Fehlgeschlagen: ${(t==null?void 0:t.message)||t}`)}finally{o(!1)}}return e.jsxs("div",{className:"flex h-full flex-col gap-4",children:[e.jsxs("div",{className:"flex flex-wrap items-end justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"bg-gradient-to-r from-foreground via-foreground to-primary bg-clip-text font-space text-2xl font-bold tracking-tight text-transparent",children:"Konsole"}),e.jsx("p",{className:"flex items-center gap-2 text-sm text-muted-foreground",children:"Direkte Shell auf der Box — wie ein SSH-Fenster, mitten im Browser."})]}),e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsxs("span",{className:"flex items-center gap-1.5 text-[11px] font-medium text-muted-foreground",children:[e.jsx("span",{className:c("h-2 w-2 rounded-full",a?"bg-emerald-500 animate-pulse":"bg-amber-500")}),a?"online":"offline"]}),r&&e.jsxs("a",{href:r,target:"_blank",rel:"noopener",className:"flex h-8 items-center gap-1.5 rounded-lg border border-border/60 bg-background/20 px-3 text-xs font-semibold text-muted-foreground transition-all hover:border-primary/50 hover:text-foreground",children:[e.jsx(g,{className:"h-3.5 w-3.5"})," In neuem Tab"]})]})]}),r?e.jsxs("div",{className:"relative min-h-[58vh] flex-1 overflow-hidden rounded-2xl border border-border/60 bg-black/50 shadow-lg shadow-black/25",children:[a===!1&&e.jsxs("div",{className:"absolute inset-0 z-10 flex flex-col items-center justify-center gap-3 bg-black/70 text-center",children:[e.jsx(p,{className:"h-8 w-8 text-amber-400"}),e.jsx("div",{className:"text-sm font-semibold text-amber-300",children:"Konsole nicht erreichbar"}),e.jsxs("p",{className:"max-w-sm text-[11px] leading-normal text-muted-foreground",children:["Der Terminal-Dienst (",e.jsx("code",{className:"font-mono text-primary",children:"box-console"}),") läuft gerade nicht."]}),e.jsxs("button",{onClick:u,disabled:l,className:"flex h-9 items-center gap-1.5 rounded-lg border border-amber-500/40 bg-amber-500/10 px-4 text-[11px] font-bold uppercase tracking-wide text-amber-300 transition-all hover:bg-amber-500/20 cursor-pointer disabled:opacity-50",children:[e.jsx(j,{className:c("h-3.5 w-3.5",l&&"animate-spin")})," Dienst neu starten"]}),i&&e.jsx("p",{className:"max-w-sm text-[11px] text-muted-foreground",children:i})]}),e.jsx("iframe",{src:r,title:"Box-Konsole",className:"h-full w-full border-0",style:{minHeight:"58vh"}})]}):e.jsxs("div",{className:"flex min-h-[58vh] flex-1 items-center justify-center rounded-2xl border border-border/60 bg-background/20 text-xs text-muted-foreground",children:[e.jsx(N,{className:"mr-2 h-4 w-4"})," Lade Konsole…"]})]})}export{y as KonsoleView};
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import{c as E,u as he,a as qe,r as j,j as e,C as Y,L as Fe,b as k,d as Re,q as V,B as re,e as Ie,E as ze,f as le,g as Be,h as Ae,i as Pe,k as Ge,l as ee,X as me,H as be,T as se,s as Oe,m as Te,n as q,o as U,p as He,S as ge,t as Qe,P as Ue,v as Ve,w as We,x as Ze,y as Je}from"./index-CCbyojll.js";import{J as Xe}from"./JobsBar-Ckecoyqy.js";import{C as Ye}from"./code-xml-AZtn6xxf.js";import{R as et}from"./rotate-ccw-DuKtbjZS.js";import{C as ue,Z as ie,L as tt,a as rt}from"./zap-CRNNnxfs.js";import{C as De}from"./chevron-down-SPeGIim5.js";import{L as st}from"./layers-Dpl2QlP2.js";/**
|
||||
import{c as E,u as he,a as qe,r as j,j as e,C as Y,L as Fe,b as k,d as Re,q as V,B as re,e as Ie,E as ze,f as le,g as Be,h as Ae,i as Pe,k as Ge,l as ee,X as me,H as be,T as se,s as Oe,m as Te,n as q,o as U,p as He,S as ge,t as Qe,P as Ue,v as Ve,w as We,x as Ze,y as Je}from"./index-DNt66je4.js";import{J as Xe}from"./JobsBar-DG8VDiAV.js";import{C as Ye}from"./code-xml-BiSOeCkP.js";import{R as et}from"./rotate-ccw-CGv9dXzB.js";import{C as ue,Z as ie,L as tt,a as rt}from"./zap-cdYTHDpR.js";import{C as De}from"./chevron-down-BTSzJRag.js";import{L as st}from"./layers-BakyhGhx.js";/**
|
||||
* @license lucide-react v0.460.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
||||
import{c as s,j as e}from"./index-CCbyojll.js";/**
|
||||
import{c as s,j as e}from"./index-DNt66je4.js";/**
|
||||
* @license lucide-react v0.460.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
var M=r=>{throw TypeError(r)};var O=(r,e,t)=>e.has(r)||M("Cannot "+t);var a=(r,e,t)=>(O(r,e,"read from private field"),t?t.call(r):e.get(r)),y=(r,e,t)=>e.has(r)?M("Cannot add the same private member more than once"):e instanceof WeakSet?e.add(r):e.set(r,t),v=(r,e,t,n)=>(O(r,e,"write to private field"),n?n.call(r,t):e.set(r,t),t),j=(r,e,t)=>(O(r,e,"access private method"),t);import{a9 as B,aa as F,ab as E,ac as I,ad as P,u as A,r as f,ae as J,af as Q,c as T,ag as U,j as s,G as D,T as H,b as K,L,M as G,q as V,n as R}from"./index-CCbyojll.js";import{J as _}from"./JobsBar-Ckecoyqy.js";var c,g,o,h,m,w,C,q,z=(q=class extends B{constructor(e,t){super();y(this,m);y(this,c);y(this,g);y(this,o);y(this,h);v(this,c,e),this.setOptions(t),this.bindMethods(),j(this,m,w).call(this)}bindMethods(){this.mutate=this.mutate.bind(this),this.reset=this.reset.bind(this)}setOptions(e){var n;const t=this.options;this.options=a(this,c).defaultMutationOptions(e),F(this.options,t)||a(this,c).getMutationCache().notify({type:"observerOptionsUpdated",mutation:a(this,o),observer:this}),t!=null&&t.mutationKey&&this.options.mutationKey&&E(t.mutationKey)!==E(this.options.mutationKey)?this.reset():((n=a(this,o))==null?void 0:n.state.status)==="pending"&&a(this,o).setOptions(this.options)}onUnsubscribe(){var e;this.hasListeners()||(e=a(this,o))==null||e.removeObserver(this)}onMutationUpdate(e){j(this,m,w).call(this),j(this,m,C).call(this,e)}getCurrentResult(){return a(this,g)}reset(){var e;(e=a(this,o))==null||e.removeObserver(this),v(this,o,void 0),j(this,m,w).call(this),j(this,m,C).call(this)}mutate(e,t){var n;return v(this,h,t),(n=a(this,o))==null||n.removeObserver(this),v(this,o,a(this,c).getMutationCache().build(a(this,c),this.options)),a(this,o).addObserver(this),a(this,o).execute(e)}},c=new WeakMap,g=new WeakMap,o=new WeakMap,h=new WeakMap,m=new WeakSet,w=function(){var t;const e=((t=a(this,o))==null?void 0:t.state)??I();v(this,g,{...e,isPending:e.status==="pending",isSuccess:e.status==="success",isError:e.status==="error",isIdle:e.status==="idle",mutate:this.mutate,reset:this.reset})},C=function(e){P.batch(()=>{var t,n,l,x,d,p,k,i;if(a(this,h)&&this.hasListeners()){const u=a(this,g).variables,N=a(this,g).context,S={client:a(this,c),meta:this.options.meta,mutationKey:this.options.mutationKey};if((e==null?void 0:e.type)==="success"){try{(n=(t=a(this,h)).onSuccess)==null||n.call(t,e.data,u,N,S)}catch(b){Promise.reject(b)}try{(x=(l=a(this,h)).onSettled)==null||x.call(l,e.data,null,u,N,S)}catch(b){Promise.reject(b)}}else if((e==null?void 0:e.type)==="error"){try{(p=(d=a(this,h)).onError)==null||p.call(d,e.error,u,N,S)}catch(b){Promise.reject(b)}try{(i=(k=a(this,h)).onSettled)==null||i.call(k,void 0,e.error,u,N,S)}catch(b){Promise.reject(b)}}}this.listeners.forEach(u=>{u(a(this,g))})})},q);function W(r,e){const t=A(),[n]=f.useState(()=>new z(t,r));f.useEffect(()=>{n.setOptions(r)},[n,r]);const l=f.useSyncExternalStore(f.useCallback(d=>n.subscribe(P.batchCalls(d)),[n]),()=>n.getCurrentResult(),()=>n.getCurrentResult()),x=f.useCallback((d,p)=>{n.mutate(d,p).catch(J)},[n]);if(l.error&&Q(n.options.throwOnError,[l.error]))throw l.error;return{...l,mutate:x,mutateAsync:l.mutate}}/**
|
||||
var M=r=>{throw TypeError(r)};var O=(r,e,t)=>e.has(r)||M("Cannot "+t);var a=(r,e,t)=>(O(r,e,"read from private field"),t?t.call(r):e.get(r)),y=(r,e,t)=>e.has(r)?M("Cannot add the same private member more than once"):e instanceof WeakSet?e.add(r):e.set(r,t),v=(r,e,t,n)=>(O(r,e,"write to private field"),n?n.call(r,t):e.set(r,t),t),j=(r,e,t)=>(O(r,e,"access private method"),t);import{a9 as B,aa as F,ab as E,ac as I,ad as P,u as A,r as f,ae as J,af as Q,c as T,ag as U,j as s,G as D,T as H,b as K,L,M as G,q as V,n as R}from"./index-DNt66je4.js";import{J as _}from"./JobsBar-DG8VDiAV.js";var c,g,o,h,m,w,C,q,z=(q=class extends B{constructor(e,t){super();y(this,m);y(this,c);y(this,g);y(this,o);y(this,h);v(this,c,e),this.setOptions(t),this.bindMethods(),j(this,m,w).call(this)}bindMethods(){this.mutate=this.mutate.bind(this),this.reset=this.reset.bind(this)}setOptions(e){var n;const t=this.options;this.options=a(this,c).defaultMutationOptions(e),F(this.options,t)||a(this,c).getMutationCache().notify({type:"observerOptionsUpdated",mutation:a(this,o),observer:this}),t!=null&&t.mutationKey&&this.options.mutationKey&&E(t.mutationKey)!==E(this.options.mutationKey)?this.reset():((n=a(this,o))==null?void 0:n.state.status)==="pending"&&a(this,o).setOptions(this.options)}onUnsubscribe(){var e;this.hasListeners()||(e=a(this,o))==null||e.removeObserver(this)}onMutationUpdate(e){j(this,m,w).call(this),j(this,m,C).call(this,e)}getCurrentResult(){return a(this,g)}reset(){var e;(e=a(this,o))==null||e.removeObserver(this),v(this,o,void 0),j(this,m,w).call(this),j(this,m,C).call(this)}mutate(e,t){var n;return v(this,h,t),(n=a(this,o))==null||n.removeObserver(this),v(this,o,a(this,c).getMutationCache().build(a(this,c),this.options)),a(this,o).addObserver(this),a(this,o).execute(e)}},c=new WeakMap,g=new WeakMap,o=new WeakMap,h=new WeakMap,m=new WeakSet,w=function(){var t;const e=((t=a(this,o))==null?void 0:t.state)??I();v(this,g,{...e,isPending:e.status==="pending",isSuccess:e.status==="success",isError:e.status==="error",isIdle:e.status==="idle",mutate:this.mutate,reset:this.reset})},C=function(e){P.batch(()=>{var t,n,l,x,d,p,k,i;if(a(this,h)&&this.hasListeners()){const u=a(this,g).variables,N=a(this,g).context,S={client:a(this,c),meta:this.options.meta,mutationKey:this.options.mutationKey};if((e==null?void 0:e.type)==="success"){try{(n=(t=a(this,h)).onSuccess)==null||n.call(t,e.data,u,N,S)}catch(b){Promise.reject(b)}try{(x=(l=a(this,h)).onSettled)==null||x.call(l,e.data,null,u,N,S)}catch(b){Promise.reject(b)}}else if((e==null?void 0:e.type)==="error"){try{(p=(d=a(this,h)).onError)==null||p.call(d,e.error,u,N,S)}catch(b){Promise.reject(b)}try{(i=(k=a(this,h)).onSettled)==null||i.call(k,void 0,e.error,u,N,S)}catch(b){Promise.reject(b)}}}this.listeners.forEach(u=>{u(a(this,g))})})},q);function W(r,e){const t=A(),[n]=f.useState(()=>new z(t,r));f.useEffect(()=>{n.setOptions(r)},[n,r]);const l=f.useSyncExternalStore(f.useCallback(d=>n.subscribe(P.batchCalls(d)),[n]),()=>n.getCurrentResult(),()=>n.getCurrentResult()),x=f.useCallback((d,p)=>{n.mutate(d,p).catch(J)},[n]);if(l.error&&Q(n.options.throwOnError,[l.error]))throw l.error;return{...l,mutate:x,mutateAsync:l.mutate}}/**
|
||||
* @license lucide-react v0.460.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
+17
-12
File diff suppressed because one or more lines are too long
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
||||
import{c as o}from"./index-CCbyojll.js";/**
|
||||
import{c as o}from"./index-DNt66je4.js";/**
|
||||
* @license lucide-react v0.460.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import{c as e}from"./index-CCbyojll.js";/**
|
||||
import{c as e}from"./index-DNt66je4.js";/**
|
||||
* @license lucide-react v0.460.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
@@ -1,6 +0,0 @@
|
||||
import{c as a}from"./index-CCbyojll.js";/**
|
||||
* @license lucide-react v0.460.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
* See the LICENSE file in the root directory of this source tree.
|
||||
*/const o=a("FolderOpen",[["path",{d:"m6 14 1.5-2.9A2 2 0 0 1 9.24 10H20a2 2 0 0 1 1.94 2.5l-1.54 6a2 2 0 0 1-1.95 1.5H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H18a2 2 0 0 1 2 2v2",key:"usdka0"}]]);export{o as F};
|
||||
+39
-39
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
@@ -1,4 +1,4 @@
|
||||
import{c as a}from"./index-CCbyojll.js";/**
|
||||
import{c as a}from"./index-DNt66je4.js";/**
|
||||
* @license lucide-react v0.460.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import{c as t}from"./index-CCbyojll.js";/**
|
||||
import{c as t}from"./index-DNt66je4.js";/**
|
||||
* @license lucide-react v0.460.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import{c as a}from"./index-CCbyojll.js";/**
|
||||
import{c as a}from"./index-DNt66je4.js";/**
|
||||
* @license lucide-react v0.460.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
Vendored
+2
-2
@@ -7,8 +7,8 @@
|
||||
<link rel="manifest" href="/manifest.webmanifest" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<title>Mission Control 2.0</title>
|
||||
<script type="module" crossorigin src="/assets/index-CCbyojll.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-Dv1-nhwH.css">
|
||||
<script type="module" crossorigin src="/assets/index-DNt66je4.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-qQDuX0H0.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>␍
|
||||
|
||||
@@ -2,8 +2,8 @@ import { Gauge } from "lucide-react"
|
||||
import { useVoiceTrace } from "@/lib/queries"
|
||||
import type { VoiceTurn } from "@/lib/api"
|
||||
|
||||
// Balken-Stufen in kanonischer Reihenfolge (zeitlich disjunkt). Mem0 ist ein Unter-Detail
|
||||
// INNERHALB von „Hirn" und wird NICHT als eigenes Segment addiert (sonst Doppelzählung).
|
||||
// Balken-Stufen in kanonischer Reihenfolge (zeitlich disjunkt). Der Gedächtnis-Abruf läuft
|
||||
// Hermes-intern und ist für MC2 nicht messbar — er steckt in „Hirn".
|
||||
const SEGMENTS = [
|
||||
{ key: "stt_ms", label: "STT", color: "#f59e0b" },
|
||||
{ key: "vision_ms", label: "Sehen", color: "#a78bfa" },
|
||||
@@ -39,7 +39,6 @@ function culprit(t: VoiceTurn): { label: string; color: string; ms: number } | n
|
||||
|
||||
function TurnRow({ t, scale }: { t: VoiceTurn; scale: number }) {
|
||||
const title = SEGMENTS.map((s) => `${s.label} ${fmt(t[s.key] as number | null)}`).join(" · ")
|
||||
+ (t.mem0_ms != null ? ` (davon Gedächtnis ${fmt(t.mem0_ms)})` : "")
|
||||
return (
|
||||
<div className="flex items-center gap-2.5">
|
||||
<span className="w-14 shrink-0 text-right font-mono text-[10px] text-muted-foreground/60">{ago(t.ts)}</span>
|
||||
@@ -103,7 +102,6 @@ export function LatencyCard() {
|
||||
{latest && !latest.error && (
|
||||
<div className="mt-0.5 font-mono text-[11px] text-muted-foreground/70">
|
||||
{SEGMENTS.filter((s) => (latest[s.key] as number | null) != null).map((s) => `${s.label} ${fmt(latest[s.key] as number)}`).join(" · ")}
|
||||
{latest.mem0_ms != null && <span className="text-muted-foreground/50"> · davon Gedächtnis {fmt(latest.mem0_ms)}</span>}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
@@ -128,7 +126,7 @@ export function LatencyCard() {
|
||||
)}
|
||||
|
||||
<div className="mt-3 border-t border-border/30 pt-2 text-[10px] leading-relaxed text-muted-foreground/70">
|
||||
„Hirn" = Zeit bis zum ersten Wort (Agent + Mem0-Suche + Modell); Tool-Runden stecken in „Antwort". Reine
|
||||
„Hirn" = Zeit bis zum ersten Wort (Agent + Gedächtnis-Suche + Modell); Tool-Runden stecken in „Antwort". Reine
|
||||
Telegram-Turns laufen an MC2 vorbei und erscheinen hier nicht.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+6
-52
@@ -338,7 +338,6 @@ export interface ConnectResp {
|
||||
gateway_url: string
|
||||
mc_url: string
|
||||
tools: Record<string, ConnectTool> // Leitung 1 — Modell (IDEs/Agenten → Gateway)
|
||||
memory: ConnectTool // Leitung 2 — Gedächtnis (separater MCP-Server)
|
||||
}
|
||||
|
||||
export interface ConnectLine {
|
||||
@@ -347,20 +346,12 @@ export interface ConnectLine {
|
||||
}
|
||||
export interface ConnectHealth {
|
||||
gateway: ConnectLine
|
||||
memory: ConnectLine
|
||||
memory: ConnectLine // Leitung 2 — Hermes-natives Gedächtnis (nur Status, nichts zu konfigurieren)
|
||||
desktop_gateway: ConnectLine
|
||||
}
|
||||
|
||||
export interface Memory {
|
||||
id: string
|
||||
content: string
|
||||
category: string
|
||||
source: string
|
||||
created_at: string
|
||||
updated_at: string
|
||||
score?: number // Relevanz bei semantischer Suche (q gesetzt); sonst undefined
|
||||
}
|
||||
|
||||
// Graph-Ansicht des Wissens-Vaults (GET /api/wissen/graph) — trägt aus historischen Gründen
|
||||
// noch „Memory" im Namen; die Daten kommen aus dem Vault, nicht aus einem Gedächtnis-Dienst.
|
||||
export interface MemoryGraphNode {
|
||||
id: string
|
||||
content: string
|
||||
@@ -372,13 +363,6 @@ export interface MemoryGraph {
|
||||
edges: { source: string; target: string; weight: number }[]
|
||||
}
|
||||
|
||||
export interface DedupeResult {
|
||||
groups: { keep: { id: string; content: string; category: string }; remove: { id: string; content: string }[] }[]
|
||||
duplicate_count: number
|
||||
removed: number
|
||||
applied: boolean
|
||||
}
|
||||
|
||||
export interface AgentStatus {
|
||||
gateway_url: string
|
||||
box_console_url?: string
|
||||
@@ -443,7 +427,8 @@ export interface TokenStats {
|
||||
}
|
||||
|
||||
// Per-Turn-Latenz-Trace (GET /api/voice/trace). Balken-Stufen (zeitlich disjunkt):
|
||||
// stt · vision · hirn · gen. mem0 = Unter-Detail INNERHALB von hirn (nicht zum Balken addieren).
|
||||
// stt · vision · hirn · gen. Der Gedächtnis-Abruf läuft seit der Mem0-Ablösung Hermes-intern
|
||||
// (kein Rückruf an MC2) und steckt daher unsichtbar in hirn_ms.
|
||||
export interface VoiceTurn {
|
||||
id: string
|
||||
ts: number // Epoch-Sekunden
|
||||
@@ -452,9 +437,8 @@ export interface VoiceTurn {
|
||||
had_images: boolean
|
||||
stt_ms: number | null
|
||||
vision_ms: number | null
|
||||
hirn_ms: number | null // Zeit bis erstes Inhalts-Token (Agent + Mem0 + LLM-TTFT)
|
||||
hirn_ms: number | null // Zeit bis erstes Inhalts-Token (Agent + Gedächtnis + LLM-TTFT)
|
||||
gen_ms: number | null // Generierung nach dem ersten Token bis Stream-Ende
|
||||
mem0_ms: number | null // Teil VON hirn (Mem0-Retrieve), best-effort
|
||||
total_ms: number
|
||||
error: string | null
|
||||
}
|
||||
@@ -583,36 +567,6 @@ export interface ChronikResp {
|
||||
items: ChronikItem[]
|
||||
}
|
||||
|
||||
// ── Eigenleben („Von allein": Skills + Vorschlags-Bilanz der Box) ────────────
|
||||
export interface EigenlebenSkill {
|
||||
id: string
|
||||
name: string
|
||||
kategorie: string | null
|
||||
aktiv: boolean | null // null = nicht ermittelbar (Dev-Modus)
|
||||
beschreibung: string
|
||||
version: string
|
||||
autor: string
|
||||
herkunft: "selbst" | "repo" | "bundled"
|
||||
herkunft_label: string
|
||||
genutzt: number
|
||||
zuletzt_genutzt: string | null
|
||||
erstellt: string | null
|
||||
status: string
|
||||
geaendert: number
|
||||
}
|
||||
export interface EigenlebenEintrag {
|
||||
art: string // "angenommen" | "abgelehnt" | sonstiger Chronik-State
|
||||
titel: string
|
||||
detail: string
|
||||
ts: number
|
||||
}
|
||||
export interface EigenlebenResp {
|
||||
available: boolean
|
||||
skills: EigenlebenSkill[]
|
||||
selbst_erstellt: number
|
||||
bilanz: { eintraege: EigenlebenEintrag[]; angenommen: number; abgelehnt: number }
|
||||
}
|
||||
|
||||
// ── Wissens-Vault (Traum-Notizen, read-only) ─────────────────────────────────
|
||||
export interface WissenFile {
|
||||
path: string
|
||||
|
||||
@@ -13,7 +13,6 @@ import {
|
||||
type ConnectHealth,
|
||||
type DiscoverResp,
|
||||
type DraftsResp,
|
||||
type EigenlebenResp,
|
||||
type GroupsResp,
|
||||
type HermesBrainResp,
|
||||
type Health,
|
||||
@@ -21,7 +20,6 @@ import {
|
||||
type IdeenLogResp,
|
||||
type IdeenResp,
|
||||
type Job,
|
||||
type Memory,
|
||||
type MemoryGraph,
|
||||
type ModelsResp,
|
||||
type Reminder,
|
||||
@@ -54,13 +52,11 @@ export const qk = {
|
||||
drafts: (target?: string) => ["drafts", target ?? ""] as const,
|
||||
connect: (params?: string) => ["connect", params ?? ""] as const,
|
||||
connectHealth: ["connect-health"] as const,
|
||||
memory: (q?: string, category?: string) => ["memory", q ?? "", category ?? ""] as const,
|
||||
memoryGraph: ["memory-graph"] as const,
|
||||
voiceTrace: ["voice-trace"] as const,
|
||||
auftragsbuch: ["auftragsbuch"] as const,
|
||||
ideen: ["ideen"] as const,
|
||||
chronik: ["chronik"] as const,
|
||||
eigenleben: ["eigenleben"] as const,
|
||||
wissen: ["wissen"] as const,
|
||||
zeitmaschine: ["zeitmaschine"] as const,
|
||||
reminders: ["reminders"] as const,
|
||||
@@ -125,13 +121,6 @@ export const useChronik = (limit = 150, refetchInterval: number = TAKT.gemuetlic
|
||||
export const useWissen = () =>
|
||||
useQuery({ queryKey: qk.wissen, queryFn: () => api<WissenResp>("/api/wissen") })
|
||||
|
||||
export const useEigenleben = (refetchInterval: number = TAKT.traege) =>
|
||||
useQuery({
|
||||
queryKey: qk.eigenleben,
|
||||
queryFn: () => api<EigenlebenResp>("/api/eigenleben"),
|
||||
refetchInterval,
|
||||
})
|
||||
|
||||
export const useZeitmaschine = (refetchInterval: number = TAKT.traege, enabled = true) =>
|
||||
useQuery({
|
||||
queryKey: qk.zeitmaschine,
|
||||
@@ -248,18 +237,6 @@ export const useConnectHealth = () =>
|
||||
refetchInterval: 15000,
|
||||
})
|
||||
|
||||
export const useMemory = (opts?: { q?: string; category?: string; limit?: number }) =>
|
||||
useQuery({
|
||||
queryKey: qk.memory(opts?.q, opts?.category),
|
||||
queryFn: () => {
|
||||
const p = new URLSearchParams()
|
||||
if (opts?.q) p.set("q", opts.q)
|
||||
if (opts?.category) p.set("category", opts.category)
|
||||
return api<Memory[]>(`/api/memory?${p}`)
|
||||
},
|
||||
select: (d) => (opts?.limit ? d.slice(0, opts.limit) : d),
|
||||
})
|
||||
|
||||
/** Nach Mutationen die betroffenen Listen-Queries neu ziehen. */
|
||||
export function invalidate(qc: QueryClient, ...keys: (readonly unknown[])[]) {
|
||||
for (const key of keys) qc.invalidateQueries({ queryKey: key })
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useState } from "react"
|
||||
import {
|
||||
Check, Copy, Cpu, Brain, Globe, FolderOpen, Laptop, ArrowRight,
|
||||
Check, Copy, Cpu, Brain, Globe, Laptop, ArrowRight,
|
||||
Info, CircleCheck, CircleX, Loader2, ChevronDown, ChevronRight,
|
||||
} from "lucide-react"
|
||||
import { useConnect, useConnectHealth } from "@/lib/queries"
|
||||
@@ -82,14 +82,12 @@ function defaultHost(): string {
|
||||
|
||||
export function ConnectView() {
|
||||
const [host, setHost] = useState(localStorage.getItem("mc_host") || defaultHost())
|
||||
const [mcpPath, setMcpPath] = useState(localStorage.getItem("mc_mcp_path") || "")
|
||||
// Legacy-Tools (roher /v1-Zugang) leben im Ausklapper — Hermes Desktop ist der Hauptweg.
|
||||
const [active, setActive] = useState("kilo")
|
||||
const [sonstigeOffen, setSonstigeOffen] = useState(false)
|
||||
const [copied, setCopied] = useState<"desktop" | "model" | "memory" | null>(null)
|
||||
const [copied, setCopied] = useState<"desktop" | "model" | null>(null)
|
||||
|
||||
const params = new URLSearchParams({ host })
|
||||
if (mcpPath) params.set("mcp_path", mcpPath)
|
||||
const { data, error: dataErr } = useConnect(params.toString())
|
||||
const { data: health, isLoading: healthLoading } = useConnectHealth()
|
||||
const error = dataErr ? String(dataErr) : ""
|
||||
@@ -99,15 +97,10 @@ export function ConnectView() {
|
||||
if (v) localStorage.setItem("mc_host", v)
|
||||
}
|
||||
|
||||
function saveMcpPath(v: string) {
|
||||
setMcpPath(v)
|
||||
localStorage.setItem("mc_mcp_path", v)
|
||||
}
|
||||
|
||||
const desktop = data?.tools["hermes_desktop"]
|
||||
const tool = data?.tools[active]
|
||||
|
||||
async function copy(which: "desktop" | "model" | "memory", snippet?: string) {
|
||||
async function copy(which: "desktop" | "model", snippet?: string) {
|
||||
if (!snippet) return
|
||||
await navigator.clipboard.writeText(snippet)
|
||||
setCopied(which)
|
||||
@@ -123,7 +116,7 @@ export function ConnectView() {
|
||||
</h1>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
<span className="text-foreground">Hermes Desktop</span> ist die Tür zur Box — einmal verbinden, fertig.
|
||||
Für Spezialfälle gibt es darunter die rohen Leitungen (Gateway /v1 + Gedächtnis-MCP) für sonstige Tools.
|
||||
Für Spezialfälle gibt es darunter den rohen Gateway-Zugang ( /v1) für sonstige Tools.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -165,7 +158,7 @@ export function ConnectView() {
|
||||
<StatusBadge line={health?.memory} loading={healthLoading} />
|
||||
</div>
|
||||
<div className="mt-1 text-[11px] font-mono text-violet-300/80">
|
||||
MCP · mcp_memory.py · separat
|
||||
Hermes-nativ · im Agenten · nichts einzurichten
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -187,9 +180,9 @@ export function ConnectView() {
|
||||
</div>
|
||||
</div>
|
||||
<p className="mt-3.5 text-[11px] text-muted-foreground leading-relaxed">
|
||||
Der Gateway liefert <span className="text-foreground">nur das LLM</span>. Das geteilte Gedächtnis läuft über einen
|
||||
<span className="text-foreground"> eigenen MCP-Server</span> und das Desktop-Gateway bietet die Agenten-Schnittstelle —
|
||||
alle drei Leitungen werden unabhängig eingerichtet. IDEs wählen die <span className="text-foreground">echten Modelle</span>
|
||||
Der Gateway liefert <span className="text-foreground">nur das LLM</span>. Das Gedächtnis führt
|
||||
<span className="text-foreground"> Hermes selbst</span> (nichts einzurichten — die Kachel zeigt nur, ob es lebt), und das
|
||||
Desktop-Gateway bietet die Agenten-Schnittstelle. IDEs wählen die <span className="text-foreground">echten Modelle</span>
|
||||
{" "}(coder · heavy · vision); daneben gibt es die virtuellen Lanes <span className="text-foreground">chat</span> und
|
||||
{" "}<span className="text-foreground">coding</span>, die je Anfrage selbst das passende Modell wählen (Alltags-Chat, simple Tools).
|
||||
</p>
|
||||
@@ -260,12 +253,12 @@ export function ConnectView() {
|
||||
className="flex w-full items-center gap-2 p-4 text-sm font-space font-bold text-foreground cursor-pointer hover:text-primary transition-colors"
|
||||
>
|
||||
{sonstigeOffen ? <ChevronDown className="h-4 w-4" /> : <ChevronRight className="h-4 w-4" />}
|
||||
Sonstige Tools (roher /v1-Zugang + Gedächtnis-MCP)
|
||||
Sonstige Tools (roher /v1-Zugang)
|
||||
<span className="text-[10px] font-medium text-muted-foreground normal-case">Kilo Code · Claude Code · Eigenbau</span>
|
||||
</button>
|
||||
|
||||
{sonstigeOffen && (
|
||||
<div className="grid gap-5 lg:grid-cols-2 p-4 pt-0">
|
||||
<div className="grid gap-5 p-4 pt-0">
|
||||
{/* Leitung 1 — Modell anbinden */}
|
||||
<div className="space-y-3 rounded-2xl border border-border/60 border-t-2 border-t-primary/70 bg-card/30 p-4">
|
||||
<div>
|
||||
@@ -312,51 +305,6 @@ export function ConnectView() {
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Leitung 2 — Gedächtnis anbinden */}
|
||||
<div className="space-y-3 rounded-2xl border border-border/60 border-t-2 border-t-violet-500/70 bg-card/30 p-4">
|
||||
<div>
|
||||
<div className="flex items-center gap-2 text-sm font-space font-bold text-foreground">
|
||||
<span className="flex h-5 w-5 items-center justify-center rounded-md bg-violet-500/15 text-violet-300 text-[11px]">2</span>
|
||||
Gedächtnis anbinden
|
||||
<span className="text-[10px] font-medium text-muted-foreground normal-case">optional</span>
|
||||
</div>
|
||||
<p className="text-[11px] text-muted-foreground mt-0.5">Ein MCP-Block — gilt zusätzlich für <em>jedes</em> Tool aus Schritt 1.</p>
|
||||
</div>
|
||||
|
||||
<div className="flex items-start gap-2.5 p-3 rounded-xl bg-violet-500/5 border border-violet-500/20 text-[11px] text-muted-foreground leading-relaxed">
|
||||
<Info className="h-4 w-4 text-violet-400 shrink-0 mt-0.5" />
|
||||
<span>{data.memory.note}</span>
|
||||
</div>
|
||||
|
||||
{/* Der Pfad wirkt NUR auf dieses Snippet — deshalb wohnt das Feld hier,
|
||||
nicht mehr prominent in der Kopfzeile („Wann brauche ich das?"). */}
|
||||
<div className="space-y-1.5">
|
||||
<label className="text-[10px] font-bold uppercase tracking-wider text-muted-foreground flex items-center gap-1.5">
|
||||
<FolderOpen className="h-3.5 w-3.5 text-violet-400" /> Wo liegt mcp_memory.py auf DIESEM PC?
|
||||
</label>
|
||||
<input
|
||||
value={mcpPath}
|
||||
onChange={(e) => saveMcpPath(e.target.value)}
|
||||
aria-label="Lokaler MCP-Scriptpfad"
|
||||
spellCheck={false}
|
||||
placeholder="z.B. F:\Coding Stuff\mission-control-2\mcp\mcp_memory.py"
|
||||
className="w-full h-9 rounded-lg border border-border/60 bg-background/40 px-3 font-mono text-xs outline-none focus:ring-1 focus:ring-violet-500/50 text-foreground"
|
||||
/>
|
||||
<p className="text-[10px] text-muted-foreground/70">
|
||||
Nur nötig, wenn du das Gedächtnis in einem PC-Tool anschließt — das Script läuft lokal
|
||||
und spricht mit der Box. Der Pfad landet direkt im Snippet unten.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<CodeWindow
|
||||
tool={data.memory}
|
||||
fileName="mcp.json"
|
||||
accent="violet"
|
||||
copied={copied === "memory"}
|
||||
onCopy={() => copy("memory", data.memory.snippet)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -345,10 +345,12 @@ description: Treibt Entwicklung mit strikter TDD-Praxis
|
||||
</div>
|
||||
</div>
|
||||
<Stack>
|
||||
Dein Gedächtnis (Tab <strong>Gedächtnis</strong>) ist <strong>Mem0</strong>-basiert: auto-lernend &
|
||||
semantisch, <strong>graph-first</strong> dargestellt, mit 4-Typen-Taxonomie
|
||||
(<Pill>Identität</Pill> · <Pill>Wissen</Pill> · <Pill>Regeln</Pill> · <Pill>Ereignisse</Pill>). Der Agent
|
||||
lernt im Hintergrund nach jedem Turn — egal ob du per Desktop, Konsole, Telegram oder Lucy mit ihm sprichst.
|
||||
Dein Gedächtnis führt <strong>Hermes</strong> selbst — auto-lernend und semantisch. Der Agent lernt im
|
||||
Hintergrund nach jedem Turn, egal ob du per Desktop, Konsole, Telegram oder Lucy mit ihm sprichst.
|
||||
<br />Deshalb hat das Steuerpult <strong>keinen eigenen Gedächtnis-Tab</strong>: bis August 2026 lag das
|
||||
Gedächtnis in einem MC2-Sidecar, seit dessen Ablösung ist Hermes die einzige Quelle — angesehen und
|
||||
gepflegt wird es dort, nicht hier. Unter <strong>Wissen</strong> findest du weiterhin die Graph-Sicht
|
||||
auf Lucys Wissens-Vault.
|
||||
<br /><strong>Gotcha:</strong> ein gelöschter Fakt kann wieder auftauchen, solange die Original-Nachricht noch im Verlauf steht (additive Extraktion).
|
||||
</Stack>
|
||||
</Card>
|
||||
|
||||
Reference in New Issue
Block a user