getContent(), true); $prompt = trim((string) ($data['prompt'] ?? '')); $cookieResponse = new Response(); $clientId = $this->clientIdResolver->resolve($request, $cookieResponse); return new StreamedResponse( function () use ($prompt, $clientId, $cookieResponse): void { // --------------------------------------------------------- // Disable all PHP output buffering // --------------------------------------------------------- while (ob_get_level() > 0) { ob_end_flush(); } // --------------------------------------------------------- // Forward cookies // --------------------------------------------------------- foreach ($cookieResponse->headers->getCookies() as $cookie) { header('Set-Cookie: ' . $cookie, false); } // --------------------------------------------------------- // SSE prelude // --------------------------------------------------------- echo "retry: 3000\n\n"; flush(); if ($prompt === '') { $this->sendEvent('error', 'Empty prompt'); $this->sendEvent('done', '[DONE]'); return; } // --------------------------------------------------------- // đŸ”„ FIXED: Sende Chunks direkt (behĂ€lt \n!) // --------------------------------------------------------- try { foreach ($this->agentRunner->run($prompt, $clientId, true) as $chunk) { $chunk = str_replace(["\r\n", "\r"], "\n", $chunk); $this->sendData($chunk); } } catch (\Throwable $e) { $this->sendEvent( 'error', '❌ Stream abgebrochen: ' . $e->getMessage() ); } // --------------------------------------------------------- // Signal completion // --------------------------------------------------------- $this->sendEvent('done', '[DONE]'); }, 200, [ 'Content-Type' => 'text/event-stream; charset=utf-8', 'Cache-Control' => 'no-cache, no-store, must-revalidate', 'Connection' => 'keep-alive', 'X-Accel-Buffering' => 'no', ] ); } /** * FIXED: BehĂ€lt Markdown-Struktur (\n) bei * * SSE erlaubt mehrere "data:"-Zeilen pro Event. * Jede Zeile wird als separate data-Zeile gesendet. */ private function sendData(string $data): void { // Split by \n und sende jede Zeile einzeln $lines = explode("\n", $data); foreach ($lines as $line) { echo 'data: ' . $line . "\n"; } // Leere Zeile = Ende der SSE-Message echo "\n\n"; flush(); } /** * Sends a named SSE event. */ private function sendEvent(string $event, string $data): void { $safe = str_replace(["\r", "\n"], ' ', $data); echo "event: {$event}\n"; echo "data: {$safe}\n\n"; flush(); } }