Commit Graph
192 Commits
Author SHA1 Message Date
Meleki 6c38ccfe12 Web-Search: Streaming-Fix (pauseStreamBubble statt resumeStreamBubble), leere Suchergebnisse nicht speichern, Sources auf Shared-Pages anzeigen 2026-03-07 10:46:45 +01:00
Meleki d81dab635a fix(web-search): Text-Bubbles nach Web-Search zu einer Bubble zusammenführen
- history.js: _mergeConsecutiveAssistantTexts überspringt web_search_result
  Messages beim Suchen des vorherigen Text-Blocks, sodass Text vor und
  nach einer Web-Search in der History als eine Bubble gerendert wird
- Text-Blöcke werden mit doppeltem Zeilenumbruch statt Leerzeichen
  zusammengefügt (besseres Markdown-Rendering)
- chat.css: web_search Tool-Box von Opacity-Regel ausgenommen
2026-03-07 10:06:23 +01:00
Meleki f64052caf4 feat: Web-Search Sources anzeigen (Streaming + History + Archive + Shared)
Backend:
- web_search_tool_result Sources extrahieren (url, title)
- Als 'web_search_result' Message-Typ in DB persistieren
- Sources im web_search_end SSE-Event mitsenden
- Alle 3 Chat-Pfade: StreamChat, RunAgentChat, ChatNonStreaming

Frontend:
- renderToolBoxContent: Sources-Sektion mit klickbaren Domain-Links
- finishToolBox/addToolBoxStatic: sources-Parameter durchgereicht
- History: web_search_result Message-Typ in allen 3 Render-Pfaden
- web_search immer sichtbar (auch bei 'modifications' Filter)

CSS:
- .web-search-sources: Flex-Wrap Container
- .web-search-source: Domain-Pill mit Hover-Effekt, Title-Ellipsis
2026-03-07 09:56:09 +01:00
Meleki 116f21105c fix(chat): Web-Search-Streaming – Text-Bubbles nach Search in gleicher Bubble fortsetzen
- chat.js: _afterWebSearch Flag trackt ob gerade eine Web-Search beendet wurde
  - text_start nach Web-Search: resumeStreamBubble() statt neue Bubble
  - web_search_start: Bubble NICHT beenden (bleibt finalisiert im DOM)
  - web_search_end: setzt _afterWebSearch=true
  - Flag wird bei tool_start, review_start, finalizer_start, error, done zurückgesetzt
- ui.js: Neue resumeStreamBubble() Funktion
  - _lastStreamDiv/_lastStreamText speichern letzte finalisierte Bubble
  - resumeStreamBubble() reaktiviert die letzte Bubble zum Weiter-Streamen
  - Verhindert separate Message-Blöcke bei mehrfachen Web-Searches
2026-03-07 09:48:14 +01:00
Meleki 4bec740765 feat: Finalizer-Agent – dritter Agent der nach Worker + Review einschreitet
Backend:
- SessionRecord + DB-Migration: finalizer_agent_id auf sessions
- ChatContext.FinalizerContext (Model, SystemPrompt, Tools, Workspace)
- ChatService: FinalizerContext aufbauen (analog zu ReviewContext)
- AnthropicService: RunFinalizer() nach Review-Phase (oder direkt nach Worker)
- RunReviewAgentChat() refactored zu generischem RunAgentChat()
  mit agentType-Parameter ('review' | 'finalizer') für SSE-Events und DB-Tags
- SSE-Events: finalizer_start, finalizer_text, finalizer_tool_use, finalizer_done

Frontend:
- Session-Page: Finalizer-Agent-Picker (im 'Weitere Einstellungen' Bereich)
- Chat: SSE-Events für Finalizer-Phase verarbeiten
- UI: addReviewBubble/finalizeReviewBubble unterstützen agentType 'finalizer'
  mit eigener Farbe (success-green) und Flag-Checkered-Icon
- renderMarkdown: [Finalizer: AgentName] Tags parsen
- History: Finalizer-Messages als .finalizer-bubble rendern
- Shared-Page: Finalizer-Messages korrekt erkennen und stylen
- Dashboard: Finalizer-Badge (flag-checkered) auf Session-Cards
2026-03-06 23:35:30 +01:00
Meleki bfd78278ab feat: Servereinstellungen-Seite für Admins
- Neuer Endpoint GET/PUT /api/admin/server-settings
  - Liest appsettings.Production.json (Fallback: appsettings.json → Standardwert)
  - Schreibt immer in appsettings.Production.json
  - Definierte Settings: AnthropicToken, MaxIterations, PayloadLogging, PayloadLoggingGzip, KreaToken, KreaApiKey
