Commit Graph
102 Commits
Author SHA1 Message Date
Meleki 83945689a6 Remove tool_choice agent option - auto-detect based on workspace/skills/memory
- Remove tool_choice from AgentEndpoint (create, update, list responses)
- ChatService: automatically set tool_choice='any' when workspace, memory
  or skills present, null otherwise. Same for preparer/review/finalizer
- SystemPromptBuilder: remove 3 toolAny-conditional prompt blocks
  (KRITISCH, Verhalten, ERINNERUNG)
- Frontend: remove checkbox, badge and JS references
- Agent.ToolChoice DB field preserved for backward compat, no longer read
2026-03-09 05:39:09 +01:00
Meleki 4f847bd33d Telegram: Auto-Link bei /start und normalen Nachrichten
Wenn eine Telegram-Nachricht von einem nicht verknüpften Chat eingeht:
- Sucht nach Sessions mit diesem Bot, die noch keine Chat-ID haben
- Genau 1 unverknüpfte Session → automatisch zuweisen + Bestätigung
- 0 oder mehrere → Chat-ID anzeigen, manuell im Web-UI zuweisen

Neue DB-Methode: FindUnlinkedSessionsForBot(botId)
2026-03-08 23:00:13 +01:00
Meleki bed4b1687e fix: openclaw-import Messages aus LLM-History nicht mehr ausfiltern
Der Tag-Filter in BuildHistoryFromDb filterte alle Messages mit Tag
aus, sofern der Tag nicht dem angeforderten includeTag entsprach.
openclaw-import ist jedoch kein Sub-Agent-Tag (wie preparer/review/
finalizer), sondern ein Herkunfts-Tag und muss immer in der History
enthalten sein.
2026-03-08 20:41:32 +01:00
Meleki b0d8bef5ea feat: Public-Flag für Agents + verfügbare Agents/Bots Endpoints erweitert
- AgentRecord: neues IsPublic-Feld mit DB-Migration
- GET /api/agents/available: eigene + public Agents (alle Properties + isOwner)
- GET /api/telegram/bots/available: alle Properties außer Token/Secret + sessionCount
- Agent-Page: Public-Checkbox (andere User können Agent in Sessions verwenden)
- Dashboard: agentMap aus availableAgents gebaut (public Agents fremder User auflösbar)
- Session-Page + Cronjob-Page: Agent-Picker nutzt /available statt /agents
- Agent-Cards: Public- und Fremd-Badges
- Fix: Chat-Button bei Sessions mit public Agent eines anderen Users nicht mehr disabled
2026-03-08 20:25:52 +01:00
Meleki ec73ccd71e Telegram Bots als eigenständige Entität mit eigener Page
- Neue Tabelle 'telegram_bots' (bot_id, name, bot_token, webhook_secret, is_public)
- Automatische Migration bestehender Session-Telegram-Configs in telegram_bots
- Sessions verweisen via telegram_bot_id auf Bot (mehrere Sessions pro Bot möglich)
- Webhook-URL: /api/telegram/webhook/{botId} statt {sessionId}
- Eigene Telegram-Bot-Page (wie Agent/Cronjob/Session) statt Modal
- Bot-Page: Name, Token, Secret, Webhook-Verwaltung (registrieren/status/entfernen), Löschen
- Dashboard: Telegram Bots Section mit Cards (Name, maskierter Token, Session-Count)
- Session-Page: Bot-Picker (wie Agent-Picker) statt Token-Input, Chat-ID readonly + Unlink-Button
- Public-Flag: Bot kann von anderen Usern in ihren Sessions ausgewählt werden
- Vereinfacht: 1 Session = max. 1 Telegram Chat, allowed_chat_ids entfällt
- /start zeigt Chat-ID an, /unlink entfernt (Unlink nur über Web-UI)
- Nachrichten-Routing: Bot + Chat-ID → Session Lookup
2026-03-08 19:27:05 +01:00
Meleki 3b7bdb7a20 feat: OpenClaw session import with sorted history
Backend:
- New OpenClawEndpoint with GET /api/openclaw/sessions and POST /api/openclaw/import
- Lists all OpenClaw sessions with preview messages, model, summary
- Imports user/assistant text messages (skips tool-use/tool-result)
- Cleans user messages (removes webchat prefixes, cron tags, conversation info blocks)
- Re-import support: deletes previous openclaw-import chains before importing
- New DatabaseService methods: CreateChainForImport, CreateMessageForImport, DeleteOpenClawImport
- Added SortKey to MessageRecord (computed: openclaw-import gets id-10B, else id)

