# 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 · **KaTeX** (Math) · **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 + WorkspaceHelper) ├── 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/ui-helpers.js # DOM-Helpers ($, esc, truncate), Toast, ScrollDown │ ├── js/markdown.js # Markdown-Rendering (renderMarkdown, LaTeX-Schutz) │ ├── js/cards.js # Card-Builder (buildSessionCard, buildAgentCard) │ ├── js/msg-actions.js # Nachrichten-Aktionen (Delete, Mark, Share, Reply) │ ├── js/tool-ui.js # Tool-Boxes, Diffs, Visibility-Logik │ ├── js/modals.js # Modale Dialoge (System-Prompt, Command-Output) │ ├── js/stream-ui.js # Stream-Bubble, Review-Streaming │ ├── js/bubbles.js # Message Bubbles (User, Assistant, Error, Choice) │ ├── js/chat.js # SSE-Stream-Handling, sendMessage, Plan-Mode │ ├── js/history.js # History laden, Polling, Rendering │ ├── js/archive.js # Archiv-Loading │ ├── js/reply.js # Reply/Quote-Handling │ ├── js/files.js # File-Upload, Workspace-Refs │ ├── 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 User 1──* SharedMessage ──1 Message ``` | Tabelle | Zweck | |---------|-------| | `users` | Login, Persona, Settings (JSON), DefaultPath | | `tokens` | Auth-Tokens → User | | `agents` | AI-Agenten (Model, Tools, Config, AvatarScale, AvatarOffsetX/Y, AvatarSmall) | | `sessions` | Chat-Sessions (Workspace, Context, Telegram, AvatarScale, AvatarOffsetX/Y, AllowedChatIds, PreparerAgentId, ReviewAgentId, MaxReviewIterations, FinalizerAgentId, ImageSmall) | | `chains` | Ein Request-Response-Zyklus (Tokens, Timing, Iterations, PlanMode) | | `messages` | Einzelne Nachrichten (text / tool_use / tool_result / error / web_search_result), Tag für Sub-Agent-Markierung | | `attachments` | Base64-Anhänge (Bilder, Dokumente) | | `archives` | Archivierte Chain-Gruppen | | `cronjobs` | Geplante Tasks (Cron-Expression + Prompt) | | `agent_skills` | N:M Agent ↔ Skill | | `shared_messages` | Geteilte Nachrichten (öffentliche Links via Share-Token) | | `telegram_links` | Telegram Chat-ID ↔ Session | --- ## API-Endpunkte (Übersicht) | Gruppe | Route | Wichtigstes | |--------|-------|-------------| | Auth | `/api/auth/` | `POST login`, `POST logout`, `GET me`, `GET autologin` | | Chat | `/api/chat` | `POST` → SSE Stream, `POST stop` | | History | `/api/history` | GET history, poll, archive, marks, delete | | Sessions | `/api/sessions/` | CRUD + system-prompt, exec, git-status (Liste inkl. inline Git-Status) | | Agents | `/api/agents/` | CRUD (Liste inkl. inline Skills) | | Admin | `/api/admin/` | User CRUD, impersonate, login-link (Admin-only) | | Workspace | `/api/workspace/` | tree, file read/write, mkdir, rmdir, browse, agent-files | | Telegram | `/api/telegram/` | webhook (unauth), config, registration | | Cronjobs | `/api/cronjobs/` | CRUD + toggle, manual run | | Krea | `/api/images/` | generate, list, file-serve, thumb, status (file/* ohne Auth) | | 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) | | Shared | `/api/shared/`, `/api/messages/{id}/share` | Share erstellen, öffentlich abrufen, löschen | | Info | `/api/info` | GET → Build-Zeitstempel | | ServerSettings | `/api/admin/server-settings` | `GET`, `PUT` (Admin-only, liest/schreibt `appsettings.Production.json`) | --- ## 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) | | **WorkspaceHelper** | Workspace-Pfad-Auflösung (relativ → absolut), Path-Traversal-Schutz (static) | | **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 + WebP-Konvertierung (512px + 256px Thumbnail) | | **StreamingTracker** | Tracking aktiver Streams + CancellationTokenSource pro Session für Stop | --- ## Chat-Pipeline (Flow) ``` User-Input → POST /api/chat (SSE) → ChatService.BuildContext() → History aus DB laden (letzte N Chains) → SystemPromptBuilder: 14 Blöcke zusammensetzen (+ Plan-Modus/Preparer-Blöcke) → Tool-Definitionen vom ToolService holen (im Plan-Modus: nur Read-only) → Preparer-Phase (optional, wenn PreparerAgentId gesetzt): → RunPreparer() → RunAgentChat(agentType: "preparer") → Antwort ohne [QUESTION] → automatisch weiterleiten (Default = Forward) → [QUESTION] → Rückfrage an User, Flow stoppt → AnthropicService.StreamChat() → Claude API Call (SSE) → Token-für-Token an Client streamen → Bei tool_use → ToolService.Execute() → Ergebnis zurück → neuer API Call → Bei ask_user_choice → SSE user_choice Event → Flow stoppt (awaiting_user_choice) → Loop bis end_turn oder max_iterations (100) → Bei end_turn + ReviewAgent → Review-Phase: → Review-Agent prüft (eigene Tools, max 25 Iterationen) → [APPROVED] → Fertig | Feedback → Worker korrigiert → erneuter Review → Bei FinalizerAgent → Finalizer-Phase: → Finalizer-Agent arbeitet (eigene Tools, z.B. git commit) → Einmalig, kein Feedback-Loop → Stop-Button: POST /api/chat/stop → StreamingTracker.Cancel() → CancellationToken durchgereicht bis ToolService → Prozess-Kill → client_disconnected → Chain + Messages in DB speichern ``` **History-Optimierung:** Ältere Chains nur Text-Messages (keine Tool-Calls). Letzte Chain vollständig. Tool-Results auf 20.000 Zeichen gekürzt. Attachments nur für letzte User-Message. **Rendering:** Markdown via marked.js + LaTeX via KaTeX (`$$...$$` Block, `$...$` Inline). Timestamps im Format `dd.MM.yyyy HH:mm:ss` on hover. --- ## Tool-System (13 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 | | `ask_user_choice` | Interaktive Rückfrage mit 2-5 Auswahlmöglichkeiten (wenn AllowUserChoice aktiv) | **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 (14+ Blöcke, in Reihenfolge) 1. **Identity** – `IDENTITY.md` des Agents 2. **Soul** – `SOUL.md` des Agents 3. **Anweisungen** – `TaskInstruction` des Agents (optional, wenn gesetzt) 4. **User** – `USER.md` (globale User-Infos) + Persona 5. **Rules** – Verhaltensregeln (Tool-Nutzung, Workspace) 6. **Workspace** – Pfad-Info, Tool-Liste 7. **Rückfragen** – Hinweis zu `ask_user_choice` (wenn AllowUserChoice aktiv) 8. **Context** – Session-Kontext (custom system prompt) 9. **Skills** – Zugeordnete Skill-Prompts 10. **Memory** – Aktueller MEMORY.md-Inhalt + Regeln 11. **Git** – Commit-Verhalten (wenn AutoCommit konfiguriert) 12. **Verhaltensregeln** – "IMMER Tools aufrufen" (wenn Workspace + any) 13. **Erinnerung** – Höchste Priorität: Tool-Aufrufe! (wenn Workspace + any) 14. **Markierte Nachrichten** – Vom User als wichtig markiert - **[Plan-Modus]** – Überspringt 5, 11, 12, 13; Read-only Tools; "Nur analysieren" - **[Preparer-Block]** – Instruktionen für Vorbereiter-Agents --- ## 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 | | `#/admin` | `admin-page.js` | Benutzerverwaltung (Admin) | | `#/server-settings` | `server-settings-page.js` | Servereinstellungen (Admin) | | `#/login` | `login-page.js` | Login | | `#/shared/{token}` | `shared-page.js` | Geteilte Nachricht (öffentlich, kein Auth) | --- ## 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, Autologin, Telegram-Webhook, `GET /api/shared/{token}`, `GET /api/images/file/*` brauchen kein Auth 4. **Krea API-Key**: `/api/images/`-Routen akzeptieren `X-Api-Key`-Header (Config: `KreaApiKey`) für Automation ohne User-Kontext 5. **Impersonate**: Admin kann via `POST /api/admin/users/{id}/impersonate` als anderer User einloggen 6. **Login-Link**: Admin generiert via `POST /api/admin/users/{id}/login-link` einen Autologin-Link (Token-basiert, `GET /api/auth/autologin?token=xxx`) 7. **DefaultPath**: Pro User ein Basis-Ordner (nur vom Admin setzbar), Session-Workspaces sind relativ dazu --- ## Konfiguration (appsettings.json) ```json { "Port": 19000, // Server-Port (erfordert Neustart) "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) } ``` Verwaltung über **Admin-UI** (`#/server-settings`): Liest `appsettings.Production.json` (Fallback: `appsettings.json` → Default). Schreibt immer in `appsettings.Production.json`. Die Datei wird **nicht** beim Publish mitkopiert. --- ## Deployment ```bash ./deploy.sh # dotnet publish → systemctl restart gott ``` Läuft als `systemd`-Service, Kestrel auf konfigurierbarem Port (Default 19000), typisch hinter Nginx/Caddy Reverse Proxy. --- ## Multi-Agent System (Preparer + Review + Finalizer) Eine Session kann bis zu **vier Agents** haben: Worker (Pflicht), Preparer (optional, `preparer_agent_id`), Review (optional, `review_agent_id`, `max_review_iterations`), Finalizer (optional, `finalizer_agent_id`). **Flow:** Preparer analysiert User-Anfrage (→ Vorarbeit leisten oder `[QUESTION]` Rückfrage) → Worker-Agent arbeitet → Review-Agent prüft (`[APPROVED]` / Feedback-Loop) → Finalizer-Agent arbeitet (einmalig) → Fertig. **Preparer:** Default = Forward (jede Antwort wird automatisch weitergeleitet, `[QUESTION]` stoppt). Bekommt eigene History mit `includeTag: "preparer"`. Aufbereiteter Prompt wird als `[Vorbereitet von AgentName]:` User-Message gespeichert. **Backend:** `ChatService` baut `PreparerContext` + `ReviewContext` + `FinalizerContext`. `RunPreparer()` im ChatEndpoint (vor StreamChat). `RunReview()` + `RunFinalizer()` in AnthropicService. Alle nutzen `RunAgentChat()` (mit `Tag`-Markierung, Sub-Agent-Messages aus API-History gefiltert). **SSE-Events:** - Preparer: `preparer_start`, `preparer_text`, `preparer_tool_use`, `preparer_done` - Review: `review_start`, `review_text`, `review_tool_use`, `review_feedback`, `review_approved` - Finalizer: `finalizer_start`, `finalizer_text`, `finalizer_tool_use`, `finalizer_done` **Frontend-Rendering:** - Streaming: `chat.js` rendert Preparer-/Review-/Finalizer-Events als eigene Bubbles - History: `renderMarkdown` parst `[Preparer: AgentName]`, `[Vorbereitet von AgentName]`, `[Review: AgentName]`, `[Finalizer: AgentName]`, filtert `[APPROVED]`, `[FORWARD]`, `[QUESTION]` - Bubble-Klassen: `.preparer-bubble` (Info-Farbe), `.review-bubble` (sekundäre Farbe), `.finalizer-bubble` (grüne Farbe) **Web-Search Sources:** - `web_search_result`-Messages in DB gespeichert (Sources als JSON-Array, leere werden übersprungen) - History + Shared-Page: Tool-Box mit klickbaren Source-Links (Domain + Title) - Streaming: `pauseStreamBubble()` hält Bubble offen zwischen Web-Searches (keine Doppel-Bubbles) --- ## 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`)