getContent(), true); $prompt = trim((string) ($data['prompt'] ?? '')); /** * Default: * - Browser chat uses budgeted recent context * - Full context must be explicitly requested */ $includeFullContext = filter_var( $data['fullContext'] ?? false, FILTER_VALIDATE_BOOL ); $cookieResponse = new Response(); $clientId = $this->clientIdResolver->resolve($request, $cookieResponse); return new StreamedResponse( function () use ($prompt, $clientId, $cookieResponse, $includeFullContext): void { @set_time_limit(0); @ini_set('output_buffering', 'off'); @ini_set('zlib.output_compression', '0'); while (ob_get_level() > 0) { ob_end_flush(); } foreach ($cookieResponse->headers->getCookies() as $cookie) { header('Set-Cookie: ' . $cookie, false); } echo "retry: 3000\n\n"; $this->sendComment('stream-open'); if ($prompt === '') { $this->sendEvent('error', 'Empty prompt'); $this->sendEvent('done', '[DONE]'); return; } try { foreach ($this->agentRunner->run($prompt, $clientId, $includeFullContext) as $chunk) { if (connection_aborted() === 1) { return; } $chunk = str_replace(["\r\n", "\r"], "\n", $chunk); $this->sendData($chunk); } } catch (\Throwable $e) { $this->sendEvent( 'error', '❌ Stream abgebrochen: ' . $e->getMessage() ); } $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', 'X-Content-Type-Options' => 'nosniff', ] ); } private function sendData(string $data): void { if ($data === '') { $this->sendComment('keepalive'); return; } $lines = explode("\n", $data); foreach ($lines as $line) { echo 'data: ' . $line . "\n"; } echo "\n\n"; $this->flushOutput(); } private function sendEvent(string $event, string $data): void { $safe = str_replace(["\r", "\n"], ' ', $data); echo "event: {$event}\n"; echo "data: {$safe}\n\n"; $this->flushOutput(); } private function sendComment(string $comment): void { $safe = str_replace(["\r", "\n"], ' ', $comment); echo ': ' . $safe . "\n\n"; $this->flushOutput(); } private function flushOutput(): void { if (function_exists('ob_flush')) { @ob_flush(); } @flush(); } }