session()->get('ldap_username', ''); $indexRuns = $this->projectSearch->isAvailable() ? $this->projectSearch->indexStatus() : []; $activeSession = $username !== '' && $this->chat->isAvailable() ? $this->chat->activeSession($username) : null; $messages = $activeSession !== null ? $this->chat->messagesForSessionId((int) $activeSession['id']) : []; $chatHistory = $username !== '' && $this->chat->isAvailable() ? $this->chat->recentEndedSessions($username, 8) : []; return view('project-search.index', [ 'sources' => $this->projectSearch->listSources(), 'indexRuns' => array_slice($indexRuns, 0, 5), 'indexAvailable' => $this->projectSearch->isAvailable(), 'chatAvailable' => $this->chat->isAvailable(), 'ollamaConfigured' => (string) config('ollama.base_url') !== '', 'oauthClientId' => (string) config('project_search.oauth_client_id'), 'oauthScope' => (string) config('project_search.oauth_scope'), 'oauthTokenUrl' => rtrim((string) config('app.url'), '/').'/oauth/token', 'activeSession' => $activeSession, 'messages' => $messages, 'chatHistory' => $chatHistory, ]); } public function ask(Request $request): JsonResponse { $validated = $request->validate([ 'query' => ['required', 'string', 'min:3', 'max:500'], 'sources' => ['sometimes', 'array'], 'sources.*' => ['string', 'max:64'], 'limit' => ['sometimes', 'integer', 'min:1', 'max:50'], ]); $username = (string) $request->session()->get('ldap_username', ''); if ($username === '') { return response()->json(['message' => 'Sesi login tidak valid.'], 401); } try { $sources = $validated['sources'] ?? []; $session = $this->chat->getOrCreateActiveSession($username, $sources); $sessionId = (int) $session['id']; $history = $this->chat->conversationHistoryForOllama($sessionId); $userMessage = $this->chat->addUserMessage($sessionId, $validated['query']); $result = $this->projectSearch->ask( $validated['query'], $sources, (int) ($validated['limit'] ?? config('project_search.default_limit', 20)), $history ); $assistantMessage = $this->chat->addAssistantMessage( $sessionId, $result['answer'], $result['results'], $result['meta'] ); $this->audit->log( 'project_search.chat.ask', 'web', $username, null, 'project_search', $request, 200, [ 'session_id' => $sessionId, 'query' => $validated['query'], 'result_count' => $result['meta']['result_count'] ?? 0, 'sources' => $result['meta']['sources'] ?? [], ] ); return response()->json([ 'session' => $session, 'user_message' => $userMessage, 'assistant_message' => $assistantMessage, ]); } catch (RuntimeException $e) { return response()->json(['message' => $e->getMessage()], 422); } catch (Throwable) { return response()->json(['message' => 'Gagal memproses pencarian proyek.'], 500); } } public function endChat(Request $request): JsonResponse { $username = (string) $request->session()->get('ldap_username', ''); if ($username === '') { return response()->json(['message' => 'Sesi login tidak valid.'], 401); } $ended = $this->chat->endActiveSession($username); if ($ended) { $this->audit->log( 'project_search.chat.end', 'web', $username, null, 'project_search', $request, 200, [] ); } return response()->json(['ended' => $ended]); } }