History sorting:
- OpenClaw-imported messages always appear before native messages
- Sort by CASE WHEN tag='openclaw-import' THEN id-10000000000 ELSE id END
- Cursor-based paging updated from beforeId/afterId to beforeSortKey/afterSortKey
- All history queries (GetLatestActive, Before, After, CountBefore) updated

Frontend:
- Dashboard: new 'OpenClaw Import' menu item in session card dropdown
- Modal: shows OpenClaw sessions with metadata, summary, preview messages
- Imported messages display blue 'OC' badge in chat
- API functions: apiGetOpenclawSessions, apiImportOpenclawSession
- History paging updated to use sortKey cursors
2026-03-08 17:32:32 +01:00
Meleki 1597c10a3c Review-Agent: [FEEDBACK]-Tag in Markdown ausblenden + Kommentar aktualisiert 2026-03-08 15:17:11 +01:00
Meleki 1fc6889ced Review-Agent: Default=Approved + vollständige Tool-Boxes für Sub-Agents
Backend:
- Review-Agent: Default = Approved (analog zum Preparer Default=Forward)
  Nur bei explizitem [FEEDBACK]-Tag wird Feedback zurückgespielt
  Verhindert Loop wenn Review-Agent bestätigt ohne [APPROVED]-Tag
- Neues SSE-Event {agentType}_tool_end für Sub-Agent Tool-Ergebnisse
  Sendet toolName, input, result, isError nach Tool-Ausführung

Frontend Streaming (stream-ui.js + chat.js):
- addReviewToolUse: Vollständige Tool-Box mit Loading-Spinner statt nur Name
- finishReviewToolBox: Befüllt Tool-Box nach tool_end mit Details (Pfad, Diff, Result)
- Event-Handler für preparer/review/finalizer_tool_end

Frontend History (history.js):
- _renderReviewGroup: Vollständige Tool-Boxes statt einfache Tool-Use-Indikatoren
- Tool-Result Look-Ahead für korrekte Zuordnung (toolCallId-Match)
- Web-Search-Sources in Review-Bubbles unterstützt
- Tool-Visibility-Filter (isToolVisible) auch für Sub-Agent-Tools

CSS:
- .review-tool-use → .review-tool-box (erbt normale Tool-Box-Styles)
2026-03-08 15:08:59 +01:00
Meleki f3b6491643 Review-Agent: nur Text-Konversation übergeben + Doku aktualisiert
BuildReviewMessages() komplett umgebaut:
- Tool-Calls und Tool-Results werden nicht mehr übergeben
- Nur noch die reine Text-Konversation (user/assistant) wird extrahiert
- Aufeinanderfolgende Messages gleicher Rolle werden zusammengeführt
- Korrekte user/assistant-Abwechslung sichergestellt
- Fallback wenn nur Tool-Calls ohne Text vorhanden
- Unnötigen Serialisierungs-Roundtrip für Rollen-Prüfung entfernt

Erwartete Token-Ersparnis: 50-100k+ Input-Tokens pro Review-Runde
bei typischen Worker-Sessions mit vielen write_file/edit_file-Calls.

ARCHITECTURE.md:
- Inhaltsverzeichnis-Nummerierung korrigiert (22-28 statt doppelt 20-21)
- ServerSettingsEndpoint.cs in Projektstruktur ergänzt
- Tabellenbeschreibungen vervollständigt (users, agents, sessions, chains,
  messages, cronjobs) mit allen fehlenden Feldern