- Neue Frontend-Seite 'server-settings' (Admin-only)
  - Dynamisches Formular basierend auf Setting-Definitionen vom Backend
  - Password-Felder mit Eye-Toggle, Checkboxen für Booleans, Number-Inputs
  - Hinweis dass Neustart erforderlich ist
- Dashboard: Neuer Link 'Servereinstellungen' für Admins
- appsettings.Production.json vom Publish ausgeschlossen (CopyToPublishDirectory=Never)
2026-03-06 22:32:33 +01:00
Meleki 4775b8ded7 feat: Avatar Position-Offset (translate X/Y)
Backend:
- AgentRecord + SessionRecord: AvatarOffsetX, AvatarOffsetY Properties
- DB-Migration: avatar_offset_x/y REAL DEFAULT 0 auf agents + sessions
- Agent/Session Endpoints: Create + Update lesen/schreiben Offset-Felder
- GetSessionsWithStats: Offset-Felder ans Frontend

Frontend:
- Avatar-Editor: X/Y Offset-Slider (-50% bis +50%) im Modal
  - buildTransformStyle() Helper für transform: scale() translate()
  - getOffsetX()/getOffsetY() Public API
  - Reset bei Clear/AI-Generate/Upload
- ui.js: buildAgentCard + buildSessionCard rendern transform mit Offset
- Agent-Page + Session-Page: initialOffsetX/Y + Save
- CSS: .av-offset-row Styles (gruppiert mit .av-scale-row)
2026-03-06 21:14:51 +01:00
Meleki 6369f7f09c Review-Nachrichten: konsistentes Styling in History, Chat und Shared-Links
- renderMarkdown: [Review: Agent], [Review-Feedback ...], [APPROVED] Tags parsen
  → styled HTML-Header bzw. ausgeblendet (zentral für alle Views)
- history.js: Review-Messages als .review-bubble rendern statt .assistant/.user
  Review-Messages vom Merging ausgenommen
- shared-page.js: Review-Messages erkennen → .review-bubble Klasse
  Merge-Logik schützt Review-Messages vor Zusammenführung
- addReviewBubbleStatic(): Neue Funktion für History-Rendering mit allen
  Buttons (Reply, Delete, Mark, Share)
- chat.css: .review-inline-header, .review-inline-feedback Styles
2026-03-06 17:31:30 +01:00
Meleki 5fe3f8ac87 feat: Review-Agent (Multi-Agent-Kommunikation)
- Session hat optionalen ReviewAgentId + MaxReviewIterations
- Nach end_turn des Worker-Agents wird der Review-Agent aufgerufen
- Review-Agent bekommt Worker-Konversation als Kontext + kann Tools nutzen
- [APPROVED] in Review-Antwort → fertig, sonst Feedback an Worker
- Worker korrigiert und wird erneut reviewed (max N Runden)
- SSE-Events: review_start, review_text, review_tool_use, review_feedback, review_approved
- Chat-UI: Review-Phase als eigene Bubble mit Header, Text, Status
- Session-Page: Review-Agent-Picker (gleicher Agent-Card-Helper)
- Dashboard: Review-Agent-Badge auf Session-Cards
- DB-Migration: review_agent_id, max_review_iterations auf sessions
2026-03-06 16:04:00 +01:00
Meleki 40c8fee531 feat: zuverlässiger Stop-Button für Chat-Streaming
- StreamingTracker: CancellationTokenSource pro Session, Cancel()-Methode
- ChatEndpoint: POST /api/chat/stop Endpoint, linkedCts verknüpft
  Stop-Token mit Client-Disconnect-Token
- AnthropicService: cancellationToken an ExecuteTool durchgereicht
- ToolService: CancellationToken-Parameter, execute-Tool verknüpft
  externen Token mit 180s-Timeout, killt Prozess bei Abbruch
