role) !== 'admin') { abort(403, 'Nur für Admins'); } } private function ollamaStatus(): array { $host = rtrim(env('OLLAMA_HOST', 'http://127.0.0.1:11434'), '/'); $model = env('OLLAMA_MODEL', 'llama3'); try { $res = Http::timeout(2)->get($host . '/api/tags'); return ['healthy' => $res->ok(), 'host' => $host, 'model' => $model, 'error' => $res->ok() ? null : 'Keine Verbindung']; } catch (\Throwable $e) { return ['healthy' => false, 'host' => $host, 'model' => $model, 'error' => $e->getMessage()]; } } private function getThreads(): array { $index = cache()->get('support_threads_index', []); $threads = []; foreach (array_reverse($index) as $row) { $full = cache()->get('support_threads:' . $row['id']); if (is_array($full)) { $threads[] = $full; } else { $threads[] = $row; } } return $threads; } public function index(Request $request): Response { $this->assertAdmin(); $enabled = (bool) (cache()->get('support_chat_enabled') ?? config('app.support_chat_enabled', true)); return Inertia::render('Admin/Support', [ 'enabled' => $enabled, 'threads' => $this->getThreads(), 'ollama' => $this->ollamaStatus(), ]); } public function settings(Request $request) { $this->assertAdmin(); $data = $request->validate(['enabled' => 'required|boolean']); cache()->put('support_chat_enabled', (bool) $data['enabled'], now()->addYear()); return back()->with('success', 'Support-Chat Einstellungen gespeichert.'); } public function reply(Request $request, string $thread) { $this->assertAdmin(); $data = $request->validate(['text' => 'required|string|min:1|max:1000']); $record = cache()->get('support_threads:' . $thread); if (!is_array($record)) { return back()->withErrors(['text' => 'Thread nicht gefunden.']); } $record['messages'][] = [ 'id' => Str::uuid()->toString(), 'sender' => 'agent', 'body' => $data['text'], 'at' => now()->toIso8601String(), ]; $record['status'] = 'agent'; $record['updated_at'] = now()->toIso8601String(); cache()->put('support_threads:' . $thread, $record, now()->addDay()); // Update index entry $index = cache()->get('support_threads_index', []); foreach ($index as &$row) { if (($row['id'] ?? null) === $thread) { $row['status'] = 'agent'; $row['updated_at'] = $record['updated_at']; break; } } cache()->put('support_threads_index', $index, now()->addDay()); return back()->with('success', 'Nachricht gesendet.'); } public function close(Request $request, string $thread) { $this->assertAdmin(); $record = cache()->get('support_threads:' . $thread); if (is_array($record)) { $record['status'] = 'closed'; $record['updated_at'] = now()->toIso8601String(); cache()->put('support_threads:' . $thread, $record, now()->addDay()); } $index = cache()->get('support_threads_index', []); foreach ($index as &$row) { if (($row['id'] ?? null) === $thread) { $row['status'] = 'closed'; break; } } cache()->put('support_threads_index', $index, now()->addDay()); return back()->with('success', 'Chat geschlossen.'); } }