Commit Graph
74 Commits
Author SHA1 Message Date
MelekiandClaude Opus 4.8 268f11fa6d Add multi-model panel with Fusion mode
Panel agents answer the user prompt in parallel (read-only, non-streaming);
their responses are merged into the worker's last user message as a
<panel_responses> block, and the session agent synthesizes one final
streamed answer. The RunPanel engine is built layer-ready for future MoA.

- New session fields: multi_model_mode (off/fusion), panel_agent_ids (CSV)
  with idempotent column migration
- New partial Services/AnthropicService.Panel.cs holding the RunPanel engine
- Provider-agnostic members: Anthropic RunNonStreamingToolLoop / OpenAI
  CompleteText / CLI plan-mode; all forced read-only, persisted with Tag=panel
- SSE events: panel_start, panel_member_start, panel_member_done, panel_done
- Frontend: multi-agent picker, live panel bubbles, history rendering
- Graceful degradation: panel errors fall back to worker-only

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 12:55:06 +02:00
MelekiandClaude Opus 4.8 de07b49b67 Persist steering messages that arrive during chain finalization
A steering message confirmed to the user as injected:true could still be
lost: after the loop's last HasPending check it runs out and the chain
finalizes (done event + final messages still streaming — the "few extra
messages" the user sees), then the finally block called Clear() and threw
the queue away. A message arriving in that window was accepted
(IsStreaming still true, Stop runs only in finally) but never drained and
never persisted, so it vanished after F5. Platform-independent; Windows
only widened the window via slower CLI teardown.

Replace the queue with a per-session gated state: Open() at chain start,
Close() at chain end. TryEnqueue() and Close() are mutually exclusive via
a per-session lock, so a confirmed injection can no longer be lost — the
loop either drains it or Close() returns it as leftover. The endpoint now
opens the gate at chain start, uses TryEnqueue as the authoritative check
(false → client resends as a normal message), and in finally closes the
gate and persists any leftover as Type="steer" instead of discarding it,
so it survives F5 and the model sees it on the next message.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 14:50:31 +02:00
MelekiandClaude Opus 4.8 f2fd493e5f Add live steering injection into running chains
Let the user inject a message into a running chain instead of only being
able to abort it. While a chain streams, typing + Enter sends the text to
a new /api/chat/steer endpoint; it is drained at the next iteration
boundary, wrapped with a hint so the model actively classifies it
("complements the task -> keep working" vs. "changes course -> adjust"),
and stored as a Type="steer" user message so it survives reload.

Shared infrastructure (provider-agnostic):
- SteeringQueue: out-of-band queue keyed by sessionId, mirrored from
  StreamingTracker (Enqueue/Drain/Clear).
- Program.cs registers it as a singleton and passes it to AnthropicService.
- ChatEndpoint: POST /api/chat/steer enqueues only while IsStreaming,
  Clear() in the finally.
- ChatService.BuildHistoryFromDb groups Type="steer" so no two
  consecutive user turns are produced on re-chat.
- Frontend api.js/chat.js/bubbles.js/history.js + chat.css render the
  optimistic steer bubble and the steer_injected SSE event; Enter during
  a stream sends a steer instead of being blocked.

Anthropic API path:
- Drain point B (tool boundary, merged into the tool_result user turn)
  and C (turn end -> inject + continue instead of finalize).

Claude CLI path (kill-and-restart):
- The agentic loop runs inside the claude child, so true mid-turn inject
  is impossible. On a pending steer the child is killed at the next tool
  boundary, progress is rebuilt from the DB as a <work_in_progress>
  transcript, and the CLI is restarted with the steer appended.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 06:49:58 +02:00
MelekiandClaude Opus 4.7 3f913f14b5 Add per-agent reasoning effort
Opus 4.5+ and Sonnet 4.6+ support a new "effort" knob that controls how
much budget the model spends on thinking and tool calls. Plumb it through
end to end so each agent can pick its own level.

Storage & shape:
- New TEXT column agents.effort (default '') added via TryAddColumn.
- AgentRecord.Effort + INSERT/UPDATE in DatabaseService.Agents.cs.
- ChatContext.Effort + SubAgentContext.Effort so the value travels with the
  request alongside model and tool settings.

Agent editor:
- Effort dropdown above git-commit behavior in the agent form (low/medium/
  high/xhigh/max plus empty = "use default"). Always visible; on OpenAI
  providers the value is sent but silently ignored.
- agent-page.js load/save and AgentEndpoint create/update wired up.

Anthropic API path:
- StreamChat and RunNonStreamingToolLoop add output_config: { effort } when
  effort is set and not "high" – empty/null/"high" means "omit and let the
  API pick its default".
- Sub-agents (preparer/review/finalizer) get the parameter through
  RunAgentChat so each step uses its own agent's effort.

Anthropic CLI path:
- ClaudeCliService.ChatStreamingAsync takes an effort parameter and exports
  CLAUDE_CODE_EFFORT_LEVEL on the spawned process. Env-var beats the
  --effort flag because it also covers "max" and "ultracode".
- StreamChatViaCli, ChatNonStreamingViaCli, RunSubAgentViaCli, and the
  ChatEndpoint anthropic branches all hand the value through.

ARCHITECTURE.md / ARCHITECTURE_QUICK.md updated with the new field.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-31 21:33:32 +02:00
MelekiandClaude Opus 4.6 358d9328be fix(openai): Tool-Calling-Reliability verbessern (maxIterations, forced tool_choice, Thinking-Strip)
- maxIterations aus Server-Settings an OpenAI-StreamChat durchreichen (war hardcoded 10)
- Auto-Continue: tool_choice="required" erzwingt Tool-Call statt erneuter Ankündigung,
  wird nach erfolgreichem Tool-Call wieder auf "auto" zurückgesetzt
- Direktive Continuation-Message statt einfaches "Continue."
- StripOldThinking: <think>-Blöcke aus älteren Assistant-Messages entfernen (nur letzte 4 behalten),
  reduziert Kontext-Inflation die ab ~20k Tokens zu Tool-Call-Degradation führt
- reasoning_split=true entfernt (wird von MiniMax-API ignoriert)
- parallel_tool_calls=false für MiniMax (Streaming, Non-Streaming, Payload-Preview)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-14 12:16:55 +02:00
MelekiandClaude Opus 4.6 1fe04025d3 fix(openai): Auto-Context, Tool-Result-Matching, Payload-Preview, leere Bubbles
- Auto-Context (Embedding-Suche) für OpenAI-Provider aktiviert: BuildAutoContextAsync
  auf internal static refactored und in StreamChat + ChatNonStreaming integriert
- Tool-Results mit Role="tool" (OpenAI-Konvention) werden in BuildHistoryFromDb
  jetzt korrekt erkannt (vorher nur Role="user"/Anthropic)
- Payload-Preview zeigt für OpenAI-Provider echtes API-Format (function-Wrapper,
  tool_choice:"auto", max_tokens, stream_options, extra_body)
- Tool-Input (Argumente) wird im SSE tool_end-Event mitgesendet (fehlte im OpenAI-Pfad)
- Leere Bubbles durch Whitespace-only Text nach </think>-Extraktion behoben
  (Trim in DB-Save, BuildHistoryFromDb und Frontend-Guard)
- History-Toggle-Bug: var→const in for-Loop (Block-Scoping für Closures),
  tool_result-Matching per data-tool-call-id statt blindes letztes Element
- Non-Streaming max_tokens für MiniMax auf 32768 + extra_body.reasoning_split

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-14 11:16:40 +02:00
MelekiandClaude Opus 4.7 ecddbe5f36 fix(openai): ask_user_choice-Intercept, Interleaved Thinking in History, MiniMax-Debug-Log
OpenAI-kompatible Provider (MiniMax, DeepSeek-R1, QwQ, Kimi K2, etc.) verloren bei
jeder neuen Iteration ihre eigene Chain-of-Thought, weil thinking-Messages aus der
DB-History rausgefiltert wurden. Folge: Modell kündigt Action an, ruft Tool aber
nicht auf → Stream endet mit finish_reason:stop ohne Tool-Call. Zusätzlich fehlte
der ask_user_choice-Intercept (Tool wurde als unbekannt abgelehnt) und es gab keine
Diagnose-Möglichkeit für unerwartete Stop-Verhalten.

- ChatService.BuildHistoryFromDb(includeThinking): neuer Parameter, fügt
  thinking-Messages als {type:"thinking"}-Block in die Assistant-Message ein.
  Text/Tool-Use derselben Iteration werden via AppendToLastMessage angehängt
  → ein Assistant-Block enthält [thinking, text, tool_use…].
- OpenAiService.ConvertMessage + StreamChat + ChatNonStreaming: Thinking als
  <think>...</think>-Prefix dem Assistant-Content voranstellen (Per-Iteration und
  beim DB-History-Aufbau). Konvention von MiniMax-Docs, wird auch von DeepSeek-R1,
  QwQ, Kimi K2 verstanden.
- ChatEndpoint, SessionEndpoint, CronjobService, TelegramService, ToolService:
  includeThinking je nach Provider durchgereicht. Anthropic-Pfad bleibt aus
  (lehnt thinking-Blöcke ohne Signature ab).
- OpenAiService: ask_user_choice-Intercept im Streaming-Pfad (analog
  AnthropicService.Streaming) – Tool nicht ausführen, SSE user_choice rausschicken,
  mit stopReason awaiting_user_choice finalisieren und return.
- OpenAiService: MiniMax-SSE-Debug-Log in data/openai-debug/ (JSONL: Header +
  Roh-data-Zeilen + Summary mit promptTokens/completionTokens/finishReason/
  toolCalls/duration) – nur für provider=="minimax", nicht-blockierend.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-14 10:19:06 +02:00
MelekiandClaude Opus 4.6 1526891cd9 feat: CLI-Fallback für Sub-Agents (Preparer/Review/Finalizer) wenn kein API-Key zugewiesen
Statt Hard-Error "Kein API-Key zugewiesen" nutzen Sub-Agents jetzt
Claude CLI als Fallback. Preparer wird nur übersprungen wenn weder
Key noch CLI verfügbar sind.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-17 10:11:34 +02:00
MelekiandClaude Opus 4.6 53cee67bef feat: Remote-Execute für Linux/Bash – OS-basierte Tool-Descriptions und remote.sh Script
Remote-Verbindungen erkennen jetzt das OS des Clients und passen die Tool-Description
dynamisch an (PowerShell für Windows, Bash für Linux). Neues remote.sh Script für
Linux/macOS-Clients mit embedded Python WebSocket-Client.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-16 09:31:56 +02:00
MelekiandClaude Opus 4.6 3f2baa1639 feat: AutoContext-Suche grundlegend verbessern + Embedding-Debug-Tool
Hybrid-Suche (Vektor + FTS5-Keyword), Recency-Boost, Query-Erweiterung
(letzte 2-3 User-Messages), Chunk-Overlapping, FullText-Speicherung,
konfigurierbares Embedding-Modell/MaxSeqLen, deduplizierter AutoContext-
Code (Streaming + CLI shared), Admin-Diagnose-Seite mit Re-Embed-Funktion.
Threshold von 0.45 auf 0.35 gesenkt (Hybrid-Suche ist präziser).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-01 08:50:41 +02:00
MelekiandClaude Opus 4.6 f03fbd298e feat: User-Berechtigungen für Agent-Erstellung und CLI-Nutzung
- Neue Felder CanCreateAgents und CanUseCli im UserRecord (Default: true)
- DB-Migration mit Abwärtskompatibilität (bestehende User behalten alle Rechte)
- Admin-UI: Checkboxen für beide Berechtigungen pro User
- AgentEndpoint: Prüfung auf CanCreateAgents beim Erstellen
- ChatEndpoint: CLI-Fallback nur wenn CanUseCli erlaubt
- Frontend: Neuer-Agent-Button und Agent-Page bei fehlender Berechtigung gesperrt
- Chat: Proaktive Warnung wenn kein API-Key und keine CLI-Berechtigung
- Bug Fix: is_public fehlte im Agent-INSERT (Public Agents erst nach erneutem Speichern sichtbar)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 18:47:56 +01:00
MelekiandClaude Opus 4.6 500c00f948 feat: Unity MCP-Server Integration pro Session
Sessions können jetzt einen Unity MCP-Server (URL + Token) konfigurieren.
Die CLI erhält automatisch die MCP-Config mit korrektem Transport-Typ
(URL-basierte Erkennung: /sse → SSE, sonst HTTP für streamableHttp).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 18:34:47 +01:00
MelekiandClaude Opus 4.6 3e0a69e7a4 feat: MCP-Tools ask_user_choice + memory_read/write/list, Text-Marker entfernt
MCP-Server erweitert um ask_user_choice (Long-Poll), memory_read, memory_write
und memory_list Tools. MCP-Config wird jetzt immer generiert (nicht nur bei
Remote-Verbindung). InternalEndpoint um PendingChoices + choice-respond Endpoint
ergänzt. Frontend differenziert CLI-Modus (choice-respond API) vs. API-Modus.
Gesamter :::ASK_USER_CHOICE::: Text-Marker-Mechanismus aus ClaudeCliService,
AnthropicService, markdown.js und stream-ui.js entfernt.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 09:54:30 +01:00
MelekiandClaude Opus 4.6 3b068a7866 feat: MCP-Server für remote_execute + Inline-Choice-UI
- Python MCP-Server (stdio, JSON-RPC 2.0) für remote_execute via Claude CLI
- Interner API-Endpoint /api/internal/remote-execute mit Token-Auth
- MCP-Config wird automatisch generiert wenn Remote-Verbindung vorhanden
- Auth-Middleware: /api/internal/ von Auth ausgenommen
- Frontend: :::ASK_USER_CHOICE::: Blöcke als interaktive Buttons rendern
- Streaming: Unvollständige Choice-Blöcke werden während des Streams versteckt
- tool-ui.js: MCP-Tool-Namen generisch normalisieren (mcp__server__tool → tool)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 09:00:50 +01:00
MelekiandClaude Opus 4.6 ee0b817f25 fix: CLI-Stream überlebt Page-Reload (Token-Trennung workCt/sseCt)
workCt steuert den CLI-Prozess (nur Stop-Button), sseCt die SSE-Writes
(Client-Disconnect). Page-Reload cancelt nur sseCt → CLI läuft weiter.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 07:01:00 +01:00
MelekiandClaude Opus 4.6 4af9430466 feat: Claude CLI Pfad mit ask_user_choice, Plan-Modus und Tool-Konfiguration
- ClaudeCliService: Marker-basierte ask_user_choice Erkennung im Stream-Parser
- AnthropicService: StreamChatViaCli mit allowUserChoice, planMode, webSearch
- BuildHistoryContext erweitert für tool_use/tool_result (Choice-Antworten)
- Tool-Use Records werden in DB persistiert (Poll-Kompatibilität)
- CLI Tools konfigurierbar: Workspace/Plan-Modus/WebSearch/kein Workspace
- OAuth DB-Felder für zukünftige Token-Verwaltung

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 22:25:39 +01:00
Meleki 02f5fe2faf Provider-Abstraktion: Agents unterstützen jetzt OpenAI + Anthropic
Backend:
- ChatEndpoint: Globaler OpenAI-Fallback entfernt, Key-Check pro Provider
- TelegramService/CronjobService: Provider-Weiche statt hardcoded Anthropic
- AnthropicService: Preparer/Review/Finalizer sind Provider-aware
- OpenAiService: Neue ChatNonStreaming()-Methode für agentic loop
- ToolService: send_to_session lädt Key des Ziel-Agents
- SubAgentContext: Provider-Feld hinzugefügt
- ChatService: BuildSubAgentContext setzt Provider

Frontend:
- Key-Switch-Modal: 'Kein Key'-Option zum Entfernen der Zuweisung
- ApiKeysEndpoint: keyId='none' löscht Key-Zuweisung
2026-03-14 22:59:33 +01:00
Meleki 1effc6d00f feat: API Key pro Agent statt pro User
- Neue Tabelle agent_api_keys (user_id, agent_id, key_id)
- Migration: bestehende selected_api_key_id auf alle Agents verteilt
- Backend: GetAgentApiKeyRecord(userId, agentId) in Chat, Telegram, Cronjobs
- Endpoints: select/selected mit ?agentId Query-Parameter
- Frontend: currentAgentId aus Session, alle Key-Calls agent-aware
- DeleteApiKey bereinigt agent_api_keys statt users.selected_api_key_id
2026-03-14 21:41:27 +01:00
Meleki 122000487c Refactor: Server-Settings von appsettings.json in DB-Tabelle (server_settings)
- Neuer ServerSettingsService: zentrale Settings in SQLite mit In-Memory-Cache
- Auto-Migration: bestehende appsettings.Production.json wird einmalig in DB übernommen
- Alle Services umgestellt: IConfiguration → ServerSettingsService (dynamisch, kein Neustart)
- Port bleibt als einziges Setting in appsettings.Production.json (erfordert Neustart)
- ServerSettingsEndpoint: liest/schreibt DB statt JSON-Datei, Port als Sonder-Setting
- IConfiguration komplett entfernt aus allen Services (ChatService, ToolService, AnthropicService,
  OpenAiService, KreaService, TelegramService, KeyScannerService, GitHubEventScannerService)
- AuthMiddleware: KreaApiKey dynamisch aus DB
- appsettings.json bereinigt: nur noch Port und Logging
- Dokumentation aktualisiert (ARCHITECTURE.md, ARCHITECTURE_QUICK.md, README.md)
2026-03-14 13:06:44 +01:00
Meleki 542a031172 feat: OpenAI Provider, Key-Checker Quota-Erkennung, persistierte Scanner-Logs
- OpenAI als vollwertiger Chat-Provider (Modell-Auswahl, Key-Routing, StreamChat)
- Hardcoded OpenAI-Modelle im Cache (gpt-5.x, gpt-4.1, o3, o4-mini etc.)
- /api/models/openai Endpoint, OpenAI-Optgroup im Agent-Dropdown
- Key-Routing: OpenAI-Key aus api_keys-Tabelle, Fallback via GetFirstActiveKeyByProvider
- OpenAI-Checker: 2-Schritt-Check (Models + chat/completions mit max_tokens=1)
- Google-Checker: 2-Schritt-Check (Models + generateContent mit maxOutputTokens=1)
- 429 insufficient_quota und billing_not_active korrekt als quota_exceeded erkannt
- Provider-Erkennung beim Adopt via KeyPatterns.DetectType() statt hardcoded anthropic
- HandleCheck/HandleCheckAll unterstützt jetzt Anthropic, OpenAI und Google
- Neue scanner_logs-Tabelle mit details-Spalte (JSON) für strukturierte Auswertung
- GitHubEventScannerService: AddLog persistiert in DB, detaillierte Key-Fund-Logs
- KeyScannerService: AddLog-Methode mit DB-Persistierung, detaillierte Logs
- Frontend: Ungeprüfte-prüfen-Button (sequenziell, stoppt bei valid)
- Frontend: Provider-Indicator im Key-Switch-Modal (Anthropic/OpenAI/Google)
- Frontend: Check-Button für alle Provider (nicht nur Anthropic)
2026-03-14 11:19:33 +01:00
Meleki dde0fede7d User-spezifische API-Key-Auswahl, globales is_active entfernt
Backend:
- is_active komplett entfernt, durch is_public (Admin-Toggle) ersetzt
- Neues selected_api_key_id auf users-Tabelle
- AnthropicService: globaler _token entfernt, apiToken pro Request
- Token-Durchreichung: StreamChat → ProcessStream → RunAgentChat →
  RunPreparer/RunReview/RunFinalizer, ExecuteTool, send_to_session
- ChatEndpoint: User-Key aus DB laden, an StreamChat übergeben
- TelegramService: Key per bot.UserId auflösen
- CronjobService: Key per job.UserId auflösen
- Neue Endpoints: GET /api/api-keys/available, PUT /api/api-keys/select/{keyId},
  GET /api/api-keys/selected, PUT /api/admin/api-keys/{keyId}/public,
  POST /api/admin/api-keys/check-all
- Program.cs: AnthropicService ohne Token-Parameter

Frontend:
- API-Keys-Page: Public-Toggle (Globe/Lock) statt Activate/Deactivate
- Alle prüfen Button für Batch-Key-Check
- Chat: Key-Auswahl für alle User (nicht nur Admin)
- Dummy-Badge wenn kein Key ausgewählt
- Fallback-Badge bei Key ohne Usage-Daten
- Key-Switch-Modal: apiGetAvailableKeys + apiSelectApiKey
2026-03-13 12:27:03 +01:00
Meleki 192f41e91e feat: Serper Web Search als Agent-Tool
- ToolService: serper_web_search Tool-Definition + ExecuteSerperWebSearch()
  Google-Suche via Serper.dev API mit Titel, Link, Snippet
  Knowledge Graph + Answer Box + organische Ergebnisse
- AgentRecord: UseSerperSearch Property (Default: false)
- DB-Migration: use_serper_search Spalte
- AnthropicService + ChatService: useSerperSearch Parameter durchreichen
- ChatEndpoint + AgentEndpoint: useSerperSearch in API
- Frontend: Checkbox, Badge (Serper Search), laden/speichern
- Aktivierung: Agent-Checkbox + SerperApiKey in Server-Einstellungen
2026-03-13 09:41:56 +01:00
Meleki 89122e2170 feat: GitHub Code Search als Agent-Tool + Dashboard-Badges
- UseGitHubSearch Property im AgentRecord (Default: false)
- DB-Migration: use_github_search Spalte in agents
- Checkbox im Agent-Formular (Standard: unchecked)
- Tool nur aktiv wenn Agent-Checkbox UND GitHubToken konfiguriert
- includeGitHubSearch Parameter durch StreamChat/AddToolsToPayload
- Dashboard-Badges: 🔮 Auto-Kontext + 🐙 GitHub Search
2026-03-13 08:26:15 +01:00
Meleki db1a7c7f64 Refactoring + Dokumentation: api.js komprimiert (745→267 Zeilen), SseHelper extrahiert, DatabaseService in Partial Classes aufgeteilt, unbenutztes CSS entfernt, ARCHITECTURE.md/ARCHITECTURE_QUICK.md/README.md aktualisiert (neue Features: Embedding, Remote, API-Keys, 16 Tools) 2026-03-12 13:29:19 +01:00
Meleki 7972ca6a3a feat: OpenAI-kompatibler Provider (Nvidia/g4f.space) mit Tool-Calling und SSE-Streaming
- OpenAiService.cs: Neuer Service für OpenAI-kompatible APIs
  - SSE-Streaming mit text_start/text_delta/text_end Events
  - Tool-Calling: list_files, read_file, write_file, edit_file, delete_file, execute
  - Agentic Loop (max 10 Iterationen)
  - Tool-Use + Tool-Result in DB gespeichert
  - History-Rebuild: Anthropic-Format → OpenAI-Format (tool_use/tool_result korrekt konvertiert)
- ChatContext.cs: Provider-Feld hinzugefügt
- ChatService.cs: OpenAI-Provider-Erkennung in ResolveModelId + PrepareContext
- ChatEndpoint.cs: Provider-Dispatch (nvidia → OpenAiService, sonst → AnthropicService)
- Program.cs: OpenAiService als Singleton registriert
- wwwroot/index.html: nvidia:moonshotai/kimi-k2.5 in Modell-Auswahl
2026-03-11 16:15:09 +01:00
Meleki c18b94cd4e feat: send_to_session tool – agent-to-agent messaging
- Neues Tool send_to_session: Agent kann Nachrichten in andere Sessions schicken
- Ziel-Session per ID oder Name (case-insensitive) auffindbar
- User-Message wird nicht in DB gespeichert (wie Cronjob) – keine Bubble im Frontend
- Nachricht wird als '[Nachricht von Agent "X"]' kontextualisiert injiziert
- Sicherheitscheck: Ziel-Session muss demselben User gehören, keine eigene Session
- Zirkuläre Abhängigkeit ChatService ↔ AnthropicService via SetChatService() gelöst
- tool-ui.js: Display-Name für send_to_session
2026-03-11 12:56:36 +01:00
Meleki 148d1459a3 Auto-Context: Semantische Kontext-Injektion, Memory-File-Embeddings, Agent-Toggle
- Automatische Embedding-basierte Kontext-Injektion vor jeder API-Anfrage
  (Top 5 Chat-Ergebnisse + Top 3 Memory-File-Treffer als recalled_context)
- Memory-Dateien (.md) werden embedded (Backfill + Live nach memory_write)
- Neue Agent-Option 'useAutoContext' (Checkbox, Default: aktiviert)
- VectorSearchService: SearchMemoryFilesAsync, EmbedMemoryFileAsync, Chunking
- EmbeddingBackgroundService: Memory-File-Backfill + EnqueueMemoryFile
- ToolService: memory_write löst Re-Embedding aus
- embeddingBg Parameter an ExecuteTool durchgereicht
2026-03-11 09:45:50 +01:00
Meleki add111ffe1 feat: Semantische Suche über Chat-History (memory_search)
- Lokales Embedding-Model (all-MiniLM-L6-v2, ONNX, CPU)
- EmbeddingService: WordPiece-Tokenizer + Mean Pooling (384 Dim)
- VectorSearchService: SQLite-basierte Vektor-Speicherung + Cosine Similarity
- EmbeddingBackgroundService: Backfill bestehender Messages + Live-Queue
- Neues Tool memory_search: Semantische Suche über alle Sessions (inkl. archivierte)
- ~9000 Messages embedded, Suche über komplette Chat-History
2026-03-11 09:22:11 +01:00
Meleki 10da2bd964 feat: Remote-Verbindungen – Windows-Workstations per WebSocket steuern
- 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
2026-03-11 07:04:24 +01:00
Meleki b1d449b997 Doppel-Klick Hard-Stop + ReadLineAsync Cancellation-Fix
Stop-Button: Zwei Stufen statt einer:
- 1. Klick: Graceful Stop (workCt) - laufende API-Calls/Tools abbrechen
- 2. Klick: Hard Stop (hardCt) - sofortiger Abbruch aus while-Loop

StreamingTracker: Zwei separate CancellationTokenSources (StopCts + HardCts),
Cancel() gibt 'graceful'/'hard'/null zurück je nach Stufe.

ReadLineAsync Cancellation-Fix: StreamReader.ReadLineAsync propagiert den
CancellationToken nicht zuverlässig an den underlying NetworkStream.
Bei extended thinking blockiert ReadLineAsync minutenlang ohne Reaktion
auf Cancellation. Fix: workCt.Register() disposed den HTTP-Stream,
damit ReadLineAsync sofort mit Exception abbricht.

Bug-Fix: OperationCanceledException in RunAgentChat/ChatNonStreaming wurde
vom generischen catch(Exception) geschluckt - Agent lief trotz Stop weiter.
Jetzt: catch(OperationCanceledException) { throw; } vor catch(Exception).

Frontend: Stop-Button zeigt Hard-Stop visuell (rot + Pulse-Animation),
SSE-Stream wird erst beim 2. Klick clientseitig abgebrochen.
2026-03-10 10:53:23 +01:00
Meleki e9b1e8ef20 Agent-Arbeit vom Client-Disconnect entkoppeln
Zwei separate CancellationTokens:
- workCt (nur Stop-Button): Anthropic API-Calls, Tool-Ausfuehrungen, DB-Writes
  Agent laeuft bei SSE-Disconnect weiter, Client pollt Ergebnisse
- sseCt (Stop-Button + Client-Disconnect): SSE-Writes an Browser
  Bei Disconnect werden Writes zu stillen No-Ops

Vorher: HttpContext.RequestAborted killte den gesamten Agent-Lauf
wenn die SSE-Verbindung abriss (Browser-Tab idle, Netzwerk-Hickup).
Jetzt arbeitet der Agent im Hintergrund weiter.

OperationCanceledException = 'stopped' (nur Stop-Button)
statt 'client_disconnected' (war falsch verknuepft)
2026-03-10 06:28:35 +01:00
Meleki dd99216913 fix: SSE-Stream-Stabilität und History-Trimming tool_use/tool_result-Schutz
- Kestrel MinResponseDataRate per-Request deaktivieren für SSE-Streams
  (Default 240 bytes/s + 5s Grace → client_disconnected bei langen Tools)
- SSE-Heartbeat alle 15s während Stream (schützt gegen Browser/Netzwerk-Idle)
- History-Trimming: RemoveRange schneidet nicht mehr in tool_use/tool_result-Paare
- Reminder-Insertion: kein Einfügen zwischen tool_use und tool_result
2026-03-09 20:13:22 +01:00
Meleki 3e590a6d03 fix: Windows-Kompatibilität - Streaming, Execute-Deadlock, Plan-Modus bei Choice
- HttpResponseMessage mit using disposen (3 Stellen in AnthropicService)
  verhindert Socket-Exhaustion unter Windows (2 Connections/Host Limit)
- SSE DisableBuffering() in ChatEndpoint für sofortigen Flush unter Windows
- Execute: stdout/stderr vor WaitForExitAsync lesen statt danach
  verhindert Pipe-Deadlock bei vollem Buffer (Windows: 4KB)
- Plan-Modus: Frontend sendet planMode bei Choice-Response mit
  Backend-Fallback auf vorherigen Chain entfernt - User-Entscheidung gilt
2026-03-09 17:01:18 +01:00
Meleki 47d6f44e07 Auto-Reminder alle 30 Messages + History-Limit 120
- SystemPromptBuilder.BuildReminder(): generiert automatisch Reminder-Text
  aus den aktiven Prompt-Blöcken (Identity, Workspace, Memory, etc.)
- Alle ~30 Messages wird ein [System Reminder]-Paar in die History injiziert
  (nur nach assistant-Messages, um user/assistant-Alternierung zu wahren)
- History auf maximal 120 Messages begrenzt (älteste werden entfernt)
- ChatContext um PromptBlocks-Property erweitert
- Alle Aufrufer (ChatEndpoint, TelegramService, CronjobService) übergeben
  promptBlocks an BuildHistoryFromDb
2026-03-09 06:35:35 +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 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 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 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 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 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 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 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 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 7149904ae4 Profil-Seite: Anzeigename, Passwort ändern, Persona (ersetzt USER.md)
- Neuer Menüpunkt 'Mein Profil' statt 'Logout'
- Profil-Page: Anzeigename, Persona (Freitext), Passwort ändern, Logout
- ProfileEndpoint: GET/PUT /api/profile, PUT /api/profile/password
- User-Persona im System-Prompt statt USER.md (Fallback: Anzeigename/Username)
- SystemPromptBuilder: dataDir-Parameter entfernt, userPersona-Parameter hinzugefügt
- DB-Migration: persona-Spalte in users-Tabelle
2026-03-02 15:02:39 +01:00
Meleki 8039b47dec Web-Suche (Agent-Toggle mit Versionswahl), Admin-only Backup, Haiku 4.5
- Agent: Web-Suche als Dropdown (Deaktiviert / 2025 / 2026) statt bool
- AnthropicService: web_search Tool dynamisch nach Version einfügen
- Stream: server_tool_use + web_search_tool_result Events verarbeiten
- Chat-Frontend: web_search_start/end Events mit Suchindikator
- Dashboard: Badge zeigt Web-Suche mit Jahresversion
- UserRecord: IsAdmin Feld, DB-Migration is_admin Spalte
- AuthMiddleware: IsAdmin aus DB laden und in Context setzen
- BackupEndpoint: Admin-Check (403 für Nicht-Admins)
- AuthEndpoint: isAdmin in Login/Me Response
- Frontend: Backup-Section nur für Admins sichtbar
- Haiku 4.5 als Model-Option (Agent-Dropdown + ChatEndpoint)
- TODO: Cronjobs, Haiku ergänzt
2026-03-02 14:05:59 +01:00
Meleki d05023b1da Fallback-Workspace /tmp wenn Skills aktiv aber kein Workspace gesetzt 2026-03-02 12:31:28 +01:00
Meleki 7614141760 feat: User-Zuordnung für Sessions und Agents
- UserId-Feld zu SessionRecord und AgentRecord hinzugefügt
- DB-Migration: user_id Spalte + bestehende Daten dem Admin zuweisen
- Alle Endpoints filtern/prüfen nach UserId des eingeloggten Users
- HttpContextExtensions.GetUserId() Helper für konsistenten Zugriff
- Betrifft: Agent, Session, Chat, History, Workspace, Skill Endpoints
- Sessions/Agents anderer User sind nicht sichtbar/zugreifbar
2026-03-02 11:39:55 +01:00