sessionsUseCase = $sessionsUseCase ?? new ManageChatSessionsUseCase(); $this->messageUseCase = $messageUseCase ?? new SendChatMessageUseCase(); $this->formatter = $formatter ?? new ChatMessageFormatter(); } public function index(): void { $uuid = $this->sessionsUseCase->createSession(); header('Location: /chat/' . $uuid); exit; } public function show(string $uuid): void { $session = $this->sessionsUseCase->getSession($uuid); if ($session === null) { header('Location: /chat'); exit; } $this->view('chat.index', [ 'title' => $session['title'] ?? 'KI-Chat', 'session' => $session, 'messages' => $this->sessionsUseCase->getMessages($session['id']), 'sessions' => $this->sessionsUseCase->getAllSessions(), 'authorProfiles' => $this->sessionsUseCase->getAuthorProfiles(), 'systemPrompts' => $this->sessionsUseCase->getSystemPrompts(), 'outputStructures' => $this->sessionsUseCase->getOutputStructures(), 'collections' => $this->sessionsUseCase->getAvailableCollections(), 'models' => ModelConfig::getAll(), 'defaultModel' => ModelConfig::DEFAULT_MODEL, ]); } public function sessionList(): void { $this->view('chat.partials.session-list', [ 'sessions' => $this->sessionsUseCase->getAllSessions(), 'currentUuid' => $this->getString('current') ?: null, ]); } public function message(string $uuid): void { $session = $this->sessionsUseCase->getSession($uuid); if ($session === null) { $this->view('chat.partials.error', ['error' => 'Session nicht gefunden.']); return; } $question = trim($_POST['message'] ?? ''); $model = ModelConfig::validate($_POST['model'] ?? $session['model']); $sessionCollections = $this->decodeJson($session['collections'] ?? null) ?: ['documents']; $collections = $_POST['collections'] ?? $sessionCollections; $contextLimit = (int) ($_POST['context_limit'] ?? $session['context_limit'] ?? 5); $authorProfileId = (int) ($_POST['author_profile_id'] ?? $session['author_profile_id'] ?? 0); $systemPromptId = (int) ($_POST['system_prompt_id'] ?? $session['system_prompt_id'] ?? 1); $structureId = (int) ($_POST['structure_id'] ?? 0); $temperature = (float) ($_POST['temperature'] ?? $session['temperature'] ?? 0.7); $maxTokens = (int) ($_POST['max_tokens'] ?? $session['max_tokens'] ?? 4096); if ($this->sessionsUseCase->settingsHaveChanged($session, $model, $collections, $contextLimit, $authorProfileId, $temperature, $maxTokens)) { $this->sessionsUseCase->updateSettings($session['id'], $model, $collections, $contextLimit, $authorProfileId, $temperature, $maxTokens); } if ($question === '') { $this->view('chat.partials.error', ['error' => 'Bitte gib eine Frage ein.']); return; } if (!empty($collections)) { $compatibility = $this->sessionsUseCase->validateCollectionCompatibility($collections); if (!$compatibility['valid']) { $this->view('chat.partials.error', [ 'error' => 'Collection-Fehler: ' . $compatibility['error'], 'details' => 'Bitte wähle nur Collections mit gleichem Embedding-Modell.', ]); return; } } $response = $this->messageUseCase->execute( sessionUuid: $uuid, message: $question, model: $model, collections: $collections, contextLimit: $contextLimit, authorProfileId: $authorProfileId, systemPromptId: $systemPromptId, temperature: $temperature, maxTokens: $maxTokens, structureId: $structureId ); if ($response->hasError()) { $this->view('chat.partials.error', ['error' => $response->getError()]); return; } $result = $response->toArray(); $this->view('chat.partials.response', [ 'question' => $question, 'result' => $result, 'model' => $model, 'formattedAnswer' => $this->formatter->formatAnswer($result['answer'] ?? ''), ]); } public function updateTitle(string $uuid): void { $session = $this->sessionsUseCase->getSession($uuid); if ($session === null) { $this->notFound('Session nicht gefunden'); } $title = $this->sessionsUseCase->updateTitle($session['id'], $_POST['title'] ?? ''); echo htmlspecialchars($title); } public function systemPrompt(string $uuid): void { $session = $this->sessionsUseCase->getSession($uuid); if ($session === null) { $this->notFound('Session nicht gefunden'); } $result = $this->sessionsUseCase->updateSystemPrompt($session['id'], $_POST['system_prompt'] ?? ''); $this->view('chat.partials.success', ['message' => $result->message]); } public function getSystemPrompt(string $uuid): void { $session = $this->sessionsUseCase->getSession($uuid); if ($session === null) { $this->notFound('Session nicht gefunden'); } $this->view('chat.partials.system-prompt-modal', [ 'session' => $session, 'currentPrompt' => $session['system_prompt'] ?? '', 'defaultPrompt' => $this->sessionsUseCase->getDefaultSystemPrompt(), ]); } public function delete(string $uuid): void { $session = $this->sessionsUseCase->getSession($uuid); if ($session !== null) { $this->sessionsUseCase->deleteSession($session['id']); } header('HX-Redirect: /chat'); echo 'OK'; } public function export(string $uuid): void { $format = $this->getString('format') ?: 'markdown'; $exportUseCase = new ExportChatSessionUseCase(); $filename = $exportUseCase->generateFilename($uuid, $format); if ($format === 'json') { $data = $exportUseCase->exportAsJson($uuid); if ($data === null) { $this->notFound('Session nicht gefunden'); } header('Content-Type: application/json; charset=utf-8'); header('Content-Disposition: attachment; filename="' . $filename . '"'); echo json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); } else { $content = $exportUseCase->exportAsMarkdown($uuid); if ($content === null) { $this->notFound('Session nicht gefunden'); } header('Content-Type: text/markdown; charset=utf-8'); header('Content-Disposition: attachment; filename="' . $filename . '"'); echo $content; } } }