- ChainRecord/MessageRecord/SessionWithStats Felder aktualisiert
- AutoCommit mention-Beschreibung korrigiert

ARCHITECTURE_QUICK.md:
- ToolService 12 → 13 Tools korrigiert
- Tabellenbeschreibungen analog zur Hauptdoku aktualisiert
2026-03-08 00:50:29 +01:00
Meleki 9abb5fd217 fix: esc() Quote-Escaping für Attribut-Kontexte + cache_control für Sub-Agents/Telegram
- esc() um "→" Escaping erweitert (Bug: Anführungszeichen in value="..."-Attributen brachen HTML)
- cache_control: ephemeral zu RunAgentChat() hinzugefügt (Preparer/Review/Finalizer hatten kein Prompt Caching)
- cache_control: ephemeral zu ChatNonStreaming() hinzugefügt (Telegram hatte kein Prompt Caching)
- Trailing-Leerzeile in commands-ui.js bereinigt
2026-03-07 22:42:20 +01:00
Meleki 2a2e98ca68 feat: Thumbnail-Varianten (256px) für Agent-Avatare und Session-Images
- ImageService: ResizeDataUrlSmall() für 256px WebP-Thumbnails (Quality 70)
- Neue DB-Spalten: agents.avatar_small, sessions.image_small
- Migration generiert Thumbnails für bestehende Bilder automatisch
- Listen-Endpoints (/api/agents, /api/sessions) liefern kleine Variante
- Detail-Endpoints liefern weiterhin das volle 512px-Bild
- Frontend unverändert (Cards nutzen automatisch die kleineren Bilder)
2026-03-07 20:09:01 +01:00
Meleki 8efce5f2d5 Bilder auf WebP umstellen: ImageService + DB-Migration
- ImageService: PNG-Encoder durch WebP-Encoder ersetzt (Quality 80)
- Bilder werden jetzt immer zu WebP konvertiert (auch kleine)
- DB-Migration: Bestehende PNG/JPEG-Avatare und Session-Images
  automatisch zu WebP konvertiert beim Start
- Migration ist idempotent (überspringt bereits konvertierte Bilder)
- Kein Frontend-Code betroffen (Data-URLs sind format-agnostisch)
2026-03-07 19:50:03 +01:00
Meleki 11acfde081 Dashboard-Performance: API-Endpoints konsolidieren
Backend:
- GET /api/sessions: Git-Status inline integriert (parallel pro Session)
  - Neue Hilfsmethoden GetGitStatusSummaryAsync (Counts) und
    GetGitStatusDetailedAsync (Dateinamen, für Einzel-Endpoint)
  - GetSessionsWithStats gibt typisierte SessionWithStats zurück
  - Neue Models: SessionWithStats, GitStatusSummary
- GET /api/agents: Skills inline pro Agent integriert
  - SkillService als Parameter in HandleList
  - Skills als Array mit slug/name/description

Frontend:
- Dashboard: 1 paralleler Promise.all statt sequentieller Requests
  - Vorher: agents → sessions → N×git-status → M×agent-skills → cronjobs → shares
  - Nachher: Promise.all([agents, sessions, cronjobs, shares]) (4 Requests)
  - Git-Status direkt aus Session-Response, Skills aus Agent-Response
- Session-Page: Agent-Skills aus inline-Daten statt N×apiGetAgentSkills

Reduziert Dashboard-Requests von ~4+N+M auf 4 (fix).
2026-03-07 19:40:26 +01:00
Meleki 4f027360fd feat: Anweisungen-Feld für Agents mit EasyMDE-Editor
- AgentRecord: TaskInstruction (string, nullable)
- DB-Migration: task_instruction TEXT Spalte
- AgentEndpoint: Create/Update lesen taskInstruction
- SystemPromptBuilder: '## Anweisungen' Block nach Soul, nur wenn nicht leer
- HTML: Textarea #agentTaskInstruction nach Rückfragen-Checkbox
- agent-page.js: EasyMDE-Editor mit Init, Laden, Speichern, Destroy
2026-03-07 17:20:38 +01:00
Meleki 14e721f95b fix(preparer): Logik invertiert - Default=Forward, [QUESTION]=Stopp
Kernproblem: Claude vergisst [FORWARD]-Tag → Preparer leitet nie weiter.

