Warning: session_start(): Session cannot be started after headers have already been sent in /home/tvrreohg/public_html/manga.php on line 13
ensureAccess($request, $caseRecord); $session = $this->sessionFor($request, $caseRecord); $caseRecord->load(['documents', 'generatedPackets' => fn ($query) => $query->latest()]); $session->load(['messages' => fn ($query) => $query->oldest()]); return view('cases.assistant', compact('caseRecord', 'session')); } public function accept(Request $request, CaseRecord $caseRecord) { $this->ensureAccess($request, $caseRecord); $session = $this->sessionFor($request, $caseRecord); $session->update(['disclaimer_accepted_at' => now()]); if ($session->messages()->doesntExist()) { $session->messages()->create([ 'role' => 'assistant', 'content' => "Welcome to the CaseReady Assistant. Let’s slow things down and organize this clearly.\n\nTo begin: what happened, what outcome are you hoping for, and what is your biggest concern right now?\n\n".CaseReadyAssistantService::DISCLAIMER, ]); } return redirect()->route('cases.assistant.show', $caseRecord)->with('success', 'CaseReady preparation disclaimer accepted.'); } public function message(Request $request, CaseRecord $caseRecord, CaseReadyAssistantService $assistant) { $this->ensureAccess($request, $caseRecord); $data = $request->validate([ 'message' => ['required', 'string', 'max:12000'], ]); $session = $this->sessionFor($request, $caseRecord); if (! $session->disclaimer_accepted_at) { return back()->withErrors(['assistant' => 'Please accept the CaseReady preparation disclaimer before using the assistant.']); } $session->messages()->create([ 'user_id' => $request->user()->id, 'role' => 'user', 'content' => $data['message'], ]); try { $result = $assistant->reply($caseRecord, $session, $data['message']); } catch (RuntimeException $exception) { return back()->withErrors(['assistant' => $exception->getMessage()]); } $session->messages()->create([ 'role' => 'assistant', 'content' => $result['content'], 'metadata' => [ 'model' => $result['model'] ?? null, 'input_tokens' => $result['input_tokens'] ?? null, 'output_tokens' => $result['output_tokens'] ?? null, ], ]); $session->update(['phase' => $this->guessPhase($result['content'])]); return redirect()->route('cases.assistant.show', $caseRecord)->with('success', 'CaseReady Assistant replied.'); } private function sessionFor(Request $request, CaseRecord $caseRecord): AssistantSession { return AssistantSession::firstOrCreate( ['case_record_id' => $caseRecord->id, 'user_id' => $request->user()->id, 'status' => 'active'], ['title' => 'CaseReady preparation chat', 'phase' => 'understand'] ); } private function ensureAccess(Request $request, CaseRecord $caseRecord): void { abort_unless($request->user()->isAdmin() || $caseRecord->user_id === $request->user()->id, 403); } private function guessPhase(string $content): string { $lower = str($content)->lower(); return match (true) { $lower->contains(['checklist', 'questions to ask', 'packet']) => 'prepare', $lower->contains(['missing', 'document', 'unclear']) => 'organize', default => 'understand', }; } }