docs: ARCHITECTURE.md + ARCHITECTURE_QUICK.md aktualisiert

- Chat: POST /api/chat/stop Endpoint + Stop-Mechanismus (zwei Ebenen) dokumentiert
- StreamingTracker: CancellationTokenSource pro Session beschrieben
- Auth: GET /api/auth/autologin, GET /api/images/file/* ohne Auth
- Admin: POST login-link Endpoint + Login-Link-Sektion
- Krea: Thumb-Endpoint, Status-Endpoint, öffentliches Bild-Serving
- Frontend: buildAgentCard(), buildSessionCard() UI-Helpers + Picker-Modals
- ui.js in Verzeichnisstruktur ergänzt
This commit is contained in:
Meleki committed 2026-03-06 15:51:47 +01:00
1 parent 40c8fee531
commit 2598656f1c
2 files changed
+58 -22

No files matched your search

+46 -14
View File
@@ -124,7 +124,7 @@ gott/
│ ├── 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
│ ├── StreamingTracker.cs # Tracking aktiver Streams + CancellationTokenSource für Stop
│ └── WorkspaceHelper.cs # Workspace-Pfad-Auflösung (relativ → absolut)
│
├── Endpoints/ # HTTP API (Minimal API)
@@ -336,7 +336,7 @@ AuthService → DatabaseService → EnsureDefaultUser
| `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 |
| `StreamingTracker` | Singleton | Trackt aktive Streams + CancellationTokenSource pro Session für Stop-Button |
### Endpoints (API)
@@ -344,16 +344,16 @@ Alle Endpoints folgen dem **Minimal API**-Pattern mit Extension Methods (`MapXxx
| Gruppe | Basis-Route | Methoden |
|---------------|----------------------------|---------------------------------------------|
| **Auth** | `/api/auth/` | `POST login`, `POST logout`, `GET me` |
| **Chat** | `/api/chat` | `POST` (SSE Streaming) |
| **Auth** | `/api/auth/` | `POST login`, `POST logout`, `GET me`, `GET autologin` |
| **Chat** | `/api/chat` | `POST` (SSE Streaming), `POST stop` |
| **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) |
| **Admin** | `/api/admin/` | `GET users`, `POST users`, `PUT users/{id}`, `PUT users/{id}/password`, `DELETE users/{id}`, `POST users/{id}/impersonate`, `POST users/{id}/login-link` (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` |
| **Krea** | `/api/images/` | `POST generate`, `GET list`, `GET file/{name}`, `GET file/{name}/thumb`, `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` |
@@ -371,6 +371,7 @@ Ausnahmen (kein Auth nötig):
- `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)
- `GET /api/images/file/*` (Krea-Bilder und Thumbnails, öffentlich)
**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.
@@ -422,13 +423,19 @@ Das Frontend ist eine **Single-Page Application** ohne Build-Step, komplett in V
- **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.)
- **ui.js** – UI-Utilities (Modals, Toasts, Confirmations), Card-Builder (`buildAgentCard()`, `buildSessionCard()`), Markdown-Rendering-Helpers (`esc()`, `prettyModelName()`)
- **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
### Wiederverwendbare Card-Builder (ui.js)
- **`buildAgentCard(agent, skills)`** – Erzeugt ein `.card` DOM-Element für einen Agent (Avatar, Name, Model-Badge, Feature-Badges: toolChoice, autoCommit, useSoul, useIdentity, useUserInfo, useMemory, webSearch, Skills). Wird im Dashboard und im Agent-Picker-Modal (Session-Formular) verwendet.
- **`buildSessionCard(session, agent)`** – Erzeugt ein `.card` DOM-Element für eine Session (Avatar, Name, Badges: Agent, Kontext, Telegram, Meta: Nachrichten/Archiv/Workspace). Wird im Dashboard und im Session-Picker-Modal (Cronjob-Formular) verwendet.
- **Picker-Modals** – Agent- und Session-Auswahl in Formularen (Session-/Cronjob-Seiten) erfolgt über modale Dialoge mit den Card-Buildern statt über Dropdowns.
- **emoji.js** – Emoji-Picker mit Kategorien und Suche
- **tooltip.js** – Tooltip-System für Hover-Infos
- **title.js** – Dynamisches Tab-Titel-Management
@@ -482,12 +489,23 @@ Der Chat-Flow von User-Input bis zur gerenderten Antwort:
### Abbruch (Stop-Button)
Das `CancellationToken` wird durchgängig propagiert:
1. Frontend: `AbortController.abort()` → SSE-Fetch abgebrochen
2. ASP.NET: `RequestAborted` Token wird gecancelled
Der Stop-Mechanismus arbeitet auf zwei Ebenen:
**1. Expliziter Stop-Endpoint (`POST /api/chat/stop`):**
- Frontend ruft `apiStopChat(sessionId)` auf
- `StreamingTracker` hält pro Session einen `CancellationTokenSource`
- `StreamingTracker.Cancel(sessionId)` cancelt den Token sofort
- Der Chat-Handler verknüpft den Stop-Token mit dem Request-Token via `CreateLinkedTokenSource`
**2. CancellationToken-Propagierung:**
1. Frontend: `AbortController.abort()` → SSE-Fetch abgebrochen + `POST /api/chat/stop`
2. `StreamingTracker.Cancel()` → CancellationTokenSource 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
4. `ToolService.ExecuteTool()`: CancellationToken wird durchgereicht → bei `execute` wird der Prozess gekillt
5. `WriteSseEvent()`: Alle SSE-Writes mit CancellationToken → sofortiger Abbruch
6. Chain wird mit `StopReason = "client_disconnected"` finalisiert
**Warum zwei Ebenen?** Kestrel erkennt einen Client-Disconnect erst beim nächsten Write auf den Response-Stream. Wenn das Backend in einer langen Tool-Ausführung steckt, wird nichts geschrieben – der explizite Stop-Endpoint garantiert sofortigen Abbruch.
### Streaming vs Non-Streaming
@@ -781,7 +799,11 @@ chatgpt-image, runway-gen-4
### Bild-Serving
- `GET /api/images` – Liste aller generierten Bilder (aus Metadaten-JSON)
- `GET /api/images/file/{filename}` – Einzelnes Bild ausliefern
- `GET /api/images/file/{filename}` – Einzelnes Bild ausliefern (ohne Auth)
- `GET /api/images/file/{filename}/thumb` – Thumbnail (320px WebP, gecacht in `data/cache/images/`, ohne Auth)
- `GET /api/images/status` – Generierungsstatus abfragen
Bild-Dateien und Thumbnails sind **ohne Authentifizierung** abrufbar (für externe Einbindung).
---
@@ -837,6 +859,7 @@ Admins können alle User verwalten über `AdminEndpoint.cs` (alle Endpoints erfo
| `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) |
| `POST` | `/api/admin/users/{id}/login-link` | Autologin-Token generieren → URL zurückgeben |
### Impersonate (Login-as-User)
@@ -845,11 +868,20 @@ Admins können sich als beliebiger User einloggen ohne dessen Passwort zu kennen
2. Setzt neuen `gott_token`-Cookie → Admin-Session wird zum Zieluser
3. `location.reload()` → Frontend lädt mit neuem User-Kontext
### Login-Link generieren
Admins können für jeden User einen **Autologin-Link** generieren – z.B. für Setup oder Support:
1. `POST /api/admin/users/{id}/login-link` → Erstellt Token, gibt `{ token }` zurück
2. Frontend baut URL: `{window.location.origin}/api/auth/autologin?token={token}`
3. Link wird im Modal angezeigt mit Copy-Button
4. `GET /api/auth/autologin?token={token}` → Setzt Cookie + Redirect zu `/` (ohne Auth, wie Login)
### Frontend (`admin-page.js`)
- Erreichbar über Dashboard-Link "Benutzerverwaltung" (nur für Admins sichtbar)
- User-Liste als Cards mit Edit/Delete/Impersonate-Buttons
- User-Liste als Cards mit Edit/Delete/Login-Link-Buttons
- Inline-Formular für Create/Edit
- Login-Link-Modal mit Copy-Funktion
- Sich selbst löschen ist nicht möglich
---
+12 -8
View File
@@ -26,6 +26,7 @@ gott/
│ ├── js/router.js # Hash-basiertes SPA-Routing
│ ├── js/api.js # fetch()-Wrapper
│ ├── js/chat.js # SSE-Stream, Markdown-Rendering
│ ├── js/ui.js # UI-Helpers, buildAgentCard(), buildSessionCard()
│ ├── js/pages/ # Seiten-Komponenten
│ └── css/ # Styles (theme.css = CSS Variables)
├── WindowsApp/ # WPF + WebView2 Desktop Client
@@ -70,16 +71,16 @@ User 1──* Agent 1──* Session 1──* Chain 1──* Message 1──* At
| Gruppe | Route | Wichtigstes |
|--------|-------|-------------|
| Auth | `/api/auth/` | `POST login`, `POST logout`, `GET me` |
| Chat | `/api/chat` | `POST` → SSE Stream |
| 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 |
| Agents | `/api/agents/` | CRUD |
| Admin | `/api/admin/` | User CRUD, impersonate (Admin-only) |
| 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 |
| 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) |
@@ -106,7 +107,7 @@ User 1──* Agent 1──* Session 1──* Chain 1──* Message 1──* At
| **CronjobService** | BackgroundService, minütlicher Cron-Check |
| **KreaService** | Krea API Bildgenerierung + Job-Polling |
| **ImageService** | Bild-Resize (ImageSharp, max 512px) |
| **StreamingTracker** | ConcurrentDict: wer streamt gerade? |
| **StreamingTracker** | Tracking aktiver Streams + CancellationTokenSource pro Session für Stop |
---
@@ -123,7 +124,9 @@ User-Input → POST /api/chat (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 (100)
→ CancellationToken bei Stop-Button → client_disconnected
→ Stop-Button: POST /api/chat/stop → StreamingTracker.Cancel()
→ CancellationToken durchgereicht bis ToolService → Prozess-Kill
→ client_disconnected
→ Chain + Messages in DB speichern
```
@@ -194,10 +197,11 @@ User-Input → POST /api/chat (SSE)
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, `GET /api/shared/{token}` und Autologin brauchen kein Auth
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. **DefaultPath**: Pro User ein Basis-Ordner (nur vom Admin setzbar), Session-Workspaces sind relativ dazu
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
---