Files
gott/ARCHITECTURE_QUICK.md
T

309 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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) · **OpenAI-kompatible APIs** (Nvidia, Pollinations, Gemini) · **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 + OpenAiService)
├── 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, buildTelegramBotCard)
│ ├── 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 (inkl. telegram-bot-page.js)
│ └── css/ # Styles (theme.css = CSS Variables)
├── WindowsApp/ # WPF + WebView2 Desktop Client
└── Build/ # ⛔ NICHT editieren!
├── Linux/
│ ├── bin/ obj/ publish/
└── Windows/
├── bin/ obj/ publish/
└── 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
User 1──* TelegramBot 1──* Session (via telegram_bot_id)
```
| Tabelle | Zweck |
|---------|-------|
| `users` | Login, DisplayName, IsAdmin, Persona, Settings (JSON), DefaultPath |
| `tokens` | Auth-Tokens → User |
| `agents` | AI-Agenten (Model – z.B. `claude-sonnet-4-6` oder `nvidia:model-id`, CustomCommands, AutoCommit, UseSoul/Identity/UserInfo/Memory, WebSearch, AllowUserChoice, TaskInstruction, AvatarScale/Offset, AvatarSmall, IsPublic) |
| `sessions` | Chat-Sessions (Description, Image, ImageSmall, Workspace, Context, CustomCommands, TelegramBotId, TelegramChatId, AvatarScale/Offset, PreparerAgentId, ReviewAgentId, MaxReviewIterations, FinalizerAgentId) |
| `chains` | Ein Request-Response-Zyklus (Tokens, Timing, Iterations, PlanMode, ToolChoice, ToolNames, StreamErrorInfo, ArchiveId) |
| `messages` | Einzelne Nachrichten (text / tool_use / tool_result / error / web_search_result), Tag für Sub-Agent-Markierung oder Import-Herkunft (`openclaw-import`), thought_signature (Gemini) |
| `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_bots` | Telegram Bots (BotToken, WebhookSecret, Name, IsPublic) – eigenständige Entität, 1 Bot → N Sessions |
---
## 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/` | Bot-CRUD, webhook/{botId} (unauth), session-config, registration |
| OpenClaw | `/api/openclaw/` | Import von OpenClaw-Sessions (sessions, import) |
| 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 |
| Models | `/api/models/` | `GET nvidia`, `GET pollinations`, `GET gemini`, `POST refresh` |
| 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 |
| **OpenAiService** | OpenAI-kompatible Provider (Nvidia, Pollinations, Gemini) mit Tool-Calling, Streaming, Modell-Caching |
| **ToolService** | Tool-Definitionen + Ausführung (13 Tools) |
| **WorkspaceHelper** | Workspace-Pfad-Auflösung (relativ → absolut), Path-Traversal-Schutz (static) |
| **SystemPromptBuilder** | System-Prompt aus modularen Blöcken zusammenbauen + Reminder-Generierung (static) |
| **MemoryService** | Agent-Gedächtnis auf Dateisystem |
| **SkillService** | Skill-Discovery aus Dateisystem |
| **TelegramService** | Telegram Bot API (Bot-basiert, Multi-Session-Routing) |
| **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: 11 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:** Max 120 Messages. Ä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. System-Prompt-Reminder alle ~30 Messages.
**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:** Automatisch `any` wenn Workspace/Skills/Memory vorhanden, sonst `auto`. Wird zu `none` bei `/no-tools`. Einzelne Tools forcierbar via `/tool:toolname`.
---
## System-Prompt (11+ 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. **Workspace** – Pfad-Info, Tool-Liste
6. **Rückfragen** – Hinweis zu `ask_user_choice` (wenn AllowUserChoice aktiv)
7. **Context** – Session-Kontext (custom system prompt)
8. **Skills** – Zugeordnete Skill-Prompts
9. **Memory** – Aktueller MEMORY.md-Inhalt + Regeln
10. **Git** – Commit-Verhalten (wenn AutoCommit konfiguriert)
11. **Markierte Nachrichten** – Vom User als wichtig markiert
- **[Plan-Modus]** – Überspringt 10; Read-only Tools; "Nur analysieren"
- **[Preparer-Block]** – Instruktionen für Vorbereiter-Agents
**Tool-Choice:** Automatisch `any` wenn Workspace/Skills/Memory vorhanden, sonst `auto`. Nicht konfigurierbar pro Agent.
**History-Reminder:** Alle ~30 Messages wird ein automatisch generierter Reminder injiziert (`[System Reminder] Beachte weiterhin den System-Prompt (...)`) – bekämpft "Lost-in-the-Middle"-Problem.
---
## 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 |
| `#/telegram-bot/{id}` | `telegram-bot-page.js` | Telegram-Bot-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 (`/api/telegram/webhook/{botId}`), `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`.
---
## 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 `Build/*/publish/wwwroot/`
- ⛔ **`Build/*/publish/data/gott.db`** niemals manuell modifizieren/löschen
- ⛔ **`Build/`** generell nicht anfassen
- 🔧 **.NET 10** ohne Nullable, ohne Implicit Usings
- 📦 DB-Migrationen sind idempotent (IF NOT EXISTS Pattern in `DatabaseService`)