diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md new file mode 100644 index 0000000..f221edd --- /dev/null +++ b/ARCHITECTURE.md @@ -0,0 +1,868 @@ +# 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](#überblick) +2. [Tech-Stack](#tech-stack) +3. [Projektstruktur](#projektstruktur) +4. [Datenmodell](#datenmodell) +5. [Backend-Architektur](#backend-architektur) + - [Program.cs – Startup](#programcs--startup) + - [Services](#services) + - [Endpoints (API)](#endpoints-api) + - [Middleware](#middleware) + - [Models](#models) + - [Templates](#templates) +6. [Frontend-Architektur](#frontend-architektur) +7. [Chat-Pipeline](#chat-pipeline) +8. [Tool-System](#tool-system) +9. [Agent-System](#agent-system) +10. [System-Prompt-Aufbau](#system-prompt-aufbau) +11. [Memory-System](#memory-system) +12. [Skill-System](#skill-system) +13. [Telegram-Integration](#telegram-integration) +14. [Cronjob-System](#cronjob-system) +15. [Krea-Bildgenerierung](#krea-bildgenerierung) +16. [Auth & Multi-User](#auth--multi-user) +17. [Workspace & File-Explorer](#workspace--file-explorer) +18. [Windows Desktop App](#windows-desktop-app) +19. [Deployment](#deployment) +20. [Konfiguration](#konfiguration) +21. [Datenbank-Migrationen](#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 │ +│ │ SSE │ │ │ │ gram │ jobs │ Images │ +├──────┴──────┴──────┴──────┴──────┴──────┴──────┴───────────┤ +│ 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) | +| **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 +│ ├── 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 +│ +├── 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 +│ ├── 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 +│ │ ├── markdown.css # Markdown-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 +│ │ ├── codemirror.min.css # CodeMirror Editor +│ │ └── easymde.min.css # EasyMDE Editor +│ ├── 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 +│ │ ├── 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 +│ │ │ ├── settings-page.js # App-Einstellungen +│ │ │ └── login-page.js # Login-Formular +│ │ └── lib/ # Vendor-Libraries +│ │ ├── marked.min.js # Markdown Parser +│ │ ├── codemirror.min.js # Code Editor +│ │ ├── codemirror.cjs # CM CommonJS Wrapper +│ │ ├── easymde.min.js # Markdown Editor +│ │ └── 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 +``` + +### Tabellen + +| Tabelle | Beschreibung | +|-------------------|-----------------------------------------------------| +| `users` | Benutzer (username, password_hash, persona, settings) | +| `tokens` | Auth-Tokens (token → user_id) | +| `agents` | AI-Agenten (model, soul, identity, memory, tools) | +| `sessions` | Chat-Sessions (workspace, context, telegram-config) | +| `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) | +| `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 14 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 | +| `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 | +| **Workspace** | `/api/workspace/` | `GET tree`, `GET/PUT file`, `GET browse`, `GET agent/tree`, `GET/PUT agent/file`, `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) | +| **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` +- `POST /api/telegram/webhook/{sessionId}` (authentifiziert via Secret-Header) + +Bei Erfolg werden `UserId` und `IsAdmin` in `HttpContext.Items` 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 | +| `#/login` | `login-page.js` | Login | + +### 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, Tool-Output-Darstellung +- **history.js** – Chat-History laden, paginieren, rendern +- **session.js** – Session-State-Management +- **file-explorer.js** – Workspace File-Explorer Panel +- **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│ + └─────────────────────────────────────────┘ + ↓ +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 +``` + +### 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 +"opus" → claude-opus-4-6 +"haiku" → claude-haiku-4-5 +``` + +--- + +## 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 + ├── 2025-07-13.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 + +```yaml +--- +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 + +### 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 + - /clear → History archivieren + - /status → Session-Info anzeigen + - /unlink → Verknüpfung aufheben + - Text → An Claude weiterleiten (Non-Streaming) +``` + +### 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 + +### 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. + +--- + +## Workspace & File-Explorer + +### Workspace + +Eine Session kann einen **Workspace-Pfad** haben (z.B. `/app/gott`). Dieser: +- 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) + +### 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 | +| `GET /api/workspace/browse` | Verzeichnis-Browser (für Pfad-Auswahl)| +| `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 | + +### 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` + +--- + +## 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 + +```bash +#!/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 + +```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) +} +``` + +### 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 diff --git a/ARCHITECTURE_QUICK.md b/ARCHITECTURE_QUICK.md new file mode 100644 index 0000000..b0fa745 --- /dev/null +++ b/ARCHITECTURE_QUICK.md @@ -0,0 +1,223 @@ +# ARCHITECTURE_QUICK.md – Schnellreferenz + +> Kurzfassung der [ARCHITECTURE.md](ARCHITECTURE.md) für schnelles Nachschlagen beim Entwickeln. + +--- + +## Tech-Stack + +**.NET 10** Minimal API · **SQLite** + Dapper · **Anthropic Claude API** (SSE Streaming) · **Vanilla JS** SPA · **Kestrel** auf Port 19000 + +--- + +## Verzeichnisstruktur (nur Schlüssel-Dateien) + +``` +gott/ +├── Program.cs # Startup, DI, Middleware, Routing +├── appsettings.json # Tokens, API-Keys, Limits +├── Models/ # Records (reine Daten) +├── Services/ # Business-Logic (alle Singletons) +├── Endpoints/ # HTTP API (Minimal API MapXxx-Pattern) +├── Middleware/ # AuthMiddleware +├── Templates/ # Vorlagen für neue Agents (IDENTITY, SOUL, USER) +├── wwwroot/ # ⚠️ HIER Frontend editieren! +│ ├── js/app.js # App-Init +│ ├── js/router.js # Hash-basiertes SPA-Routing +│ ├── js/api.js # fetch()-Wrapper +│ ├── js/chat.js # SSE-Stream, Markdown-Rendering +│ ├── js/pages/ # Seiten-Komponenten +│ └── css/ # Styles (theme.css = CSS Variables) +├── WindowsApp/ # WPF + WebView2 Desktop Client +└── publish/ # ⛔ NICHT editieren! + └── data/ + ├── gott.db # SQLite DB + ├── agents/{id}/ # Memory-Dateien pro Agent + ├── skills/{slug}/ # Skill-Dateien + └── images/ # Krea-generierte Bilder +``` + +--- + +## Datenmodell (Kurzform) + +``` +User 1──* Agent 1──* Session 1──* Chain 1──* Message 1──* Attachment + Agent *──* Skill (via agent_skills) + Session 1──* Cronjob + Session 1──* Archive +``` + +| Tabelle | Zweck | +|---------|-------| +| `users` | Login, Persona, Settings (JSON) | +| `tokens` | Auth-Tokens → User | +| `agents` | AI-Agenten (Model, Tools, Config) | +| `sessions` | Chat-Sessions (Workspace, Context, Telegram) | +| `chains` | Ein Request-Response-Zyklus (Tokens, Timing, Iterations) | +| `messages` | Einzelne Nachrichten (text / tool_use / tool_result / error) | +| `attachments` | Base64-Anhänge (Bilder, Dokumente) | +| `archives` | Archivierte Chain-Gruppen | +| `cronjobs` | Geplante Tasks (Cron-Expression + Prompt) | +| `agent_skills` | N:M Agent ↔ Skill | +| `telegram_links` | Telegram Chat-ID ↔ Session | + +--- + +## API-Endpunkte (Übersicht) + +| Gruppe | Route | Wichtigstes | +|--------|-------|-------------| +| Auth | `/api/auth/` | `POST login`, `POST logout`, `GET me` | +| Chat | `/api/chat` | `POST` → SSE Stream | +| History | `/api/history` | GET history, poll, archive, marks, delete | +| Sessions | `/api/sessions/` | CRUD + system-prompt, exec, git-status | +| Agents | `/api/agents/` | CRUD | +| Workspace | `/api/workspace/` | tree, file read/write, browse, agent-files | +| Telegram | `/api/telegram/` | webhook (unauth), config, registration | +| Cronjobs | `/api/cronjobs/` | CRUD + toggle, manual run | +| Krea | `/api/images/` | generate, list, file-serve | +| Skills | `/api/skills` | list, agent-mapping, output-files | +| Profile | `/api/profile` | GET, PUT, password | +| Settings | `/api/settings` | GET, PUT (JSON blob) | +| Backup | `/api/backup` | POST → tar.gz download (Admin) | +| Info | `/api/info` | GET → Build-Zeitstempel | + +--- + +## Services (alle Singletons) + +| Service | Was es tut | +|---------|-----------| +| **DatabaseService** | Alles DB: Schema, Migrationen, CRUD | +| **AuthService** | Token-Auth, Passwort-Hashing (SHA256) | +| **ChatService** | Chat-Kontext aufbauen, History aus DB laden | +| **AnthropicService** | Claude API: SSE Streaming + Non-Streaming | +| **ToolService** | Tool-Definitionen + Ausführung (12 Tools) | +| **SystemPromptBuilder** | System-Prompt aus modularen Blöcken zusammenbauen (static) | +| **MemoryService** | Agent-Gedächtnis auf Dateisystem | +| **SkillService** | Skill-Discovery aus Dateisystem | +| **TelegramService** | Telegram Bot API | +| **CronjobService** | BackgroundService, minütlicher Cron-Check | +| **KreaService** | Krea API Bildgenerierung + Job-Polling | +| **ImageService** | Bild-Resize (ImageSharp, max 512px) | +| **StreamingTracker** | ConcurrentDict: wer streamt gerade? | + +--- + +## Chat-Pipeline (Flow) + +``` +User-Input → POST /api/chat (SSE) + → ChatService.BuildContext() + → History aus DB laden (letzte N Chains) + → SystemPromptBuilder: 12 Blöcke zusammensetzen + → Tool-Definitionen vom ToolService holen + → AnthropicService.StreamChat() + → Claude API Call (SSE) + → Token-für-Token an Client streamen + → Bei tool_use → ToolService.Execute() → Ergebnis zurück → neuer API Call + → Loop bis end_turn oder max_iterations (50) + → Chain + Messages in DB speichern +``` + +**History-Optimierung:** Ältere Nachrichten werden auf 20% gekürzt, Tool-Results auf 500 Zeichen. Neueste 3 Chains bleiben vollständig. + +--- + +## Tool-System (12 Tools) + +| Tool | Funktion | +|------|----------| +| `read_file` | Datei lesen | +| `write_file` | Datei erstellen/überschreiben | +| `edit_file` | Exakten Textabschnitt ersetzen | +| `list_files` | Verzeichnisinhalt auflisten | +| `delete_file` | Datei/leeres Verzeichnis löschen | +| `execute` | Shell-Befehl ausführen (bash, 180s Timeout) | +| `glob` | Dateien per Glob-Pattern finden | +| `grep` | Dateien per Regex/Text durchsuchen | +| `todo_write` | Aufgabenliste schreiben (wird im Prompt angezeigt) | +| `memory_read` | Memory-Datei lesen | +| `memory_write` | Memory-Datei schreiben/appenden | +| `memory_list` | Memory-Dateien auflisten | + +**Sicherheit:** Alle Pfade werden auf das Workspace-Verzeichnis beschränkt (`..` wird blockiert). Tools sind pro Agent konfigurierbar (Feld `tools` als komma-separierte Liste). + +**Tool-Choice:** Standard `auto`. Wird zu `none` bei `/no-tools`. Einzelne Tools forcierbar via `/tool:toolname`. + +--- + +## System-Prompt (12 Blöcke, in Reihenfolge) + +1. **Identity** – `IDENTITY.md` des Agents +2. **Soul** – `SOUL.md` des Agents +3. **User** – `USER.md` (globale User-Infos) + Persona +4. **Rules** – Verhaltensregeln (Tool-Nutzung, Workspace) +5. **Context** – Session-Kontext (custom system prompt) +6. **Marked Messages** – Als wichtig markierte Nachrichten +7. **Memory** – Aktueller MEMORY.md-Inhalt +8. **Skills** – Zugeordnete Skill-Prompts +9. **Todos** – Aktuelle Todo-Liste +10. **Tools** – Tool-Beschreibungen und -Regeln +11. **Workspace** – Pfad-Info, Dateibaum des Workspace +12. **Date** – Aktuelles Datum/Uhrzeit + +--- + +## Frontend-Routing + +| Hash-Route | Page-Datei | Beschreibung | +|------------|-----------|--------------| +| `#/` | `dashboard.js` | Session-Übersicht | +| `#/chat/{id}` | `chat-page.js` | Chat | +| `#/session/{id}` | `session-page.js` | Session-Settings | +| `#/agent/{id}` | `agent-page.js` | Agent-Editor | +| `#/cronjobs` | `cronjob-page.js` | Cronjobs | +| `#/profile` | `profile-page.js` | Profil | +| `#/settings` | `settings-page.js` | Einstellungen | +| `#/login` | `login-page.js` | Login | + +--- + +## Auth-Flow + +1. `POST /api/auth/login` → Token generiert, als `gott_token` HttpOnly Cookie gesetzt +2. Jeder `/api/`-Request → `AuthMiddleware` prüft Cookie → setzt `UserId` + `IsAdmin` +3. Ausnahmen: Login + Telegram-Webhook brauchen kein Auth + +--- + +## Konfiguration (appsettings.json) + +```json +{ + "AnthropicApiKey": "sk-ant-...", + "TelegramBotToken": "...", + "KreaApiKey": "...", + "DataDirectory": "data", + "MaxHistoryChains": 50, + "MaxIterations": 50, + "DefaultModel": "claude-sonnet-4-20250514" +} +``` + +--- + +## Deployment + +```bash +./deploy.sh # dotnet publish → systemctl restart gott +``` + +Läuft als `systemd`-Service, Kestrel auf Port 19000, typisch hinter Nginx/Caddy Reverse Proxy. + +--- + +## Wichtige Regeln beim Entwickeln + +- ⚠️ **Quelldateien in `wwwroot/`** editieren, NICHT in `publish/wwwroot/` +- ⛔ **`publish/data/gott.db`** niemals manuell modifizieren/löschen +- ⛔ **`publish/`** generell nicht anfassen +- 🔧 **.NET 10** ohne Nullable, ohne Implicit Usings +- 📦 DB-Migrationen sind idempotent (IF NOT EXISTS Pattern in `DatabaseService`) diff --git a/wwwroot/css/chat.css b/wwwroot/css/chat.css index 738b283..77def5f 100644 --- a/wwwroot/css/chat.css +++ b/wwwroot/css/chat.css @@ -103,6 +103,7 @@ border: var(--border-width) solid var(--f3-border); } +.msg.user.markdown pre, .msg.user.markdown code { background: var(--f2-bg); }