- typing-phrases.js in index.html eingebunden
- startTypingIndicator() / stopTypingIndicator() in chat.js
- Agent-Name via setCurrentAgentName() aus chat-page.js gesetzt
- Phrase wechselt alle 3 Sekunden zufällig
- Cleanup bei destroy() und finally-Block
- RemoteConnectionManager: Singleton-Service verwaltet WebSocket-Verbindungen
mit Command-Execution (Send/Receive mit Timeout + SemaphoreSlim-Locking)
- RemoteEndpoint: WebSocket-Endpoint /api/remote (auth-frei), REST-APIs für
Connections/Assign/Unassign, PowerShell-Script-Auslieferung mit dynamischer URL
- remote.ps1: PowerShell-Client für Windows – verbindet per WebSocket,
sendet Hostname/User/OS, empfängt und führt Befehle aus, Heartbeat
- remote_execute Tool: Neues Agent-Tool, nur verfügbar wenn Session eine
zugeordnete Remote-Verbindung hat, führt PowerShell-Befehle remote aus
- Frontend: Menüpunkt 'Remote-Verbindungen' im Chat-Dropdown, Modal zeigt
alle aktiven WebSocket-Verbindungen (Hostname, User, OS, Verbindungszeit),
Verbinden/Trennen-Buttons pro Verbindung und Session
- Auth: /api/remote und /remote.ps1 von Authentifizierung ausgenommen
Architektur: Windows-Client → WebSocket → GOTT-Server → Agent-Tool
Session-gebunden: Eine Verbindung wird einer Session zugeordnet
Problem: API 400 'web_search tool use without corresponding
web_search_tool_result block' – weil web_search_tool_result nur als
Sources-Array gespeichert wurde und in BuildHistoryFromDb kein Handler
dafür existierte. Der server_tool_use-Block war in der History, aber
der zugehörige web_search_tool_result fehlte.
Backend (AnthropicService):
- 3 Speicher-Stellen (StreamChat, RunAgentChat, ChatNonStreaming):
Raw-JSON statt ExtractWebSearchSources-Array speichern
Backend (ChatService):
- Neuer Handler für web_search_result in BuildHistoryFromDb:
Raw-JSON als web_search_tool_result in assistant content einfügen
- Rückwärtskompatibilität: Alte Array-Einträge überspringen
- CleanOrphanedWebSearchBlocks(): Post-Processing entfernt
orphaned server_tool_use mit name web_search (alte DB-Einträge)
Frontend (history.js, shared-page.js):
- _extractWebSearchSources(): Unterstützt altes Array-Format und
neues Raw-JSON Format (content[].type === web_search_result)
- Telegram-Bot-Page: Webhook-Secret und Webhook-Section immer sichtbar (hidden-Logik entfernt)
- Agent-Page: Public-Checkbox in scrollbaren Bereich verschoben, Sichtbarkeit-Label hinzugefügt
- Konsistente Bezeichnung: Public → Öffentlich mit Hint-Text
- Session-Page: Redundantes Telegram-Label entfernt
- Telegram-Bots-Überschrift: Icon entfernt (konsistent mit anderen Sektionen)
- 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
- 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
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
- 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)
- 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
- 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
- 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
- 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
- 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-*
- 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)
- 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
- 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
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
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
- 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
- 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
- #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