Files
gott/ARCHITECTURE.md
T
Meleki 20f96f69d0 feat: API-Key-Auth für Krea-Endpoints (Automation ohne User-Kontext)
- AuthMiddleware: X-Api-Key Header-Prüfung für /api/images/* Routen
- Neues Config-Feld KreaApiKey in appsettings.json
- Bei gültigem API-Key wird Request ohne Cookie-Auth durchgelassen
- Normaler User-Auth funktioniert weiterhin als Fallback
- ARCHITECTURE.md + ARCHITECTURE_QUICK.md aktualisiert
2026-03-06 15:00:11 +01:00

51 KiB
Raw Blame History

ARCHITECTURE.md – Gott

Gott ist eine selbst-gehostete AI-Chat-Plattform, gebaut auf .NET 10 und der Anthropic Claude API. Sie bietet Multi-User-Support, persistente Agent-Memory, Datei-/Shell-Tools, Telegram-Integration, Cronjobs und eine Krea-Bildgenerierung – alles über ein Vanilla-JavaScript-Frontend gesteuert.


Inhaltsverzeichnis

  1. Überblick
  2. Tech-Stack
  3. Projektstruktur
  4. Datenmodell
  5. Backend-Architektur
  6. Frontend-Architektur
  7. Chat-Pipeline
  8. Tool-System
  9. Agent-System
  10. System-Prompt-Aufbau
  11. Memory-System
  12. Skill-System
  13. Telegram-Integration
  14. Cronjob-System
  15. Krea-Bildgenerierung
  16. Auth & Multi-User
  17. Admin-Benutzerverwaltung
  18. Nachrichten teilen (Shared Messages)
  19. Workspace & File-Explorer
  20. Avatar-System
  21. LaTeX/Math-Rendering
  22. Windows Desktop App
  23. Deployment
  24. Konfiguration
  25. Datenbank-Migrationen

Überblick

┌─────────────────────────────────────────────────────────────┐
│                      Browser / WebView2                     │
│              Vanilla JS SPA (wwwroot/)                      │
├─────────────────────────────────────────────────────────────┤
│                   ASP.NET 10 Minimal API                    │
│              http://0.0.0.0:19000                           │
├──────┬──────┬──────┬──────┬──────┬──────┬──────┬──────┬────┤
│ Auth │ Chat │ Hist │ Sess │Agent │ Tele │ Cron │ Krea │Adm │
│      │  SSE │      │      │      │ gram │ jobs │ Img  │ in │
├──────┴──────┴──────┴──────┴──────┴──────┴──────┴──────┴────┤
│              Services Layer                                 │
│  AnthropicService · ChatService · ToolService               │
│  DatabaseService · MemoryService · SkillService             │
│  TelegramService · CronjobService · KreaService             │
├─────────────────────────────────────────────────────────────┤
│              SQLite (data/gott.db) via Dapper               │
│              Filesystem (data/agents/, data/skills/)        │
├─────────────────────────────────────────────────────────────┤
│              Anthropic Claude API (claude-sonnet/opus/haiku) │
│              Krea API (Bildgenerierung)                     │
│              Telegram Bot API                               │
└─────────────────────────────────────────────────────────────┘

Tech-Stack

Schicht Technologie
Runtime .NET 10 (ohne Nullable, ohne Implicit Usings)
Web ASP.NET Minimal API, Kestrel
Datenbank SQLite via Microsoft.Data.Sqlite + Dapper
AI Anthropic Claude API (Streaming SSE + Non-Streaming)
Images SixLabors.ImageSharp (Resize, Thumbnails)
Cron Cronos (Cron-Expression-Parsing)
Frontend Vanilla JavaScript SPA (kein Framework)
Markdown marked.js (Client-side Rendering)
LaTeX KaTeX 0.16.21 (Math-Rendering, self-hosted mit woff2-Fonts)
Editor CodeMirror 5 + EasyMDE
Icons Font Awesome
Fonts Inter, JetBrains Mono (self-hosted)
Desktop WPF + WebView2 (.NET 10, Windows-only)

Projektstruktur

gott/
├── Program.cs                    # Startup, DI, Middleware, Routing
├── gott.csproj                   # Projekt-Definition (.NET 10)
├── appsettings.json              # Konfiguration (Tokens, Limits)
├── deploy.sh                     # Deployment-Script (systemctl)
│
├── Models/                       # Daten-Modelle (Records)
│   ├── UserRecord.cs
│   ├── AgentRecord.cs
│   ├── SessionRecord.cs
│   ├── ChainRecord.cs
│   ├── MessageRecord.cs          # + AttachmentRecord
│   ├── ArchiveRecord.cs
│   ├── CronjobRecord.cs
│   ├── KreaImageRecord.cs
│   ├── SharedMessageRecord.cs    # Geteilte Nachrichten (Share-Token)
│   ├── ChatModels.cs             # ChatMessage, ChatRequest, AttachmentInfo/Block
│   └── ChatContext.cs            # Runtime-Kontext für einen Chat
│
├── Services/                     # Business-Logic
│   ├── DatabaseService.cs        # SQLite CRUD, Schema, Migrationen
│   ├── AuthService.cs            # Token-basierte Authentifizierung
│   ├── ChatService.cs            # Kontext-Aufbau, History-Builder
│   ├── AnthropicService.cs       # Claude API (Streaming + Non-Streaming)
│   ├── ToolService.cs            # Tool-Definitionen + Ausführung
│   ├── SystemPromptBuilder.cs    # Modularer System-Prompt aus Blöcken
│   ├── MemoryService.cs          # Agent-Gedächtnis (Dateisystem)
│   ├── SkillService.cs           # Skill-Verwaltung (Dateisystem)
│   ├── TelegramService.cs        # Telegram Bot API Integration
│   ├── CronjobService.cs         # BackgroundService für Cron-Tasks
│   ├── KreaService.cs            # Krea Image Generation API
│   ├── ImageService.cs           # Bild-Resize (Avatar, Session-Image)
│   ├── StreamingTracker.cs       # Concurrent Tracking aktiver Streams
│   └── WorkspaceHelper.cs       # Workspace-Pfad-Auflösung (relativ → absolut)
│
├── Endpoints/                    # HTTP API (Minimal API)
│   ├── AuthEndpoint.cs           # Login, Logout, Me
│   ├── ChatEndpoint.cs           # POST /api/chat (SSE Streaming)
│   ├── HistoryEndpoint.cs        # History, Archive, Attachments, Marks
│   ├── SessionEndpoint.cs        # CRUD + SystemPrompt, Exec, Git-Status
│   ├── AgentEndpoint.cs          # CRUD
│   ├── WorkspaceEndpoint.cs      # File-Tree, File-Read/Write, Browse, Agent-Files
│   ├── TelegramEndpoint.cs       # Webhook, Config, Registration
│   ├── CronjobEndpoint.cs        # CRUD + Toggle, Manual Run
│   ├── KreaEndpoint.cs           # Generate, List, File-Serve
│   ├── SkillEndpoint.cs          # List, Agent-Skill-Mapping, Output-Files
│   ├── SharedEndpoint.cs         # Nachrichten teilen (öffentliche Links)
│   ├── AdminEndpoint.cs          # Admin: User-CRUD, Impersonate (Admin-only)
│   ├── ProfileEndpoint.cs        # Profil, Persona, Passwort
│   ├── SettingsEndpoint.cs       # User-Settings (JSON blob)
│   ├── BackupEndpoint.cs         # Backup als tar.gz Download
│   └── InfoEndpoint.cs           # Build-Zeitstempel
│
├── Middleware/
│   └── AuthMiddleware.cs         # Cookie-basierte Token-Validierung
│
├── Extensions/
│   └── HttpContextExtensions.cs  # GetUserId(), IsAdmin()
│
├── Templates/                    # Standard-Templates für neue Agents
│   ├── IDENTITY.md               # Wer bin ich? (Name, Sprache)
│   ├── SOUL.md                   # Persönlichkeit, Verhalten
│   └── USER.md                   # Infos über den User
│
├── wwwroot/                      # Frontend (Vanilla JS SPA)
│   ├── index.html                # Single HTML Entry Point
│   ├── css/                      # Stylesheets
│   │   ├── theme.css             # CSS Custom Properties (Dark Theme)
│   │   ├── base.css              # Reset, Grundlayout
│   │   ├── main.css              # Sidebar, Layout-Struktur
│   │   ├── chat.css              # Chat-Nachrichten, Bubbles
│   │   ├── dashboard.css         # Dashboard-Grid
│   │   ├── form.css              # Formulare, Inputs, Avatar-Editor-Modal
│   │   ├── markdown.css          # Markdown + KaTeX Rendering-Styles
│   │   ├── file-explorer.css     # File-Explorer Panel
│   │   ├── login.css             # Login-Seite
│   │   ├── mobile.css            # Responsive Anpassungen
│   │   ├── tooltip.css           # Tooltip-Styles
│   │   ├── fonts.css             # @font-face Definitionen
│   │   ├── placeholder.css       # Placeholder/Loading States
│   │   ├── katex.min.css          # KaTeX Math-Rendering Styles
│   │   ├── codemirror.min.css    # CodeMirror Editor
│   │   ├── easymde.min.css       # EasyMDE Editor
│   │   └── fonts/                # KaTeX woff2 Fonts (21 Dateien)
│   ├── js/
│   │   ├── app.js                # App-Initialisierung, Auth-Check
│   │   ├── router.js             # Client-side SPA Router
│   │   ├── api.js                # API-Client (fetch wrapper)
│   │   ├── ui.js                 # UI-Utilities (Modal, Toast, etc.)
│   │   ├── chat.js               # Chat-Logic, SSE-Streaming
│   │   ├── history.js            # History-Rendering, Pagination
│   │   ├── session.js            # Session-Verwaltung
│   │   ├── file-explorer.js      # File-Explorer Komponente
│   │   ├── avatar-editor.js      # Wiederverwendbares Avatar-Editor-Modal
│   │   ├── commands-ui.js        # Custom-Commands UI
│   │   ├── emoji.js              # Emoji-Picker
│   │   ├── emoji.userdata.js     # Häufig genutzte Emojis
│   │   ├── tooltip.js            # Tooltip-System
│   │   ├── title.js              # Tab-Titel-Management
│   │   ├── pages/                # Seiten-Komponenten
│   │   │   ├── chat-page.js      # Haupt-Chat-Ansicht
│   │   │   ├── dashboard.js      # Dashboard / Home
│   │   │   ├── session-page.js   # Session-Einstellungen
│   │   │   ├── agent-page.js     # Agent-Editor
│   │   │   ├── cronjob-page.js   # Cronjob-Verwaltung
│   │   │   ├── profile-page.js   # Profil-Bearbeitung
│   │   │   ├── admin-page.js      # Admin: Benutzerverwaltung
│   │   │   ├── settings-page.js  # App-Einstellungen
│   │   │   ├── login-page.js     # Login-Formular
│   │   │   └── shared-page.js    # Öffentliche geteilte Nachricht
│   │   └── lib/                  # Vendor-Libraries
│   │       ├── marked.min.js     # Markdown Parser
│   │       ├── codemirror.min.js # Code Editor
│   │       ├── codemirror.cjs    # CM CommonJS Wrapper
│   │       ├── easymde.min.js    # Markdown Editor
│   │       ├── katex.min.js      # KaTeX Math-Rendering Engine
│   │       └── cm-mode-*.min.js  # CodeMirror Syntax-Modes
│   ├── fonts/                    # Self-hosted Fonts (Inter, JetBrains Mono)
│   └── lib/font-awesome/         # Font Awesome Icons
│
├── WindowsApp/                   # Windows Desktop Client (WPF)
│   ├── Gott.csproj               # .NET 10 Windows, WebView2
│   ├── App.xaml / App.xaml.cs     # WPF Application
│   ├── MainWindow.xaml/cs        # WebView2 Host Window
│   └── appsettings.json          # Server-URL Konfiguration
│
└── publish/                      # Build-Output (NICHT editieren!)
    └── data/
        ├── gott.db               # SQLite Datenbank
        ├── agents/               # Agent Memory-Dateien
        │   └── {agentId}/
        │       ├── IDENTITY.md
        │       ├── SOUL.md
        │       ├── MEMORY.md
        │       └── memory/       # Tages-Logs etc.
        ├── skills/               # Skill-Verzeichnisse
        │   └── {slug}/
        │       ├── SKILL.md
        │       ├── PROMPT.md
        │       └── output/
        ├── images/               # Krea-generierte Bilder
        ├── logs/                 # Payload-Logs (optional)
        └── backup/               # Backup-Archive

Datenmodell

Entity-Relationship

User (1) ─── (*) Agent
User (1) ─── (*) Session
Agent (1) ─── (*) Session     (Session hat optional einen Agent)
Agent (*) ─── (*) Skill       (via agent_skills Tabelle)
Session (1) ─── (*) Chain     (ein Chat-Request = eine Chain)
Session (1) ─── (*) Archive   (archivierte Chains)
Chain (1) ─── (*) Message
Message (1) ─── (*) Attachment
Session (1) ─── (*) Cronjob
User (1) ─── (*) Cronjob
User (1) ─── (*) SharedMessage
Message (1) ─── (*) SharedMessage

Tabellen

Tabelle Beschreibung
users Benutzer (username, password_hash, persona, settings, default_path)
tokens Auth-Tokens (token → user_id)
agents AI-Agenten (model, soul, identity, memory, tools, avatar_scale)
sessions Chat-Sessions (workspace, context, telegram-config, avatar_scale, telegram_allowed_chat_ids)
chains Request-Chains (model, tokens, iterations, timing)
messages Einzelne Nachrichten (text, tool_use, tool_result)
attachments Datei-Anhänge (base64, image/document)
archives Archivierte Chain-Gruppen
agent_skills Agent ↔ Skill Zuordnung
cronjobs Geplante Tasks (cron expression, prompt)
shared_messages Geteilte Nachrichten (Share-Token, Ablaufdatum)
telegram_links Telegram Chat ↔ Session Verknüpfung

Zentrale Records

ChainRecord – Repräsentiert einen kompletten Request-Response-Zyklus:

  • ChainId – Eindeutige ID
  • SessionId – Zugehörige Session
  • Model – Verwendetes Claude-Modell (z.B. claude-sonnet-4-6)
  • SystemPrompt – Der vollständige System-Prompt (gespeichert für Nachvollziehbarkeit)
  • InputTokens, OutputTokens, CacheCreationTokens, CacheReadTokens – Token-Verbrauch
  • Iterations – Anzahl der Tool-Loop-Durchläufe
  • StopReason – end_turn, tool_use, max_iterations, error, client_disconnected
  • DurationMs – Gesamtdauer der Chain

MessageRecord – Eine einzelne Nachricht innerhalb einer Chain:

  • Role – user, assistant, system
  • Type – text, tool_use, tool_result, error
  • Content – Textinhalt oder JSON (bei tool_use: Input-JSON)
  • ToolName, ToolCallId – Bei Tool-Aufrufen
  • IsMarked – Als wichtig markierte Nachricht (wird in System-Prompt aufgenommen)
  • DeletedOn – Soft-Delete Zeitstempel

Backend-Architektur

Program.cs – Startup

Die Program.cs ist der zentrale Einstiegspunkt und konfiguriert:

  1. Service-Registrierung – Alle Services als Singletons im DI-Container
  2. Datenbank-Initialisierung – DatabaseService erstellt Schema + Migrationen
  3. Default-User – Wird automatisch angelegt falls keine User existieren
  4. Middleware – Static Files → AuthMiddleware → Endpoints
  5. Endpoint-Mapping – Alle 16 Endpoint-Gruppen registriert
  6. Server – Kestrel auf http://0.0.0.0:19000

Initialisierungsreihenfolge:

AuthService → DatabaseService → EnsureDefaultUser
→ ImageService, StreamingTracker, MemoryService, SkillService
→ ToolService → ChatService
→ AnthropicService → TelegramService → KreaService
→ CronjobService (BackgroundService)

Services

Service Typ Aufgabe
DatabaseService Singleton SQLite CRUD, Schema-Init, Migrationen, alle DB-Operationen
AuthService Singleton Token-Erzeugung/-Validierung, Passwort-Hashing (SHA256)
ChatService Singleton Chat-Kontext aufbauen, History aus DB rekonstruieren
AnthropicService Singleton Claude API Kommunikation (Streaming SSE + Non-Streaming)
ToolService Singleton Tool-Definitionen bereitstellen, Tool-Aufrufe ausführen
WorkspaceHelper Static Workspace-Pfad-Auflösung (relativ → absolut), Path-Traversal-Schutz
SystemPromptBuilder Static Modularer System-Prompt aus konfigurierbaren Blöcken
MemoryService Singleton Agent-Gedächtnis auf Dateisystem (MEMORY.md, IDENTITY.md etc.)
SkillService Singleton Skill-Discovery und -Management aus Dateisystem
TelegramService Singleton Telegram Bot API, Webhook-Handling, Nachrichten senden
CronjobService Background Minütlicher Check auf fällige Cronjobs, Ausführung via Claude
KreaService Singleton Krea API für Bildgenerierung, Job-Polling, Image-Download
ImageService Singleton Bild-Resize (max 512px) für Avatare und Session-Bilder
StreamingTracker Singleton ConcurrentDictionary – trackt welche Sessions gerade streamen

Endpoints (API)

Alle Endpoints folgen dem Minimal API-Pattern mit Extension Methods (MapXxxEndpoints).

Gruppe Basis-Route Methoden
Auth /api/auth/ POST login, POST logout, GET me
Chat /api/chat POST (SSE Streaming)
History /api/history GET history, GET poll, POST archive, GET archives, GET archive/{id}, GET attachments/{id}, PUT messages/{id}/mark, PUT messages/{id}/delete, GET chains/{id}
Sessions /api/sessions/ CRUD + GET system-prompt, GET system-prompt-blocks, GET streaming, POST exec, GET git-status
Agents /api/agents/ CRUD
Admin /api/admin/ GET users, POST users, PUT users/{id}, PUT users/{id}/password, DELETE users/{id}, POST users/{id}/impersonate (Admin-only)
Workspace /api/workspace/ GET tree, GET/PUT file, GET browse, POST mkdir, DELETE dir, POST browse/mkdir, GET agent/tree, GET/PUT agent/file, POST agent/mkdir, GET raw
Telegram /api/telegram/ POST webhook/{sessionId} (unauthenticated), Session-Config CRUD, Webhook-Management
Cronjobs /api/cronjobs/ CRUD + POST toggle, POST run
Krea /api/images/ POST generate, GET list, GET file/{name}, GET status
Skills /api/skills GET list, GET/PUT agent skills, Output-Files + Thumbnails
Profile /api/profile GET, PUT, PUT password
Settings /api/settings GET, PUT
Backup /api/backup POST (Admin only, tar.gz Download)
Shared /api/shared/, /api/messages/{id}/share Share erstellen, öffentlich abrufen, auflisten, löschen
Info /api/info GET (Build-Zeitstempel)

Middleware

AuthMiddleware prüft jede /api/-Anfrage auf ein gültiges gott_token-Cookie.

Ausnahmen (kein Auth nötig):

  • Statische Dateien (nicht /api/)
  • POST /api/auth/login
  • GET /api/auth/autologin (Token-basierter Autologin via Link)
  • POST /api/telegram/webhook/{sessionId} (authentifiziert via Secret-Header)
  • GET /api/shared/{token} (öffentlicher Zugriff auf geteilte Nachrichten)

API-Key Auth (ohne User-Kontext):

  • /api/images/*-Routen akzeptieren einen X-Api-Key-Header. Wenn der Key mit KreaApiKey aus der Config übereinstimmt, wird der Request ohne User-Authentifizierung durchgelassen. Normaler Cookie-Auth funktioniert weiterhin als Fallback.

Bei Erfolg werden UserId und IsAdmin in HttpContext.Items gesetzt (bei API-Key-Auth sind diese nicht gesetzt).

Models

Die Models in Models/ sind reine Daten-Records ohne Business-Logic (Ausnahme: ChatMessage hat Helper-Methoden für Content-Extraktion und UserRecord hat GetEffectivePersona()).

ChatContext ist ein Runtime-Objekt das den vollständigen Kontext eines Chat-Requests hält:

  • Chain-ID, Session-ID, Model-ID
  • Aufgelöster System-Prompt (Text + strukturierte Blöcke)
  • Workspace-Pfad, Tool-Choice
  • Referenzen auf Agent und Session Records

Templates

Templates/ enthält Vorlagen die beim Erstellen eines neuen Agents in dessen Memory-Verzeichnis kopiert werden:

  • IDENTITY.md – Name und Grundinfos (Platzhalter {NAME} wird ersetzt)
  • SOUL.md – Persönlichkeit und Verhaltensgrundsätze
  • USER.md – Informationen über den User (global, nicht agent-spezifisch)

Frontend-Architektur

Das Frontend ist eine Single-Page Application ohne Build-Step, komplett in Vanilla JavaScript.

Routing

router.js implementiert ein Hash-basiertes Client-Side-Routing:

Route Page Beschreibung
#/ dashboard.js Session-Übersicht
#/chat/{sessionId} chat-page.js Chat-Ansicht
#/session/{sessionId} session-page.js Session-Einstellungen
#/agent/{agentId} agent-page.js Agent-Editor
#/cronjobs cronjob-page.js Cronjob-Verwaltung
#/profile profile-page.js Profil
#/settings settings-page.js App-Einstellungen
#/admin admin-page.js Benutzerverwaltung (Admin-only)
#/login login-page.js Login
#/shared/{token} shared-page.js Öffentliche geteilte Nachricht (kein Auth)

Kern-Module

  • app.js – Initialisierung, Auth-Check, globale Event-Handler
  • api.js – Zentraler API-Client mit fetch()-Wrapper, Auth-Redirect bei 401
  • ui.js – UI-Utilities (Modals, Toasts, Confirmations, etc.)
  • chat.js – SSE-Stream-Handling, Markdown-Rendering (mit KaTeX), Tool-Output-Darstellung
  • history.js – Chat-History laden, paginieren, rendern
  • session.js – Session-State-Management
  • file-explorer.js – Workspace File-Explorer Panel (Dateien, Ordner erstellen/löschen, Folder-Browser)
  • avatar-editor.js – Wiederverwendbares Avatar-Editor-Modal (Upload, Paste, AI-Generate, Scale)
  • commands-ui.js – Custom-Commands UI-Komponente
  • emoji.js – Emoji-Picker mit Kategorien und Suche
  • tooltip.js – Tooltip-System für Hover-Infos
  • title.js – Dynamisches Tab-Titel-Management

Styling

CSS ist in modulare Dateien aufgeteilt mit CSS Custom Properties für Theming:

  • theme.css – Alle Farben, Abstände, Schriften als CSS Variables
  • base.css – Reset und Grundlayout
  • main.css – Sidebar, Content-Area, Responsive Layout
  • chat.css – Chat-Bubbles, Streaming-Animation, Tool-Outputs
  • markdown.css – Rendering von Markdown in Nachrichten
  • mobile.css – Responsive Breakpoints und Anpassungen

Chat-Pipeline

Der Chat-Flow von User-Input bis zur gerenderten Antwort:

1. User tippt Nachricht + optionale Attachments (Bilder/Dokumente)
   ↓
2. Frontend: POST /api/chat { content, sessionId }
   ↓
3. ChatEndpoint:
   a) User-Message + Attachments in DB speichern
   b) ChatService.PrepareContext() → Agent, Model, System-Prompt, Chain
   c) ChatService.BuildHistoryFromDb() → vollständige Message-History
   d) AnthropicService.StreamChat() starten
   ↓
4. AnthropicService (Agentic Loop):
   ┌─────────────────────────────────────────┐
   │  while (iterations < maxIterations)      │
   │    → Claude API Request (SSE)            │
   │    → Stream-Processing:                  │
   │      • Text-Tokens → SSE an Frontend     │
   │      • Tool-Use → ToolService.Execute()  │
   │      • Tool-Results → nächste Iteration  │
   │    → Messages in DB persistieren         │
   │    → Stop wenn: end_turn / max_iterations│
   │    → CancellationToken bei Abbruch       │
   └─────────────────────────────────────────┘
   ↓
5. Frontend: SSE Events empfangen und rendern
   • "text" → Markdown parsen, Token für Token anzeigen
   • "tool_*" → Tool-Aufrufe collapsible darstellen
   • "done" → Token-Stats, Dauer, Model anzeigen

Abbruch (Stop-Button)

Das CancellationToken wird durchgängig propagiert:

  1. Frontend: AbortController.abort() → SSE-Fetch abgebrochen
  2. ASP.NET: RequestAborted Token wird gecancelled
  3. AnthropicService: ThrowIfCancellationRequested() am Loop-Anfang, vor/nach Tool-Execution
  4. WriteSseEvent(): Alle SSE-Writes mit CancellationToken → sofortiger Abbruch bei Client-Disconnect
  5. Chain wird mit StopReason = "client_disconnected" finalisiert

Streaming vs Non-Streaming

  • Web-Chat: Streaming via SSE (text/event-stream). Tokens werden in Echtzeit gerendert.
  • Telegram: Non-Streaming via ChatNonStreaming(). Vollständige Antwort wird abgewartet und als Telegram-Nachricht gesendet.
  • Cronjobs: Non-Streaming, wie Telegram.

History-Optimierung

Die History-Rekonstruktion in BuildHistoryFromDb() ist optimiert:

  • Ältere Chains: Nur text-Messages (user + assistant), keine Tool-Calls
  • Letzte Chain: Vollständig mit allen Tool-Use/Tool-Result Blöcken
  • Attachments: Nur für die letzte User-Message geladen (spart enorme Token)
  • Tool-Results: In der History auf 20.000 Zeichen gekürzt (vollständig in DB)

Tool-System

Der Agent hat Zugriff auf folgende Tools, abhängig von Konfiguration:

Datei-Tools (wenn Workspace konfiguriert)

Tool Beschreibung
read_file Datei lesen (relativer Pfad zum Workspace)
write_file Datei erstellen/überschreiben
edit_file Exakten Textabschnitt in Datei ersetzen
list_files Verzeichnis-Listing
delete_file Datei oder leeres Verzeichnis löschen
execute Shell-Befehl ausführen (bash, 180s Timeout)
glob Dateien via Glob-Pattern finden
grep Dateien nach Regex/Text durchsuchen
todo_write Todo-Liste schreiben (als Datei im Workspace)

Memory-Tools (wenn UseMemory aktiviert)

Tool Beschreibung
memory_read Memory-Datei des Agents lesen
memory_write Memory-Datei schreiben (überschreiben/append)
memory_list Alle Memory-Dateien des Agents auflisten

Web-Suche (wenn WebSearchVersion konfiguriert)

Nutzt Anthropics eingebaute Web-Suche als Server-Side-Tool.

Tool-Choice Strategien

  • any: Erste Iteration erzwingt Tool-Nutzung, danach auto. Verhindert dass der Agent nur Text antwortet wenn Tools benötigt werden.
  • auto: Claude entscheidet frei ob Tools nötig sind.

Pfad-Sicherheit

Alle Dateipfade werden via ResolvePath() aufgelöst und gegen den Workspace/Memory-Ordner geprüft – Path-Traversal-Angriffe werden verhindert.


Agent-System

Ein Agent definiert die Persönlichkeit und Fähigkeiten der AI:

Eigenschaft Beschreibung
Name Anzeigename
Avatar Base64 Data-URL (auf 512px resized)
Model sonnet, sonnet-4-5, sonnet-4-6, opus, opus-4-5, opus-4-6, haiku, haiku-4-5
ToolChoice any oder auto
CustomCommands JSON-Array mit Slash-Commands (Label + Prompt)
AutoCommit "" (nichts), "mention" (verbieten), "enforce" (erzwingen), "forbid" (strikt verboten)
UseSoul SOUL.md in System-Prompt einbinden
UseIdentity IDENTITY.md in System-Prompt einbinden
UseUserInfo User-Persona in System-Prompt einbinden
UseMemory Memory-Tools aktivieren
WebSearchVersion Web-Suche aktivieren (z.B. web_search_20260209)

Model-Auflösung

"sonnet"     → claude-sonnet-4-6
"sonnet-4-5" → claude-sonnet-4-5
"sonnet-4-6" → claude-sonnet-4-6
"opus"       → claude-opus-4-6
"opus-4-5"   → claude-opus-4-5
"opus-4-6"   → claude-opus-4-6
"haiku"      → claude-haiku-4-5
"haiku-4-5"  → claude-haiku-4-5
(default)    → claude-sonnet-4-6

System-Prompt-Aufbau

Der SystemPromptBuilder erzeugt den System-Prompt modular aus konfigurierbaren Blöcken:

┌──────────────────────────────────────────┐
│ 1. IDENTITY.md (UseIdentity)             │  → Wer ist der Agent?
│ 2. SOUL.md (UseSoul)                     │  → Persönlichkeit, Verhalten
│ 3. User-Persona (UseUserInfo)            │  → Infos über den User
│ 4. Tool-Nutzung (Workspace + any)        │  → "IMMER Tools benutzen"
│ 5. Workspace-Info                        │  → Tools + Workspace-Pfad
│ 6. Session-Kontext                       │  → Freiformtext
│ 7. Skills (Agent-Skills)                 │  → Skill-Prompts
│ 8. Memory (UseMemory)                    │  → Memory-Regeln + MEMORY.md Inhalt
│ 9. Git-Verhalten (AutoCommit)            │  → Commit-Regeln
│10. Verhaltensregeln (Workspace + any)    │  → "IMMER Tools aufrufen"
│11. Erinnerung (Workspace + any)          │  → Höchste Priorität: Tool-Aufrufe!
│12. Markierte Nachrichten                 │  → Vom User als wichtig markierte Messages
└──────────────────────────────────────────┘

Jeder Block hat:

  • Icon – Font Awesome Icon-Klasse
  • Label – Beschreibender Titel
  • Content – Markdown-Text

Die Blöcke sind über die API als JSON abrufbar (GET /api/sessions/{id}/system-prompt-blocks), sodass das Frontend sie einzeln inspizierbar darstellen kann.


Memory-System

Jeder Agent hat ein eigenes Dateisystem-basiertes Gedächtnis:

data/agents/{agentId}/
├── IDENTITY.md      # Identität (aus Template initialisiert)
├── SOUL.md          # Persönlichkeit (aus Template initialisiert)
├── MEMORY.md        # Haupt-Memory (kuratierte Informationen)
└── memory/          # Unterordner für Tages-Logs, Themen
    ├── YYYY-MM-DD.md
    └── ...

Funktionsweise

  1. Initialisierung: Beim Erstellen eines Agents werden IDENTITY.md und SOUL.md aus Templates/ kopiert
  2. Lesen: Der Agent kann seine Memory-Dateien via memory_read Tool lesen
  3. Schreiben: Via memory_write (überschreiben oder append)
  4. Auflisten: Via memory_list alle Dateien durchsuchen
  5. System-Prompt: MEMORY.md Inhalt wird automatisch in den System-Prompt eingebettet
  6. IDENTITY.md und SOUL.md: Werden als eigene System-Prompt-Blöcke eingebunden (wenn aktiviert)

Sandbox

Alle Pfade werden gegen das Agent-Verzeichnis geprüft – kein Zugriff außerhalb möglich.


Skill-System

Skills sind Dateisystem-basierte Erweiterungen die einem Agent zugeordnet werden können:

data/skills/{slug}/
├── SKILL.md          # Metadaten (Name, Description, Version im Frontmatter)
├── PROMPT.md         # System-Prompt-Erweiterung (in Agent-Prompt eingebettet)
├── _meta.json        # Alternative Metadaten (Fallback)
└── output/           # Skill-Output (Bilder, Dateien, etc.)

SKILL.md Frontmatter

---
name: Mein Skill
description: Beschreibung
version: 1.0
---

Agent-Zuordnung

Skills werden über die agent_skills Tabelle einem Agent zugeordnet. Der PROMPT.md-Inhalt aller zugeordneten Skills wird als ein System-Prompt-Block eingefügt.

Workspace-Implikation

Wenn ein Agent Skills hat aber kein Workspace konfiguriert ist, wird automatisch /tmp als Workspace gesetzt (damit execute für Skill-Commands funktioniert).


Telegram-Integration

Sessions können mit einem Telegram Bot verbunden werden:

Konfiguration

Pro Session werden gespeichert:

  • TelegramBotToken – Bot-Token von @BotFather
  • TelegramWebhookSecret – Geheimer Token für Webhook-Verifizierung
  • TelegramChatId – Verknüpfte Chat-ID (Owner)
  • TelegramAllowedChatIds – Kommagetrennte Chat-ID-Whitelist für Zugriffskontrolle

Webhook-Flow

1. User konfiguriert Bot-Token in Session-Settings
2. User registriert Webhook (POST .../telegram/register-webhook)
   → Setzt Webhook-URL: {baseUrl}/api/telegram/webhook/{sessionId}
3. Telegram sendet Updates an Webhook
4. AuthMiddleware lässt Webhook-Requests durch (kein Cookie nötig)
5. TelegramEndpoint prüft X-Telegram-Bot-Api-Secret-Token Header
6. TelegramService verarbeitet Update:
   - /start → Session verknüpfen (nur wenn noch kein Owner ODER Whitelist-Match)
   - /clear → History archivieren
   - /status → Session-Info anzeigen
   - /unlink → Verknüpfung aufheben
   - Text → An Claude weiterleiten (Non-Streaming)

Zugriffskontrolle (Chat-ID-Whitelist)

Nicht jeder Telegram-User darf den Bot nutzen:

  1. Erster /start: Kein Owner → User wird automatisch Owner (TelegramChatId gesetzt)
  2. Fremder /start: User bekommt 🔒 Zugriff verweigert + seine Chat-ID angezeigt
  3. Owner-Benachrichtigung: Owner erhält 🔔 Zugriffsanfrage mit Username + Chat-ID
  4. Freigabe: Owner/Admin trägt Chat-ID in Session-Settings ein (TelegramAllowedChatIds)
  5. Prüfung: Alle Commands + Nachrichten prüfen via IsChatIdAllowed() (Owner + Whitelist)

Non-Streaming Chat

Telegram-Nachrichten werden über AnthropicService.ChatNonStreaming() verarbeitet. Die History wird genauso aus der DB aufgebaut wie beim Web-Chat. Antworten über 4096 Zeichen werden automatisch in Chunks aufgeteilt.


Cronjob-System

Der CronjobService ist ein BackgroundService der minütlich nach fälligen Jobs prüft.

Datenmodell

Feld Beschreibung
CronExpression Standard-Cron-Format (5 Felder), via Cronos
SessionId Session in der der Job läuft
Prompt Text der als User-Message an Claude gesendet wird
NotifySessionId Optionale Session für Benachrichtigung
IsEnabled Aktiviert/Deaktiviert
NextRunAt Nächste geplante Ausführung (UTC)

Ausführungsflow

1. CronjobService prüft jede Minute
2. Fällige Jobs (next_run_at <= jetzt) werden geladen
3. Für jeden Job:
   a) ChatService.PrepareContext() – Chain + System-Prompt aufbauen
   b) History aus DB laden
   c) Prompt als User-Message anhängen + in DB speichern
   d) AnthropicService.ChatNonStreaming() ausführen
   e) Telegram-Benachrichtigung senden (auf Arbeits-Session)
   f) Optional: Zusammenfassung in Notify-Session schreiben + Telegram dort
   g) Nächste Ausführung berechnen + DB aktualisieren

Benachrichtigungen

  • Arbeits-Session: Wenn die Session Telegram hat, wird die Antwort dort gepostet
  • Notify-Session: Wenn konfiguriert, wird eine Zusammenfassung in eine andere Session geschrieben und der Agent dort antwortet darauf

Krea-Bildgenerierung

Die KreaService ermöglicht Bildgenerierung über die Krea API.

Unterstützte Modelle

flux, flux-kontext, flux-1.1-pro, flux-1.1-pro-ultra,
nano-banana, nano-banana-pro, imagen-3, imagen-4, imagen-4-fast, imagen-4-ultra,
ideogram-2-turbo, ideogram-3, seedream-3, seedream-4,
chatgpt-image, runway-gen-4

Flow

1. POST /api/images/generate { prompt, model, width, height, ... }
2. KreaService sendet Request an Krea API
3. Job-Polling bis Status "completed"
4. Bilder herunterladen nach data/images/
5. Metadaten als JSON speichern
6. Response mit Dateinamen + URLs

Bild-Serving

  • GET /api/images – Liste aller generierten Bilder (aus Metadaten-JSON)
  • GET /api/images/file/{filename} – Einzelnes Bild ausliefern

Auth & Multi-User

Authentifizierung

  • Login: Username + Passwort → SHA256 Hash-Vergleich → Token generieren
  • Token: 32 Bytes Random, als gott_token HttpOnly Cookie (365 Tage)
  • Validierung: Jeder API-Call prüft Token → User-ID
  • Logout: Token aus DB löschen + Cookie entfernen

Multi-User-Isolation

  • Sessions sind an user_id gebunden
  • Agents sind an user_id gebunden
  • Cronjobs sind an user_id gebunden
  • Jeder User sieht nur seine eigenen Daten
  • Admin-Flag (is_admin) für Backup-Endpoint, Admin-Benutzerverwaltung, Impersonate

Default-Path (Base-Path)

Jeder User hat einen optionalen DefaultPath – den Basis-Ordner für alle Workspaces. Wird nur vom Admin gesetzt.

  • Session-Workspace: Speichert nur den relativen Pfad zum DefaultPath (z.B. myapp statt /home/user/projects/myapp)
  • Auflösung: WorkspaceHelper.ResolveWorkspace() kombiniert DefaultPath + relativen Workspace → absoluter Pfad
  • System-Prompt: Bekommt den aufgelösten absoluten Pfad, damit der Agent korrekt navigieren kann
  • Path-Traversal-Schutz: .. in relativen Workspace-Pfaden wird blockiert (400 Bad Request)
  • Legacy-Support: Absolute Pfade in session.Workspace funktionieren weiterhin als Fallback
  • Folder-Browser: Startet beim DefaultPath, User kann nicht über den Base-Path hinaus navigieren

Default-User

Beim ersten Start wird automatisch ein Default-User erstellt (DatabaseService.EnsureDefaultUser()).

User-Persona

Jeder User hat eine optionale Persona – ein Freitext der beschreibt wer er ist. Diese wird (wenn UseUserInfo am Agent aktiv ist) in den System-Prompt als "Dein Gegenüber" eingebettet.


Admin-Benutzerverwaltung

Admins können alle User verwalten über AdminEndpoint.cs (alle Endpoints erfordern is_admin).

API-Endpunkte

Methode Route Beschreibung
GET /api/admin/users Alle User auflisten
POST /api/admin/users Neuen User erstellen
PUT /api/admin/users/{id} User bearbeiten (Name, Username, Admin, DefaultPath)
PUT /api/admin/users/{id}/password Passwort zurücksetzen
DELETE /api/admin/users/{id} User löschen (+ Tokens, Shared Messages)
POST /api/admin/users/{id}/impersonate Als anderer User einloggen (Login-as-User)

Impersonate (Login-as-User)

Admins können sich als beliebiger User einloggen ohne dessen Passwort zu kennen:

  1. POST /api/admin/users/{id}/impersonate → Erstellt Token für Zieluser
  2. Setzt neuen gott_token-Cookie → Admin-Session wird zum Zieluser
  3. location.reload() → Frontend lädt mit neuem User-Kontext

Frontend (admin-page.js)

  • Erreichbar über Dashboard-Link "Benutzerverwaltung" (nur für Admins sichtbar)
  • User-Liste als Cards mit Edit/Delete/Impersonate-Buttons
  • Inline-Formular für Create/Edit
  • Sich selbst löschen ist nicht möglich

Nachrichten teilen (Shared Messages)

Einzelne Nachrichten oder ganze Threads können als öffentliche Links geteilt werden – ohne Login aufrufbar.

Datenmodell

Tabelle shared_messages:

Spalte Typ Beschreibung
id INTEGER Primary Key
share_token TEXT UUID – öffentlicher Zugangsschlüssel
message_id INTEGER FK auf messages.id
user_id INTEGER Wer hat geteilt
include_context INTEGER 0 = Einzelnachricht, 1 = Thread bis dahin
created_at TEXT Erstellzeitpunkt
expires_at TEXT Optional: Ablaufdatum

API-Endpunkte (SharedEndpoint.cs)

Methode Route Auth Beschreibung
POST /api/messages/{id}/share ✅ Share erstellen (Body: {includeContext})
GET /api/shared/{token} ❌ Öffentlich: Geteilte Nachricht abrufen
GET /api/shared ✅ Eigene Shares auflisten
DELETE /api/shared/{token} ✅ Share-Link widerrufen

Frontend-Flow

  1. Share-Button (🔗) erscheint an jeder Nachricht im Chat (neben Reply, Delete, Mark)
  2. Klick öffnet Kontext-Menü: "Einzelne Nachricht" oder "Thread teilen"
  3. POST /api/messages/{id}/share → Token zurück → URL in Zwischenablage kopiert
  4. Toast: "Link kopiert!"

Öffentliche Ansicht (#/shared/{token})

  • Route #/shared/{token} → shared-page.js
  • Kein Auth nötig – Auth-Bypass in app.js + AuthMiddleware
  • Minimales Layout: Header ("// gott · Geteilte Nachricht"), Nachrichten mit Markdown-Rendering
  • Zwei Modi: single (eine Nachricht) oder context (Thread mit User/Assistant-Wechsel)

Workspace & File-Explorer

Workspace

Eine Session kann einen Workspace-Pfad haben. Dieser wird relativ zum DefaultPath des Users gespeichert (z.B. myapp) und via WorkspaceHelper.ResolveWorkspace() zum absoluten Pfad aufgelöst. Der Workspace:

  • Aktiviert die Datei-/Shell-Tools für den Agent
  • Ermöglicht den File-Explorer im Frontend
  • Bietet git status Informationen
  • Erlaubt das Ausführen von Shell-Befehlen (foreground + background)

WorkspaceHelper

Services/WorkspaceHelper.cs – Statische Hilfsklasse für Workspace-Pfade:

Methode Beschreibung
ResolveWorkspace(session, user) Relativer Workspace + DefaultPath → absoluter Pfad
ValidateRelativeWorkspace(workspace) Prüft auf .., ~, absolute Pfade → null bei ungültig
ToRelativeWorkspace(absolute, defaultPath) Absoluter Pfad → relativ zum DefaultPath

File-Explorer API

Endpoint Beschreibung
GET /api/workspace/tree Verzeichnisbaum (mit Ignore-Filtern)
GET /api/workspace/file Dateiinhalt lesen (max 2MB)
PUT /api/workspace/file Datei speichern
POST /api/workspace/mkdir Ordner erstellen im Workspace
DELETE /api/workspace/dir Leeren Ordner löschen im Workspace
GET /api/workspace/browse Verzeichnis-Browser (für Pfad-Auswahl)
POST /api/workspace/browse/mkdir Ordner erstellen per absolutem Pfad
GET /api/workspace/raw Raw-Datei ausliefern (Bilder, PDFs)
GET /api/workspace/agent/tree Agent-Memory-Verzeichnis
GET/PUT /api/workspace/agent/file Agent-Memory-Dateien lesen/schreiben
POST /api/workspace/agent/mkdir Ordner erstellen im Agent-Memory

Ignored Directories

bin, obj, node_modules, .git, .vs, .idea, publish, dist, out, build, target, .cache

Session-Exec

POST /api/sessions/{id}/exec führt Shell-Befehle im Workspace aus:

  • foreground: Synchron, wartet auf Ergebnis (30s Timeout)
  • background: Fire-and-forget via systemd-run

Avatar-System

Sessions und Agents können ein Bild/Avatar haben mit konfigurierbarem Zoom.

Datenfelder

Feld Tabellen Beschreibung
image / avatar sessions / agents Base64-kodiertes Bild (JPEG, max 512px via ImageService)
avatar_scale sessions, agents Zoom-Faktor (0.5× – 3×, Default 1.0), angewandt via CSS transform: scale()

Avatar-Editor (avatar-editor.js)

Wiederverwendbares Modal-Modul, genutzt in Session- und Agent-Pages:

const editor = AvatarEditor.init({
    previewEl:      document.querySelector('.avatar-preview'),
    currentImage:   existingBase64OrNull,
    currentScale:   1.0,
    onImageChange:  (base64) => { /* Preview aktualisieren */ },
    onScaleChange:  (scale) => { /* Live-Preview skalieren */ }
});
// Werte auslesen: editor.getImage(), editor.getScale()
// Aufräumen: editor.destroy()