- Frontend: apiStopChat() + stopStreaming() ruft Backend-Stop auf
2026-03-06 15:44:08 +01:00
Meleki 1f5f49228b fix: Krea-Bild-URLs auf /api/images/file/ korrigieren, Thumbnail-Endpoint hinzufügen
- ui.js: [Krea: datei] URLs von /api/skills/krea-api/output/ auf /api/images/file/ geändert
- KreaEndpoint: GET /api/images/file/{filename}/thumb mit gecachten WebP-Thumbnails (320px)
- Thumbnail-Cache in data/cache/images/, analog zum SkillEndpoint
2026-03-06 15:10:26 +01:00
Meleki 1b9cc29421 Admin: Login-Link mit window.location.origin statt Server-Host
- Backend gibt nur Token zurück statt fertigen Link
- Frontend baut Link via window.location.origin zusammen
- Zeigt korrekte Domain/Port statt internes http://127.0.0.1

Backend:
- AdminEndpoint: POST /api/admin/users/{userId}/login-link gibt { token }
- AuthEndpoint: GET /api/auth/autologin?token=xxx setzt Cookie + redirect
- AuthMiddleware: autologin-Route von Auth ausgenommen

Frontend:
- api.js: apiAdminGetLoginLink() Funktion
- admin-page.js: Login-as-User Button → Login-Link Button mit Modal
- form.css: Styling für Login-Link Modal
2026-03-06 14:35:01 +01:00
Meleki eeecd3da62 cleanup: lokale escapeHtml/esc Duplikate entfernt, globale esc() aus ui.js verwenden 2026-03-06 14:24:20 +01:00
Meleki e45498ac50 Session-Cards: buildSessionCard() Helper + Picker-Modal für Cronjob-Formular
- buildSessionCard(session, agent) Helper in ui.js (analog zu buildAgentCard)
  Erzeugt .card mit Avatar, Name, Badges (Agent, Kontext, Telegram) und Meta (Nachrichten, Archiv, Workspace)
- Dashboard refactored: Session-Cards nutzen buildSessionCard() statt inline HTML
- Cronjob-Formular: <select> für Session und Benachrichtigungs-Session durch
  klickbare Session-Cards + Picker-Modal ersetzt
- openSessionPickerModal() mit filterWithAgent-Option (Session-Dropdown nur
  Sessions mit Agent, Notify-Dropdown alle Sessions)
- CSS: .session-select-card und .session-select-change Klassen analog zu agent-*
2026-03-06 14:05:32 +01:00
Meleki 92c20402eb refactor: Agent-Auswahl in Session-Form als Card + Picker-Modal
- buildAgentCard() Helper in ui.js erstellt (wiederverwendbar für Dashboard + Picker)
- Session-Form: select-Dropdown durch klickbare Agent-Card ersetzt
- Agent-Picker-Modal zeigt alle Agents mit identischen Cards wie am Dashboard
- Dashboard refactored: nutzt buildAgentCard() statt dupliziertem Inline-HTML
- Kein duplizierter Code mehr für Agent-Card-Rendering (Badges, Skills, Avatar)
2026-03-06 14:01:27 +01:00
Meleki 011b26c37f feat(telegram): Zugriffskontrolle mit Chat-ID-Whitelist
- TelegramService: IsChatIdAllowed() prüft Owner + Whitelist
- /start von unbekannter ChatId: Zugriff verweigert + ChatId angezeigt
- Owner wird bei Zugriffsanfrage benachrichtigt (Username + ChatId)
- Alle Commands/Messages prüfen Whitelist vor Verarbeitung
- Neues Feld telegram_allowed_chat_ids in sessions-Tabelle
- Frontend: Input für erlaubte Chat-IDs in Session-Telegram-Settings
- API: allowedChatIds in Save/Get durchgereicht
2026-03-06 13:04:02 +01:00
Meleki 34cecd03a1 refactor: Avatar-Editor als wiederverwendbares Modal-Modul
- Neues avatar-editor.js: Upload, Paste, AI-Generate, Scale, Clear in einem Modal
- Session + Agent Pages: ~280 Zeilen doppelter Avatar-Code → je 5 Zeilen AvatarEditor.init/destroy
- Avatar-Preview klickbar → öffnet Modal mit allen Einstellungen
- chat.css: Shared-Content Message-Styling (max-width, border)
2026-03-06 11:55:00 +01:00
Meleki 057d37d76f feat: Avatar Scale (0.5×–3×) + Krea AI Bildgenerierung für Avatare
Backend:
- SessionRecord + AgentRecord: neues Feld AvatarScale (double, Default 1.0)
- DatabaseService: avatar_scale Migration, in Create/Update/GetWithStats
- SessionEndpoint + AgentEndpoint: avatarScale in Create/Update
- api.js: apiKreaStatus(), apiKreaGenerate()