Lösung - Logik umgedreht:
- Jede Antwort wird automatisch an Session-Agent weitergeleitet (Default)
- Nur bei explizitem [QUESTION]-Tag wird gestoppt (Rückfrage an User)
- [FORWARD] wird weiterhin erkannt und entfernt, ist aber optional

Weitere Fixes:
- Preparer bekommt eigene History mit includeTag='preparer',
  damit er den Kontext seiner vorherigen Rückfragen sieht
- Session-Agent bekommt saubere History ohne Sub-Agent-Messages
  (nach Preparer-Phase frisch aus DB geladen)
- [QUESTION] wird im Frontend-Markdown ausgeblendet
2026-03-07 16:35:29 +01:00
Meleki 43d3e9dc26 fix: Tag-Feld für Sub-Agent-Messages – verhindert API 400 bei tool_use ohne tool_result
- MessageRecord: neues Tag-Feld (null=normal, preparer/review/finalizer=Sub-Agent)
- DatabaseService: Migration tag-Spalte, INSERT-Statements erweitert
- AnthropicService: RunAgentChat setzt Tag=agentType bei allen 4 SaveMessage-Aufrufen
- ChatService: BuildHistoryFromDb filtert getaggte Messages aus API-History

Sub-Agent-Messages bleiben in der DB (Frontend-Anzeige), werden aber
nie an die Claude API geschickt – löst das Problem für Preparer,
Review und Finalizer gleichermaßen.
2026-03-07 15:37:28 +01:00
Meleki 494f431963 feat: Vorbereiter-Agent (Preparer) für Sessions
- Neues optionales Session-Feld 'preparerAgentId' (DB + Model + API)
- PreparerContext im ChatContext für Agent-Konfiguration
- RunPreparer() in AnthropicService: führt Preparer vor dem Worker aus
  - [FORWARD] → aufbereiteter Prompt wird an Session-Agent weitergegeben
  - Ohne [FORWARD] → Rückfrage an User, Flow stoppt (preparer_query)
- Preparer-System-Prompt: erklärt Rolle, [FORWARD]-Mechanismus, Vorarbeit
- Preparer kann eigene Tools + Fähigkeiten aktiv nutzen
- ChatEndpoint: Preparer-Phase vor StreamChat integriert
- Frontend: SSE-Events (preparer_start/text/tool_use/done)
- Preparer-Bubble (Info-Farbe) mit Status Weitergeleitet/Rückfrage
- [Preparer: Name] → hübscher Header, [FORWARD] ausgeblendet
- [Vorbereitet von Name] → dezenter Header in User-Bubble
- Agent-Picker im Session-Form (vor Review-Agent)
2026-03-07 15:23:22 +01:00
Meleki 55cbf02ed2 fix: Plan-Modus – execute-Tool als readonly erlauben + Plaintext-Endpoint planMode-Parameter
- ToolService: execute in ReadOnlyToolNames aufgenommen
- SystemPromptBuilder: Plan-Modus Tools-Text um execute ergänzt
- SessionEndpoint: HandleSystemPrompt liest planMode Query-Parameter
2026-03-07 12:29:16 +01:00
Meleki 8e0ae90dc6 Plan-Modus: System-Prompt-Blöcke kontextabhängig anpassen
- SystemPromptBuilder.BuildBlocks/Build bekommt planMode-Parameter
- Im Plan-Modus: Tools-Block zeigt nur Read-only-Tools (read_file, list_files, glob, grep)
- Im Plan-Modus: KRITISCH, Verhalten, Erinnerung und Git-Blöcke werden übersprungen
- Im Plan-Modus: Skills als 'nicht ausführbar' markiert
- Plan-Modus-Block zentral im SystemPromptBuilder statt doppelt in AnthropicService + SessionEndpoint
- ChatService reicht planMode an SystemPromptBuilder durch
- SessionEndpoint reicht planMode Query-Parameter an BuildBlocks durch
- System-Prompt-Modal zeigt korrekte Blöcke je nach Plan-Modus-Status
2026-03-07 12:20:44 +01:00
Meleki 6d95f9aec2 feat: Plan-Modus – Toggle im Chat zum Umschalten zwischen Plan/Ausführung
- Toggle-Button (🗺️) im Chat-Input-Bereich neben Explorer
- Plan-Modus wird per ChatRequest.planMode an Backend gesendet
- Backend: Write-Tools gefiltert (nur read_file, list_files, glob, grep,
  todo_write, memory_*, ask_user_choice bleiben), System-Prompt-Block
  ergänzt der Änderungen verbietet, tool_choice nie 'any' erzwungen