Features:

  • Upload: Datei-Input für Bild-Upload
  • Paste: Ctrl+V → Bild aus Zwischenablage einfügen
  • AI-Generate: Text-Prompt → Krea API → Bild generieren (nur wenn KreaToken konfiguriert)
  • Scale: Range-Slider 0.5× – 3× mit Live-Preview
  • Clear: Bild entfernen

Dashboard-Darstellung

Cards zeigen Avatare mit transform: scale(avatarScale) im .card-image Container (overflow: hidden).


LaTeX/Math-Rendering

Chat-Nachrichten unterstützen LaTeX-Formeln via KaTeX:

Syntax

  • $$...$$ → Block-Math (zentriert, eigene Zeile)
  • $...$ → Inline-Math (im Fließtext)

Rendering-Pipeline (in ui.js renderMarkdown())

1. Code-Blöcke extrahieren und schützen (Platzhalter)
2. Block-LaTeX ($$...$$) extrahieren und schützen
3. Inline-LaTeX ($...$) extrahieren und schützen
4. Markdown-Rendering via marked.js
5. Code-Blöcke wiederherstellen
6. LaTeX-Platzhalter durch KaTeX.renderToString() ersetzen
7. Bei fehlerhaftem LaTeX: Fallback als <code class="katex-error">

