6.9 KiB
JARVIS Einstellungen - Design
Datum: 2026-09-13 Status: Approved, bereit fuer Implementierungsplan
Kontext
JARVIS hat aktuell keine editierbaren Identitaets-/Branding-Werte. Der
Assistenten-Name ("JARVIS") und die Einleitung im System-Prompt
("Du bist JARVIS, ein KI-Assistent fuer Business-Automatisierung.") stehen
fest im Code bzw. als CLAUDE_SYSTEM_PROMPT-Env-Var-Default (main.py:58-61)
- letztere wird im Deployment nirgends gesetzt, ist also faktisch immer der
hartcodierte Default. Es gibt weder eine Backend-Tabelle noch eine
Frontend-Ansicht, um das zu aendern. Feature-Wunsch
(
.claude/JARVIS_FEATURES.md, Punkt 9): ein Einstellungen-Menuepunkt mit Werten wie E-Mailadresse, Firmenname, Name des Assistenten.
Dies ist Feature 2 von 3 einer priorisierten Roadmap (Feature 1, Bestellungen erfassen via Nextcloud Deck, ist fertig implementiert und deployt).
Scope-Entscheidungen (im Brainstorming geklaert)
- E-Mailadresse ist ein reiner Anzeige-/Branding-Wert. Das technische
Postfach (
EMAIL_USER/EMAIL_PASSWORD, IMAP/SMTP-Zugangsdaten fuer die echten Mail-Tools) bleibt unveraendert ein Deployment-Secret in.env- diese Einstellung dient nur dazu, dass Claude bei Bedarf eine Kontakt-Adresse nennen kann, nicht um das tatsaechliche Postfach zu wechseln. - Speicherort: neue Postgres-Tabelle, nicht
.env. Aenderungen wirken sofort auf den naechsten Chat-Request, kein Deploy/Neustart noetig. - Assistenten-Name wirkt auch im Frontend (Seitentitel, Chat-Header/ Platzhalter), nicht nur im Chat-Verhalten selbst.
- Aenderung nur ueber die Einstellungen-Seite, kein zusaetzliches
Chat-Tool (anders als z.B.
remember_fact) - Einstellungen werden selten geaendert, ein dediziertes Formular reicht. - Bewusste Luecke: Der Login-Screen (
Login.tsx,<h1>JARVIS</h1>) bleibt statisch. Settings liegen hinterX-Admin-Keywie alle anderen/api/v1/*-Routen und sind vor dem Login nicht abrufbar - Branding gilt nur fuer den eingeloggten Bereich.
Datenmodell (Claude outputs/migrations/007_settings.sql)
CREATE TABLE settings (
key VARCHAR(100) PRIMARY KEY,
value TEXT NOT NULL,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
Reine Key-Value-Tabelle, keine Seed-Daten. Ein fester Katalog in main.py
definiert die gueltigen Keys und ihre Defaults:
SETTINGS_DEFAULTS = {
"assistant_name": "JARVIS",
"company_name": "MBO-Tech-IT",
"contact_email": "kontakt@mbo-tech-it.de",
}
Fehlt ein Key in der Tabelle, gilt der Default - die Tabelle kann also leer bleiben, bis der Nutzer zum ersten Mal etwas aendert, und das Verhalten bleibt exakt wie heute.
DB-Helper (analog memory_facts-Pattern aus main.py)
get_setting(key: str) -> str-SELECT value FROM settings WHERE key = %s, faellt aufSETTINGS_DEFAULTS[key]zurueck, wenn keine Zeile existiert.get_all_settings() -> dict- liest alle vorhandenen Zeilen, merged sie ueberSETTINGS_DEFAULTS(Defaults zuerst, dann DB-Werte drueber) und gibt ein vollstaendiges Dict mit allen drei Keys zurueck.set_setting(key: str, value: str)-INSERT ... ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value, updated_at = CURRENT_TIMESTAMP.
REST-Endpoints
GET /api/v1/settings -> {"assistant_name": "...", "company_name": "...", "contact_email": "..."}
PUT /api/v1/settings Body: beliebige Teilmenge der drei Keys -> aktualisiertes vollstaendiges Dict
Beide hinter dependencies=[Depends(require_admin_key)], wie alle
bestehenden /api/v1/*-Routen ausser /health. PUT validiert jeden
Key gegen SETTINGS_DEFAULTS.keys() - unbekannter Key -> 400.
Einbindung in den Chat (run_chat_completion)
Die bisher statische Identitaets-Zeile (CLAUDE_SYSTEM_PROMPT-Env-Var)
wird ersetzt durch einen dynamisch aus den Settings gebauten Text, der bei
jedem Chat-Aufruf frisch berechnet wird (gleiches Prinzip wie der
bestehende _current_datetime_context()):
async def _identity_system_prompt() -> str:
settings = await get_all_settings()
return (
f"Du bist {settings['assistant_name']}, der KI-Assistent von "
f"{settings['company_name']}. Bei Fragen zur Erreichbarkeit kannst "
f"du auf {settings['contact_email']} verweisen."
)
Die CLAUDE_SYSTEM_PROMPT-Env-Var und ihr Default-Text entfallen komplett
(im Deployment ohnehin nirgends gesetzt) - die Settings-Tabelle ist ab jetzt
die einzige Quelle fuer die Identitaets-Zeile.
Frontend
- Neue Komponente
web/src/components/Settings.tsx: Formular mit drei Textfeldern (Assistentenname, Firmenname, Kontakt-E-Mail) + "Speichern"-Button. Laedt aktuelle Werte perGET /api/v1/settingsbeim Mounten (Pattern wieDashboard.tsx), speichert perPUT. App.tsx:View-Type um"settings"erweitert, neuer Nav-Button "Einstellungen". Laedt die Settings einmalig nach dem Login, setztdocument.titleaufassistant_nameund reicht den Namen als Prop anChat.tsxdurch, das damit den bisher festen Platzhaltertext ("Nachricht an JARVIS...") ersetzt.
Fehlerbehandlung
GET /api/v1/settingsschlaegt fehl (DB nicht erreichbar): Frontend zeigt eine Fehlermeldung im Settings-Formular (gleiches Muster wieCalendarWidget/EmailWidget);App.tsxfaellt beim Titel/Platzhalter auf den hartcodierten Default ("JARVIS") zurueck, kein harter Fehler.PUTmit unbekanntem Key:400, Formular zeigt die Fehlermeldung an, nichts wird gespeichert (auch nicht die gueltigen Keys aus demselben Request - alles oder nichts, kein Teil-Update bei Validierungsfehlern).
Testing
- Unit-Tests (
tests/test_settings.py, gemockte DB wie bei bestehenden Tool-Tests) fuerget_setting/get_all_settings/set_setting(Default-Fallback, Merge-Verhalten, Upsert) und die REST-Endpoints (Erfolg, unbekannter Key -> 400, fehlender Admin-Key -> 401). - Test fuer
run_chat_completion:_identity_system_prompt()wird gemockt, Ergebnis muss imsystem-Parameter des Claude-Aufrufs landen (gleiches Pattern wie der bestehende Datums-Kontext-Test). - Frontend: kein neuer Komponenten-Test (Projekt-Konvention, siehe
CalendarWidget/EmailWidget/OrdersWidget), Verifikation uebernpm run build. - Manueller End-to-End-Test nach Deployment: Einstellungen-Seite oeffnen, Assistentenname aendern und speichern, pruefen dass Seitentitel und Chat-Platzhalter sich sofort aktualisieren, im Chat fragen "wie heisst du?" und pruefen, dass die Antwort den neuen Namen nutzt.
Out of Scope (bewusst nicht Teil dieser Phase)
- Aenderung der Einstellungen per Chat-Tool (siehe Scope-Entscheidungen).
- Aendern des technischen Postfachs (
EMAIL_USER/EMAIL_PASSWORD) ueber die UI - bleibt Deployment-Secret. - Dynamisches Branding auf dem Login-Screen (siehe "bewusste Luecke" oben).
- Weitere Einstellungen ueber die drei genannten hinaus (die Tabelle ist
aber generisch genug, dass spaetere Erweiterung nur einen neuen Eintrag
in
SETTINGS_DEFAULTS+ ein Formularfeld braucht, keine Schema-Aenderung).