Frontend:
- Session + Agent Templates: Range-Slider (0.5×–3×) in Avatar-Section
- Krea AI Generate: Prompt-Input + Magic-Button (nur wenn KreaToken konfiguriert)
- Live-Preview: transform: scale() auf Avatar-Vorschau
- Dashboard: scale() auf Session- und Agent-Card-Images
- form.css: avatar-scale-row + avatar-ai-section Styling
2026-03-06 10:59:09 +01:00
Meleki 4ebbeaa818 feat: shared-page message merging + UI reorganization
Shared Page:
- Merge consecutive assistant text messages (same iteration)
- Add iteration field to thread API response
- Unified rendering for single/thread messages

UI Reorganization (manual changes):
- Session + Agent forms: collapsible 'Weitere Einstellungen' section
- Agent defaults: tool_choice unchecked, web_search 2025, model opus-4-6
- Profile: default-path field hidden, divider removed
- Form spacing adjustments, .more toggle style
2026-03-06 08:52:27 +01:00
Meleki 4e1ed81f37 feat: DefaultPath als Base-Path für User-Workspaces
- WorkspaceHelper.cs: Zentrale Workspace-Auflösung (relativ → absolut)
- Session-Workspace wird relativ zum User-DefaultPath gespeichert
- System-Prompt bekommt aufgelösten absoluten Pfad
- Path-Traversal-Schutz: '..' in Workspace-Pfaden blockiert
- Browse-API gibt '..' nicht mehr als Eintrag zurück
- Folder-Browser: basePath-Limit, Back-Button navigiert zum Parent
- DefaultPath nur durch Admin bearbeitbar (Profil: readonly)
- Legacy: Absolute Pfade in session.Workspace weiterhin kompatibel
2026-03-05 22:49:09 +01:00
Meleki 8e7bda50f9 feat: Ordner erstellen/löschen im File Explorer
Backend (WorkspaceEndpoint.cs):
- POST /api/workspace/mkdir – Ordner im Session-Workspace erstellen
- DELETE /api/workspace/dir – Leeren Ordner im Session-Workspace löschen
- POST /api/workspace/agent/mkdir – Ordner im Agent-Memory erstellen
- DELETE /api/workspace/agent/dir – Leeren Ordner im Agent-Memory löschen
- POST /api/workspace/browse/mkdir – Ordner im Folder-Browser erstellen
- Sicherheit: Path-Traversal-Schutz, Root nicht löschbar, nicht-leer → 409

Frontend (file-explorer.js):
- 📁+ Button im Header für neuen Ordner (File Explorer + Folder Browser)
- 🗑️ Button bei jedem Ordner (erscheint on hover, nur File Explorer)
- Validierung: ungültige Zeichen werden abgelehnt

CSS:
- base.css: Icon-Button mit zwei Icons (folder + plus)
- file-explorer.css: Ordner-Zeile als Flex (Label + Delete-Button)
2026-03-05 21:01:09 +01:00
Meleki d1355dcb0d feat: Login-as-User (Impersonate) + Default-Path pro User
Admin:
- POST /api/admin/users/{userId}/impersonate – erstellt Token für Zieluser
- Login-as-Button (fa-sign-in) in User-Liste (nicht für sich selbst)
- confirm-Dialog, danach location.reload() mit neuem User-Kontext
- Default-Path Feld + Browse-Button im Admin-Formular

