p63
This commit is contained in:
@@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Agent\AgentRunner;
|
||||
use App\Config\ChatMessagesConfig;
|
||||
use App\Context\ContextService;
|
||||
use App\Http\ClientIdResolver;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
@@ -27,6 +28,7 @@ final readonly class AskSseController
|
||||
|
||||
public function __construct(
|
||||
private AgentRunner $agentRunner,
|
||||
private ChatMessagesConfig $chatMessages,
|
||||
private ClientIdResolver $clientIdResolver,
|
||||
private ContextService $contextService,
|
||||
private string $projectDir,
|
||||
@@ -40,7 +42,7 @@ final readonly class AskSseController
|
||||
$prompt = trim((string) ($data['prompt'] ?? ''));
|
||||
|
||||
if ($prompt === '') {
|
||||
return new JsonResponse(['error' => 'Empty prompt'], Response::HTTP_BAD_REQUEST);
|
||||
return new JsonResponse(['error' => $this->chatMessages->getSseEmptyPrompt()], Response::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -73,7 +75,7 @@ final readonly class AskSseController
|
||||
]);
|
||||
} catch (Throwable $e) {
|
||||
return new JsonResponse(
|
||||
['error' => 'Stream job could not be created: ' . $this->formatThrowableForClient($e)],
|
||||
['error' => $this->chatMessages->getSseJobCreateFailed($this->formatThrowableForClient($e))],
|
||||
Response::HTTP_INTERNAL_SERVER_ERROR
|
||||
);
|
||||
}
|
||||
@@ -95,7 +97,7 @@ final readonly class AskSseController
|
||||
if (!is_array($job)) {
|
||||
return new JsonResponse([
|
||||
'status' => 'missing',
|
||||
'message' => 'Der Antwort-Job wurde nicht gefunden.',
|
||||
'message' => $this->chatMessages->getSseJobMissing(),
|
||||
'lastEventId' => 0,
|
||||
], Response::HTTP_NOT_FOUND);
|
||||
}
|
||||
@@ -213,8 +215,8 @@ final readonly class AskSseController
|
||||
$this->sendComment('stream-open');
|
||||
|
||||
if ($prompt === '') {
|
||||
$this->markJobStatus($jobId, self::JOB_STATUS_FAILED, 'Empty prompt');
|
||||
$this->sendEvent('error', 'Empty prompt');
|
||||
$this->markJobStatus($jobId, self::JOB_STATUS_FAILED, $this->chatMessages->getSseEmptyPrompt());
|
||||
$this->sendEvent('error', $this->chatMessages->getSseEmptyPrompt());
|
||||
$this->sendDoneEvent();
|
||||
return;
|
||||
}
|
||||
@@ -225,7 +227,7 @@ final readonly class AskSseController
|
||||
$this->markJobStatus(
|
||||
$jobId,
|
||||
self::JOB_STATUS_INTERRUPTED,
|
||||
'Die Verbindung zum Antwort-Stream wurde unterbrochen.'
|
||||
$this->chatMessages->getSseStreamInterrupted()
|
||||
);
|
||||
return;
|
||||
}
|
||||
@@ -235,11 +237,11 @@ final readonly class AskSseController
|
||||
$this->sendData($chunk, $eventId);
|
||||
}
|
||||
} catch (Throwable $e) {
|
||||
$message = 'Stream abgebrochen: ' . $this->formatThrowableForClient($e);
|
||||
$message = $this->chatMessages->getSseStreamAborted($this->formatThrowableForClient($e));
|
||||
$this->markJobStatus($jobId, self::JOB_STATUS_FAILED, $message);
|
||||
$this->sendEvent(
|
||||
'error',
|
||||
'❌ ' . $message
|
||||
$this->chatMessages->getSseStreamAbortedEvent($message)
|
||||
);
|
||||
|
||||
if ($prompt !== '' && $clientId !== '') {
|
||||
@@ -260,13 +262,13 @@ final readonly class AskSseController
|
||||
$message = trim(preg_replace('/\s+/u', ' ', $message) ?? $message);
|
||||
|
||||
if ($message === '') {
|
||||
$message = 'Unbekannter Streamfehler.';
|
||||
$message = $this->chatMessages->getSseUnknownStreamError();
|
||||
}
|
||||
|
||||
$this->contextService->appendHistory(
|
||||
$clientId,
|
||||
$prompt,
|
||||
'Systemhinweis: Antwort konnte nicht abgeschlossen werden. Ursache: ' . $message
|
||||
$this->chatMessages->getSseHistoryFailure($message)
|
||||
);
|
||||
} catch (Throwable) {
|
||||
// History persistence must never break the SSE error response.
|
||||
@@ -288,11 +290,10 @@ final readonly class AskSseController
|
||||
return;
|
||||
}
|
||||
|
||||
$message = sprintf(
|
||||
'❌ Fataler Serverfehler: %s in %s:%s',
|
||||
(string) ($error['message'] ?? 'unknown error'),
|
||||
(string) ($error['file'] ?? 'unknown file'),
|
||||
(string) ($error['line'] ?? '?')
|
||||
$message = $this->chatMessages->getSseFatalServerError(
|
||||
(string) ($error['message'] ?? $this->chatMessages->getSseFatalUnknownError()),
|
||||
(string) ($error['file'] ?? $this->chatMessages->getSseFatalUnknownFile()),
|
||||
(string) ($error['line'] ?? $this->chatMessages->getSseFatalUnknownLine())
|
||||
);
|
||||
|
||||
$this->markJobStatus($jobId, self::JOB_STATUS_FAILED, $message);
|
||||
@@ -420,13 +421,13 @@ final readonly class AskSseController
|
||||
$directory = $this->jobDirectory();
|
||||
|
||||
if (!is_dir($directory) && !mkdir($directory, 0775, true) && !is_dir($directory)) {
|
||||
throw new \RuntimeException('Stream job directory could not be created.');
|
||||
throw new \RuntimeException($this->chatMessages->getSseStorageDirectoryCreateFailed());
|
||||
}
|
||||
|
||||
$json = json_encode($payload, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
|
||||
if (file_put_contents($this->jobPath($jobId), $json, LOCK_EX) === false) {
|
||||
throw new \RuntimeException('Stream job could not be written.');
|
||||
throw new \RuntimeException($this->chatMessages->getSseStorageWriteFailed());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -664,8 +665,8 @@ final readonly class AskSseController
|
||||
$this->sendEvent(
|
||||
'error',
|
||||
$message !== ''
|
||||
? 'Der Antwort-Stream ist fehlgeschlagen: ' . $message
|
||||
: 'Der Antwort-Stream ist fehlgeschlagen. Bitte sende die Anfrage erneut.'
|
||||
? $this->chatMessages->getSseStreamFailedWithMessage($message)
|
||||
: $this->chatMessages->getSseStreamFailedRetry()
|
||||
);
|
||||
$this->sendDoneEvent();
|
||||
return;
|
||||
@@ -676,7 +677,7 @@ final readonly class AskSseController
|
||||
'error',
|
||||
$message !== ''
|
||||
? $message
|
||||
: 'Der Antwort-Stream wurde durch einen Verbindungsabbruch unterbrochen. Bitte sende die Anfrage erneut, falls die Antwort unvollständig ist.'
|
||||
: $this->chatMessages->getSseStreamInterruptedRetry()
|
||||
);
|
||||
$this->sendDoneEvent();
|
||||
return;
|
||||
@@ -857,7 +858,7 @@ final readonly class AskSseController
|
||||
return $job;
|
||||
}
|
||||
|
||||
$message = 'Der Antwort-Job liefert seit längerer Zeit keine neuen Daten. Der Stream wurde beendet, damit die Oberfläche nicht hängen bleibt.';
|
||||
$message = $this->chatMessages->getSseJobStale();
|
||||
$this->markJobStatus($jobId, self::JOB_STATUS_FAILED, $message);
|
||||
|
||||
$freshJob = $this->readJob($jobId);
|
||||
@@ -875,39 +876,40 @@ final readonly class AskSseController
|
||||
$message = is_string($claim['message'] ?? null) ? trim((string) $claim['message']) : '';
|
||||
|
||||
if ($reason === 'expired') {
|
||||
return 'Der Antwort-Job ist abgelaufen. Bitte sende die Anfrage erneut.';
|
||||
return $this->chatMessages->getSseClaimExpired();
|
||||
}
|
||||
|
||||
if ($reason === 'invalid') {
|
||||
return 'Der Antwort-Job ist ungültig. Bitte sende die Anfrage erneut.';
|
||||
return $this->chatMessages->getSseClaimInvalid();
|
||||
}
|
||||
|
||||
if ($reason === 'lock_failed') {
|
||||
return 'Der Antwort-Job ist gerade gesperrt. Bitte sende die Anfrage erneut, falls keine Antwort erscheint.';
|
||||
return $this->chatMessages->getSseClaimLockFailed();
|
||||
}
|
||||
|
||||
if ($reason === 'not_pending') {
|
||||
if ($status === self::JOB_STATUS_RUNNING) {
|
||||
return 'Der Antwort-Stream läuft bereits oder wurde nach einem Verbindungsabbruch erneut geöffnet. Bitte sende die Anfrage erneut, falls die Antwort unvollständig ist.';
|
||||
return $this->chatMessages->getSseClaimRunning();
|
||||
}
|
||||
|
||||
if ($status === self::JOB_STATUS_INTERRUPTED) {
|
||||
return 'Der Antwort-Stream wurde durch einen Verbindungsabbruch unterbrochen. Bitte sende die Anfrage erneut, falls die Antwort unvollständig ist.';
|
||||
return $this->chatMessages->getSseClaimInterrupted();
|
||||
}
|
||||
|
||||
if ($status === self::JOB_STATUS_COMPLETED) {
|
||||
return 'Der Antwort-Stream wurde bereits abgeschlossen. Bitte sende eine neue Anfrage, wenn du eine weitere Antwort brauchst.';
|
||||
return $this->chatMessages->getSseClaimCompleted();
|
||||
}
|
||||
|
||||
if ($status === self::JOB_STATUS_FAILED) {
|
||||
return $message !== ''
|
||||
? 'Der Antwort-Stream ist fehlgeschlagen: ' . $message
|
||||
: 'Der Antwort-Stream ist fehlgeschlagen. Bitte sende die Anfrage erneut.';
|
||||
? $this->chatMessages->getSseStreamFailedWithMessage($message)
|
||||
: $this->chatMessages->getSseStreamFailedRetry();
|
||||
}
|
||||
}
|
||||
|
||||
return 'Der Antwort-Job wurde nicht gefunden. Falls deine Verbindung kurz unterbrochen war, sende die Anfrage bitte erneut.';
|
||||
return $this->chatMessages->getSseClaimMissing();
|
||||
}
|
||||
|
||||
private function cleanupExpiredJobs(): void
|
||||
{
|
||||
$directory = $this->jobDirectory();
|
||||
|
||||
Reference in New Issue
Block a user