Abhängigkeiten

  • wwwroot/js/lib/katex.min.js – KaTeX Engine (v0.16.21)
  • wwwroot/css/katex.min.css – Styles
  • wwwroot/css/fonts/ – 21 woff2-Fonts (self-hosted)

Funktioniert überall wo renderMarkdown() aufgerufen wird: Chat, Streaming, History, Archiv, Shared Page.


Windows Desktop App

Im WindowsApp/-Ordner liegt ein minimaler WPF WebView2 Client:

  • .NET 10 Windows, Microsoft.Web.WebView2
  • Lädt die Web-UI in einem nativen Fenster
  • Server-URL konfigurierbar via appsettings.json
  • Dark Background um weißen Flash zu vermeiden
  • Externe Links öffnen im Standard-Browser
  • Fenster: 930px breit, 95% Bildschirmhöhe, zentriert

Deployment

deploy.sh

#!/bin/bash
set -e
cd /app/gott
export PATH="$HOME/.dotnet:$PATH"
systemctl stop gott
dotnet publish -c Release -o publish
systemctl start gott
echo "OK"

Verzeichnisse

  • Quell-Code: /app/gott/ (wwwroot/, Services/, etc.)
  • Build-Output: /app/gott/publish/
  • Laufzeit-Daten: /app/gott/publish/data/ (DB, Agents, Images, Skills)
  • WICHTIG: Änderungen IMMER in wwwroot/ machen, NIEMALS in publish/wwwroot/