Default-Path:
- Neues Feld default_path in users-Tabelle (TryAddColumn Migration)
- UserRecord.DefaultPath Property
- In allen Endpoints: Admin CRUD, Auth /me, Profile Get/Update
- Profil-Seite: Default-Path Feld + Browse-Button
- Session-Seite: Workspace-Browse nutzt defaultPath als Fallback
2026-03-05 20:42:21 +01:00
Meleki df68843e82 feat: EasyMDE-Editor für Persona und Session-Kontext
- profile-page.js: #profilePersona textarea → EasyMDE mit Toolbar und Dark-Theme
- session-page.js: #sessionContext textarea → EasyMDE mit Toolbar und Dark-Theme
- form.css: Override-Styles für EasyMDE in Formularen (height: auto, border-radius)
- base.css: ul margin-left für korrekte Listen-Einrückung
- Beide Editoren: sauberes Cleanup via toTextArea() in destroy()
- Nutzt bestehende fe-mde-wrap Styles aus file-explorer.css
2026-03-05 20:24:30 +01:00
Meleki 9140c4fcc7 feat(dashboard): klickbare Session-Cards + UI-Verbesserungen
- Session-Cards mit Agent sind klickbar (navigiert zum Chat)
- Card-Menü bleibt nutzbar via pointer-events Logik
- Menü-Reihenfolge: Bearbeiten vor Chat öffnen
- Session-Beschreibung: textarea → input (einzeilig)
- Globale Link-Styles (a { color: var(--primary) })
2026-03-05 19:50:43 +01:00
Meleki 3ef78b5eb1 feat: Admin-Benutzerverwaltung + Dashboard-Layout-Fixes
Backend:
- AdminEndpoint.cs: 5 Endpunkte (List, Create, Update, Reset PW, Delete) - Admin-only
- DatabaseService: CreateUser(), UpdateUserAdmin(), DeleteUser() (kaskadiert Tokens + Shares)
- Route in Program.cs registriert

Frontend:
- admin-page.js: User-Liste mit Edit/Delete, Inline-Formular Create/Edit
- api.js: 5 Admin-API-Funktionen
- index.html: Template tpl-admin, Script-Tag, Dashboard-Link 'Benutzerverwaltung'
- dashboard.js: Admin-Link nur für Admins sichtbar
- form.css: Styles für admin-user-list, admin-user-row, admin-checkbox-row
- dashboard.css: Header-Overflow-Fix, Agents vor Cronjobs
- index.html: Template-Reihenfolge Agents vor Cronjobs

TODO: User-Management als erledigt markiert
2026-03-05 19:19:16 +01:00
Meleki 489b5e0eb0 feat: Timestamps + LaTeX/KaTeX-Rendering im Chat
Timestamps (dd.MM.yyyy HH:mm:ss):
- Neuer _formatTimestamp() + _addTimestamp() Helper in ui.js
- Timestamp bei allen User- und Assistant-Nachrichten (live, history, archiv)
- Erscheint on hover, halbtransparent, rechts oben an der Bubble

LaTeX/Math-Rendering mit KaTeX 0.16.21:
- KaTeX lokal eingebunden (JS + CSS + 21 woff2-Fonts)
- renderMarkdown() schützt LaTeX vor Markdown-Parsing
- $$...$$ → Block-Math (zentriert), $...$ → Inline-Math
- Fehlerhafte Ausdrücke als <code> Fallback
- KaTeX-Display Styling in markdown.css

Weitere Änderungen:
- theme.css: Neue --info Farbe
- Blockquote-Styling: info-Farbe statt halbtransparent
2026-03-05 18:25:03 +01:00
Meleki dbeba6535a fix: Nachrichtenanzahl zählt nur text-Messages, keine tool_use/tool_result
- 5 SQL COUNT-Queries mit 'type = text' Filter versehen:
  - GetSessionsWithStats (activeCount + totalCount)
  - GetActiveMessageCount
  - GetActiveMessageCountBeforeId
  - CreateArchive (messageCount)
- Dashboard: Aktive und archivierte Nachrichten separat angezeigt
- ArchiveMessageCount als eigenes Feld im Session-DTO
- TODO.md: Nachrichtenzählung-Bug als erledigt markiert
2026-03-05 16:33:03 +01:00
Meleki 8a9293218b refactor: Shared Links als Card-Grid mit Card-Menü (wie Cronjobs)
- index.html: shared-links-list → card-grid
- dashboard.js: Cards mit card-compact, card-menu-dropdown, fa-cog statt fa-robot
- dashboard.css: 60 Zeilen shared-link-*/danger-icon CSS entfernt (nutzt card-Styles)
2026-03-05 15:11:05 +01:00
Meleki 38a8223228 feat: Geteilte Links auf Dashboard anzeigen + URL-Fix
Dashboard:
- Neue Section 'Geteilte Links' zeigt alle aktiven Shares
- Pro Eintrag: Role-Icon, Text-Vorschau, Session-Name, Modus, Datum
- Buttons: Link kopieren, öffnen, löschen (mit sofortigem UI-Update)
- Section nur sichtbar wenn Shares vorhanden

Backend:
- SharedEndpoint HandleListShares erweitert: Nachricht-Preview,
  Role, Session-Name pro Share mitgeliefert