- ChainRecord.PlanMode: pro Chain gespeichert (informativ für History)
- Chain-Meta-Badge '📋 Plan-Modus' bei Plan-Chains
- Choice-Response erbt planMode vom vorherigen Chain
- CSS: .plan-mode-active Styling (Primary-Color Highlight)
- Placeholder wechselt zu 'Plannen...' wenn aktiv
- Plan-Modus wird bei Session-Wechsel zurückgesetzt
2026-03-07 12:07:39 +01:00
Meleki 1c11ffa3cd feat: Dashboard-Badge + System-Prompt-Hinweis für ask_user_choice
- Dashboard: 'Rückfragen'-Badge (🔵) bei Agent-Card wenn allowUserChoice aktiv
- SystemPromptBuilder: Hinweis-Block der Claude anweist, ask_user_choice sparsam zu nutzen
2026-03-07 11:45:06 +01:00
Meleki 89ceb61948 feat: Agent-Einstellung 'Rückfragen erlauben' (allowUserChoice)
- Neues Feld AllowUserChoice (bool, default true) im AgentRecord
- DB-Migration: allow_user_choice Spalte mit DEFAULT 1
- Agent-Form: Checkbox 'Rückfragen erlauben' nach 'Tool-Nutzung erzwingen'
- ToolService.GetToolDefinitions: neuer Parameter includeUserChoice
- ask_user_choice Tool wird nur eingebunden wenn Agent es erlaubt
- Review-Agents und Non-Streaming (Cronjobs) erhalten nie ask_user_choice
- ChatEndpoint reicht Agent.AllowUserChoice an StreamChat durch
2026-03-07 11:36:02 +01:00
Meleki 5f3e308975 feat: ask_user_choice Tool – interaktive Auswahlmöglichkeiten im Chat
Neues Tool 'ask_user_choice' analog zum AskUserQuestion aus dem Claude Agent SDK.
Claude kann dem User Multiple-Choice-Fragen stellen, wenn es mehrere sinnvolle
Wege gibt. Der User wählt per Button, Claude arbeitet mit der Antwort weiter.

Backend:
- ToolService: ask_user_choice Tool-Definition (question + choices[2-5])
- AnthropicService/ProcessStream: Tool wird NICHT ausgeführt, sondern als
  SSE-Event 'user_choice' an den Client gesendet. stopReason wird auf
  'awaiting_user_choice' gesetzt (mit Guard gegen Überschreibung durch
  message_delta)
- ChatEndpoint: Erkennung von Choice-Responses (choiceToolCallId + choiceResult),
  tool_result wird in die korrekte Chain gespeichert (wo der tool_use liegt),
  toolChoice wird auf 'auto' gesetzt damit Claude frei antworten kann
- ChatService: FindChainWithToolCall() zum Auffinden der richtigen Chain,
  BuildHistoryFromDb() erweitert um Choice-Chain-Erkennung (wenn letzte Chain
  leer/nur tool_result → vorletzte Chain vollständig rekonstruieren)