systemd

Die Anwendung läuft als systemd Service (gott.service), Kestrel auf Port 19000.


Konfiguration

appsettings.json

{
  "AnthropicToken": "",         // Anthropic API Key (REQUIRED)
  "MaxIterations": 100,         // Max Tool-Loop Iterationen pro Chat
  "PayloadLogging": false,      // API-Payloads loggen (Debug)
  "PayloadLoggingGzip": false,  // Payload-Logs als .gz komprimieren
  "KreaToken": "",               // Krea API Token (optional)
  "KreaApiKey": ""               // API-Key für Krea-Endpoints ohne User-Auth (optional)
}

Environment

  • ASPNETCORE_ENVIRONMENT=Production → lädt appsettings.Production.json
  • Tokens und Secrets sollten in appsettings.Production.json stehen (nicht in Git)

Datenbank-Migrationen

Die DatabaseService.InitializeDatabase() handhabt Schema-Erstellung und Migrationen in einem einzigen Methoden-Aufruf:

  1. Tabellen-Erstellung via CREATE TABLE IF NOT EXISTS
  2. Spalten-Migration via TryAddColumn() – fängt "column already exists" ab
  3. Daten-Migration (z.B. auto_commit von INTEGER zu TEXT, use_web_search zu web_search_version)

Dieses Pattern ermöglicht:

  • Idempotente Ausführung bei jedem App-Start
  • Keine separate Migrations-Verwaltung nötig
  • Neue Features können einfach Spalten hinzufügen
  • Abwärtskompatibel – bestehende Daten bleiben erhalten