From a0ec07a99ccc726968d081b16b96967d7bb98f68 Mon Sep 17 00:00:00 2001 From: team 1 Date: Sun, 19 Apr 2026 20:24:34 +0200 Subject: [PATCH] optimize code --- public/assets/js/base.js | 17 +++++---- src/Agent/AgentRunner.php | 10 +++--- src/Controller/AskSseController.php | 54 ++++++++++------------------- 3 files changed, 34 insertions(+), 47 deletions(-) diff --git a/public/assets/js/base.js b/public/assets/js/base.js index 0b0bcd4..f374d77 100644 --- a/public/assets/js/base.js +++ b/public/assets/js/base.js @@ -14,7 +14,7 @@ document.addEventListener('DOMContentLoaded', () => { reader: null, }; - marked.setOptions({ breaks: true }); + marked.setOptions({breaks: true}); function renderMarkdown(text) { return DOMPurify.sanitize(marked.parse(text)); @@ -365,8 +365,11 @@ document.addEventListener('DOMContentLoaded', () => { try { const res = await fetch('/ask-sse', { method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ prompt }), + headers: {'Content-Type': 'application/json'}, + body: JSON.stringify({ + prompt, + fullContext: false, + }), signal: state.abortController.signal, }); @@ -382,13 +385,13 @@ document.addEventListener('DOMContentLoaded', () => { const decoder = new TextDecoder(); while (!state.abortRequested) { - const { value, done } = await state.reader.read(); + const {value, done} = await state.reader.read(); if (done) { break; } - sseBuffer += decoder.decode(value, { stream: true }); + sseBuffer += decoder.decode(value, {stream: true}); const parsed = parseSseEvents(sseBuffer); sseBuffer = parsed.rest; @@ -398,7 +401,7 @@ document.addEventListener('DOMContentLoaded', () => { continue; } - const { eventName, data } = readSseEvent(rawEvent); + const {eventName, data} = readSseEvent(rawEvent); if (!data && eventName !== 'done') { continue; @@ -480,7 +483,7 @@ document.addEventListener('DOMContentLoaded', () => { } try { - await fetch('/history/delete', { method: 'POST' }); + await fetch('/history/delete', {method: 'POST'}); } catch (err) { console.error('History delete failed:', err); } diff --git a/src/Agent/AgentRunner.php b/src/Agent/AgentRunner.php index 083e056..dc496a1 100644 --- a/src/Agent/AgentRunner.php +++ b/src/Agent/AgentRunner.php @@ -41,7 +41,7 @@ final readonly class AgentRunner $this->systemMsgOn = true; } - public function run(string $prompt, string $userId, bool $includeFullContext = false): Generator + public function run(string $prompt, string $userId, bool $forceFullContext = false): Generator { $prompt = trim($prompt); @@ -66,7 +66,7 @@ final readonly class AgentRunner ]); try { - if ($includeFullContext) { + if ($forceFullContext) { // Full context mode is already passed to PromptBuilder. // Additional context strategies can be added here later. } @@ -164,7 +164,7 @@ final readonly class AgentRunner urlContent: $urlContent, knowledgeChunks: $knowledgeChunks, shopResults: $shopResults, - fullContext: $includeFullContext, + fullContext: $forceFullContext, swagFullOutPut: $optimizedShopQuery ); @@ -187,7 +187,7 @@ final readonly class AgentRunner 'userId' => $userId, 'context' => $this->contextService->buildUserContext( $userId, - $includeFullContext + $forceFullContext ), ]); } @@ -217,7 +217,7 @@ final readonly class AgentRunner $this->agentLogger->info('Agent run finished', [ 'userId' => $userId, 'outputLength' => mb_strlen($fullOutput), - 'contextMode' => $includeFullContext ? 'full' : 'recent', + 'contextMode' => $forceFullContext ? 'full' : 'recent', 'commerceIntent' => $commerceIntent, 'primaryShopResultsCount' => count($primaryShopResults), 'shopResultsCount' => count($shopResults), diff --git a/src/Controller/AskSseController.php b/src/Controller/AskSseController.php index a5848a9..8df8068 100644 --- a/src/Controller/AskSseController.php +++ b/src/Controller/AskSseController.php @@ -14,39 +14,40 @@ use Symfony\Component\Routing\Annotation\Route; final readonly class AskSseController { public function __construct( - private AgentRunner $agentRunner, + private AgentRunner $agentRunner, private ClientIdResolver $clientIdResolver, - ) {} + ) { + } #[Route('/ask-sse', name: 'ask_sse', methods: ['POST'])] public function stream(Request $request): StreamedResponse { - $data = json_decode($request->getContent(), true); + $data = json_decode($request->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): void { - - // --------------------------------------------------------- - // Disable all PHP output buffering - // --------------------------------------------------------- + function () use ($prompt, $clientId, $cookieResponse, $includeFullContext): void { 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(); @@ -56,11 +57,8 @@ final readonly class AskSseController return; } - // --------------------------------------------------------- - // 🔥 FIXED: Sende Chunks direkt (behält \n!) - // --------------------------------------------------------- try { - foreach ($this->agentRunner->run($prompt, $clientId, true) as $chunk) { + foreach ($this->agentRunner->run($prompt, $clientId, $includeFullContext) as $chunk) { $chunk = str_replace(["\r\n", "\r"], "\n", $chunk); $this->sendData($chunk); } @@ -71,44 +69,30 @@ final readonly class AskSseController ); } - // --------------------------------------------------------- - // 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', + '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);