- ChatModels: ChatRequest um ChoiceToolCallId + ChoiceResult erweitert

Frontend:
- api.js: apiChatChoice() für Choice-Responses
- chat.js: handleStreamEvent() als shared Handler extrahiert (sendMessage +
  handleChoiceClick nutzen denselben Code), handleChoiceClick() startet neuen
  Stream nach Button-Klick
- ui.js: addChoiceBubble() (live/interaktiv) + addChoiceBubbleStatic() (History)
- history.js: Choice-Bubbles in _renderMessagesIntoFragment + renderMessages,
  Voraus-Suche nach zugehörigem tool_result, unbeantwortet = klickbare Buttons
- chat.css: Styling für Choice-Bubbles (Primary-Color-Outline-Buttons, Hover,
  Selected/Unselected States)

Robustheit:
- Backend-Fallback wenn Claude choices als String statt Array sendet
- Frontend-Guard: Array.isArray(choices) an allen 4 Render-Stellen
- Page-Refresh mit offener Choice → aktive Buttons werden korrekt gerendert
2026-03-07 11:30:55 +01:00
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 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 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 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 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 58468701b9 feat(skills): read description from skill.json 2026-03-06 15:31:53 +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 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 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 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 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 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 4ae894304f fix: CancellationToken durchgängig in AnthropicService propagieren
- ThrowIfCancellationRequested() am Anfang jeder while-Loop-Iteration
- WriteSseEvent() erhält CancellationToken-Parameter, prüft vor Schreiben
- WriteAsync/FlushAsync mit CancellationToken aufgerufen
- Cancellation-Check vor und nach Tool-Execution
- OperationCanceledException in ExecuteTool wird re-thrown statt geschluckt
- Behebt: Stop-Button brach nur Frontend-Stream ab, Backend lief weiter
2026-03-05 15:28:48 +01:00
Meleki 5a0b355acd refactor: Beispiel-Daten in Memory-Pfaden durch YYYY-MM-DD Platzhalter ersetzen
- ToolService.cs: memory_read/memory_write Description nutzt YYYY-MM-DD
- SystemPromptBuilder.cs: Memory-Regel ohne festes Beispiel-Datum
- ARCHITECTURE.md: Dateibaum-Beispiel angepasst
2026-03-05 09:44:52 +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 26da25967d feat: Krea Image Generation Endpoint
- KreaService: GenerateAsync() mit Job-Polling, Image-Download, Metadaten-Speicherung
- KreaEndpoint: POST /api/images/generate, GET /api/images, GET /api/images/file/{filename}, GET /api/images/status
- KreaImageRecord: Output-Model
- Output: data/images/<timestamp>-<index>.<ext> + data/images/<timestamp>.json
- 16 Modelle: flux, flux-kontext, flux-1.1-pro, imagen-3/4, chatgpt-image, runway-gen-4, etc.
- appsettings.json: KreaToken (Format: KEY_ID:SECRET), obsolete TelegramBotToken/WebhookSecret entfernt
2026-03-04 18:24:51 +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 d482f5dca3 feat: API-Payload-Logging in data/logs/ für Debugging
- LogPayload() schreibt den kompletten Claude-API-Request als indented JSON
- Dateiname: <unixtime>-<sessionId>-<chainId>-iter<N>-payload.json
- Beide Pfade abgedeckt: StreamChat (Web) + ChatNonStreaming (Telegram/Cronjobs)
- try/catch: Logging-Fehler crashen nie die App
2026-03-04 14:35:15 +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 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 5f2b2e2f18 feat: add glob, grep and todo_write builtin tools 2026-03-03 14:10:07 +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 f203ed7f47 feat: Auth-Tokens in SQLite persistieren statt in-memory
Tokens überleben jetzt App-Restarts. AuthService schreibt/liest
Tokens aus einer 'tokens'-Tabelle in der SQLite-DB.
Logout (RevokeToken) funktioniert weiterhin korrekt.
2026-03-03 10:07:06 +01:00