Frontend:
- apiListShares() Funktion hinzugefügt
- Bugfix: Share-URL '/#/shared/' → '/#shared/' (Extra-Slash
  verursachte 404 weil parseHash leeren Page-Namen ergab)
2026-03-05 12:01:28 +01:00
Meleki be29984b25 feat: Einzelne Nachrichten als Link teilen
Backend:
- SharedMessageRecord Model + shared_messages DB-Tabelle
- SharedEndpoint: POST /api/messages/{id}/share, GET /api/shared/{token},
  GET /api/shared (Liste), DELETE /api/shared/{token}
- Auth-Ausnahme für GET /api/shared/{token} (öffentlich ohne Login)
- DB-Methoden: CreateSharedMessage, GetSharedMessage, GetChainMessagesUpTo

Frontend:
- Share-Button (fa-share-alt) an jeder Nachricht
- Kontextmenü: Einzelnachricht oder mit Thread-Kontext teilen
- Link wird automatisch in Zwischenablage kopiert
- Öffentliche Shared-Page (#shared/{token}) ohne Login
- Markdown-Rendering in der geteilten Ansicht
- CSS für Share-Button, Share-Menü und Shared-Page
2026-03-04 23:34:00 +01:00
Meleki f552b44b05 feat: payload logging (on/off + gzip) via appsettings + fix destroy messages ref 2026-03-04 16:10:09 +01:00
Meleki 8fc29c82d9 refactor: Chat-Payload vereinfacht + Inline-Bilder statt Platzhalter
Backend:
- ChatEndpoint empfängt nur noch content + sessionId (nicht mehr die gesamte History)
- History wird komplett aus DB aufgebaut via BuildHistoryFromDb
- Gelöschte Nachrichten (deleted_on) werden aus History gefiltert
- Leere Nachrichten werden übersprungen (kein API 400 mehr)
- BuildHistoryFromDb optimiert: nur Text für ältere Chains, Tool-Calls nur für aktuelle Chain
- GetChainMessages: includeDeleted-Parameter (Default: false)
- Archiv-Export nutzt includeDeleted: true

Frontend:
- messages[]-Array komplett entfernt (kein Client-seitiger History-State mehr)
- apiChat() sendet nur content + sessionId
- Inline-Bilder: [Bild: name] wird durch <img> ersetzt (live mit DataURL, History per API-Nachladen)
- _autoLoadImageAttachments() für History/Archiv/ältere Nachrichten
- Klick auf Inline-Bild öffnet Vollbild-Modal
2026-03-04 14:29:33 +01:00
Meleki 07ea0fcafb Zeilenreferenz-Hinweis (cat -n) aus System-Prompt entfernt und automatisch an User-Nachricht angehängt
- System-Prompt: 3x cat-n Hinweise entfernt (Workspace-Block, toolAny-Erinnerung, Workspace-Erinnerung)
- chat.js: <hint> Tag mit cat-n Hinweis wird automatisch angehängt wenn Datei-Refs Zeilennummern haben
- chat.js: Einzelne Zeilen (path:11) werden jetzt korrekt geparst und angezeigt
- chat.css: hint Tag Styling, file-ref-chip Spacing angepasst
2026-03-04 11:59:19 +01:00
Meleki d88b046575 UI: Cronjob-Formular Layout-Verbesserungen
- form-container Wrapper entfernt, flache Struktur
- Aktiv-Checkbox nach oben verschoben
- .secondary-btn durch .positive-btn ersetzt (currentcolor)
- .danger-btn nutzt currentcolor für Border
- .form-group mit Padding, leere Status-Box wird versteckt
- .skill-name entfernt (ungenutzt)
- Status-Box: <br> durch inline-spans ersetzt
- Button-Icons bei Speichern/Löschen entfernt
2026-03-04 10:33:32 +01:00
Meleki b645625b56 Cronjobs + AnthropicService Singleton Refactoring
Cronjobs:
- CronjobService (BackgroundService) prüft jede Minute auf fällige Jobs
- Cron-Expression in Server-Lokalzeit via Cronos (CronFormat.Standard)
- Cronjob-Ausführung: Prompt → Session → Agent-Antwort in Chat-History
- Optionale Benachrichtigungs-Session (notify_session_id): Zusammenfassung
  wird in separate Session geschrieben (z.B. mit Telegram)
- Telegram-Benachrichtigung mit Cronjob-Name + Ursprungs-Session
- REST API: CRUD + toggle + manuelles Ausführen (/run)
- Frontend: Dashboard-Cards, Cronjob-Formular mit Cron-Vorschau,
  Session-Dropdown, Notify-Session-Dropdown, Status-Box

Refactoring:
- AnthropicService als Singleton in DI registriert
- ChatEndpoint + TelegramService nutzen injizierte Instanz
- Redundante Dependencies (Token, ToolService, MemoryService) entfernt

Neue Dateien:
- Models/CronjobRecord.cs
- Services/CronjobService.cs
- Endpoints/CronjobEndpoint.cs
- wwwroot/js/pages/cronjob-page.js
- PLAN-Cronjob.md
2026-03-03 22:44:46 +01:00
Meleki 0120bb8f73 Telegram: Bot=Session statt User-Level, Chat-Code-Refactoring
- Telegram-Config (Bot-Token, Webhook-Secret, ChatId) von User-Settings
  in sessions-Tabelle verschoben → jede Session hat ihren eigenen Bot
- Link-Code-System komplett entfernt (TelegramLinkRecord gelöscht)
- /start verknüpft automatisch, kein /link mehr nötig
- Alle Endpoints session-basiert: /api/sessions/{id}/telegram/*
- Webhook-URL pro Session: /api/telegram/webhook/{sessionId}

Refactoring: Doppelten Chat-Code eliminiert
- Neuer ChatService: PrepareContext, BuildHistoryFromDb, ResolveModelId
- Neues ChatContext-Model als gemeinsame Datenstruktur
- AnthropicService.ChatNonStreaming() für Telegram (statt eigenem Loop)
- TelegramService um ~180 Zeilen reduziert, kein eigener Claude-Loop mehr
- ChatEndpoint nutzt ChatService.PrepareContext() statt eigener Setup-Logik
- Model-Mapping nur noch an einer Stelle (3x → 1x)

Frontend
- Telegram-Section von Settings-Page in Session-Bearbeitungsseite verschoben
- Webhook-Secret readonly, wird einmalig generiert und persistent gespeichert
- Status wird automatisch geladen, Register/Delete je nach Webhook-Status
- Toast-Notification-System (showToast) in ui.js
- Link-Code-Modal und Telegram-Menüpunkt im Dashboard entfernt
- Telegram-Badge auf Session-Cards (konfiguriert/verbunden)

Bugfix: Bearer statt x-api-key für OAuth-Tokens im TelegramService
2026-03-03 21:46:59 +01:00
Meleki a0752ea492 feat: Settings in Datenbank speichern statt localStorage
- Neue Spalte 'settings' in users-Tabelle (Migration via TryAddColumn)
- SettingsEndpoint: GET/PUT /api/settings
- DatabaseService: GetUserSettings() + UpdateUserSettings()
- Frontend: currentSettings als globaler State in app.js
- settings-page.js: localStorage komplett entfernt, nutzt API
- Settings werden beim App-Start aus DB geladen und angewendet
2026-03-03 16:47:56 +01:00
Meleki c9c15279d5 Claude-Statusbar global auf allen Seiten anzeigen + Schließen-Button
- #claudeStatusBar aus Dashboard-Template nach body verschoben (vor #app)
- loadClaudeStatus() von dashboard.js nach app.js (einmalig beim Start)
- Schließen-Button (×) zum Ausblenden der Statusbar
- Status-Bar CSS von dashboard.css nach main.css verschoben
2026-03-03 16:25:23 +01:00
Meleki 2673aecc5b feat: Emoji-Picker Button im Chat-Input (rechts neben Senden)
- #emojiBtn links neben #send platziert
- Fluent Emoji 3D Rendering via parseFluentEmojis()
- Kein Tooltip auf den Emoji-Buttons
- Picker öffnet sich rechts-ausgerichtet über dem Button
- emoji.userdata.js geladen (Kategorien + Mappings)
- Schließt beim Klick außerhalb oder beim destroy()
2026-03-03 16:18:00 +01:00
Meleki c720a06c16 feat: todo_write tool-box mit custom parser, kein input, standardmäßig sichtbar 2026-03-03 14:50:22 +01:00
Meleki a14a991a0f feat: Nachrichten als gelöscht markieren
- DB: deleted_on TEXT Spalte in messages (Migration)
- Backend: ToggleMessageDelete(), includeDeleted-Parameter in allen History-Queries
- Neuer Endpoint: PUT /api/messages/{id}/delete
- Frontend: Trash-Button zwischen Reply- und Mark-Button
- Gelöschte Nachrichten: durchgestrichen + roter Rand (oder versteckt je nach Einstellung)
- Einstellungen: Toggle-Switch 'Gelöschte Nachrichten anzeigen'
- KI-Payload: gelöschte Nachrichten werden nicht mitgeschickt
2026-03-03 11:45:52 +01:00
Meleki 493dfcda1c fix: various small fixes (TODO, CSS z-index, telegram status styling, settings prompt) 2026-03-03 10:30:36 +01:00
Meleki 0c4d32de0f fix: Backup-Download (0 Bytes + fehlender Dateiname)
- api.js: credentials: 'include' hinzugefügt (Auth-Cookie)
- BackupEndpoint.cs: Task<IResult> → Task mit direktem Response-Handling
  (ASP.NET hat IResult nicht korrekt verarbeitet → leerer Body)
2026-03-03 10:01:30 +01:00
Meleki a32de29d25 style: Card-Dropdown öffnet nach links unten statt rechts
- Position: unterhalb des Trigger-Buttons
- Rechte Kante des Dropdowns an rechter Kante des Buttons ausgerichtet
- Fallback: nach oben wenn unten kein Platz
2026-03-03 09:29:58 +01:00
Meleki e2927893f7 style: Card-Dropdown öffnet nach rechts statt unten
- Position: rechts neben dem Trigger-Button (gleiche Höhe)
- Fallback: links öffnen wenn rechts kein Platz
- Viewport-Overflow-Check für unten und links
2026-03-03 09:27:09 +01:00
Meleki 90afd79e76 fix: Dashboard Card-Dropdown nicht mehr abgeschnitten
- CSS: position: fixed statt absolute, z-index: 1000, box-shadow
- JS: Position dynamisch berechnet (getBoundingClientRect) beim Öffnen
- Viewport-Overflow-Korrektur falls Dropdown zu weit rechts/links
2026-03-03 09:24:26 +01:00
Meleki 4fa0111c33 feat: Erweiterte Model-Auswahl für Agents
- Model-Optionen: sonnet-4-5, sonnet-4-6, opus-4-5, opus-4-6, haiku-4-5
- ChatEndpoint + TelegramService: Model-Mapping für alle Varianten
- Agent-Formular: Dropdown mit allen Model-Versionen
- ui.js: prettyModelName() vereinfacht für neue Model-Werte
2026-03-03 09:22:47 +01:00
Meleki e5d76bb0a9 fix: credentials: include bei allen Telegram API-Requests 2026-03-03 09:09:15 +01:00
Meleki 4ac042e512 Telegram: Webhook-Verwaltung in Einstellungen-Seite
- Backend: DELETE /api/telegram/webhook Endpoint + TelegramService.DeleteWebhook()
- api.js: apiTelegramWebhookInfo(), apiTelegramRegisterWebhook(), apiTelegramDeleteWebhook()
- Settings-Page: Neue 'Telegram Bot' Section (nur für Admins, nur wenn konfiguriert)
  - Status abrufen: Webhook-URL, ausstehende Updates, letzter Fehler, Aktiv-Badge
  - Webhook registrieren: prompt() für Base-URL, POST an Telegram API
  - Webhook entfernen: Bestätigungsdialog + DELETE
- CSS: .telegram-status-box, .tg-status-row, .tg-label, .tg-value, .tg-badge
2026-03-03 09:06:22 +01:00
Meleki 7d237c866a Dashboard: Telegram-Verknüpfung Button + Modal
- Session-Card-Menü: 'Telegram verknüpfen' zwischen Chat öffnen und Bearbeiten
- Button nur sichtbar wenn Telegram Bot konfiguriert (GET /api/telegram/status)
- Klick generiert 6-stelligen Link-Code (POST /api/telegram/link)
- Modal zeigt '/link CODE' mit Copy-Button, 5 Min gültig
- Neuer Backend-Endpoint GET /api/telegram/status (IsConfigured)
- API-Funktionen: apiTelegramStatus(), apiTelegramLink()
- Modal-CSS nach bestehendem .fe-overlay Pattern
2026-03-03 07:40:17 +01:00